Auto merge of #46931 - clarcharr:float_bits_core, r=alexcrichton

Expose float from_bits and to_bits in libcore.

These methods have no dependencies on libm and thus should be offered in libcore.
diff --git a/.gitmodules b/.gitmodules
index 0a1188e..ffa7b32 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -21,10 +21,10 @@
 [submodule "src/tools/cargo"]
 	path = src/tools/cargo
 	url = https://github.com/rust-lang/cargo.git
-[submodule "reference"]
+[submodule "src/doc/reference"]
 	path = src/doc/reference
 	url = https://github.com/rust-lang-nursery/reference.git
-[submodule "book"]
+[submodule "src/doc/book"]
 	path = src/doc/book
 	url = https://github.com/rust-lang/book.git
 [submodule "src/tools/rls"]
@@ -48,3 +48,6 @@
 [submodule "src/binaryen"]
 	path = src/binaryen
 	url = https://github.com/alexcrichton/binaryen.git
+[submodule "src/doc/rust-by-example"]
+	path = src/doc/rust-by-example
+	url = https://github.com/rust-lang/rust-by-example
diff --git a/.mailmap b/.mailmap
index c2d3b28..9034aae 100644
--- a/.mailmap
+++ b/.mailmap
@@ -41,11 +41,12 @@
 Brandon Sanderson <singingboyo@gmail.com> Brandon Sanderson <singingboyo@hotmail.com>
 Brett Cannon <brett@python.org> Brett Cannon <brettcannon@users.noreply.github.com>
 Brian Anderson <banderson@mozilla.com> <andersrb@gmail.com>
+Brian Anderson <banderson@mozilla.com> <banderson@mozilla.org>
 Brian Dawn <brian.t.dawn@gmail.com>
 Brian Leibig <brian@brianleibig.com> Brian Leibig <brian.leibig@gmail.com>
 Carl-Anton Ingmarsson <mail@carlanton.se> <ca.ingmarsson@gmail.com>
-Carol (Nichols || Goulding) <carol.nichols@gmail.com>
-Carol (Nichols || Goulding) <cnichols@thinkthroughmath.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> <cnichols@thinkthroughmath.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> Carol Nichols <carol.nichols@gmail.com>
 Carol Willing <carolcode@willingconsulting.com>
 Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
 Chris Pressey <cpressey@gmail.com>
diff --git a/.travis.yml b/.travis.yml
index d0f1dbc..6e242b7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,11 @@
 language: shell
 sudo: required
 dist: trusty
-group: deprecated-2017Q4
 services:
   - docker
 
 git:
-  depth: 1
+  depth: 2
   submodules: false
 
 matrix:
@@ -127,7 +126,7 @@
       if: branch = auto
     - env: IMAGE=dist-armv7-linux DEPLOY=1
       if: branch = auto
-    - env: IMAGE=dist-i586-gnu-i686-musl DEPLOY=1
+    - env: IMAGE=dist-i586-gnu-i586-i686-musl DEPLOY=1
       if: branch = auto
     - env: IMAGE=dist-i686-freebsd DEPLOY=1
       if: branch = auto
@@ -180,6 +179,17 @@
     - env: IMAGE=x86_64-gnu-incremental
       if: branch = auto
 
+    - stage: publish toolstate
+      if: branch = master AND type = push
+      before_install: []
+      install: []
+      cache: false
+      sudo: false
+      script:
+        MESSAGE_FILE=$(mktemp -t msg.XXXXXX);
+        . src/ci/docker/x86_64-gnu-tools/repo.sh;
+        commit_toolstate_change "$MESSAGE_FILE" "$TRAVIS_BUILD_DIR/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE"
+
 env:
   global:
     - SCCACHE_BUCKET=rust-lang-ci-sccache2
@@ -187,10 +197,19 @@
     - AWS_ACCESS_KEY_ID=AKIAJAMV3QAMMA6AXHFQ
     # AWS_SECRET_ACCESS_KEY=...
     - secure: "j96XxTVOSUf4s4r4htIxn/fvIa5DWbMgLqWl7r8z2QfgUwscmkMXAwXuFNc7s7bGTpV/+CgDiMFFM6BAFLGKutytIF6oA02s9b+usQYnM0th7YQ2AIgm9GtMTJCJp4AoyfFmh8F2faUICBZlfVLUJ34udHEe35vOklix+0k4WDo="
+    # TOOLSTATE_REPO_ACCESS_TOKEN=...
+    - secure: "cFh8thThqEJLC98XKI5pfqflUzOlxsYPRW20AWRaYOOgYHPTiGWypTXiPbGSKaeAXTZoOA+DpQtEmefc0U6lt9dHc7a/MIaK6isFurjlnKYiLOeTruzyu1z7PWCeZ/jKXsU2RK/88DBtlNwfMdaMIeuKj14IVfpepPPL71ETbuk="
 
 before_install:
   - zcat $HOME/docker/rust-ci.tar.gz | docker load || true
   - mkdir -p $HOME/rustsrc
+  # FIXME(#46924): these two commands are required to enable IPv6,
+  # they shouldn't exist, please revert once more official solutions appeared.
+  # see https://github.com/travis-ci/travis-ci/issues/8891#issuecomment-353403729
+  - if [ "$TRAVIS_OS_NAME" = linux ]; then
+      echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json;
+      sudo service docker restart;
+    fi
 
 install:
   - case "$TRAVIS_OS_NAME" in
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index d42476b..e9b3971 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -12,13 +12,13 @@
 * Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
 * Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
 * We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behaviour. We interpret the term "harassment" as including the definition in the <a href="http://citizencodeofconduct.org/">Citizen Code of Conduct</a>; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
-* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team](/team.html#Moderation) immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
+* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
 * Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome.
 
 ## Moderation
 
 
-These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team](/team.html#Moderation).
+These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team].
 
 1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.)
 2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.
@@ -35,4 +35,6 @@
 
 The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
 
-*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](http://contributor-covenant.org/version/1/3/0/).*
+*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
+
+[mod_team]: https://www.rust-lang.org/team.html#Moderation-team
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 919d832..70376c1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -301,12 +301,12 @@
 [pull-requests]: #pull-requests
 
 Pull requests are the primary mechanism we use to change Rust. GitHub itself
-has some [great documentation][pull-requests] on using the Pull Request feature.
+has some [great documentation][about-pull-requests] on using the Pull Request feature.
 We use the "fork and pull" model [described here][development-models], where
 contributors push changes to their personal fork and create pull requests to
 bring those changes into the source repository.
 
-[pull-requests]: https://help.github.com/articles/about-pull-requests/
+[about-pull-requests]: https://help.github.com/articles/about-pull-requests/
 [development-models]: https://help.github.com/articles/about-collaborative-development-models/
 
 Please make pull requests against the `master` branch.
@@ -369,26 +369,29 @@
 
 * [clippy](https://github.com/rust-lang-nursery/rust-clippy)
 * [miri](https://github.com/solson/miri)
+* [rustfmt](https://github.com/rust-lang-nursery/rustfmt)
+* [rls](https://github.com/rust-lang-nursery/rls/)
 
-If your changes break one of these projects, you need to fix them by opening
-a pull request against the broken project asking to put the fix on a branch.
-Then you can disable the tool building via `src/tools/toolstate.toml`.
-Once the branch containing your fix is likely to be merged, you can point
-the affected submodule at this branch.
+We allow breakage of these tools in the nightly channel. Maintainers of these
+projects will be notified of the breakages and should fix them as soon as
+possible.
 
-Don't forget to also add your changes with
+After the external is fixed, one could add the changes with
 
-```
+```sh
 git add path/to/submodule
 ```
 
 outside the submodule.
 
-In order to prepare your PR, you can run the build locally by doing
+In order to prepare your tool-fixing PR, you can run the build locally by doing
 `./x.py build src/tools/TOOL`. If you will be editing the sources
 there, you may wish to set `submodules = false` in the `config.toml`
 to prevent `x.py` from resetting to the original branch.
 
+Breakage is not allowed in the beta and stable channels, and must be addressed
+before the PR is merged.
+
 #### Breaking Tools Built With The Compiler
 [breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler
 
@@ -406,12 +409,12 @@
 That means that, in the default state, you can't update the compiler without first
 fixing rustfmt, rls and the other tools that the compiler builds.
 
-Luckily, a feature was [added to Rust's build](https://github.com/rust-lang/rust/pull/45243)
-to make all of this easy to handle. The idea is that you mark the tools as "broken",
+Luckily, a feature was [added to Rust's build](https://github.com/rust-lang/rust/issues/45861)
+to make all of this easy to handle. The idea is that we allow these tools to be "broken",
 so that the rust-lang/rust build passes without trying to build them, then land the change
 in the compiler, wait for a nightly, and go update the tools that you broke. Once you're done
-and the tools are working again, you go back in the compiler and change the tools back
-from "broken".
+and the tools are working again, you go back in the compiler and update the tools
+so they can be distributed again.
 
 This should avoid a bunch of synchronization dances and is also much easier on contributors as
 there's no need to block on rls/rustfmt/other tools changes going upstream.
@@ -430,15 +433,10 @@
 4. (optional) Maintainers of these submodules will **not** merge the PR. The PR can't be
    merged because CI will be broken. You'll want to write a message on the PR referencing
    your change, and how the PR should be merged once your change makes it into a nightly.
-5. Update `src/tools/toolstate.toml` to indicate that the tool in question is "broken",
-   that will disable building it on CI. See the documentation in that file for the exact
-   configuration values you can use.
-6. Commit the changes to `src/tools/toolstate.toml`, **do not update submodules in your commit**,
-   and then update the PR you have for rust-lang/rust.
-7. Wait for your PR to merge.
-8. Wait for a nightly
-9. (optional) Help land your PR on the upstream repository now that your changes are in nightly.
-10. (optional) Send a PR to rust-lang/rust updating the submodule, reverting `src/tools/toolstate.toml` back to a "building" or "testing" state.
+5. Wait for your PR to merge.
+6. Wait for a nightly
+7. (optional) Help land your PR on the upstream repository now that your changes are in nightly.
+8. (optional) Send a PR to rust-lang/rust updating the submodule.
 
 #### Updating submodules
 [updating-submodules]: #updating-submodules
diff --git a/RELEASES.md b/RELEASES.md
index 57434eb..45c389d 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,92 @@
+Version 1.23.0 (2018-01-04)
+==========================
+
+Language
+--------
+- [Arbitrary `auto` traits are now permitted in trait objects.][45772]
+- [rustc now uses subtyping on the left hand side of binary operations.][45435]
+  Which should fix some confusing errors in some operations.
+
+Compiler
+--------
+- [Enabled `TrapUnreachable` in LLVM which should mitigate the impact of
+  undefined behaviour.][45920]
+- [rustc now suggests renaming import if names clash.][45660]
+- [Display errors/warnings correctly when there are zero-width or
+  wide characters.][45711]
+- [rustc now avoids unnecessary copies of arguments that are
+  simple bindings][45380] This should improve memory usage on average by 5-10%.
+- [Updated musl used to build musl rustc to 1.1.17][45393]
+
+Libraries
+---------
+- [Allow a trailing comma in `assert_eq/ne` macro][45887]
+- [Implement Hash for raw pointers to unsized types][45483]
+- [impl `From<*mut T>` for `AtomicPtr<T>`][45610]
+- [impl `From<usize/isize>` for `AtomicUsize/AtomicIsize`.][45610]
+- [Removed the `T: Sync` requirement for `RwLock<T>: Send`][45267]
+- [Removed `T: Sized` requirement for `{<*const T>, <*mut T>}::as_ref`
+  and `<*mut T>::as_mut`][44932]
+- [Optimized `Thread::{park, unpark}` implementation][45524]
+- [Improved `SliceExt::binary_search` performance.][45333]
+- [impl `FromIterator<()>` for `()`][45379]
+- [Copied `AsciiExt` trait methods to primitive types.][44042] Use of `AsciiExt`
+  is now deprecated.
+
+Stabilized APIs
+---------------
+
+Cargo
+-----
+- [Cargo now supports uninstallation of multiple packages][cargo/4561]
+  eg. `cargo uninstall foo bar` uninstalls `foo` and `bar`.
+- [Added unit test checking to `cargo check`][cargo/4592]
+- [Cargo now lets you install a specific version
+  using `cargo install --version`][cargo/4637]
+
+Misc
+----
+- [Releases now ship with the Cargo book documentation.][45692]
+- [rustdoc now prints rendering warnings on every run.][45324]
+
+Compatibility Notes
+-------------------
+- [Changes have been made to type equality to make it more correct,
+  in rare cases this could break some code.][45853] [Tracking issue for
+  further information][45852]
+- [`char::escape_debug` now uses Unicode 10 over 9.][45571]
+- [Upgraded Android SDK to 27, and NDK to r15c.][45580] This drops support for
+  Android 9, the minimum supported version is Android 14.
+- [Bumped the minimum LLVM to 3.9][45326]
+
+[44042]: https://github.com/rust-lang/rust/pull/44042
+[44932]: https://github.com/rust-lang/rust/pull/44932
+[45267]: https://github.com/rust-lang/rust/pull/45267
+[45324]: https://github.com/rust-lang/rust/pull/45324
+[45326]: https://github.com/rust-lang/rust/pull/45326
+[45333]: https://github.com/rust-lang/rust/pull/45333
+[45379]: https://github.com/rust-lang/rust/pull/45379
+[45380]: https://github.com/rust-lang/rust/pull/45380
+[45393]: https://github.com/rust-lang/rust/pull/45393
+[45435]: https://github.com/rust-lang/rust/pull/45435
+[45483]: https://github.com/rust-lang/rust/pull/45483
+[45524]: https://github.com/rust-lang/rust/pull/45524
+[45571]: https://github.com/rust-lang/rust/pull/45571
+[45580]: https://github.com/rust-lang/rust/pull/45580
+[45610]: https://github.com/rust-lang/rust/pull/45610
+[45660]: https://github.com/rust-lang/rust/pull/45660
+[45692]: https://github.com/rust-lang/rust/pull/45692
+[45711]: https://github.com/rust-lang/rust/pull/45711
+[45772]: https://github.com/rust-lang/rust/pull/45772
+[45852]: https://github.com/rust-lang/rust/issues/45852
+[45853]: https://github.com/rust-lang/rust/pull/45853
+[45887]: https://github.com/rust-lang/rust/pull/45887
+[45920]: https://github.com/rust-lang/rust/pull/45920
+[cargo/4561]: https://github.com/rust-lang/cargo/pull/4561
+[cargo/4592]: https://github.com/rust-lang/cargo/pull/4592
+[cargo/4637]: https://github.com/rust-lang/cargo/pull/4637
+
+
 Version 1.22.1 (2017-11-22)
 ==========================
 
@@ -488,7 +577,7 @@
   a warning.
 - [From the pound escape, lines consisting of multiple `#`s are
   now visible][41785]
-- [It is an error to reexport private enum variants][42460]. This is
+- [It is an error to re-export private enum variants][42460]. This is
   known to break a number of crates that depend on an older version of
   mustache.
 - [On Windows, if `VCINSTALLDIR` is set incorrectly, `rustc` will try
@@ -2162,10 +2251,10 @@
 -------
 
 * [Fix empty implementation section on some module pages](https://github.com/rust-lang/rust/pull/34536)
-* [Fix inlined renamed reexports in import lists](https://github.com/rust-lang/rust/pull/34479)
+* [Fix inlined renamed re-exports in import lists](https://github.com/rust-lang/rust/pull/34479)
 * [Fix search result layout for enum variants and struct fields](https://github.com/rust-lang/rust/pull/34477)
 * [Fix issues with source links to external crates](https://github.com/rust-lang/rust/pull/34387)
-* [Fix redirect pages for renamed reexports](https://github.com/rust-lang/rust/pull/34245)
+* [Fix redirect pages for renamed re-exports](https://github.com/rust-lang/rust/pull/34245)
 
 Tooling
 -------
@@ -4899,7 +4988,7 @@
     * std: The `vec` module has been renamed to `slice`.
     * std: A new vector type, `Vec<T>`, has been added in preparation for DST.
       This will become the only growable vector in the future.
-    * std: `std::io` now has more public-reexports. Types such as `BufferedReader`
+    * std: `std::io` now has more public re-exports. Types such as `BufferedReader`
       are now found at `std::io::BufferedReader` instead of
       `std::io::buffered::BufferedReader`.
     * std: `print` and `println` are no longer in the prelude, the `print!` and
@@ -4990,8 +5079,8 @@
       * render standalone markdown files.
       * the --test flag tests all code blocks by default.
       * exported macros are displayed.
-      * reexported types have their documentation inlined at the location of the
-        first reexport.
+      * re-exported types have their documentation inlined at the location of the
+        first re-export.
       * search works across crates that have been rendered to the same output
         directory.
 
@@ -5378,7 +5467,7 @@
         incl. `any`, `all`. removed.
       * std: The `finalize` method of `Drop` renamed to `drop`.
       * std: The `drop` method now takes `&mut self` instead of `&self`.
-      * std: The prelude no longer reexports any modules, only types and traits.
+      * std: The prelude no longer re-exports any modules, only types and traits.
       * std: Prelude additions: `print`, `println`, `FromStr`, `ApproxEq`, `Equiv`,
         `Iterator`, `IteratorUtil`, many numeric traits, many tuple traits.
       * std: New numeric traits: `Fractional`, `Real`, `RealExt`, `Integer`, `Ratio`,
diff --git a/appveyor.yml b/appveyor.yml
index b8fd479..1a186c0 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,6 +5,8 @@
   AWS_SECRET_ACCESS_KEY:
     secure: 7Y+JiquYedOAgnUU26uL0DPzrxmTtR+qIwG6rNKSuWDffqU3vVZxbGXim9QpTO80
   SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c
+  TOOLSTATE_REPO_ACCESS_TOKEN:
+    secure: PTZiSxJMVUZ0VnMR5i13E4OagbXfglj7pcskDQiKufVrDm13mLoI0vDJAEM35+bY
 
   # By default schannel checks revocation of certificates unlike some other SSL
   # backends, but we've historically had problems on CI where a revocation
@@ -27,8 +29,8 @@
 
   # MSVC tools tests
   - MSYS_BITS: 64
-    SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py toolstates.json
-    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=toolstates.json
+    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
 
   # 32/64-bit MinGW builds.
   #
@@ -94,7 +96,7 @@
 matrix:
   fast_finish: true
 
-clone_depth: 1
+clone_depth: 2
 build: false
 
 install:
diff --git a/src/Cargo.lock b/src/Cargo.lock
index c22187e..ae9e755 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -28,7 +28,7 @@
 version = "0.0.0"
 dependencies = [
  "core 0.0.0",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "std_unicode 0.0.0",
 ]
 
@@ -39,7 +39,7 @@
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.0.0",
 ]
@@ -70,27 +70,24 @@
 
 [[package]]
 name = "atty"
-version = "0.2.3"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "backtrace"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "dbghelp-sys 0.2.0 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -98,8 +95,8 @@
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -126,16 +123,16 @@
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -152,8 +149,8 @@
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -161,61 +158,59 @@
 name = "build_helper"
 version = "0.1.0"
 dependencies = [
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "byteorder"
-version = "1.1.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cargo"
-version = "0.25.0"
+version = "0.26.0"
 dependencies = [
- "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargotest 0.1.0",
  "core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "crates-io 0.14.0",
- "crossbeam 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crates-io 0.15.0",
+ "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "crypto-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.8 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ignore 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -223,35 +218,35 @@
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cargo_metadata"
-version = "0.3.3"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cargotest"
 version = "0.1.0"
 dependencies = [
- "cargo 0.25.0",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo 0.26.0",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -262,7 +257,7 @@
 
 [[package]]
 name = "cc"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -272,11 +267,11 @@
 
 [[package]]
 name = "clap"
-version = "2.28.0"
+version = "2.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -295,9 +290,9 @@
  "compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -314,10 +309,10 @@
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -325,10 +320,10 @@
 
 [[package]]
 name = "cmake"
-version = "0.1.28"
+version = "0.1.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -353,14 +348,14 @@
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -370,12 +365,12 @@
 dependencies = [
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -386,12 +381,13 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -409,7 +405,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -417,29 +413,29 @@
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crates-io"
-version = "0.14.0"
+version = "0.15.0"
 dependencies = [
- "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crossbeam"
-version = "0.2.10"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "crossbeam"
-version = "0.3.0"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -450,7 +446,7 @@
  "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -480,38 +476,31 @@
 
 [[package]]
 name = "curl"
-version = "0.4.8"
+version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.1 (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.36 (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.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "curl-sys"
-version = "0.3.15"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "dbghelp-sys"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -550,13 +539,13 @@
 
 [[package]]
 name = "docopt"
-version = "0.8.1"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -599,7 +588,7 @@
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -608,8 +597,8 @@
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -617,7 +606,7 @@
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -625,7 +614,7 @@
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -636,17 +625,36 @@
 ]
 
 [[package]]
+name = "failure"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "failure_derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "features"
 version = "0.1.0"
 
 [[package]]
 name = "filetime"
-version = "0.1.14"
+version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -659,10 +667,10 @@
 
 [[package]]
 name = "flate2"
-version = "0.2.20"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -690,29 +698,26 @@
 
 [[package]]
 name = "fs2"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fuchsia-zircon"
-version = "0.2.1"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fuchsia-zircon-sys"
-version = "0.2.0"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
 
 [[package]]
 name = "futf"
@@ -735,14 +740,14 @@
 
 [[package]]
 name = "git2"
-version = "0.6.8"
+version = "0.6.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.19 (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.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -751,9 +756,9 @@
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -769,9 +774,9 @@
 dependencies = [
  "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -793,12 +798,12 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -807,6 +812,11 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "hex"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "home"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -820,7 +830,7 @@
 
 [[package]]
 name = "html-diff"
-version = "0.0.5"
+version = "0.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kuchiki 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -831,7 +841,7 @@
 version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "markup5ever 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -855,17 +865,18 @@
 
 [[package]]
 name = "ignore"
-version = "0.2.2"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -884,15 +895,16 @@
 name = "installer"
 version = "0.0.0"
 dependencies = [
- "clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -910,23 +922,28 @@
 
 [[package]]
 name = "jobserver"
-version = "0.1.8"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "json"
+version = "0.11.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "jsonrpc-core"
-version = "7.1.1"
+version = "8.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -955,9 +972,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -968,6 +985,11 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "lazy_static"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "lazycell"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -981,21 +1003,21 @@
 
 [[package]]
 name = "libc"
-version = "0.2.34"
+version = "0.2.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libgit2-sys"
-version = "0.6.16"
+version = "0.6.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1004,10 +1026,10 @@
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1016,8 +1038,8 @@
 version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1028,8 +1050,19 @@
 
 [[package]]
 name = "log"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "log"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "log_settings"
@@ -1044,9 +1077,9 @@
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1075,21 +1108,21 @@
 
 [[package]]
 name = "mdbook"
-version = "0.0.26"
+version = "0.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1099,15 +1132,7 @@
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "memchr"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1115,7 +1140,7 @@
 version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1123,8 +1148,8 @@
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1139,6 +1164,17 @@
 ]
 
 [[package]]
+name = "miri"
+version = "0.1.0"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "multiple_bins"
 version = "0.1.0"
 
@@ -1149,7 +1185,7 @@
 dependencies = [
  "cfg-if 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)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1166,7 +1202,7 @@
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1190,7 +1226,7 @@
 dependencies = [
  "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1238,10 +1274,10 @@
 
 [[package]]
 name = "num_cpus"
-version = "1.7.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1251,28 +1287,28 @@
 
 [[package]]
 name = "openssl"
-version = "0.9.22"
+version = "0.9.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (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 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "openssl-probe"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.22"
+version = "0.9.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1319,17 +1355,17 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "parking_lot_core"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1367,7 +1403,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1406,20 +1442,11 @@
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
 [[package]]
-name = "psapi-sys"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "pulldown-cmark"
 version = "0.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1457,10 +1484,10 @@
 version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1477,11 +1504,11 @@
 
 [[package]]
 name = "rand"
-version = "0.3.18"
+version = "0.3.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (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.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1500,14 +1527,14 @@
 dependencies = [
  "coco 0.1.1 (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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (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.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.32"
+version = "0.1.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1515,7 +1542,7 @@
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1540,13 +1567,13 @@
 
 [[package]]
 name = "regex"
-version = "0.2.3"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1557,7 +1584,7 @@
 
 [[package]]
 name = "regex-syntax"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1572,57 +1599,50 @@
 name = "rls"
 version = "0.124.0"
 dependencies = [
- "cargo 0.25.0",
+ "cargo 0.26.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.3.2",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.3.6",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rls-analysis"
-version = "0.9.3"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rls-data"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rls-data"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1636,8 +1656,8 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1653,8 +1673,8 @@
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1662,14 +1682,14 @@
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
- "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_apfloat 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
@@ -1681,6 +1701,72 @@
 ]
 
 [[package]]
+name = "rustc-ap-rustc_cratesio_shim"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_data_structures"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_errors"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-serialize"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-ap-syntax"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-syntax_pos"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "rustc-demangle"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1723,7 +1809,7 @@
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1731,8 +1817,8 @@
 name = "rustc_back"
 version = "0.0.0"
 dependencies = [
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "syntax 0.0.0",
 ]
@@ -1741,9 +1827,9 @@
 name = "rustc_binaryen"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1751,7 +1837,7 @@
 version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_mir 0.0.0",
@@ -1764,7 +1850,7 @@
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -1794,9 +1880,9 @@
 version = "0.0.0"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1809,7 +1895,7 @@
  "arena 0.0.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_allocator 0.0.0",
  "rustc_back 0.0.0",
@@ -1850,8 +1936,8 @@
 version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
@@ -1863,7 +1949,7 @@
 name = "rustc_lint"
 version = "0.0.0"
 dependencies = [
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_const_eval 0.0.0",
  "syntax 0.0.0",
@@ -1876,7 +1962,7 @@
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
 ]
 
@@ -1887,7 +1973,7 @@
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1895,8 +1981,8 @@
 name = "rustc_metadata"
 version = "0.0.0"
 dependencies = [
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
@@ -1913,17 +1999,17 @@
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_apfloat 0.0.0",
+ "rustc_back 0.0.0",
  "rustc_const_eval 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_trans_utils 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -1936,7 +2022,7 @@
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1944,7 +2030,7 @@
 name = "rustc_passes"
 version = "0.0.0"
 dependencies = [
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_const_eval 0.0.0",
  "rustc_const_math 0.0.0",
@@ -1983,7 +2069,7 @@
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -1995,7 +2081,7 @@
 name = "rustc_save_analysis"
 version = "0.0.0"
 dependencies = [
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -2011,11 +2097,11 @@
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
@@ -2041,11 +2127,13 @@
 version = "0.0.0"
 dependencies = [
  "ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_data_structures 0.0.0",
+ "rustc_incremental 0.0.0",
+ "rustc_mir 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2057,7 +2145,7 @@
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2067,7 +2155,7 @@
 dependencies = [
  "arena 0.0.0",
  "fmt_macros 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -2082,8 +2170,8 @@
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "html-diff 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "html-diff 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2097,20 +2185,23 @@
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.3.2"
+version = "0.3.6"
 dependencies = [
- "cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.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.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2127,6 +2218,23 @@
 ]
 
 [[package]]
+name = "same-file"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "scoped-tls"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2170,7 +2278,16 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2180,22 +2297,22 @@
 
 [[package]]
 name = "serde"
-version = "1.0.23"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.23"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_derive_internals"
-version = "0.17.0"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2207,18 +2324,18 @@
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.7"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2231,7 +2348,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2257,14 +2374,12 @@
 
 [[package]]
 name = "socket2"
-version = "0.2.4"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 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)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2286,7 +2401,7 @@
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -2311,7 +2426,7 @@
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2356,11 +2471,20 @@
 ]
 
 [[package]]
+name = "synstructure"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "syntax"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -2393,8 +2517,8 @@
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2415,8 +2539,8 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2429,9 +2553,9 @@
 version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2440,7 +2564,7 @@
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2479,8 +2603,8 @@
 version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2506,7 +2630,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2519,10 +2643,10 @@
 
 [[package]]
 name = "thread_local"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2543,7 +2667,7 @@
 version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2625,7 +2749,7 @@
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2682,16 +2806,43 @@
 ]
 
 [[package]]
+name = "walkdir"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "winapi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "winapi-build"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "wincolor"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2718,12 +2869,12 @@
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "xz2"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2740,38 +2891,37 @@
 "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
 "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
 "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
-"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
-"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e"
+"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
+"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
 "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
 "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
-"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
+"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
 "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
-"checksum cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f56ec3e469bca7c276f2eea015aa05c5e381356febdbb0683c2580189604537"
-"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
+"checksum cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6fb2b5574726329c85cdba0df0347fddfec3cf9c8b588f9931708280f5643"
+"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
-"checksum clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34bf7d5d66268b466b9852bca925ec1d2650654dab4da081e63fd230145c2e"
-"checksum cmake 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e14cd15a7cbc2c6a905677e54b831ee91af2ff43b352010f6133236463b65cac"
+"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
+"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
 "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
 "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
 "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
 "checksum compiletest_rs 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "562bafeec9aef1e3e08f1c5b0c542220bb80ff2894e5373a1f9d17c346412c66"
 "checksum core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8047f547cd6856d45b1cdd75ef8d2f21f3d0e4bf1dab0a0041b0ae9a5dda9c0e"
 "checksum core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "152195421a2e6497a8179195672e9d4ee8e45ed8c465b626f1606d27a08ebcd5"
-"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
-"checksum crossbeam 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8837ab96533202c5b610ed44bc7f4183e7957c1c8f56e8cc78bb098593c8ba0a"
+"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be"
+"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
 "checksum crypto-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34903878eec1694faf53cae8473a088df333181de421d4d3d48061d6559fe602"
 "checksum cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef6124306e5ebc5ab11891d063aeafdd0cdc308079b708c8b566125f3680292b"
 "checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
-"checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c"
-"checksum curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4bee31aa3a079d5f3ff9579ea4dcfb1b1a17a40886f5f467436d383e78134b55"
-"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
+"checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e"
+"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "415f627ab054041c3eb748c2e1da0ef751989f5f0c386b63a098e545854a98ba"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
-"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
+"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c"
 "checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
@@ -2781,52 +2931,57 @@
 "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46"
-"checksum filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "aa75ec8f7927063335a9583e7fa87b0110bb888cf766dc01b54c0ff70d760c8e"
-"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423"
+"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
+"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
+"checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"
+"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
-"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
-"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
-"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
+"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
 "checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1"
 "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9"
-"checksum git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1c0203d653f4140241da0c1375a404f0a397249ec818cd2076c6280c50f6fa"
+"checksum git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5b4bb7cd2a44e6e5ee3a26ba6a9ca10d4ce2771cdc3839bbc54b47b7d1be84"
 "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "464627f948c3190ae3d04b1bc6d7dca2f785bda0ac01278e6db129ad383dbeb6"
 "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4"
 "checksum handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04af2006ea09d985fef82b81e0eb25337e51b691c76403332378a53d521edc"
 "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
+"checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc"
 "checksum home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f25ae61099d8f3fee8b483df0bd4ecccf4b2731897aad40d50eca1b641fe6db"
-"checksum html-diff 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9778743e3b3c3679f471f0ed1833c690f19f4a0919e33b281f12ef5f77ad64c6"
+"checksum html-diff 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4cfdf62a484a3ac0d9b80f562d37f99366db08a63621b917ea3056565345f7"
 "checksum html5ever 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bfb46978eb757a603b7dfe2dafb1c62cb4dee3428d8ac1de734d83d6b022d06"
 "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
 "checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
-"checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5"
+"checksum ignore 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb2f0238094bd1b41800fb6eb9b16fdd5e9832ed6053ed91409f0cd5bf28dcfd"
 "checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21"
 "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
-"checksum jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "931b04e5e57d88cc909528f0d701db36a870b72a052648ded8baf80f9f445e0f"
-"checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515"
+"checksum jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "565f6106bd87b394398f813bea4e5ecad6d6b0f6aa077592d088f882a506481d"
+"checksum json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)" = "39ebf0fac977ee3a4a3242b6446004ff64514889e3e2730bbd4f764a67a2e483"
+"checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum kuchiki 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e03098e8e719c92b7794515dfd5c1724e2b12f5ce1788e61cfa4663f82eba8d8"
 "checksum languageserver-types 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "773e175c945800aeea4c21c04090bcb9db987b1a566ad9c6f569972299950e3e"
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
+"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
 "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
-"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
-"checksum libgit2-sys 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "6f74b4959cef96898f5123148724fc7dee043b9a6b99f219d948851bfbe53cb2"
+"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
+"checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357"
 "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
 "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
-"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
+"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
+"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
 "checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6"
 "checksum lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b93b78f89e8737dac81837fc8f5521ac162abcba902e1a3db949d55346d1da"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum markup5ever 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "047150a0e03b57e638fc45af33a0b63a0362305d5b9f92ecef81df472a4cceb0"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
-"checksum mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ac668292d1e5c7b1c6fd64f70d3a85105b8069a89558a0d67bdb2ff298ca1"
+"checksum mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee8ba20c002000546681dc78d7f7e91fd35832058b1e2fdd492ca842bb6e9be"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
-"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
@@ -2840,15 +2995,15 @@
 "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
 "checksum num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7cb72a95250d8a370105c828f388932373e0e94414919891a0f945222310fe"
 "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
-"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
+"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
 "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
-"checksum openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "419ef26bb651d72b6c5a603bcc4e4856a362460e62352dfffa53de91d2e81181"
-"checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
-"checksum openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5483bdc56756041ba6aa37c9cb59cc2219f012a2a1377d97ad35556ac6676ee7"
+"checksum openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "169a4b9160baf9b9b1ab975418c673686638995ba921683a7f1e01470dcb8854"
+"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
+"checksum openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "14ba54ac7d5a4eabd1d5f2c1fdeb7e7c14debfa669d94b983d01b465e767ba9e"
 "checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412"
-"checksum parking_lot_core 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "12d20aac4f67aa75f681aded784bac91f910ba3f2af1812573cdcf687414e122"
+"checksum parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6bf05dc61189828dfd7a59fd6e66d538e88d6b30390da1124a291e09fd3098b3"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
@@ -2858,7 +3013,6 @@
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum procedural-masquerade 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1bcafee1590f81acb329ae45ec627b318123f085153913620316ae9a144b2a"
-"checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478"
 "checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b"
 "checksum pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a656fdb8b6848f896df5e478a0eb9083681663e37dcb77dd16981ff65329fe8b"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
@@ -2866,42 +3020,50 @@
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "034f1c4528581c40a60e96875467c03315868084e08ff4ceb46a00f7be3b16b4"
 "checksum radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "211c49b6a9995cac0fd1dd9ca60b42cf3a51e151a12eb954b3a9e75513426ee8"
-"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
+"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"
 "checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf"
 "checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
-"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
+"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
-"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322"
+"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
-"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum rls-analysis 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "171fcab0206870b8bec0d2c60dea66f820ce648a85abffc66f7e2df95c283e06"
-"checksum rls-data 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff85bb3a0daf9f64207a5530d90ae1c10f5515cef064c88b6821090678382b44"
+"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
+"checksum rls-analysis 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "38841e3c5271715a574ac220d9b408b59ed9e2626909c3bc54b5853b4eaadb7b"
 "checksum rls-data 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8024f1feaca72d0aa4ae1e2a8d454a31b9a33ed02f8d0e9c8559bf53c267ec3c"
 "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
+"checksum rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a51c10af5abd5d698b7e3487e869e6d15f6feb04cbedb5c792e2824f9d845e"
+"checksum rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1aa227490501072780d57f74b1164d361833ff8e172f817da0da2cdf2e4280cc"
+"checksum rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21ff6c6e13ac4fc04b7d4d398828b024c4b6577045cb3175b33d35fea35ff6d0"
+"checksum rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b4e7f51e298675c2bf830f7265621a8936fb09e63b825b58144cbaac969e604"
+"checksum rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf5639869ba2f7fa581939cd217cb71a85506b82ad0ea520614fb0dceb2386c"
+"checksum rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c020cdb7379e1c733ae0a311ae47c748337ba584d2dd7b7f53baaae78de6f8b"
 "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
+"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
+"checksum schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "acece75e0f987c48863a6c792ec8b7d6c4177d4a027f8ccc72f849794f437016"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
 "checksum selectors 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c89b1c6a3c029c82263f7dd2d44d0005ee7374eb09e254ab59dede4353a8c0"
 "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
 "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c37d7f192f00041e8a613e936717923a71bc0c9051fc4425a49b104140f05"
-"checksum serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "0672de7300b02bac3f3689f8faea813c4a1ea9fe0cb49e80f714231d267518a2"
-"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
+"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
+"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
+"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
 "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
-"checksum serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ea28ea0cca944668919bec6af209864a8dfe769fd2b0b723f36b22e20c1bf69f"
+"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb"
 "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc"
 "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
 "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e"
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
-"checksum socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b4896961171cd3317c7e9603d88f379f8c6e45342212235d356496680c68fd"
+"checksum socket2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf5d5aa364bf61a0d744a293da20381617b6445b89eb524800fab857c5aed2d8"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string_cache 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "413fc7852aeeb5472f1986ef755f561ddf0c789d3d796e65f0b6fe293ecd4ef8"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
@@ -2909,6 +3071,7 @@
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
+"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
 "checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b"
 "checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac"
 "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
@@ -2921,7 +3084,7 @@
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
-"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
+"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
 "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
@@ -2942,10 +3105,14 @@
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
+"checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 "checksum wincolor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a39ee4464208f6430992ff20154216ab2357772ac871d994c51628d60e58b8b0"
 "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 "checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc"
-"checksum xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e9510bdf100731599107c61f77daf46713a69a568f75458999c1f9dbf6ba25b0"
+"checksum xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df591c3504d014dd791d998123ed00a476c7e26dc6b2e873cb55c6ac9e59fa"
 "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
diff --git a/src/Cargo.toml b/src/Cargo.toml
index abe1fe5..ad795b2 100644
--- a/src/Cargo.toml
+++ b/src/Cargo.toml
@@ -20,6 +20,7 @@
   "tools/rustdoc",
   "tools/rls",
   "tools/rustfmt",
+  "tools/miri",
   # FIXME(https://github.com/rust-lang/cargo/issues/4089): move these to exclude
   "tools/rls/test_data/bin_lib",
   "tools/rls/test_data/borrow_error",
@@ -54,8 +55,18 @@
 debug = false
 debug-assertions = false
 
+# We want the RLS to use the version of Cargo that we've got vendored in this
+# repository to ensure that the same exact version of Cargo is used by both the
+# RLS and the Cargo binary itself. The RLS depends on Cargo as a git repository
+# so we use a `[patch]` here to override the github repository with our local
+# vendored copy.
 [patch."https://github.com/rust-lang/cargo"]
 cargo = { path = "tools/cargo" }
 
 [patch.crates-io]
+# Similar to Cargo above we want the RLS to use a vendored version of `rustfmt`
+# that we're shipping as well (to ensure that the rustfmt in RLS and the
+# `rustfmt` executable are the same exact vesion). Unlike Cargo, however, the
+# RLS depends on `rustfmt` from crates.io, so we put this in a `[patch]` section
+# for crates.io
 rustfmt-nightly = { path = "tools/rustfmt" }
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 4e975ad..389b504 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -23,10 +23,17 @@
 fn main() {
     let args = env::args_os().skip(1).collect::<Vec<_>>();
     let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
-    let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
+    let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set");
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
     let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
 
+    use std::str::FromStr;
+
+    let verbose = match env::var("RUSTC_VERBOSE") {
+        Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
+        Err(_) => 0,
+    };
+
     let mut dylib_path = bootstrap::util::dylib_path();
     dylib_path.insert(0, PathBuf::from(libdir));
 
@@ -57,6 +64,14 @@
         // This "unstable-options" can be removed when `--crate-version` is stabilized
         cmd.arg("-Z").arg("unstable-options")
            .arg("--crate-version").arg(version);
+
+        // While we can assume that `-Z unstable-options` is set, let's also force rustdoc to panic
+        // if pulldown rendering differences are found
+        cmd.arg("--deny-render-differences");
+    }
+
+    if verbose > 1 {
+        eprintln!("rustdoc command: {:?}", cmd);
     }
 
     std::process::exit(match cmd.status() {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 707acee..93c3694 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -351,11 +351,6 @@
             with open(self.rustc_stamp(), 'w') as rust_stamp:
                 rust_stamp.write(self.date)
 
-            if "pc-windows-gnu" in self.build:
-                filename = "rust-mingw-{}-{}.tar.gz".format(
-                    rustc_channel, self.build)
-                self._download_stage0_helper(filename, "rust-mingw")
-
         if self.cargo().startswith(self.bin_root()) and \
                 (not os.path.exists(self.cargo()) or
                  self.program_out_of_date(self.cargo_stamp())):
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index bdc0029..7655097 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -254,11 +254,13 @@
             Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest,
                 check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Rustdoc,
                 check::Linkcheck, check::Cargotest, check::Cargo, check::Rls, check::Docs,
-                check::ErrorIndex, check::Distcheck, check::Rustfmt, check::Miri, check::Clippy),
+                check::ErrorIndex, check::Distcheck, check::Rustfmt, check::Miri, check::Clippy,
+                check::RustdocJS),
+
             Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
-                doc::Reference, doc::Rustdoc, doc::CargoBook),
+                doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook),
             Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
                 dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
                 dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign,
@@ -357,8 +359,8 @@
 
             fn run(self, builder: &Builder) -> Interned<PathBuf> {
                 let compiler = self.compiler;
-                let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() {
-                    builder.build.config.libdir_relative.clone().unwrap()
+                let lib = if compiler.stage >= 1 && builder.build.config.libdir.is_some() {
+                    builder.build.config.libdir.clone().unwrap()
                 } else {
                     PathBuf::from("lib")
                 };
@@ -416,10 +418,11 @@
         let compiler = self.compiler(self.top_stage, host);
         cmd.env("RUSTC_STAGE", compiler.stage.to_string())
            .env("RUSTC_SYSROOT", self.sysroot(compiler))
-           .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
+           .env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
            .env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
            .env("RUSTDOC_REAL", self.rustdoc(host))
-           .env("RUSTDOC_CRATE_VERSION", self.build.rust_version());
+           .env("RUSTDOC_CRATE_VERSION", self.build.rust_version())
+           .env("RUSTC_BOOTSTRAP", "1");
         if let Some(linker) = self.build.linker(host) {
             cmd.env("RUSTC_TARGET_LINKER", linker);
         }
@@ -442,7 +445,8 @@
         let out_dir = self.stage_out(compiler, mode);
         cargo.env("CARGO_TARGET_DIR", out_dir)
              .arg(cmd)
-             .arg("--target").arg(target);
+             .arg("--target")
+             .arg(target);
 
         // If we were invoked from `make` then that's already got a jobserver
         // set up for us so no need to tell Cargo about jobs all over again.
@@ -483,8 +487,8 @@
              } else {
                  PathBuf::from("/path/to/nowhere/rustdoc/not/required")
              })
-             .env("TEST_MIRI", self.config.test_miri.to_string());
-
+             .env("TEST_MIRI", self.config.test_miri.to_string())
+             .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir());
         if let Some(n) = self.config.rust_codegen_units {
             cargo.env("RUSTC_CODEGEN_UNITS", n.to_string());
         }
@@ -495,6 +499,9 @@
         if let Some(target_linker) = self.build.linker(target) {
             cargo.env("RUSTC_TARGET_LINKER", target_linker);
         }
+        if cmd != "build" {
+            cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.build.build)));
+        }
 
         if mode != Mode::Tool {
             // Tools don't get debuginfo right now, e.g. cargo and rls don't
@@ -616,6 +623,39 @@
         // Set this for all builds to make sure doc builds also get it.
         cargo.env("CFG_RELEASE_CHANNEL", &self.build.config.channel);
 
+        // This one's a bit tricky. As of the time of this writing the compiler
+        // links to the `winapi` crate on crates.io. This crate provides raw
+        // bindings to Windows system functions, sort of like libc does for
+        // Unix. This crate also, however, provides "import libraries" for the
+        // MinGW targets. There's an import library per dll in the windows
+        // distribution which is what's linked to. These custom import libraries
+        // are used because the winapi crate can reference Windows functions not
+        // present in the MinGW import libraries.
+        //
+        // For example MinGW may ship libdbghelp.a, but it may not have
+        // references to all the functions in the dbghelp dll. Instead the
+        // custom import library for dbghelp in the winapi crates has all this
+        // information.
+        //
+        // Unfortunately for us though the import libraries are linked by
+        // default via `-ldylib=winapi_foo`. That is, they're linked with the
+        // `dylib` type with a `winapi_` prefix (so the winapi ones don't
+        // conflict with the system MinGW ones). This consequently means that
+        // the binaries we ship of things like rustc_trans (aka the rustc_trans
+        // DLL) when linked against *again*, for example with procedural macros
+        // or plugins, will trigger the propagation logic of `-ldylib`, passing
+        // `-lwinapi_foo` to the linker again. This isn't actually available in
+        // our distribution, however, so the link fails.
+        //
+        // To solve this problem we tell winapi to not use its bundled import
+        // libraries. This means that it will link to the system MinGW import
+        // libraries by default, and the `-ldylib=foo` directives will still get
+        // passed to the final linker, but they'll look like `-lfoo` which can
+        // be resolved because MinGW has the import library. The downside is we
+        // don't get newer functions from Windows, but we don't use any of them
+        // anyway.
+        cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
+
         if self.is_very_verbose() {
             cargo.arg("-v");
         }
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 0485ebe..e412dd9 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -24,12 +24,7 @@
 use config::Config;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.24.0";
-
-// An optional number to put after the label, e.g. '.2' -> '-beta.2'
-// Be sure to make this starts with a dot to conform to semver pre-release
-// versions (section 9)
-pub const CFG_PRERELEASE_VERSION: &str = ".1";
+pub const CFG_RELEASE_NUM: &str = "1.25.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index eee403d..5faec27 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -23,7 +23,7 @@
 use std::process::Command;
 use std::io::Read;
 
-use build_helper::{self, output, BuildExpectation};
+use build_helper::{self, output};
 
 use builder::{Kind, RunConfig, ShouldRun, Builder, Compiler, Step};
 use cache::{INTERNER, Interned};
@@ -65,23 +65,19 @@
     }
 }
 
-fn try_run_expecting(build: &Build, cmd: &mut Command, expect: BuildExpectation) -> bool {
+fn try_run(build: &Build, cmd: &mut Command) -> bool {
     if !build.fail_fast {
-        if !build.try_run(cmd, expect) {
+        if !build.try_run(cmd) {
             let mut failures = build.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
             return false;
         }
     } else {
-        build.run_expecting(cmd, expect);
+        build.run(cmd);
     }
     true
 }
 
-fn try_run(build: &Build, cmd: &mut Command) {
-    try_run_expecting(build, cmd, BuildExpectation::None);
-}
-
 fn try_run_quiet(build: &Build, cmd: &mut Command) {
     if !build.fail_fast {
         if !build.try_run_quiet(cmd) {
@@ -259,12 +255,8 @@
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
-        if try_run_expecting(
-            build,
-            &mut cargo,
-            builder.build.config.toolstate.rls.passes(ToolState::Testing),
-        ) {
-            build.save_toolstate("rls", ToolState::Testing);
+        if try_run(build, &mut cargo) {
+            build.save_toolstate("rls", ToolState::TestPass);
         }
     }
 }
@@ -309,12 +301,8 @@
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
-        if try_run_expecting(
-            build,
-            &mut cargo,
-            builder.build.config.toolstate.rustfmt.passes(ToolState::Testing),
-        ) {
-            build.save_toolstate("rustfmt", ToolState::Testing);
+        if try_run(build, &mut cargo) {
+            build.save_toolstate("rustfmt", ToolState::TestPass);
         }
     }
 }
@@ -363,12 +351,8 @@
 
             builder.add_rustc_lib_path(compiler, &mut cargo);
 
-            if try_run_expecting(
-                build,
-                &mut cargo,
-                builder.build.config.toolstate.miri.passes(ToolState::Testing),
-            ) {
-                build.save_toolstate("miri", ToolState::Testing);
+            if try_run(build, &mut cargo) {
+                build.save_toolstate("miri", ToolState::TestPass);
             }
         } else {
             eprintln!("failed to test miri: could not build");
@@ -422,12 +406,8 @@
 
             builder.add_rustc_lib_path(compiler, &mut cargo);
 
-            if try_run_expecting(
-                build,
-                &mut cargo,
-                builder.build.config.toolstate.clippy.passes(ToolState::Testing),
-            ) {
-                build.save_toolstate("clippy-driver", ToolState::Testing);
+            if try_run(build, &mut cargo) {
+                build.save_toolstate("clippy-driver", ToolState::TestPass);
             }
         } else {
             eprintln!("failed to test clippy: could not build");
@@ -444,6 +424,43 @@
     env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
 }
 
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct RustdocJS {
+    pub host: Interned<String>,
+    pub target: Interned<String>,
+}
+
+impl Step for RustdocJS {
+    type Output = ();
+    const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/test/rustdoc-js")
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(RustdocJS {
+            host: run.host,
+            target: run.target,
+        });
+    }
+
+    fn run(self, builder: &Builder) {
+        if let Some(ref nodejs) = builder.config.nodejs {
+            let mut command = Command::new(nodejs);
+            command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]);
+            builder.ensure(::doc::Std {
+                target: self.target,
+                stage: builder.top_stage,
+            });
+            builder.run(&mut command);
+        } else {
+            println!("No nodejs found, skipping \"src/test/rustdoc-js\" tests");
+        }
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Tidy {
     host: Interned<String>,
@@ -588,6 +605,11 @@
         mode: "compile-fail",
         suite: "compile-fail-fulldeps",
     },
+    Test {
+        path: "src/test/incremental-fulldeps",
+        mode: "incremental",
+        suite: "incremental-fulldeps",
+    },
     Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" },
     Test { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" },
 
@@ -770,6 +792,7 @@
             flags.push("-g".to_string());
         }
         flags.push("-Zmiri -Zunstable-options".to_string());
+        flags.push(build.config.cmd.rustc_args().join(" "));
 
         if let Some(linker) = build.linker(target) {
             cmd.arg("--linker").arg(linker);
@@ -995,7 +1018,8 @@
         build.run(builder.tool_cmd(Tool::ErrorIndex)
                     .arg("markdown")
                     .arg(&output)
-                    .env("CFG_BUILD", &build.build));
+                    .env("CFG_BUILD", &build.build)
+                    .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir()));
 
         markdown_test(builder, compiler, &output);
     }
@@ -1185,7 +1209,7 @@
             }
             Mode::Librustc => {
                 builder.ensure(compile::Rustc { compiler, target });
-                compile::rustc_cargo(build, &compiler, target, &mut cargo);
+                compile::rustc_cargo(build, target, &mut cargo);
                 ("librustc", "rustc-main")
             }
             _ => panic!("can only test libraries"),
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 4c76230..c6adfc7 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -485,7 +485,7 @@
         build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target));
 
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
-        rustc_cargo(build, &compiler, target, &mut cargo);
+        rustc_cargo(build, target, &mut cargo);
         run_cargo(build,
                   &mut cargo,
                   &librustc_stamp(build, compiler, target));
@@ -500,7 +500,6 @@
 
 /// Same as `std_cargo`, but for libtest
 pub fn rustc_cargo(build: &Build,
-                   compiler: &Compiler,
                    target: Interned<String>,
                    cargo: &mut Command) {
     cargo.arg("--features").arg(build.rustc_features())
@@ -514,13 +513,9 @@
          .env("CFG_VERSION", build.rust_version())
          .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
 
-    if compiler.stage == 0 {
-        cargo.env("CFG_LIBDIR_RELATIVE", "lib");
-    } else {
-        let libdir_relative =
-            build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib"));
-        cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
-    }
+    let libdir_relative =
+        build.config.libdir.clone().unwrap_or(PathBuf::from("lib"));
+    cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
 
     // If we're not building a compiler with debugging information then remove
     // these two env vars which would be set otherwise.
@@ -550,6 +545,7 @@
     // Building with a static libstdc++ is only supported on linux right now,
     // not for MSVC or macOS
     if build.config.llvm_static_stdcpp &&
+       !target.contains("freebsd") &&
        !target.contains("windows") &&
        !target.contains("apple") {
         cargo.env("LLVM_STATIC_STDCPP",
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 87b1db3..72e75fd 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -27,7 +27,6 @@
 use cache::{INTERNER, Interned};
 use flags::Flags;
 pub use flags::Subcommand;
-use toolstate::ToolStates;
 
 /// Global configuration for the entire build and/or bootstrap.
 ///
@@ -122,7 +121,6 @@
     pub docdir: Option<PathBuf>,
     pub bindir: Option<PathBuf>,
     pub libdir: Option<PathBuf>,
-    pub libdir_relative: Option<PathBuf>,
     pub mandir: Option<PathBuf>,
     pub codegen_tests: bool,
     pub nodejs: Option<PathBuf>,
@@ -134,8 +132,6 @@
     // These are either the stage0 downloaded binaries or the locally installed ones.
     pub initial_cargo: PathBuf,
     pub initial_rustc: PathBuf,
-
-    pub toolstate: ToolStates,
 }
 
 /// Per-target configuration stored in the global configuration structure.
@@ -348,18 +344,6 @@
             }
         }).unwrap_or_else(|| TomlConfig::default());
 
-        let toolstate_toml_path = config.src.join("src/tools/toolstate.toml");
-        let parse_toolstate = || -> Result<_, Box<::std::error::Error>> {
-            let mut f = File::open(toolstate_toml_path)?;
-            let mut contents = String::new();
-            f.read_to_string(&mut contents)?;
-            Ok(toml::from_str(&contents)?)
-        };
-        config.toolstate = parse_toolstate().unwrap_or_else(|err| {
-            println!("failed to parse TOML configuration 'toolstate.toml': {}", err);
-            process::exit(2);
-        });
-
         let build = toml.build.clone().unwrap_or(Build::default());
         set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x)));
         set(&mut config.build, flags.build);
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 48ca283..aa9fe45 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -108,6 +108,8 @@
   "MUSL root installation directory (deprecated)")
 v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",
   "x86_64-unknown-linux-musl install directory")
+v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root",
+  "i586-unknown-linux-musl install directory")
 v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root",
   "i686-unknown-linux-musl install directory")
 v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 78de9ec..224b31e 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -224,6 +224,8 @@
         "libwinspool.a",
         "libws2_32.a",
         "libwsock32.a",
+        "libdbghelp.a",
+        "libmsimg32.a",
     ];
 
     //Find mingw artifacts we want to bundle
@@ -1077,11 +1079,6 @@
         let target = self.target;
         assert!(build.config.extended);
 
-        if !builder.config.toolstate.rls.testing() {
-            println!("skipping Dist RLS stage{} ({})", stage, target);
-            return None
-        }
-
         println!("Dist RLS stage{} ({})", stage, target);
         let src = build.src.join("src/tools/rls");
         let release_num = build.release_num("rls");
@@ -1164,11 +1161,6 @@
         let target = self.target;
         assert!(build.config.extended);
 
-        if !builder.config.toolstate.rustfmt.testing() {
-            println!("skipping Dist Rustfmt stage{} ({})", stage, target);
-            return None
-        }
-
         println!("Dist Rustfmt stage{} ({})", stage, target);
         let src = build.src.join("src/tools/rustfmt");
         let release_num = build.release_num("rustfmt");
@@ -1660,7 +1652,6 @@
     cmd.env("CFG_RELEASE_INFO", build.rust_version())
        .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
        .env("CFG_RELEASE", build.rust_release())
-       .env("CFG_PRERELEASE_VERSION", channel::CFG_PRERELEASE_VERSION)
        .env("CFG_VER_MAJOR", parts.next().unwrap())
        .env("CFG_VER_MINOR", parts.next().unwrap())
        .env("CFG_VER_PATCH", parts.next().unwrap())
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 3c12cfc..9bf762a 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -12,7 +12,7 @@
 //!
 //! This module implements generation for all bits and pieces of documentation
 //! for the Rust project. This notably includes suites like the rust book, the
-//! nomicon, standalone documentation, etc.
+//! nomicon, rust by example, standalone documentation, etc.
 //!
 //! Everything here is basically just a shim around calling either `rustbook` or
 //! `rustdoc`.
@@ -69,6 +69,7 @@
     Nomicon, "src/doc/nomicon", "nomicon";
     Reference, "src/doc/reference", "reference";
     Rustdoc, "src/doc/rustdoc", "rustdoc";
+    RustByExample, "src/doc/rust-by-example", "rust-by-example";
 );
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@@ -159,7 +160,7 @@
 
         let target = self.target;
         let name = self.name;
-        let src = build.src.join("src/tools/cargo/src/doc/book");
+        let src = build.src.join("src/tools/cargo/src/doc");
 
         let out = build.doc_out(target);
         t!(fs::create_dir_all(&out));
@@ -418,8 +419,8 @@
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Std {
-    stage: u32,
-    target: Interned<String>,
+    pub stage: u32,
+    pub target: Interned<String>,
 }
 
 impl Step for Std {
@@ -616,7 +617,7 @@
         t!(symlink_dir_force(&my_out, &out_dir));
 
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
-        compile::rustc_cargo(build, &compiler, target, &mut cargo);
+        compile::rustc_cargo(build, target, &mut cargo);
 
         if build.config.compiler_docs {
             // src/rustc/Cargo.toml contains a bin crate called rustc which
@@ -671,7 +672,8 @@
         index.arg(out.join("error-index.html"));
 
         // FIXME: shouldn't have to pass this env var
-        index.env("CFG_BUILD", &build.build);
+        index.env("CFG_BUILD", &build.build)
+             .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir());
 
         build.run(&mut index);
     }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index b5d5159..0816c4d 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -54,6 +54,7 @@
     Test {
         paths: Vec<PathBuf>,
         test_args: Vec<String>,
+        rustc_args: Vec<String>,
         fail_fast: bool,
     },
     Bench {
@@ -150,6 +151,12 @@
             "test"  => {
                 opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
                 opts.optmulti("", "test-args", "extra arguments", "ARGS");
+                opts.optmulti(
+                    "",
+                    "rustc-args",
+                    "extra options to pass the compiler when running tests",
+                    "ARGS",
+                );
             },
             "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
             "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -283,6 +290,7 @@
                 Subcommand::Test {
                     paths,
                     test_args: matches.opt_strs("test-args"),
+                    rustc_args: matches.opt_strs("rustc-args"),
                     fail_fast: !matches.opt_present("no-fail-fast"),
                 }
             }
@@ -362,6 +370,15 @@
         }
     }
 
+    pub fn rustc_args(&self) -> Vec<&str> {
+        match *self {
+            Subcommand::Test { ref rustc_args, .. } => {
+                rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
+            }
+            _ => Vec::new(),
+        }
+    }
+
     pub fn fail_fast(&self) -> bool {
         match *self {
             Subcommand::Test { fail_fast, .. } => fail_fast,
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 2f00c31..3738828 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -134,7 +134,7 @@
 #[cfg(unix)]
 extern crate libc;
 
-use std::cell::RefCell;
+use std::cell::{RefCell, Cell};
 use std::collections::{HashSet, HashMap};
 use std::env;
 use std::fs::{self, File};
@@ -143,8 +143,7 @@
 use std::process::{self, Command};
 use std::slice;
 
-use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime,
-                   BuildExpectation};
+use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime};
 
 use util::{exe, libdir, OutputFolder, CiEnv};
 
@@ -251,6 +250,7 @@
     is_sudo: bool,
     ci_env: CiEnv,
     delayed_failures: RefCell<Vec<String>>,
+    prerelease_version: Cell<Option<u32>>,
 }
 
 #[derive(Debug)]
@@ -336,6 +336,7 @@
             is_sudo,
             ci_env: CiEnv::current(),
             delayed_failures: RefCell::new(Vec::new()),
+            prerelease_version: Cell::new(None),
         }
     }
 
@@ -569,31 +570,24 @@
             .join(libdir(&self.config.build))
     }
 
-    /// Runs a command, printing out nice contextual information if its build
-    /// status is not the expected one
-    fn run_expecting(&self, cmd: &mut Command, expect: BuildExpectation) {
-        self.verbose(&format!("running: {:?}", cmd));
-        run_silent(cmd, expect)
-    }
-
     /// Runs a command, printing out nice contextual information if it fails.
     fn run(&self, cmd: &mut Command) {
-        self.run_expecting(cmd, BuildExpectation::None)
+        self.verbose(&format!("running: {:?}", cmd));
+        run_silent(cmd)
     }
 
     /// Runs a command, printing out nice contextual information if it fails.
     fn run_quiet(&self, cmd: &mut Command) {
         self.verbose(&format!("running: {:?}", cmd));
-        run_suppressed(cmd, BuildExpectation::None)
+        run_suppressed(cmd)
     }
 
-    /// Runs a command, printing out nice contextual information if its build
-    /// status is not the expected one.
-    /// Exits if the command failed to execute at all, otherwise returns whether
-    /// the expectation was met
-    fn try_run(&self, cmd: &mut Command, expect: BuildExpectation) -> bool {
+    /// Runs a command, printing out nice contextual information if it fails.
+    /// Exits if the command failed to execute at all, otherwise returns its
+    /// `status.success()`.
+    fn try_run(&self, cmd: &mut Command) -> bool {
         self.verbose(&format!("running: {:?}", cmd));
-        try_run_silent(cmd, expect)
+        try_run_silent(cmd)
     }
 
     /// Runs a command, printing out nice contextual information if it fails.
@@ -601,7 +595,7 @@
     /// `status.success()`.
     fn try_run_quiet(&self, cmd: &mut Command) -> bool {
         self.verbose(&format!("running: {:?}", cmd));
-        try_run_suppressed(cmd, BuildExpectation::None)
+        try_run_suppressed(cmd)
     }
 
     pub fn is_verbose(&self) -> bool {
@@ -726,6 +720,11 @@
         self.config.python.as_ref().unwrap()
     }
 
+    /// Temporary directory that extended error information is emitted to.
+    fn extended_error_dir(&self) -> PathBuf {
+        self.out.join("tmp/extended-error-metadata")
+    }
+
     /// Tests whether the `compiler` compiling for `target` should be forced to
     /// use a stage1 compiler instead.
     ///
@@ -777,12 +776,59 @@
     fn release(&self, num: &str) -> String {
         match &self.config.channel[..] {
             "stable" => num.to_string(),
-            "beta" => format!("{}-beta{}", num, channel::CFG_PRERELEASE_VERSION),
+            "beta" => format!("{}-beta.{}", num, self.beta_prerelease_version()),
             "nightly" => format!("{}-nightly", num),
             _ => format!("{}-dev", num),
         }
     }
 
+    fn beta_prerelease_version(&self) -> u32 {
+        if let Some(s) = self.prerelease_version.get() {
+            return s
+        }
+
+        let beta = output(
+            Command::new("git")
+                .arg("ls-remote")
+                .arg("origin")
+                .arg("beta")
+                .current_dir(&self.src)
+        );
+        let beta = beta.trim().split_whitespace().next().unwrap();
+        let master = output(
+            Command::new("git")
+                .arg("ls-remote")
+                .arg("origin")
+                .arg("master")
+                .current_dir(&self.src)
+        );
+        let master = master.trim().split_whitespace().next().unwrap();
+
+        // Figure out where the current beta branch started.
+        let base = output(
+            Command::new("git")
+                .arg("merge-base")
+                .arg(beta)
+                .arg(master)
+                .current_dir(&self.src),
+        );
+        let base = base.trim();
+
+        // Next figure out how many merge commits happened since we branched off
+        // beta. That's our beta number!
+        let count = output(
+            Command::new("git")
+                .arg("rev-list")
+                .arg("--count")
+                .arg("--merges")
+                .arg(format!("{}...HEAD", base))
+                .current_dir(&self.src),
+        );
+        let n = count.trim().parse().unwrap();
+        self.prerelease_version.set(Some(n));
+        n
+    }
+
     /// Returns the value of `release` above for Rust itself.
     fn rust_release(&self) -> String {
         self.release(channel::CFG_RELEASE_NUM)
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index a5408ee..ba8cf3a 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -429,6 +429,8 @@
             "arm-unknown-linux-gnueabihf" => "linux-armv4",
             "armv7-linux-androideabi" => "android-armv7",
             "armv7-unknown-linux-gnueabihf" => "linux-armv4",
+            "i586-unknown-linux-gnu" => "linux-elf",
+            "i586-unknown-linux-musl" => "linux-elf",
             "i686-apple-darwin" => "darwin-i386-cc",
             "i686-linux-android" => "android-x86",
             "i686-unknown-freebsd" => "BSD-x86-elf",
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index bc275b7..a8b43ad 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -21,9 +21,10 @@
 use std::collections::HashMap;
 use std::env;
 use std::ffi::{OsString, OsStr};
-use std::fs;
-use std::process::Command;
+use std::fs::{self, File};
+use std::io::Read;
 use std::path::PathBuf;
+use std::process::Command;
 
 use build_helper::output;
 
@@ -234,4 +235,14 @@
     if let Some(ref s) = build.config.ccache {
         cmd_finder.must_have(s);
     }
+
+    if build.config.channel == "stable" {
+        let mut stage0 = String::new();
+        t!(t!(File::open(build.src.join("src/stage0.txt")))
+            .read_to_string(&mut stage0));
+        if stage0.contains("\ndev:") {
+            panic!("bootstrapping from a dev compiler in a stable release, but \
+                    should only be bootstrapping from a released compiler!");
+        }
+    }
 }
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index fa9bdc4..ea055cb 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -22,7 +22,6 @@
 use channel::GitInfo;
 use cache::Interned;
 use toolstate::ToolState;
-use build_helper::BuildExpectation;
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct CleanTools {
@@ -82,7 +81,7 @@
     tool: &'static str,
     path: &'static str,
     mode: Mode,
-    expectation: BuildExpectation,
+    is_ext_tool: bool,
 }
 
 impl Step for ToolBuild {
@@ -102,7 +101,7 @@
         let target = self.target;
         let tool = self.tool;
         let path = self.path;
-        let expectation = self.expectation;
+        let is_ext_tool = self.is_ext_tool;
 
         match self.mode {
             Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
@@ -115,34 +114,25 @@
         println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
 
         let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
-        let is_expected = build.try_run(&mut cargo, expectation);
-        // If the expectation is "Failing", `try_run` returning true actually
-        // means a build-failure is successfully observed, i.e. the tool is
-        // broken. Thus the XOR here.
-        // Sorry for the complicated logic, but we can remove this expectation
-        // logic after #45861 is fully fixed.
-        build.save_toolstate(tool, if is_expected ^ (expectation == BuildExpectation::Failing) {
-            ToolState::Compiling
+        let is_expected = build.try_run(&mut cargo);
+        build.save_toolstate(tool, if is_expected {
+            ToolState::TestFail
         } else {
-            ToolState::Broken
+            ToolState::BuildFail
         });
 
         if !is_expected {
-            if expectation == BuildExpectation::None {
+            if !is_ext_tool {
                 exit(1);
             } else {
                 return None;
             }
-        }
-
-        if expectation == BuildExpectation::Succeeding || expectation == BuildExpectation::None {
+        } else {
             let cargo_out = build.cargo_out(compiler, Mode::Tool, target)
                 .join(exe(tool, &compiler.host));
             let bin = build.tools_dir(compiler).join(exe(tool, &compiler.host));
             copy(&cargo_out, &bin);
             Some(bin)
-        } else {
-            None
         }
     }
 }
@@ -251,8 +241,8 @@
                     tool: $tool_name,
                     mode: $mode,
                     path: $path,
-                    expectation: BuildExpectation::None,
-                }).expect("expected to build -- BuildExpectation::None")
+                    is_ext_tool: false,
+                }).expect("expected to build -- essential tool")
             }
         }
         )+
@@ -299,8 +289,8 @@
             tool: "remote-test-server",
             mode: Mode::Libstd,
             path: "src/tools/remote-test-server",
-            expectation: BuildExpectation::None,
-        }).expect("expected to build -- BuildExpectation::None")
+            is_ext_tool: false,
+        }).expect("expected to build -- essential tool")
     }
 }
 
@@ -417,8 +407,8 @@
             tool: "cargo",
             mode: Mode::Librustc,
             path: "src/tools/cargo",
-            expectation: BuildExpectation::None,
-        }).expect("BuildExpectation::None - expected to build")
+            is_ext_tool: false,
+        }).expect("expected to build -- essential tool")
     }
 }
 
@@ -455,14 +445,13 @@
 
             fn run($sel, $builder: &Builder) -> Option<PathBuf> {
                 $extra_deps
-                let toolstate = $builder.build.config.toolstate.$toolstate;
                 $builder.ensure(ToolBuild {
                     compiler: $sel.compiler,
                     target: $sel.target,
                     tool: $tool_name,
                     mode: Mode::Librustc,
                     path: $path,
-                    expectation: toolstate.passes(ToolState::Compiling),
+                    is_ext_tool: true,
                 })
             }
         }
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 00dbcc8..f63c198 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -8,51 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use build_helper::BuildExpectation;
-
 #[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
+#[serde(rename_all = "kebab-case")]
 /// Whether a tool can be compiled, tested or neither
 pub enum ToolState {
     /// The tool compiles successfully, but the test suite fails
-    Compiling = 1,
+    TestFail = 1,
     /// The tool compiles successfully and its test suite passes
-    Testing = 2,
+    TestPass = 2,
     /// The tool can't even be compiled
-    Broken = 0,
-}
-
-impl ToolState {
-    /// If a tool with the current toolstate should be working on
-    /// the given toolstate
-    pub fn passes(self, other: ToolState) -> BuildExpectation {
-        if self as usize >= other as usize {
-            BuildExpectation::Succeeding
-        } else {
-            BuildExpectation::Failing
-        }
-    }
-
-    pub fn testing(&self) -> bool {
-        match *self {
-            ToolState::Testing => true,
-            _ => false,
-        }
-    }
+    BuildFail = 0,
 }
 
 impl Default for ToolState {
     fn default() -> Self {
         // err on the safe side
-        ToolState::Broken
+        ToolState::BuildFail
     }
 }
-
-#[derive(Copy, Clone, Debug, Deserialize, Default)]
-/// Used to express which tools should (not) be compiled or tested.
-/// This is created from `toolstate.toml`.
-pub struct ToolStates {
-    pub miri: ToolState,
-    pub clippy: ToolState,
-    pub rls: ToolState,
-    pub rustfmt: ToolState,
-}
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 874065f..07941e5 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -315,7 +315,7 @@
             let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
             let db = data.as_mut_ptr()
                             as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
-            let buf = &mut (*db).ReparseTarget as *mut _;
+            let buf = &mut (*db).ReparseTarget as *mut u16;
             let mut i = 0;
             // FIXME: this conversion is very hacky
             let v = br"\??\";
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 2b6e282..363bbd7 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -35,97 +35,55 @@
     })
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub enum BuildExpectation {
-    Succeeding,
-    Failing,
-    None,
-}
-
-pub fn run(cmd: &mut Command, expect: BuildExpectation) {
+pub fn run(cmd: &mut Command) {
     println!("running: {:?}", cmd);
-    run_silent(cmd, expect);
+    run_silent(cmd);
 }
 
-pub fn run_silent(cmd: &mut Command, expect: BuildExpectation) {
-    if !try_run_silent(cmd, expect) {
+pub fn run_silent(cmd: &mut Command) {
+    if !try_run_silent(cmd) {
         std::process::exit(1);
     }
 }
 
-pub fn try_run_silent(cmd: &mut Command, expect: BuildExpectation) -> bool {
+pub fn try_run_silent(cmd: &mut Command) -> bool {
     let status = match cmd.status() {
         Ok(status) => status,
         Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
                                 cmd, e)),
     };
-    process_status(
-        cmd,
-        status.success(),
-        expect,
-        || println!("\n\ncommand did not execute successfully: {:?}\n\
-                    expected success, got: {}\n\n",
-                    cmd,
-                    status))
-}
-
-fn process_status<F: FnOnce()>(
-    cmd: &Command,
-    success: bool,
-    expect: BuildExpectation,
-    f: F,
-) -> bool {
-    use BuildExpectation::*;
-    match (expect, success) {
-        (None, false) => { f(); false },
-        // Non-tool build succeeds, everything is good
-        (None, true) => true,
-        // Tool expected to work and is working
-        (Succeeding, true) => true,
-        // Tool expected to fail and is failing
-        (Failing, false) => {
-            println!("This failure is expected (see `src/tools/toolstate.toml`)");
-            true
-        },
-        // Tool expected to work, but is failing
-        (Succeeding, false) => {
-            f();
-            println!("You can disable the tool in `src/tools/toolstate.toml`");
-            false
-        },
-        // Tool expected to fail, but is working
-        (Failing, true) => {
-            println!("Expected `{:?}` to fail, but it succeeded.\n\
-                     Please adjust `src/tools/toolstate.toml` accordingly", cmd);
-            false
-        }
+    if !status.success() {
+        println!("\n\ncommand did not execute successfully: {:?}\n\
+                  expected success, got: {}\n\n",
+                 cmd,
+                 status);
     }
+    status.success()
 }
 
-pub fn run_suppressed(cmd: &mut Command, expect: BuildExpectation) {
-    if !try_run_suppressed(cmd, expect) {
+pub fn run_suppressed(cmd: &mut Command) {
+    if !try_run_suppressed(cmd) {
         std::process::exit(1);
     }
 }
 
-pub fn try_run_suppressed(cmd: &mut Command, expect: BuildExpectation) -> bool {
+pub fn try_run_suppressed(cmd: &mut Command) -> bool {
     let output = match cmd.output() {
         Ok(status) => status,
         Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
                                 cmd, e)),
     };
-    process_status(
-        cmd,
-        output.status.success(),
-        expect,
-        || println!("\n\ncommand did not execute successfully: {:?}\n\
+    if !output.status.success() {
+        println!("\n\ncommand did not execute successfully: {:?}\n\
                   expected success, got: {}\n\n\
                   stdout ----\n{}\n\
                   stderr ----\n{}\n\n",
                  cmd,
                  output.status,
                  String::from_utf8_lossy(&output.stdout),
-                 String::from_utf8_lossy(&output.stderr)))
+                 String::from_utf8_lossy(&output.stderr));
+    }
+    output.status.success()
 }
 
 pub fn gnu_target(target: &str) -> String {
diff --git a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile
new file mode 100644
index 0000000..4c9d4b3
--- /dev/null
+++ b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile
@@ -0,0 +1,54 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++-multilib \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  xz-utils \
+  sudo \
+  gdb \
+  patch \
+  libssl-dev \
+  pkg-config
+
+WORKDIR /build/
+COPY scripts/musl.sh /build/
+RUN CC=gcc CFLAGS="-m32 -fPIC -Wa,-mrelax-relocations=no" \
+    CXX=g++ CXXFLAGS="-m32 -Wa,-mrelax-relocations=no" \
+    bash musl.sh i686 --target=i686 && \
+    CC=gcc CFLAGS="-march=pentium -m32 -fPIC -Wa,-mrelax-relocations=no" \
+    CXX=g++ CXXFLAGS="-march=pentium -m32 -Wa,-mrelax-relocations=no" \
+    bash musl.sh i586 --target=i586 && \
+    rm -rf /build
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV RUST_CONFIGURE_ARGS \
+      --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
+      --musl-root-i586=/musl-i586 \
+      --musl-root-i686=/musl-i686 \
+      --enable-extended
+
+# Newer binutils broke things on some vms/distros (i.e., linking against
+# unknown relocs disabled by the following flag), so we need to go out of our
+# way to produce "super compatible" binaries.
+#
+# See: https://github.com/rust-lang/rust/issues/34978
+ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
+ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
+# FIXME remove -Wl,-melf_i386 after cc is updated to include
+#       https://github.com/alexcrichton/cc-rs/pull/281
+ENV CFLAGS_i586_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wl,-melf_i386"
+
+ENV TARGETS=i586-unknown-linux-gnu
+ENV TARGETS=$TARGETS,i686-unknown-linux-musl
+
+ENV SCRIPT \
+      python2.7 ../x.py test --target $TARGETS && \
+      python2.7 ../x.py dist --target $TARGETS,i586-unknown-linux-musl
diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
deleted file mode 100644
index 2fb1219..0000000
--- a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
+++ /dev/null
@@ -1,46 +0,0 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++-multilib \
-  make \
-  file \
-  curl \
-  ca-certificates \
-  python2.7 \
-  git \
-  cmake \
-  xz-utils \
-  sudo \
-  gdb \
-  patch \
-  libssl-dev \
-  pkg-config
-
-WORKDIR /build/
-COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/
-RUN sh /build/build-musl.sh && rm -rf /build
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-ENV RUST_CONFIGURE_ARGS \
-      --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
-      --musl-root-i686=/musl-i686 \
-      --enable-extended
-
-# Newer binutils broke things on some vms/distros (i.e., linking against
-# unknown relocs disabled by the following flag), so we need to go out of our
-# way to produce "super compatible" binaries.
-#
-# See: https://github.com/rust-lang/rust/issues/34978
-ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
-ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
-
-ENV SCRIPT \
-      python2.7 ../x.py test \
-          --target i686-unknown-linux-musl \
-          --target i586-unknown-linux-gnu \
-          && \
-      python2.7 ../x.py dist \
-          --target i686-unknown-linux-musl \
-          --target i586-unknown-linux-gnu
diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh b/src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh
deleted file mode 100644
index 883859d..0000000
--- a/src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
-export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
-export CXXFLAGS="-Wa,-mrelax-relocations=no"
-
-MUSL=musl-1.1.17
-curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
-cd $MUSL
-CC=gcc \
-  CFLAGS="$CFLAGS -m32" \
-  ./configure --prefix=/musl-i686 --disable-shared \
-    --target=i686
-make AR=ar RANLIB=ranlib -j10
-make install
-cd ..
-
-# To build MUSL we're going to need a libunwind lying around, so acquire that
-# here and build it.
-curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf -
-curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf -
-
-# Whoa what's this mysterious patch we're applying to libunwind! Why are we
-# swapping the values of ESP/EBP in libunwind?!
-#
-# Discovered in #35599 it turns out that the vanilla build of libunwind is not
-# suitable for unwinding 32-bit musl. After some investigation it ended up
-# looking like the register values for ESP/EBP were indeed incorrect (swapped)
-# in the source. Similar commits in libunwind (r280099 and r282589) have noticed
-# this for other platforms, and we just need to realize it for musl linux as
-# well.
-#
-# More technical info can be found at #35599
-cd libunwind-release_37
-patch -Np1 < /build/musl-libunwind-patch.patch
-cd ..
-
-mkdir libunwind-build
-cd libunwind-build
-CFLAGS="$CFLAGS -m32" CXXFLAGS="$CXXFLAGS -m32" cmake ../libunwind-release_37 \
-          -DLLVM_PATH=/build/llvm-release_37 \
-          -DLIBUNWIND_ENABLE_SHARED=0
-make -j10
-cp lib/libunwind.a /musl-i686/lib
diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/musl-libunwind-patch.patch b/src/ci/docker/dist-i586-gnu-i686-musl/musl-libunwind-patch.patch
deleted file mode 100644
index 99cd685..0000000
--- a/src/ci/docker/dist-i586-gnu-i686-musl/musl-libunwind-patch.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/include/libunwind.h b/include/libunwind.h
-index c5b9633..1360eb2 100644
---- a/include/libunwind.h
-+++ b/include/libunwind.h
-@@ -151,8 +151,8 @@ enum {
-   UNW_X86_ECX = 1,
-   UNW_X86_EDX = 2,
-   UNW_X86_EBX = 3,
--  UNW_X86_EBP = 4,
--  UNW_X86_ESP = 5,
-+  UNW_X86_ESP = 4,
-+  UNW_X86_EBP = 5,
-   UNW_X86_ESI = 6,
-   UNW_X86_EDI = 7
- };
diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile
index b82d227..686afc9 100644
--- a/src/ci/docker/dist-i686-freebsd/Dockerfile
+++ b/src/ci/docker/dist-i686-freebsd/Dockerfile
@@ -1,7 +1,7 @@
 FROM ubuntu:16.04
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
+  clang \
   make \
   file \
   curl \
@@ -16,16 +16,16 @@
   libssl-dev \
   pkg-config
 
-COPY dist-i686-freebsd/build-toolchain.sh /tmp/
-RUN /tmp/build-toolchain.sh i686
+COPY scripts/freebsd-toolchain.sh /tmp/
+RUN /tmp/freebsd-toolchain.sh i686
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV \
     AR_i686_unknown_freebsd=i686-unknown-freebsd10-ar \
-    CC_i686_unknown_freebsd=i686-unknown-freebsd10-gcc \
-    CXX_i686_unknown_freebsd=i686-unknown-freebsd10-g++
+    CC_i686_unknown_freebsd=i686-unknown-freebsd10-clang \
+    CXX_i686_unknown_freebsd=i686-unknown-freebsd10-clang++
 
 ENV HOSTS=i686-unknown-freebsd
 
diff --git a/src/ci/docker/dist-i686-freebsd/build-toolchain.sh b/src/ci/docker/dist-i686-freebsd/build-toolchain.sh
deleted file mode 100755
index 3c86a8e..0000000
--- a/src/ci/docker/dist-i686-freebsd/build-toolchain.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-ARCH=$1
-BINUTILS=2.25.1
-GCC=6.4.0
-
-hide_output() {
-  set +x
-  on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
-  trap "$on_err" ERR
-  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
-  PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
-  trap - ERR
-  kill $PING_LOOP_PID
-  set -x
-}
-
-mkdir binutils
-cd binutils
-
-# First up, build binutils
-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=$ARCH-unknown-freebsd10
-hide_output make -j10
-hide_output make install
-cd ../..
-rm -rf binutils
-
-# Next, download the FreeBSD libc and relevant header files
-
-mkdir freebsd
-case "$ARCH" in
-    x86_64)
-        URL=ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/10.2-RELEASE/base.txz
-        ;;
-    i686)
-        URL=ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/10.2-RELEASE/base.txz
-        ;;
-esac
-curl $URL | tar xJf - -C freebsd ./usr/include ./usr/lib ./lib
-
-dst=/usr/local/$ARCH-unknown-freebsd10
-
-cp -r freebsd/usr/include $dst/
-cp freebsd/usr/lib/crt1.o $dst/lib
-cp freebsd/usr/lib/Scrt1.o $dst/lib
-cp freebsd/usr/lib/crti.o $dst/lib
-cp freebsd/usr/lib/crtn.o $dst/lib
-cp freebsd/usr/lib/libc.a $dst/lib
-cp freebsd/usr/lib/libutil.a $dst/lib
-cp freebsd/usr/lib/libutil_p.a $dst/lib
-cp freebsd/usr/lib/libm.a $dst/lib
-cp freebsd/usr/lib/librt.so.1 $dst/lib
-cp freebsd/usr/lib/libexecinfo.so.1 $dst/lib
-cp freebsd/lib/libc.so.7 $dst/lib
-cp freebsd/lib/libm.so.5 $dst/lib
-cp freebsd/lib/libutil.so.9 $dst/lib
-cp freebsd/lib/libthr.so.3 $dst/lib/libpthread.so
-
-ln -s libc.so.7 $dst/lib/libc.so
-ln -s libm.so.5 $dst/lib/libm.so
-ln -s librt.so.1 $dst/lib/librt.so
-ln -s libutil.so.9 $dst/lib/libutil.so
-ln -s libexecinfo.so.1 $dst/lib/libexecinfo.so
-rm -rf freebsd
-
-# Finally, download and build gcc to target FreeBSD
-mkdir gcc
-cd gcc
-curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.gz | tar xzf -
-cd gcc-$GCC
-./contrib/download_prerequisites
-
-mkdir ../gcc-build
-cd ../gcc-build
-hide_output ../gcc-$GCC/configure                \
-  --enable-languages=c,c++                       \
-  --target=$ARCH-unknown-freebsd10               \
-  --disable-multilib                             \
-  --disable-nls                                  \
-  --disable-libgomp                              \
-  --disable-libquadmath                          \
-  --disable-libssp                               \
-  --disable-libvtv                               \
-  --disable-libcilkrts                           \
-  --disable-libada                               \
-  --disable-libsanitizer                         \
-  --disable-libquadmath-support                  \
-  --disable-lto
-hide_output make -j10
-hide_output make install
-cd ../..
-rm -rf gcc
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index a616693..0f08bcd 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -22,23 +22,39 @@
   libssl-dev \
   pkg-config
 
-WORKDIR /tmp
+WORKDIR /build
 
-COPY dist-various-1/build-rumprun.sh /tmp/
+COPY dist-various-1/build-rumprun.sh /build
 RUN ./build-rumprun.sh
 
-COPY dist-various-1/build-arm-musl.sh /tmp/
-RUN ./build-arm-musl.sh
+COPY dist-various-1/install-x86_64-redox.sh /build
+RUN ./install-x86_64-redox.sh
 
-COPY dist-various-1/install-mips-musl.sh /tmp/
+COPY scripts/musl.sh /build
+RUN env \
+    CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv6 -marm" \
+    CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv6 -marm" \
+    bash musl.sh arm && \
+    env \
+    CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv6 -marm" \
+    CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm" \
+    bash musl.sh armhf && \
+    env \
+    CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a" \
+    CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a" \
+    bash musl.sh armv7 && \
+    env \
+    CC=aarch64-linux-gnu-gcc \
+    CXX=aarch64-linux-gnu-g++ \
+    bash musl.sh aarch64 && \
+    rm -rf /build/*
+
+COPY dist-various-1/install-mips-musl.sh /build
 RUN ./install-mips-musl.sh
 
-COPY dist-various-1/install-mipsel-musl.sh /tmp/
+COPY dist-various-1/install-mipsel-musl.sh /build
 RUN ./install-mipsel-musl.sh
 
-COPY dist-various-1/install-x86_64-redox.sh /tmp/
-RUN ./install-x86_64-redox.sh
-
 ENV TARGETS=asmjs-unknown-emscripten
 ENV TARGETS=$TARGETS,wasm32-unknown-emscripten
 ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd
@@ -46,15 +62,20 @@
 ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf
+ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi
 ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl
 ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
 ENV TARGETS=$TARGETS,x86_64-unknown-redox
 
+# FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271
+#        get fixed and cc update
 ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
     CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
-    CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc
+    CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
+    CC_armv5te_unknown_linux_gnueabi=arm-linux-gnueabi-gcc \
+    CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft"
 
 # Suppress some warnings in the openwrt toolchains we downloaded
 ENV STAGING_DIR=/tmp
@@ -62,10 +83,10 @@
 ENV RUST_CONFIGURE_ARGS \
       --enable-extended \
       --target=$TARGETS \
-      --musl-root-arm=/usr/local/arm-linux-musleabi \
-      --musl-root-armhf=/usr/local/arm-linux-musleabihf \
-      --musl-root-armv7=/usr/local/armv7-linux-musleabihf \
-      --musl-root-aarch64=/usr/local/aarch64-linux-musl
+      --musl-root-arm=/musl-arm \
+      --musl-root-armhf=/musl-armhf \
+      --musl-root-armv7=/musl-armv7 \
+      --musl-root-aarch64=/musl-aarch64
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
 
 # sccache
diff --git a/src/ci/docker/dist-various-1/build-arm-musl.sh b/src/ci/docker/dist-various-1/build-arm-musl.sh
deleted file mode 100755
index f9444a3..0000000
--- a/src/ci/docker/dist-various-1/build-arm-musl.sh
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-MUSL=1.1.17
-
-hide_output() {
-  set +x
-  on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
-  trap "$on_err" ERR
-  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
-  PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
-  trap - ERR
-  kill $PING_LOOP_PID
-  rm /tmp/build.log
-  set -x
-}
-
-curl -O https://www.musl-libc.org/releases/musl-$MUSL.tar.gz
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=arm-linux-gnueabi-gcc \
-CFLAGS="-march=armv6 -marm" \
-    hide_output ./configure \
-        --prefix=/usr/local/arm-linux-musleabi \
-        --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL
-
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=arm-linux-gnueabihf-gcc \
-CFLAGS="-march=armv6 -marm" \
-    hide_output ./configure \
-        --prefix=/usr/local/arm-linux-musleabihf \
-        --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL
-
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=arm-linux-gnueabihf-gcc \
-CFLAGS="-march=armv7-a" \
-    hide_output ./configure \
-        --prefix=/usr/local/armv7-linux-musleabihf \
-        --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL
-
-tar xf musl-$MUSL.tar.gz
-cd musl-$MUSL
-CC=aarch64-linux-gnu-gcc \
-CFLAGS="" \
-    hide_output ./configure \
-        --prefix=/usr/local/aarch64-linux-musl \
-        --enable-wrapper=gcc
-hide_output make -j$(nproc)
-hide_output make install
-cd ..
-rm -rf musl-$MUSL*
-
-ln -nsf ../arm-linux-musleabi/bin/musl-gcc /usr/local/bin/arm-linux-musleabi-gcc
-ln -nsf ../arm-linux-musleabihf/bin/musl-gcc /usr/local/bin/arm-linux-musleabihf-gcc
-ln -nsf ../armv7-linux-musleabihf/bin/musl-gcc /usr/local/bin/armv7-linux-musleabihf-gcc
-ln -nsf ../aarch64-linux-musl/bin/musl-gcc /usr/local/bin/aarch64-unknown-linux-musl-gcc
-
-curl -L https://github.com/llvm-mirror/llvm/archive/release_39.tar.gz | tar xzf -
-curl -L https://github.com/llvm-mirror/libunwind/archive/release_39.tar.gz | tar xzf -
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
-          -DLLVM_PATH=/tmp/llvm-release_39 \
-          -DLIBUNWIND_ENABLE_SHARED=0 \
-          -DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \
-          -DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ \
-          -DCMAKE_C_FLAGS="-march=armv6 -marm" \
-          -DCMAKE_CXX_FLAGS="-march=armv6 -marm"
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/arm-linux-musleabi/lib
-cd ..
-rm -rf libunwind-build
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
-          -DLLVM_PATH=/tmp/llvm-release_39 \
-          -DLIBUNWIND_ENABLE_SHARED=0 \
-          -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \
-          -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \
-          -DCMAKE_C_FLAGS="-march=armv6 -marm" \
-          -DCMAKE_CXX_FLAGS="-march=armv6 -marm"
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/arm-linux-musleabihf/lib
-cd ..
-rm -rf libunwind-build
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
-          -DLLVM_PATH=/tmp/llvm-release_39 \
-          -DLIBUNWIND_ENABLE_SHARED=0 \
-          -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \
-          -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \
-          -DCMAKE_C_FLAGS="-march=armv7-a" \
-          -DCMAKE_CXX_FLAGS="-march=armv7-a"
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/armv7-linux-musleabihf/lib
-cd ..
-rm -rf libunwind-build
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_39 \
-          -DLLVM_PATH=/tmp/llvm-release_39 \
-          -DLIBUNWIND_ENABLE_SHARED=0 \
-          -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
-          -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
-          -DCMAKE_C_FLAGS="" \
-          -DCMAKE_CXX_FLAGS=""
-make -j$(nproc)
-cp lib/libunwind.a /usr/local/aarch64-linux-musl/lib
-cd ..
-rm -rf libunwind-build
-
-rm -rf libunwind-release_39
-rm -rf llvm-release_39
diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile
index c7885db..d8f09bf 100644
--- a/src/ci/docker/dist-various-2/Dockerfile
+++ b/src/ci/docker/dist-various-2/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:16.04
+FROM ubuntu:17.10
 
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
@@ -21,9 +21,12 @@
 RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main'
 
 WORKDIR /tmp
-COPY dist-various-2/shared.sh dist-various-2/build-fuchsia-toolchain.sh /tmp/
-COPY dist-various-2/build-solaris-toolchain.sh /tmp/
+COPY dist-various-2/shared.sh /tmp/
+COPY dist-various-2/build-cloudabi-toolchain.sh /tmp/
+RUN /tmp/build-cloudabi-toolchain.sh x86_64-unknown-cloudabi
+COPY dist-various-2/build-fuchsia-toolchain.sh /tmp/
 RUN /tmp/build-fuchsia-toolchain.sh
+COPY dist-various-2/build-solaris-toolchain.sh /tmp/
 RUN /tmp/build-solaris-toolchain.sh x86_64  amd64   solaris-i386
 RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
 
@@ -44,12 +47,20 @@
     CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \
     CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++
 
+# FIXME(EdSchouten): Remove this once cc ≥1.0.4 has been merged. It can
+# automatically pick the right compiler path.
+ENV \
+    AR_x86_64_unknown_cloudabi=x86_64-unknown-cloudabi-ar \
+    CC_x86_64_unknown_cloudabi=x86_64-unknown-cloudabi-clang \
+    CXX_x86_64_unknown_cloudabi=x86_64-unknown-cloudabi-clang++
+
 ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
 ENV TARGETS=$TARGETS,sparcv9-sun-solaris
 ENV TARGETS=$TARGETS,wasm32-unknown-unknown
 ENV TARGETS=$TARGETS,x86_64-sun-solaris
 ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
+ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi
 
 ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
diff --git a/src/ci/docker/dist-various-2/build-cloudabi-toolchain.sh b/src/ci/docker/dist-various-2/build-cloudabi-toolchain.sh
new file mode 100755
index 0000000..d64da43
--- /dev/null
+++ b/src/ci/docker/dist-various-2/build-cloudabi-toolchain.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+set -eux
+
+# Install prerequisites.
+apt-get update
+apt-get install -y --no-install-recommends \
+  apt-transport-https \
+  ca-certificates \
+  clang-5.0 \
+  cmake \
+  curl \
+  file \
+  g++ \
+  gdb \
+  git \
+  lld-5.0 \
+  make \
+  python \
+  sudo \
+  xz-utils
+
+# Set up a Clang-based cross compiler toolchain.
+# Based on the steps described at https://nuxi.nl/cloudabi/debian/
+target=$1
+for tool in ar nm objdump ranlib size; do
+  ln -s ../lib/llvm-5.0/bin/llvm-${tool} /usr/bin/${target}-${tool}
+done
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-cc
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-c++
+ln -s ../lib/llvm-5.0/bin/lld /usr/bin/${target}-ld
+ln -s ../../${target} /usr/lib/llvm-5.0/${target}
+
+# FIXME(EdSchouten): Remove this once cc ≥1.0.4 has been merged. It
+# can make use of ${target}-cc and ${target}-c++, without incorrectly
+# assuming it's MSVC.
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-clang
+ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-clang++
+
+# Install the C++ runtime libraries from CloudABI Ports.
+echo deb https://nuxi.nl/distfiles/cloudabi-ports/debian/ cloudabi cloudabi > \
+    /etc/apt/sources.list.d/cloudabi.list
+curl 'https://pgp.mit.edu/pks/lookup?op=get&search=0x0DA51B8531344B15' | \
+    apt-key add -
+apt-get update
+apt-get install -y $(echo ${target} | sed -e s/_/-/g)-cxx-runtime
diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile
index b7c00df..7483d39 100644
--- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile
@@ -1,7 +1,7 @@
 FROM ubuntu:16.04
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
+  clang \
   make \
   file \
   curl \
@@ -16,16 +16,16 @@
   libssl-dev \
   pkg-config
 
-COPY dist-x86_64-freebsd/build-toolchain.sh /tmp/
-RUN /tmp/build-toolchain.sh x86_64
+COPY scripts/freebsd-toolchain.sh /tmp/
+RUN /tmp/freebsd-toolchain.sh x86_64
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV \
     AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \
-    CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-gcc \
-    CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-g++
+    CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-clang \
+    CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-clang++
 
 ENV HOSTS=x86_64-unknown-freebsd
 
diff --git a/src/ci/docker/dist-x86_64-freebsd/build-toolchain.sh b/src/ci/docker/dist-x86_64-freebsd/build-toolchain.sh
deleted file mode 100755
index 3c86a8e..0000000
--- a/src/ci/docker/dist-x86_64-freebsd/build-toolchain.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-ARCH=$1
-BINUTILS=2.25.1
-GCC=6.4.0
-
-hide_output() {
-  set +x
-  on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
-  trap "$on_err" ERR
-  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
-  PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
-  trap - ERR
-  kill $PING_LOOP_PID
-  set -x
-}
-
-mkdir binutils
-cd binutils
-
-# First up, build binutils
-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=$ARCH-unknown-freebsd10
-hide_output make -j10
-hide_output make install
-cd ../..
-rm -rf binutils
-
-# Next, download the FreeBSD libc and relevant header files
-
-mkdir freebsd
-case "$ARCH" in
-    x86_64)
-        URL=ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/10.2-RELEASE/base.txz
-        ;;
-    i686)
-        URL=ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/10.2-RELEASE/base.txz
-        ;;
-esac
-curl $URL | tar xJf - -C freebsd ./usr/include ./usr/lib ./lib
-
-dst=/usr/local/$ARCH-unknown-freebsd10
-
-cp -r freebsd/usr/include $dst/
-cp freebsd/usr/lib/crt1.o $dst/lib
-cp freebsd/usr/lib/Scrt1.o $dst/lib
-cp freebsd/usr/lib/crti.o $dst/lib
-cp freebsd/usr/lib/crtn.o $dst/lib
-cp freebsd/usr/lib/libc.a $dst/lib
-cp freebsd/usr/lib/libutil.a $dst/lib
-cp freebsd/usr/lib/libutil_p.a $dst/lib
-cp freebsd/usr/lib/libm.a $dst/lib
-cp freebsd/usr/lib/librt.so.1 $dst/lib
-cp freebsd/usr/lib/libexecinfo.so.1 $dst/lib
-cp freebsd/lib/libc.so.7 $dst/lib
-cp freebsd/lib/libm.so.5 $dst/lib
-cp freebsd/lib/libutil.so.9 $dst/lib
-cp freebsd/lib/libthr.so.3 $dst/lib/libpthread.so
-
-ln -s libc.so.7 $dst/lib/libc.so
-ln -s libm.so.5 $dst/lib/libm.so
-ln -s librt.so.1 $dst/lib/librt.so
-ln -s libutil.so.9 $dst/lib/libutil.so
-ln -s libexecinfo.so.1 $dst/lib/libexecinfo.so
-rm -rf freebsd
-
-# Finally, download and build gcc to target FreeBSD
-mkdir gcc
-cd gcc
-curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.gz | tar xzf -
-cd gcc-$GCC
-./contrib/download_prerequisites
-
-mkdir ../gcc-build
-cd ../gcc-build
-hide_output ../gcc-$GCC/configure                \
-  --enable-languages=c,c++                       \
-  --target=$ARCH-unknown-freebsd10               \
-  --disable-multilib                             \
-  --disable-nls                                  \
-  --disable-libgomp                              \
-  --disable-libquadmath                          \
-  --disable-libssp                               \
-  --disable-libvtv                               \
-  --disable-libcilkrts                           \
-  --disable-libada                               \
-  --disable-libsanitizer                         \
-  --disable-libquadmath-support                  \
-  --disable-lto
-hide_output make -j10
-hide_output make install
-cd ../..
-rm -rf gcc
diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile
index 91ed6bf..77a55b3 100644
--- a/src/ci/docker/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/dist-x86_64-musl/Dockerfile
@@ -17,8 +17,14 @@
   pkg-config
 
 WORKDIR /build/
-COPY dist-x86_64-musl/build-musl.sh /build/
-RUN sh /build/build-musl.sh && rm -rf /build
+
+COPY scripts/musl.sh /build/
+# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
+RUN CC=gcc \
+    CFLAGS="-fPIC -Wa,-mrelax-relocations=no" \
+    CXX=g++ \
+    CXXFLAGS="-Wa,-mrelax-relocations=no" \
+    bash musl.sh x86_64 && rm -rf /build
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/dist-x86_64-musl/build-musl.sh b/src/ci/docker/dist-x86_64-musl/build-musl.sh
deleted file mode 100644
index 9be8d00..0000000
--- a/src/ci/docker/dist-x86_64-musl/build-musl.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
-export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
-export CXXFLAGS="-Wa,-mrelax-relocations=no"
-
-MUSL=musl-1.1.17
-curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
-cd $MUSL
-./configure --prefix=/musl-x86_64 --disable-shared
-make -j10
-make install
-
-cd ..
-rm -rf $MUSL
-
-# To build MUSL we're going to need a libunwind lying around, so acquire that
-# here and build it.
-curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf -
-curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf -
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_37 -DLLVM_PATH=/build/llvm-release_37 \
-          -DLIBUNWIND_ENABLE_SHARED=0
-make -j10
-cp lib/libunwind.a /musl-x86_64/lib
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index a863e1a..f743c97 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -99,6 +99,7 @@
   --env LOCAL_USER_ID=`id -u` \
   --env TRAVIS \
   --env TRAVIS_BRANCH \
+  --env TOOLSTATE_REPO_ACCESS_TOKEN \
   --volume "$HOME/.cargo:/cargo" \
   --volume "$HOME/rustsrc:$HOME/rustsrc" \
   --init \
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
new file mode 100755
index 0000000..15ed318
--- /dev/null
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+# Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+set -eux
+
+arch=$1
+binutils_version=2.25.1
+freebsd_version=10.3
+triple=$arch-unknown-freebsd10
+sysroot=/usr/local/$triple
+
+hide_output() {
+  set +x
+  local on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  local ping_loop_pid=$!
+  $@ &> /tmp/build.log
+  trap - ERR
+  kill $ping_loop_pid
+  set -x
+}
+
+# First up, build binutils
+mkdir binutils
+cd binutils
+curl https://ftp.gnu.org/gnu/binutils/binutils-${binutils_version}.tar.bz2 | tar xjf -
+mkdir binutils-build
+cd binutils-build
+hide_output ../binutils-${binutils_version}/configure \
+  --target="$triple" --with-sysroot="$sysroot"
+hide_output make -j"$(getconf _NPROCESSORS_ONLN)"
+hide_output make install
+cd ../..
+rm -rf binutils
+
+# Next, download the FreeBSD libraries and header files
+mkdir -p "$sysroot"
+case $arch in
+  (x86_64) freebsd_arch=amd64 ;;
+  (i686) freebsd_arch=i386 ;;
+esac
+
+files_to_extract=(
+"./usr/include"
+"./usr/lib/*crt*.o"
+)
+# Try to unpack only the libraries the build needs, to save space.
+for lib in c cxxrt gcc_s m thr util; do
+  files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
+done
+for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared; do
+  files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
+done
+
+URL=https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
+curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
+
+# Fix up absolute symlinks from the system image.  This can be removed
+# for FreeBSD 11.  (If there's an easy way to make them relative
+# symlinks instead, feel free to change this.)
+set +x
+find "$sysroot" -type l | while read symlink_path; do
+  symlink_target=$(readlink "$symlink_path")
+  case $symlink_target in
+    (/*)
+      echo "Fixing symlink ${symlink_path} -> ${sysroot}${symlink_target}" >&2
+      ln -nfs "${sysroot}${symlink_target}" "${symlink_path}" ;;
+  esac
+done
+set -x
+
+# Clang can do cross-builds out of the box, if we give it the right
+# flags.  (The local binutils seem to work, but they set the ELF
+# header "OS/ABI" (EI_OSABI) field to SysV rather than FreeBSD, so
+# there might be other problems.)
+#
+# The --target option is last because the cross-build of LLVM uses
+# --target without an OS version ("-freebsd" vs. "-freebsd10").  This
+# makes Clang default to libstdc++ (which no longer exists), and also
+# controls other features, like GNU-style symbol table hashing and
+# anything predicated on the version number in the __FreeBSD__
+# preprocessor macro.
+for tool in clang clang++; do
+  tool_path=/usr/local/bin/${triple}-${tool}
+  cat > "$tool_path" <<EOF
+#!/bin/sh
+exec $tool --sysroot=$sysroot --prefix=${sysroot}/bin "\$@" --target=$triple
+EOF
+  chmod +x "$tool_path"
+done
diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh
new file mode 100644
index 0000000..7a72332
--- /dev/null
+++ b/src/ci/docker/scripts/musl.sh
@@ -0,0 +1,102 @@
+# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  $@ &> /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  rm /tmp/build.log
+  set -x
+}
+
+TAG=$1
+shift
+
+MUSL=musl-1.1.18
+
+# may have been downloaded in a previous run
+if [ ! -d $MUSL ]; then
+  curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
+fi
+
+cd $MUSL
+./configure --disable-shared --prefix=/musl-$TAG $@
+if [ "$TAG" = "i586" -o "$TAG" = "i686" ]; then
+  hide_output make -j$(nproc) AR=ar RANLIB=ranlib
+else
+  hide_output make -j$(nproc)
+fi
+hide_output make install
+hide_output make clean
+
+cd ..
+
+LLVM=39
+# may have been downloaded in a previous run
+if [ ! -d libunwind-release_$LLVM ]; then
+  curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
+  curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
+  # Whoa what's this mysterious patch we're applying to libunwind! Why are we
+  # swapping the values of ESP/EBP in libunwind?!
+  #
+  # Discovered in #35599 it turns out that the vanilla build of libunwind is not
+  # suitable for unwinding i686 musl. After some investigation it ended up
+  # looking like the register values for ESP/EBP were indeed incorrect (swapped)
+  # in the source. Similar commits in libunwind (r280099 and r282589) have noticed
+  # this for other platforms, and we just need to realize it for musl linux as
+  # well.
+  #
+  # More technical info can be found at #35599
+  cd libunwind-release_$LLVM
+  patch -Np1 << EOF
+diff --git a/include/libunwind.h b/include/libunwind.h
+index c5b9633..1360eb2 100644
+--- a/include/libunwind.h
++++ b/include/libunwind.h
+@@ -151,8 +151,8 @@ enum {
+   UNW_X86_ECX = 1,
+   UNW_X86_EDX = 2,
+   UNW_X86_EBX = 3,
+-  UNW_X86_EBP = 4,
+-  UNW_X86_ESP = 5,
++  UNW_X86_ESP = 4,
++  UNW_X86_EBP = 5,
+   UNW_X86_ESI = 6,
+   UNW_X86_EDI = 7
+ };
+fi
+EOF
+  cd ..
+fi
+
+mkdir libunwind-build
+cd libunwind-build
+cmake ../libunwind-release_$LLVM \
+          -DLLVM_PATH=/build/llvm-release_$LLVM \
+          -DLIBUNWIND_ENABLE_SHARED=0 \
+          -DCMAKE_C_COMPILER=$CC \
+          -DCMAKE_CXX_COMPILER=$CXX \
+          -DCMAKE_C_FLAGS="$CFLAGS" \
+          -DCMAKE_CXX_FLAGS="$CXXFLAGS"
+
+hide_output make -j$(nproc)
+cp lib/libunwind.a /musl-$TAG/lib
+cd ../ && rm -rf libunwind-build
diff --git a/src/ci/docker/x86_64-gnu-aux/Dockerfile b/src/ci/docker/x86_64-gnu-aux/Dockerfile
index 62c55f4..44bee19 100644
--- a/src/ci/docker/x86_64-gnu-aux/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-aux/Dockerfile
@@ -21,5 +21,5 @@
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-test-miri
+ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check-aux
diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile
index d323677..7304ed6 100644
--- a/src/ci/docker/x86_64-gnu-incremental/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-incremental/Dockerfile
@@ -19,3 +19,4 @@
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache
 ENV RUST_CHECK_TARGET check
+ENV CARGO_INCREMENTAL 0
diff --git a/src/ci/docker/x86_64-gnu-tools/Dockerfile b/src/ci/docker/x86_64-gnu-tools/Dockerfile
index fffad1c..8975d41 100644
--- a/src/ci/docker/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-tools/Dockerfile
@@ -18,6 +18,10 @@
 RUN sh /scripts/sccache.sh
 
 COPY x86_64-gnu-tools/checktools.sh /tmp/
+COPY x86_64-gnu-tools/repo.sh /tmp/
 
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --save-toolstates=/tmp/toolstates.json
-ENV SCRIPT /tmp/checktools.sh ../x.py /tmp/toolstates.json
+ENV RUST_CONFIGURE_ARGS \
+  --build=x86_64-unknown-linux-gnu \
+  --enable-test-miri \
+  --save-toolstates=/tmp/toolstates.json
+ENV SCRIPT /tmp/checktools.sh ../x.py /tmp/toolstates.json linux
diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh
index bf39bc2..b9268fe 100755
--- a/src/ci/docker/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh
@@ -13,7 +13,10 @@
 set -eu
 
 X_PY="$1"
-TOOLSTATE_FILE="$2"
+TOOLSTATE_FILE="$(realpath $2)"
+OS="$3"
+COMMIT="$(git rev-parse HEAD)"
+CHANGED_FILES="$(git diff --name-status HEAD HEAD^)"
 
 touch "$TOOLSTATE_FILE"
 
@@ -23,17 +26,43 @@
     src/tools/rustfmt \
     src/tools/miri \
     src/tools/clippy
-TEST_RESULT=$?
 set -e
 
-# FIXME: Upload this file to the repository.
 cat "$TOOLSTATE_FILE"
 
-# FIXME: After we can properly inform dev-tool maintainers about failure,
-#        comment out the `exit 0` below.
-if [ "$RUST_RELEASE_CHANNEL" = nightly ]; then
-    # exit 0
-    true
+# If this PR is intended to update one of these tools, do not let the build pass
+# when they do not test-pass.
+for TOOL in rls rustfmt miri clippy; do
+    echo "Verifying status of $TOOL..."
+    if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]src/tools/$TOOL$"; then
+        echo "This PR updated 'src/tools/$TOOL', verifying if status is 'test-pass'..."
+        if grep -vq '"'"$TOOL"'[^"]*":"test-pass"' "$TOOLSTATE_FILE"; then
+            echo
+            echo "⚠️ We detected that this PR updated '$TOOL', but its tests failed."
+            echo
+            echo "If you do intend to update '$TOOL', please check the error messages above and"
+            echo "commit another update."
+            echo
+            echo "If you do NOT intend to update '$TOOL', please ensure you did not accidentally"
+            echo "change the submodule at 'src/tools/$TOOL'. You may ask your reviewer for the"
+            echo "proper steps."
+            exit 3
+        fi
+    fi
+done
+
+if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
+    . "$(dirname $0)/repo.sh"
+    MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
+    echo "($OS CI update)" > "$MESSAGE_FILE"
+    commit_toolstate_change "$MESSAGE_FILE" \
+        sed -i "1 a\\
+$COMMIT\t$(cat "$TOOLSTATE_FILE")
+" "history/$OS.tsv"
+    rm -f "$MESSAGE_FILE"
+    exit 0
 fi
 
-exit $TEST_RESULT
+if grep -q fail "$TOOLSTATE_FILE"; then
+    exit 4
+fi
diff --git a/src/ci/docker/x86_64-gnu-tools/repo.sh b/src/ci/docker/x86_64-gnu-tools/repo.sh
new file mode 100644
index 0000000..c10afef
--- /dev/null
+++ b/src/ci/docker/x86_64-gnu-tools/repo.sh
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+# This file provides the function `commit_toolstate_change` for pushing a change
+# to the `rust-toolstate` repository.
+#
+# The function relies on a GitHub bot user, which should have a Personal access
+# token defined in the environment variable $TOOLSTATE_REPO_ACCESS_TOKEN. If for
+# some reason you need to change the token, please update `.travis.yml` and
+# `appveyor.yml`:
+#
+#   1. Generate a new Personal access token:
+#
+#       * Login to the bot account, and go to Settings -> Developer settings ->
+#           Personal access tokens
+#       * Click "Generate new token"
+#       * Enable the "public_repo" permission, then click "Generate token"
+#       * Copy the generated token (should be a 40-digit hexadecimal number).
+#           Save it somewhere secure, as the token would be gone once you leave
+#           the page.
+#
+#   2. Encrypt the token for Travis CI
+#
+#       * Install the `travis` tool locally (`gem install travis`).
+#       * Encrypt the token:
+#           ```
+#           travis -r rust-lang/rust encrypt \
+#                   TOOLSTATE_REPO_ACCESS_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+#           ```
+#       * Copy output to replace the existing one in `.travis.yml`.
+#       * Details of this step can be found in
+#           <https://docs.travis-ci.com/user/encryption-keys/>
+#
+#   3. Encrypt the token for AppVeyor
+#
+#       * Login to AppVeyor using your main account, and login as the rust-lang
+#           organization.
+#       * Open the ["Encrypt data" tool](https://ci.appveyor.com/tools/encrypt)
+#       * Paste the 40-digit token into the "Value to encrypt" box, then click
+#           "Encrypt"
+#       * Copy the output to replace the existing one in `appveyor.yml`.
+#       * Details of this step can be found in
+#           <https://www.appveyor.com/docs/how-to/git-push/>
+#
+#   4. Replace the email address below if the bot account identity is changed
+#
+#       * See <https://help.github.com/articles/about-commit-email-addresses/>
+#           if a private email by GitHub is wanted.
+
+commit_toolstate_change() {
+    OLDFLAGS="$-"
+    set -eu
+
+    git config --global user.email '34210020+rust-toolstate-update@users.noreply.github.com'
+    git config --global user.name 'Rust Toolstate Update'
+    git config --global credential.helper store
+    printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \
+        > "$HOME/.git-credentials"
+    git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git
+
+    cd rust-toolstate
+    FAILURE=1
+    MESSAGE_FILE="$1"
+    shift
+    for RETRY_COUNT in 1 2 3 4 5; do
+        "$@"
+        # `git commit` failing means nothing to commit.
+        FAILURE=0
+        git commit -a -F "$MESSAGE_FILE" || break
+        # On failure randomly sleep for 0 to 3 seconds as a crude way to introduce jittering.
+        git push origin master && break || sleep $(LC_ALL=C tr -cd 0-3 < /dev/urandom | head -c 1)
+        FAILURE=1
+        git fetch origin master
+        git reset --hard origin/master
+    done
+    cd ..
+
+    set +eu
+    set "-$OLDFLAGS"
+    return $FAILURE
+}
diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile
index 7570bca..444a8fe 100644
--- a/src/ci/docker/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/x86_64-gnu/Dockerfile
@@ -16,5 +16,9 @@
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers --enable-profiler
+ENV RUST_CONFIGURE_ARGS \
+ --build=x86_64-unknown-linux-gnu \
+ --enable-sanitizers \
+ --enable-profiler \
+ --enable-compiler-docs
 ENV SCRIPT python2.7 ../x.py test
diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh
index e073a3d..14a1906 100755
--- a/src/ci/init_repo.sh
+++ b/src/ci/init_repo.sh
@@ -36,6 +36,12 @@
 rm -rf "$CACHE_DIR"
 mkdir "$CACHE_DIR"
 
+# On the beta channel we'll be automatically calculating the prerelease version
+# via the git history, so unshallow our shallow clone from CI.
+if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then
+  git fetch origin --unshallow beta master
+fi
+
 travis_fold start update_cache
 travis_time_start
 
diff --git a/src/doc/book b/src/doc/book
index 3944d61..194eb8d 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 3944d61149fa234ea991b498d4dac4fcec68a80e
+Subproject commit 194eb8d5f1753fb5f4501011cebdc1b585712474
diff --git a/src/doc/index.md b/src/doc/index.md
index 3784cc3..3add277 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -28,6 +28,7 @@
 nicknamed 'The Rust Bookshelf.'
 
 * [The Rust Programming Language][book] teaches you how to program in Rust.
+* [Rust By Example][rbe] teaches you how to program in Rust using editable examples.
 * [The Cargo Book][cargo-book] is a guide to Cargo, Rust's build tool and dependency manager.
 * [The Unstable Book][unstable-book] has documentation for unstable features.
 * [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust.
@@ -51,6 +52,7 @@
 [refchecklist]: https://github.com/rust-lang-nursery/reference/issues/9
 [err]: error-index.html
 [book]: book/index.html
+[rbe]: rust-by-example/index.html
 [nomicon]: nomicon/index.html
 [unstable-book]: unstable-book/index.html
 [rustdoc-book]: rustdoc/index.html
diff --git a/src/doc/nomicon b/src/doc/nomicon
index cfb1f2d..fec3182 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit cfb1f2d7e5eb6143915d5a63afe4cf58e8531c27
+Subproject commit fec3182d0b0a3cf8122e192b3270064a5b19be5b
diff --git a/src/doc/reference b/src/doc/reference
index 857f2c9..1d791b5 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 857f2c97c8075d39fa07eb4a404980519faa600a
+Subproject commit 1d791b55b23ec5389fbd5b3cee80db3f8bbdd162
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
new file mode 160000
index 0000000..4ebb816
--- /dev/null
+++ b/src/doc/rust-by-example
@@ -0,0 +1 @@
+Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a
diff --git a/src/doc/rust.css b/src/doc/rust.css
index 664bc0f..5f21616 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -11,181 +11,181 @@
  * except according to those terms.
  */
 @font-face {
-    font-family: 'Fira Sans';
-    font-style: normal;
-    font-weight: 400;
-    src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
+	font-family: 'Fira Sans';
+	font-style: normal;
+	font-weight: 400;
+	src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
 }
 @font-face {
-    font-family: 'Fira Sans';
-    font-style: normal;
-    font-weight: 500;
-    src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
+	font-family: 'Fira Sans';
+	font-style: normal;
+	font-weight: 500;
+	src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
 }
 @font-face {
-    font-family: 'Source Serif Pro';
-    font-style: normal;
-    font-weight: 400;
-    src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
+	font-family: 'Source Serif Pro';
+	font-style: normal;
+	font-weight: 400;
+	src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
 }
 @font-face {
-    font-family: 'Source Serif Pro';
-    font-style: italic;
-    font-weight: 400;
-    src: url("Heuristica-Italic.woff") format('woff');
+	font-family: 'Source Serif Pro';
+	font-style: italic;
+	font-weight: 400;
+	src: url("Heuristica-Italic.woff") format('woff');
 }
 @font-face {
-    font-family: 'Source Serif Pro';
-    font-style: normal;
-    font-weight: 700;
-    src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
+	font-family: 'Source Serif Pro';
+	font-style: normal;
+	font-weight: 700;
+	src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
 }
 @font-face {
-    font-family: 'Source Code Pro';
-    font-style: normal;
-    font-weight: 400;
-    /* Avoid using locally installed font because bad versions are in circulation:
-     * see https://github.com/rust-lang/rust/issues/24355 */
-    src: url("SourceCodePro-Regular.woff") format('woff');
+	font-family: 'Source Code Pro';
+	font-style: normal;
+	font-weight: 400;
+	/* Avoid using locally installed font because bad versions are in circulation:
+	 * see https://github.com/rust-lang/rust/issues/24355 */
+	src: url("SourceCodePro-Regular.woff") format('woff');
 }
 
 *:not(body) {
   -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
+	 -moz-box-sizing: border-box;
+		  box-sizing: border-box;
 }
 
 /* General structure */
 
 body {
-    background-color: white;
-    margin: 0 auto;
-    padding: 0 15px;
-    font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
-    font-size: 18px;
-    color: #333;
-    line-height: 1.428571429;
+	background-color: white;
+	margin: 0 auto;
+	padding: 0 15px;
+	font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
+	font-size: 18px;
+	color: #333;
+	line-height: 1.428571429;
 
-    -webkit-font-feature-settings: "kern", "liga";
-    -moz-font-feature-settings: "kern", "liga";
-    font-feature-settings: "kern", "liga";
+	-webkit-font-feature-settings: "kern", "liga";
+	-moz-font-feature-settings: "kern", "liga";
+	font-feature-settings: "kern", "liga";
 }
 @media (min-width: 768px) {
-    body {
-        max-width: 750px;
-    }
+	body {
+		max-width: 750px;
+	}
 }
 
 h1, h2, h3, h4, h5, h6, nav, #versioninfo {
-    font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+	font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
 }
 h1, h2, h3, h4, h5, h6 {
-    color: black;
-    font-weight: 400;
-    line-height: 1.1;
+	color: black;
+	font-weight: 400;
+	line-height: 1.1;
 }
 h1, h2, h3 {
-    margin-top: 20px;
-    margin-bottom: 15px;
+	margin-top: 20px;
+	margin-bottom: 15px;
 }
 h1 {
-    margin-bottom: 20px;
+	margin-bottom: 20px;
 }
 h4, h5, h6 {
-    margin-top: 12px;
-    margin-bottom: 10px;
-    padding: 5px 10px;
+	margin-top: 12px;
+	margin-bottom: 10px;
+	padding: 5px 10px;
 }
 h5, h6 {
-    text-decoration: underline;
+	text-decoration: underline;
 }
 
 h1 {
-    font-size: 28px;
-    font-weight: 500;
-    padding: .1em .4em;
-    border-bottom: 2px solid #ddd;
+	font-size: 28px;
+	font-weight: 500;
+	padding: .1em .4em;
+	border-bottom: 2px solid #ddd;
 }
 h1.title {
-    line-height: 1.5em;
+	line-height: 1.5em;
 }
 h2 {
-    font-size: 26px;
-    padding: .2em .5em;
-    border-bottom: 1px solid #ddd;
+	font-size: 26px;
+	padding: .2em .5em;
+	border-bottom: 1px solid #ddd;
 }
 h3 {
-    font-size: 24px;
-    padding: .2em .7em;
-    border-bottom: 1px solid #DDE8FC;
+	font-size: 24px;
+	padding: .2em .7em;
+	border-bottom: 1px solid #DDE8FC;
 }
 h4 {
-    font-size: 22px;
+	font-size: 22px;
 }
 h5 {
-    font-size: 20px;
+	font-size: 20px;
 }
 h6 {
-    font-size: 18px;
+	font-size: 18px;
 }
 @media (min-width: 992px) {
-    h1 {
-        font-size: 36px;
-    }
-    h2 {
-        font-size: 30px;
-    }
-    h3 {
-        font-size: 26px;
-    }
+	h1 {
+		font-size: 36px;
+	}
+	h2 {
+		font-size: 30px;
+	}
+	h3 {
+		font-size: 26px;
+	}
 }
 
 nav {
-    column-count: 2;
-    -moz-column-count: 2;
-    -webkit-column-count: 2;
-    font-size: 15px;
-    margin: 0 0 1em 0;
+	column-count: 2;
+	-moz-column-count: 2;
+	-webkit-column-count: 2;
+	font-size: 15px;
+	margin: 0 0 1em 0;
 }
 p {
-    margin: 0 0 1em 0;
+	margin: 0 0 1em 0;
 }
 
 strong {
-    font-weight: bold;
+	font-weight: bold;
 }
 
 em {
-    font-style: italic;
+	font-style: italic;
 }
 
 footer {
-    border-top: 1px solid #ddd;
-    font-size: 14px;
-    font-style: italic;
-    padding-top: 5px;
-    margin-top: 3em;
-    margin-bottom: 1em;
+	border-top: 1px solid #ddd;
+	font-size: 14px;
+	font-style: italic;
+	padding-top: 5px;
+	margin-top: 3em;
+	margin-bottom: 1em;
 }
 
 /* Links layout */
 
 a {
-    text-decoration: none;
-    color: #428BCA;
-    background: transparent;
+	text-decoration: none;
+	color: #428BCA;
+	background: transparent;
 }
 a:hover, a:focus {
-    color: #2A6496;
-    text-decoration: underline;
+	color: #2A6496;
+	text-decoration: underline;
 }
 a:focus {
-    outline: thin dotted #333;
-    outline: 5px auto -webkit-focus-ring-color;
-    outline-offset: -2px;
+	outline: thin dotted #333;
+	outline: 5px auto -webkit-focus-ring-color;
+	outline-offset: -2px;
 }
 a:hover, a:active {
-    outline: 0;
+	outline: 0;
 }
 
 h1 a:link, h1 a:visited, h2 a:link, h2 a:visited,
@@ -197,34 +197,34 @@
 /* Code */
 
 pre, code {
-    font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
-    word-wrap: break-word;
+	font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
+	word-wrap: break-word;
 }
 pre {
-    border-left: 2px solid #eee;
-    white-space: pre-wrap;
-    padding: 14px;
-    padding-right: 0;
-    margin: 20px 0;
-    font-size: 13px;
-    word-break: break-all;
+	border-left: 2px solid #eee;
+	white-space: pre-wrap;
+	padding: 14px;
+	padding-right: 0;
+	margin: 20px 0;
+	font-size: 15px;
+	word-break: break-all;
 }
 code {
-    padding: 0 2px;
-    color: #8D1A38;
+	padding: 0 2px;
+	color: #8D1A38;
 }
 pre code {
-    padding: 0;
-    font-size: inherit;
-    color: inherit;
+	padding: 0;
+	font-size: inherit;
+	color: inherit;
 }
 
 a > code {
-    color: #428BCA;
+	color: #428BCA;
 }
 
 .section-header > a > code {
-    color: #8D1A38;
+	color: #8D1A38;
 }
 
 /* Code highlighting */
@@ -241,178 +241,221 @@
 /* The rest */
 
 #versioninfo {
-    text-align: center;
-    margin: 0.5em;
-    font-size: 1.1em;
+	text-align: center;
+	margin: 0.5em;
+	font-size: 1.1em;
 }
 @media (min-width: 992px) {
-    #versioninfo {
-        font-size: 0.8em;
-        position: fixed;
-        bottom: 0px;
-        right: 0px;
-    }
-    .white-sticker {
-        background-color: #fff;
-        margin: 2px;
-        padding: 0 2px;
-        border-radius: .2em;
-    }
+	#versioninfo {
+		font-size: 0.8em;
+		position: fixed;
+		bottom: 0px;
+		right: 0px;
+	}
+	.white-sticker {
+		background-color: #fff;
+		margin: 2px;
+		padding: 0 2px;
+		border-radius: .2em;
+	}
 }
 #versioninfo a.hash {
-    color: gray;
-    font-size: 80%;
+	color: gray;
+	font-size: 80%;
 }
 
 blockquote {
-    color: #000;
-    margin: 20px 0;
-    padding: 15px 20px;
-    background-color: #f2f7f9;
-    border-top: .1em solid #e5eef2;
-    border-bottom: .1em solid #e5eef2;
+	color: #000;
+	margin: 20px 0;
+	padding: 15px 20px;
+	background-color: #f2f7f9;
+	border-top: .1em solid #e5eef2;
+	border-bottom: .1em solid #e5eef2;
 }
 blockquote p {
-    font-size: 17px;
-    font-weight: 300;
-    line-height: 1.4;
+	font-size: 17px;
+	font-weight: 300;
+	line-height: 1.4;
 }
 blockquote p:last-child {
-    margin-bottom: 0;
+	margin-bottom: 0;
 }
 
 ul, ol {
-    padding-left: 25px;
+	padding-left: 25px;
 }
 ul ul, ol ul, ul ol, ol ol {
-    margin-bottom: 0;
+	margin-bottom: 0;
 }
 dl {
-    margin-bottom: 20px;
+	margin-bottom: 20px;
 }
 dd {
-    margin-left: 0;
+	margin-left: 0;
 }
 
 nav ul {
-    list-style-type: none;
-    margin: 0;
-    padding-left: 0px;
+	list-style-type: none;
+	margin: 0;
+	padding-left: 0px;
 }
 
 /* Only display one level of hierarchy in the TOC */
 nav ul ul {
-    display: none;
+	display: none;
 }
 
 sub,
 sup {
-    font-size: 75%;
-    line-height: 0;
-    position: relative;
+	font-size: 75%;
+	line-height: 0;
+	position: relative;
 }
 
 hr {
-    margin-top: 20px;
-    margin-bottom: 20px;
-    border: 0;
-    border-top: 1px solid #eeeeee;
+	margin-top: 20px;
+	margin-bottom: 20px;
+	border: 0;
+	border-top: 1px solid #eeeeee;
 }
 
 table {
-    border-collapse: collapse;
-    border-spacing: 0;
-    overflow-x: auto;
-    display: block;
+	border-collapse: collapse;
+	border-spacing: 0;
+	overflow-x: auto;
+	display: block;
 }
 
 table tr.odd {
-    background: #eee;
+	background: #eee;
 }
 
 table td,
 table th {
-    border: 1px solid #ddd;
-    padding: 5px;
+	border: 1px solid #ddd;
+	padding: 5px;
 }
 
 /* Code snippets */
 
 pre.rust { position: relative; }
 a.test-arrow {
-    background-color: rgba(78, 139, 202, 0.2);
-    display: inline-block;
-    position: absolute;
-    color: #f5f5f5;
-    padding: 5px 10px 5px 10px;
-    border-radius: 5px;
-    font-size: 130%;
-    top: 5px;
-    right: 5px;
+	background-color: rgba(78, 139, 202, 0.2);
+	display: inline-block;
+	position: absolute;
+	color: #f5f5f5;
+	padding: 5px 10px 5px 10px;
+	border-radius: 5px;
+	font-size: 130%;
+	top: 5px;
+	right: 5px;
 }
 a.test-arrow:hover{
-    background-color: #4e8bca;
-    text-decoration: none;
+	background-color: #4e8bca;
+	text-decoration: none;
 }
 
 .unstable-feature {
-    border: 2px solid red;
-    padding: 5px;
+	border: 2px solid red;
+	padding: 5px;
 }
 
 @media (min-width: 1170px) {
-    pre {
-        font-size: 15px;
-    }
+	pre {
+		font-size: 15px;
+	}
 }
 
 @media print {
-    * {
-        text-shadow: none !important;
-        color: #000 !important;
-        background: transparent !important;
-        box-shadow: none !important;
-    }
-    a, a:visited {
-        text-decoration: underline;
-    }
-    p a[href]:after {
-        content: " (" attr(href) ")";
-    }
-    footer a[href]:after {
-        content: "";
-    }
-    a[href^="javascript:"]:after, a[href^="#"]:after {
-        content: "";
-    }
-    pre, blockquote {
-        border: 1px solid #999;
-        page-break-inside: avoid;
-    }
-    @page {
-        margin: 2cm .5cm;
-    }
-    h1:not(.title), h2, h3 {
-        border-bottom: 0px none;
-    }
-    p, h2, h3 {
-        orphans: 3;
-        widows: 3;
-    }
-    h2, h3 {
-        page-break-after: avoid;
-    }
-    table {
-        border-collapse: collapse !important;
-    }
-    table td, table th {
-        background-color: #fff !important;
-    }
+	* {
+		text-shadow: none !important;
+		color: #000 !important;
+		background: transparent !important;
+		box-shadow: none !important;
+	}
+	a, a:visited {
+		text-decoration: underline;
+	}
+	p a[href]:after {
+		content: " (" attr(href) ")";
+	}
+	footer a[href]:after {
+		content: "";
+	}
+	a[href^="javascript:"]:after, a[href^="#"]:after {
+		content: "";
+	}
+	pre, blockquote {
+		border: 1px solid #999;
+		page-break-inside: avoid;
+	}
+	@page {
+		margin: 2cm .5cm;
+	}
+	h1:not(.title), h2, h3 {
+		border-bottom: 0px none;
+	}
+	p, h2, h3 {
+		orphans: 3;
+		widows: 3;
+	}
+	h2, h3 {
+		page-break-after: avoid;
+	}
+	table {
+		border-collapse: collapse !important;
+	}
+	table td, table th {
+		background-color: #fff !important;
+	}
 }
 
 #keyword-table-marker + table thead { display: none; }
 #keyword-table-marker + table td { border: none; }
 #keyword-table-marker + table {
-    margin-left: 2em;
-    margin-bottom: 1em;
+	margin-left: 2em;
+	margin-bottom: 1em;
+}
+
+.error-described {
+	position: relative;
+}
+
+.information {
+	position: absolute;
+	left: -25px;
+	margin-top: 7px;
+	z-index: 1;
+}
+
+.tooltip {
+	position: relative;
+	display: inline-block;
+	cursor: pointer;
+}
+
+.tooltip .tooltiptext {
+	width: 120px;
+	display: none;
+	text-align: center;
+	padding: 5px 3px;
+	border-radius: 6px;
+	margin-left: 5px;
+	top: -5px;
+	left: 105%;
+	z-index: 1;
+}
+
+.tooltip:hover .tooltiptext {
+	display: inline;
+}
+
+.tooltip .tooltiptext::after {
+	content: " ";
+	position: absolute;
+	top: 50%;
+	left: 13px;
+	margin-top: -5px;
+	border-width: 5px;
+	border-style: solid;
 }
diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md
index aadd72d..2964227 100644
--- a/src/doc/rustdoc/src/the-doc-attribute.md
+++ b/src/doc/rustdoc/src/the-doc-attribute.md
@@ -1,7 +1,7 @@
 # The `#[doc]` attribute
 
 The `#[doc]` attribute lets you control various aspects of how `rustdoc` does
-its job. 
+its job.
 
 The most basic function of `#[doc]` is to handle the actual documentation
 text. That is, `///` is syntax sugar for `#[doc]`. This means that these two
@@ -143,7 +143,7 @@
 }
 ```
 
-The documentation will generate a "Reexports" section, and say `pub use bar::Bar;`, where
+The documentation will generate a "Re-exports" section, and say `pub use bar::Bar;`, where
 `Bar` is a link to its page.
 
 If we change the `use` line like this:
@@ -184,7 +184,7 @@
 }
 ```
 
-Now we'll have a `Reexports` line, and `Bar` will not link to anywhere.
+Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere.
 
 ## `#[doc(hidden)]`
 
diff --git a/src/doc/unstable-book/src/language-features/crate-in-paths.md b/src/doc/unstable-book/src/language-features/crate-in-paths.md
new file mode 100644
index 0000000..f165699
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/crate-in-paths.md
@@ -0,0 +1,54 @@
+# `crate_in_paths`
+
+The tracking issue for this feature is: [#44660]
+
+[#44660]: https://github.com/rust-lang/rust/issues/44660
+
+------------------------
+
+The `crate_in_paths` feature allows to explicitly refer to the crate root in absolute paths
+using keyword `crate`.
+
+`crate` can be used *only* in absolute paths, i.e. either in `::crate::a::b::c` form or in `use`
+items where the starting `::` is added implicitly.  
+Paths like `crate::a::b::c` are not accepted currently.
+
+This feature is required in `feature(extern_absolute_paths)` mode to refer to any absolute path
+in the local crate (absolute paths refer to extern crates by default in that mode), but can be
+used without `feature(extern_absolute_paths)` as well.
+
+```rust
+#![feature(crate_in_paths)]
+
+// Imports, `::` is added implicitly
+use crate::m::f;
+use crate as root;
+
+mod m {
+    pub fn f() -> u8 { 1 }
+    pub fn g() -> u8 { 2 }
+    pub fn h() -> u8 { 3 }
+
+    // OK, visibilities implicitly add starting `::` as well, like imports
+    pub(in crate::m) struct S;
+}
+
+mod n
+{
+    use crate::m::f;
+    use crate as root;
+    pub fn check() {
+        assert_eq!(f(), 1);
+        // `::` is required in non-import paths
+        assert_eq!(::crate::m::g(), 2);
+        assert_eq!(root::m::h(), 3);
+    }
+}
+
+fn main() {
+    assert_eq!(f(), 1);
+    assert_eq!(::crate::m::g(), 2);
+    assert_eq!(root::m::h(), 3);
+    n::check();
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/extern-absolute-paths.md b/src/doc/unstable-book/src/language-features/extern-absolute-paths.md
new file mode 100644
index 0000000..f45c505
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/extern-absolute-paths.md
@@ -0,0 +1,43 @@
+# `extern_absolute_paths`
+
+The tracking issue for this feature is: [#44660]
+
+[#44660]: https://github.com/rust-lang/rust/issues/44660
+
+------------------------
+
+The `extern_absolute_paths` feature enables mode allowing to refer to names from other crates
+"inline", without introducing `extern crate` items, using absolute paths like `::my_crate::a::b`.
+
+`::my_crate::a::b` will resolve to path `a::b` in crate `my_crate`.
+
+`feature(crate_in_paths)` can be used in `feature(extern_absolute_paths)` mode for referring
+to absolute paths in the local crate (`::crate::a::b`).
+
+`feature(extern_in_paths)` provides the same effect by using keyword `extern` to refer to
+paths from other crates (`extern::my_crate::a::b`).
+
+```rust,ignore
+#![feature(extern_absolute_paths)]
+
+// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern`
+// options, or standard Rust distribution, or some other means.
+
+use xcrate::Z;
+
+fn f() {
+    use xcrate;
+    use xcrate as ycrate;
+    let s = xcrate::S;
+    assert_eq!(format!("{:?}", s), "S");
+    let z = ycrate::Z;
+    assert_eq!(format!("{:?}", z), "Z");
+}
+
+fn main() {
+    let s = ::xcrate::S;
+    assert_eq!(format!("{:?}", s), "S");
+    let z = Z;
+    assert_eq!(format!("{:?}", z), "Z");
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/extern-in-paths.md b/src/doc/unstable-book/src/language-features/extern-in-paths.md
new file mode 100644
index 0000000..3ae6cc2
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/extern-in-paths.md
@@ -0,0 +1,40 @@
+# `extern_in_paths`
+
+The tracking issue for this feature is: [#44660]
+
+[#44660]: https://github.com/rust-lang/rust/issues/44660
+
+------------------------
+
+The `extern_in_paths` feature allows to refer to names from other crates "inline", without
+introducing `extern crate` items, using keyword `extern`.
+
+For example, `extern::my_crat::a::b` will resolve to path `a::b` in crate `my_crate`.
+
+`feature(extern_absolute_paths)` mode provides the same effect by resolving absolute paths like
+`::my_crate::a::b` to paths from extern crates by default.
+
+```rust,ignore
+#![feature(extern_in_paths)]
+
+// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern`
+// options, or standard Rust distribution, or some other means.
+
+use extern::xcrate::Z;
+
+fn f() {
+    use extern::xcrate;
+    use extern::xcrate as ycrate;
+    let s = xcrate::S;
+    assert_eq!(format!("{:?}", s), "S");
+    let z = ycrate::Z;
+    assert_eq!(format!("{:?}", z), "Z");
+}
+
+fn main() {
+    let s = extern::xcrate::S;
+    assert_eq!(format!("{:?}", s), "S");
+    let z = Z;
+    assert_eq!(format!("{:?}", z), "Z");
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md b/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md
new file mode 100644
index 0000000..5b585d7
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md
@@ -0,0 +1,14 @@
+# `macro_lifetime_matcher`
+
+The tracking issue for this feature is: [#46895]
+
+With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry:
+
+* `lifetime`: a lifetime. Examples: 'static, 'a.
+
+A `lifetime` variable may be followed by anything.
+
+[#46895]: https://github.com/rust-lang/rust/issues/46895
+[frags]: ../book/first-edition/macros.html#syntactic-requirements
+
+------------------------
diff --git a/src/doc/unstable-book/src/language-features/match_default_bindings.md b/src/doc/unstable-book/src/language-features/match-default-bindings.md
similarity index 100%
rename from src/doc/unstable-book/src/language-features/match_default_bindings.md
rename to src/doc/unstable-book/src/language-features/match-default-bindings.md
diff --git a/src/doc/unstable-book/src/language-features/repr-transparent.md b/src/doc/unstable-book/src/language-features/repr-transparent.md
new file mode 100644
index 0000000..62202dc
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/repr-transparent.md
@@ -0,0 +1,176 @@
+# `repr_transparent`
+
+The tracking issue for this feature is: [#43036]
+
+[#43036]: https://github.com/rust-lang/rust/issues/43036
+
+------------------------
+
+This feature enables the `repr(transparent)` attribute on structs, which enables
+the use of newtypes without the usual ABI implications of wrapping the value in
+a struct.
+
+## Background
+
+It's sometimes useful to add additional type safety by introducing *newtypes*.
+For example, code that handles numeric quantities in different units such as
+millimeters, centimeters, grams, kilograms, etc. may want to use the type system
+to rule out mistakes such as adding millimeters to grams:
+
+```rust
+use std::ops::Add;
+
+struct Millimeters(f64);
+struct Grams(f64);
+
+impl Add<Millimeters> for Millimeters {
+    type Output = Millimeters;
+
+    fn add(self, other: Millimeters) -> Millimeters {
+        Millimeters(self.0 + other.0)
+    }
+}
+
+// Likewise: impl Add<Grams> for Grams {}
+```
+
+Other uses of newtypes include using `PhantomData` to add lifetimes to raw
+pointers or to implement the "phantom types" pattern. See the [PhantomData]
+documentation and [the Nomicon][nomicon-phantom] for more details.
+
+The added type safety is especially useful when interacting with C or other
+languages. However, in those cases we need to ensure the newtypes we add do not
+introduce incompatibilities with the C ABI.
+
+## Newtypes in FFI
+
+Luckily, `repr(C)` newtypes are laid out just like the type they wrap on all
+platforms which Rust currently supports, and likely on many more. For example,
+consider this C declaration:
+
+```C
+struct Object {
+    double weight; //< in grams
+    double height; //< in millimeters
+    // ...
+}
+
+void frobnicate(struct Object *);
+```
+
+While using this C code from Rust, we could add `repr(C)` to the `Grams` and
+`Millimeters` newtypes introduced above and use them to add some type safety
+while staying compatible with the memory layout of `Object`:
+
+```rust,no_run
+#[repr(C)]
+struct Grams(f64);
+
+#[repr(C)]
+struct Millimeters(f64);
+
+#[repr(C)]
+struct Object {
+    weight: Grams,
+    height: Millimeters,
+    // ...
+}
+
+extern {
+    fn frobnicate(_: *mut Object);
+}
+```
+
+This works even when adding some `PhantomData` fields, because they are
+zero-sized and therefore don't have to affect the memory layout.
+
+However, there's more to the ABI than just memory layout: there's also the
+question of how function call arguments and return values are passed. Many
+common ABI treat a struct containing a single field differently from that field
+itself, at least when the field is a scalar (e.g., integer or float or pointer).
+
+To continue the above example, suppose the C library also exposes a function
+like this:
+
+```C
+double calculate_weight(double height);
+```
+
+Using our newtypes on the Rust side like this will cause an ABI mismatch on many
+platforms:
+
+```rust,ignore
+extern {
+    fn calculate_weight(height: Millimeters) -> Grams;
+}
+```
+
+For example, on x86_64 Linux, Rust will pass the argument in an integer
+register, while the C function expects the argument to be in a floating-point
+register. Likewise, the C function will return the result in a floating-point
+register while Rust will expect it in an integer register.
+
+Note that this problem is not specific to floats: To give another example,
+32-bit x86 linux will pass and return `struct Foo(i32);` on the stack while
+`i32` is placed in registers.
+
+## Enter `repr(transparent)`
+
+So while `repr(C)` happens to do the right thing with respect to memory layout,
+it's not quite the right tool for newtypes in FFI. Instead of declaring a C
+struct, we need to communicate to the Rust compiler that our newtype is just for
+type safety on the Rust side. This is what `repr(transparent)` does.
+
+The attribute can be applied to a newtype-like structs that contains a single
+field. It indicates that the newtype should be represented exactly like that
+field's type, i.e., the newtype should be ignored for ABI purpopses: not only is
+it laid out the same in memory, it is also passed identically in function calls.
+
+In the above example, the ABI mismatches can be prevented by making the newtypes
+`Grams` and `Millimeters` transparent like this:
+
+```rust
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Grams(f64);
+
+#[repr(transparent)]
+struct Millimeters(f64);
+```
+
+In addition to that single field, any number of zero-sized fields are permitted,
+including but not limited to `PhantomData`:
+
+```rust
+#![feature(repr_transparent)]
+
+use std::marker::PhantomData;
+
+struct Foo { /* ... */ }
+
+#[repr(transparent)]
+struct FooPtrWithLifetime<'a>(*const Foo, PhantomData<&'a Foo>);
+
+#[repr(transparent)]
+struct NumberWithUnit<T, U>(T, PhantomData<U>);
+
+struct CustomZst;
+
+#[repr(transparent)]
+struct PtrWithCustomZst<'a> {
+    ptr: FooPtrWithLifetime<'a>,
+    some_marker: CustomZst,
+}
+```
+
+Transparent structs can be nested: `PtrWithCustomZst` is also represented
+exactly like `*const Foo`.
+
+Because `repr(transparent)` delegates all representation concerns to another
+type, it is incompatible with all other `repr(..)` attributes. It also cannot be
+applied to enums, unions, empty structs, structs whose fields are all
+zero-sized, or structs with *multiple* non-zero-sized fields.
+
+[PhantomData]: https://doc.rust-lang.org/std/marker/struct.PhantomData.html
+[nomicon-phantom]: https://doc.rust-lang.org/nomicon/phantom-data.html
diff --git a/src/doc/unstable-book/src/library-features/proc-macro.md b/src/doc/unstable-book/src/library-features/proc-macro.md
deleted file mode 100644
index 19e7f66..0000000
--- a/src/doc/unstable-book/src/library-features/proc-macro.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# `proc_macro`
-
-The tracking issue for this feature is: [#38356]
-
-[#38356]: https://github.com/rust-lang/rust/issues/38356
-
-------------------------
diff --git a/src/etc/platform-intrinsics/x86/avx2.json b/src/etc/platform-intrinsics/x86/avx2.json
index 4e006c1..dc055b5 100644
--- a/src/etc/platform-intrinsics/x86/avx2.json
+++ b/src/etc/platform-intrinsics/x86/avx2.json
@@ -174,7 +174,7 @@
             "intrinsic": "256_sad_epu8",
             "width": [256],
             "llvm": "psad.bw",
-            "ret": "u8",
+            "ret": "u64",
             "args": ["0", "0"]
         },
         {
diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs
index c2a8f5f..55e8c0b 100644
--- a/src/liballoc/allocator.rs
+++ b/src/liballoc/allocator.rs
@@ -19,7 +19,7 @@
 use core::fmt;
 use core::mem;
 use core::usize;
-use core::ptr::{self, Unique};
+use core::ptr::{self, NonNull};
 
 /// Represents the combination of a starting address and
 /// a total capacity of the returned block.
@@ -895,12 +895,12 @@
     /// Clients wishing to abort computation in response to an
     /// allocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
-    fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
+    fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
         let k = Layout::new::<T>();
         if k.size() > 0 {
-            unsafe { self.alloc(k).map(|p| Unique::new_unchecked(p as *mut T)) }
+            unsafe { self.alloc(k).map(|p| NonNull::new_unchecked(p as *mut T)) }
         } else {
             Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
         }
@@ -923,7 +923,7 @@
     /// * `ptr` must denote a block of memory currently allocated via this allocator
     ///
     /// * the layout of `T` must *fit* that block of memory.
-    unsafe fn dealloc_one<T>(&mut self, ptr: Unique<T>)
+    unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
         where Self: Sized
     {
         let raw_ptr = ptr.as_ptr() as *mut u8;
@@ -963,7 +963,7 @@
     /// Clients wishing to abort computation in response to an
     /// allocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
-    fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>
+    fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
         match Layout::array::<T>(n) {
@@ -971,7 +971,7 @@
                 unsafe {
                     self.alloc(layout.clone())
                         .map(|p| {
-                            Unique::new_unchecked(p as *mut T)
+                            NonNull::new_unchecked(p as *mut T)
                         })
                 }
             }
@@ -1012,15 +1012,15 @@
     /// reallocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
     unsafe fn realloc_array<T>(&mut self,
-                               ptr: Unique<T>,
+                               ptr: NonNull<T>,
                                n_old: usize,
-                               n_new: usize) -> Result<Unique<T>, AllocErr>
+                               n_new: usize) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
         match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
             (Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
                 self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
-                    .map(|p|Unique::new_unchecked(p as *mut T))
+                    .map(|p| NonNull::new_unchecked(p as *mut T))
             }
             _ => {
                 Err(AllocErr::invalid_input("invalid layout for realloc_array"))
@@ -1048,7 +1048,7 @@
     /// constraints.
     ///
     /// Always returns `Err` on arithmetic overflow.
-    unsafe fn dealloc_array<T>(&mut self, ptr: Unique<T>, n: usize) -> Result<(), AllocErr>
+    unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr>
         where Self: Sized
     {
         let raw_ptr = ptr.as_ptr() as *mut u8;
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 844b708..6a77bf6 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -25,7 +25,7 @@
 use core::mem::{self, align_of_val, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
 use core::marker::{Unsize, PhantomData};
 use core::hash::{Hash, Hasher};
 use core::{isize, usize};
@@ -197,7 +197,7 @@
 /// [rc_examples]: ../../std/rc/index.html#examples
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Arc<T: ?Sized> {
-    ptr: Shared<ArcInner<T>>,
+    ptr: NonNull<ArcInner<T>>,
     phantom: PhantomData<T>,
 }
 
@@ -234,7 +234,7 @@
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "arc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
-    ptr: Shared<ArcInner<T>>,
+    ptr: NonNull<ArcInner<T>>,
 }
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
@@ -286,7 +286,7 @@
             weak: atomic::AtomicUsize::new(1),
             data,
         };
-        Arc { ptr: Shared::from(Box::into_unique(x)), phantom: PhantomData }
+        Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData }
     }
 
     /// Returns the contained value, if the `Arc` has exactly one strong reference.
@@ -397,7 +397,7 @@
         let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
 
         Arc {
-            ptr: Shared::new_unchecked(arc_ptr),
+            ptr: NonNull::new_unchecked(arc_ptr),
             phantom: PhantomData,
         }
     }
@@ -582,7 +582,7 @@
             // Free the allocation without dropping its contents
             box_free(bptr);
 
-            Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -609,7 +609,7 @@
             &mut (*ptr).data as *mut [T] as *mut T,
             v.len());
 
-        Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+        Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
     }
 }
 
@@ -669,7 +669,7 @@
             // All clear. Forget the guard so it doesn't free the new ArcInner.
             mem::forget(guard);
 
-            Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -991,11 +991,11 @@
     pub fn new() -> Weak<T> {
         unsafe {
             Weak {
-                ptr: Shared::from(Box::into_unique(box ArcInner {
+                ptr: Box::into_raw_non_null(box ArcInner {
                     strong: atomic::AtomicUsize::new(0),
                     weak: atomic::AtomicUsize::new(1),
                     data: uninitialized(),
-                })),
+                }),
             }
         }
     }
@@ -1377,7 +1377,8 @@
 impl<'a> From<&'a str> for Arc<str> {
     #[inline]
     fn from(v: &str) -> Arc<str> {
-        unsafe { mem::transmute(<Arc<[u8]>>::from(v.as_bytes())) }
+        let arc = Arc::<[u8]>::from(v.as_bytes());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const str) }
     }
 }
 
diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs
index 17538d8..ee5182a 100644
--- a/src/liballoc/benches/slice.rs
+++ b/src/liballoc/benches/slice.rs
@@ -343,7 +343,7 @@
         fn $name(b: &mut Bencher) {
             let size = mem::size_of_val(&$gen(1)[0]);
             let mut v = $gen($len * 8 / size);
-            b.iter(|| black_box(&mut v).rotate(($mid*8+size-1)/size));
+            b.iter(|| black_box(&mut v).rotate_left(($mid*8+size-1)/size));
             b.bytes = (v.len() * size) as u64;
         }
     }
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 6f125cd..bfe23dd 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -68,7 +68,7 @@
 use core::mem;
 use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
 use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
-use core::ptr::{self, Unique};
+use core::ptr::{self, NonNull, Unique};
 use core::convert::From;
 use str::from_boxed_utf8_unchecked;
 
@@ -269,38 +269,7 @@
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
-        Box::from_unique(Unique::new_unchecked(raw))
-    }
-
-    /// Constructs a `Box` from a `Unique<T>` pointer.
-    ///
-    /// After calling this function, the memory is owned by a `Box` and `T` can
-    /// then be destroyed and released upon drop.
-    ///
-    /// # Safety
-    ///
-    /// A `Unique<T>` can be safely created via [`Unique::new`] and thus doesn't
-    /// necessarily own the data pointed to nor is the data guaranteed to live
-    /// as long as the pointer.
-    ///
-    /// [`Unique::new`]: ../../core/ptr/struct.Unique.html#method.new
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(unique)]
-    ///
-    /// fn main() {
-    ///     let x = Box::new(5);
-    ///     let ptr = Box::into_unique(x);
-    ///     let x = unsafe { Box::from_unique(ptr) };
-    /// }
-    /// ```
-    #[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
-               issue = "27730")]
-    #[inline]
-    pub unsafe fn from_unique(u: Unique<T>) -> Self {
-        Box(u)
+        Box(Unique::new_unchecked(raw))
     }
 
     /// Consumes the `Box`, returning the wrapped raw pointer.
@@ -326,40 +295,42 @@
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub fn into_raw(b: Box<T>) -> *mut T {
-        Box::into_unique(b).as_ptr()
+        Box::into_raw_non_null(b).as_ptr()
     }
 
-    /// Consumes the `Box`, returning the wrapped pointer as `Unique<T>`.
+    /// Consumes the `Box`, returning the wrapped pointer as `NonNull<T>`.
     ///
     /// After calling this function, the caller is responsible for the
     /// memory previously managed by the `Box`. In particular, the
     /// caller should properly destroy `T` and release the memory. The
-    /// proper way to do so is to either convert the `Unique<T>` pointer:
-    ///
-    /// - Into a `Box` with the [`Box::from_unique`] function.
-    ///
-    /// - Into a raw pointer and back into a `Box` with the [`Box::from_raw`]
-    ///   function.
+    /// proper way to do so is to convert the `NonNull<T>` pointer
+    /// into a raw pointer and back into a `Box` with the [`Box::from_raw`]
+    /// function.
     ///
     /// Note: this is an associated function, which means that you have
-    /// to call it as `Box::into_unique(b)` instead of `b.into_unique()`. This
+    /// to call it as `Box::into_raw_non_null(b)`
+    /// instead of `b.into_raw_non_null()`. This
     /// is so that there is no conflict with a method on the inner type.
     ///
-    /// [`Box::from_unique`]: struct.Box.html#method.from_unique
     /// [`Box::from_raw`]: struct.Box.html#method.from_raw
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(unique)]
+    /// #![feature(box_into_raw_non_null)]
     ///
     /// fn main() {
     ///     let x = Box::new(5);
-    ///     let ptr = Box::into_unique(x);
+    ///     let ptr = Box::into_raw_non_null(x);
     /// }
     /// ```
-    #[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
-               issue = "27730")]
+    #[unstable(feature = "box_into_raw_non_null", issue = "47336")]
+    #[inline]
+    pub fn into_raw_non_null(b: Box<T>) -> NonNull<T> {
+        Box::into_unique(b).into()
+    }
+
+    #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
     #[inline]
     pub fn into_unique(b: Box<T>) -> Unique<T> {
         let unique = b.0;
diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs
index 580d2dbb..327eaaf4 100644
--- a/src/liballoc/btree/set.rs
+++ b/src/liballoc/btree/set.rs
@@ -228,43 +228,7 @@
     pub fn new() -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::new() }
     }
-}
 
-impl<T> BTreeSet<T> {
-    /// Gets an iterator that visits the values in the `BTreeSet` in ascending order.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::BTreeSet;
-    ///
-    /// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
-    /// let mut set_iter = set.iter();
-    /// assert_eq!(set_iter.next(), Some(&1));
-    /// assert_eq!(set_iter.next(), Some(&2));
-    /// assert_eq!(set_iter.next(), Some(&3));
-    /// assert_eq!(set_iter.next(), None);
-    /// ```
-    ///
-    /// Values returned by the iterator are returned in ascending order:
-    ///
-    /// ```
-    /// use std::collections::BTreeSet;
-    ///
-    /// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
-    /// let mut set_iter = set.iter();
-    /// assert_eq!(set_iter.next(), Some(&1));
-    /// assert_eq!(set_iter.next(), Some(&2));
-    /// assert_eq!(set_iter.next(), Some(&3));
-    /// assert_eq!(set_iter.next(), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter<T> {
-        Iter { iter: self.map.keys() }
-    }
-}
-
-impl<T: Ord> BTreeSet<T> {
     /// Constructs a double-ended iterator over a sub-range of elements in the set.
     /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will
     /// yield elements from min (inclusive) to max (exclusive).
@@ -293,9 +257,7 @@
     {
         Range { iter: self.map.range(range) }
     }
-}
 
-impl<T: Ord> BTreeSet<T> {
     /// Visits the values representing the difference,
     /// i.e. the values that are in `self` but not in `other`,
     /// in ascending order.
@@ -408,40 +370,6 @@
         }
     }
 
-    /// Returns the number of elements in the set.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::BTreeSet;
-    ///
-    /// let mut v = BTreeSet::new();
-    /// assert_eq!(v.len(), 0);
-    /// v.insert(1);
-    /// assert_eq!(v.len(), 1);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn len(&self) -> usize {
-        self.map.len()
-    }
-
-    /// Returns `true` if the set contains no elements.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::BTreeSet;
-    ///
-    /// let mut v = BTreeSet::new();
-    /// assert!(v.is_empty());
-    /// v.insert(1);
-    /// assert!(!v.is_empty());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
     /// Clears the set, removing all values.
     ///
     /// # Examples
@@ -487,6 +415,16 @@
     /// The value may be any borrowed form of the set's value type,
     /// but the ordering on the borrowed form *must* match the
     /// ordering on the value type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+    /// assert_eq!(set.get(&2), Some(&2));
+    /// assert_eq!(set.get(&4), None);
+    /// ```
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
         where T: Borrow<Q>,
@@ -612,6 +550,19 @@
 
     /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
     /// one. Returns the replaced value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set = BTreeSet::new();
+    /// set.insert(Vec::<i32>::new());
+    ///
+    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0);
+    /// set.replace(Vec::with_capacity(10));
+    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
+    /// ```
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn replace(&mut self, value: T) -> Option<T> {
         Recover::replace(&mut self.map, value)
@@ -648,6 +599,16 @@
     /// The value may be any borrowed form of the set's value type,
     /// but the ordering on the borrowed form *must* match the
     /// ordering on the value type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+    /// assert_eq!(set.take(&2), Some(2));
+    /// assert_eq!(set.take(&2), None);
+    /// ```
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
         where T: Borrow<Q>,
@@ -697,26 +658,26 @@
     /// Basic usage:
     ///
     /// ```
-    /// use std::collections::BTreeMap;
+    /// use std::collections::BTreeSet;
     ///
-    /// let mut a = BTreeMap::new();
-    /// a.insert(1, "a");
-    /// a.insert(2, "b");
-    /// a.insert(3, "c");
-    /// a.insert(17, "d");
-    /// a.insert(41, "e");
+    /// let mut a = BTreeSet::new();
+    /// a.insert(1);
+    /// a.insert(2);
+    /// a.insert(3);
+    /// a.insert(17);
+    /// a.insert(41);
     ///
     /// let b = a.split_off(&3);
     ///
     /// assert_eq!(a.len(), 2);
     /// assert_eq!(b.len(), 3);
     ///
-    /// assert_eq!(a[&1], "a");
-    /// assert_eq!(a[&2], "b");
+    /// assert!(a.contains(&1));
+    /// assert!(a.contains(&2));
     ///
-    /// assert_eq!(b[&3], "c");
-    /// assert_eq!(b[&17], "d");
-    /// assert_eq!(b[&41], "e");
+    /// assert!(b.contains(&3));
+    /// assert!(b.contains(&17));
+    /// assert!(b.contains(&41));
     /// ```
     #[stable(feature = "btree_split_off", since = "1.11.0")]
     pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self where T: Borrow<Q> {
@@ -724,6 +685,74 @@
     }
 }
 
+impl<T> BTreeSet<T> {
+    /// Gets an iterator that visits the values in the `BTreeSet` in ascending order.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
+    /// let mut set_iter = set.iter();
+    /// assert_eq!(set_iter.next(), Some(&1));
+    /// assert_eq!(set_iter.next(), Some(&2));
+    /// assert_eq!(set_iter.next(), Some(&3));
+    /// assert_eq!(set_iter.next(), None);
+    /// ```
+    ///
+    /// Values returned by the iterator are returned in ascending order:
+    ///
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
+    /// let mut set_iter = set.iter();
+    /// assert_eq!(set_iter.next(), Some(&1));
+    /// assert_eq!(set_iter.next(), Some(&2));
+    /// assert_eq!(set_iter.next(), Some(&3));
+    /// assert_eq!(set_iter.next(), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn iter(&self) -> Iter<T> {
+        Iter { iter: self.map.keys() }
+    }
+
+    /// Returns the number of elements in the set.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut v = BTreeSet::new();
+    /// assert_eq!(v.len(), 0);
+    /// v.insert(1);
+    /// assert_eq!(v.len(), 1);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn len(&self) -> usize {
+        self.map.len()
+    }
+
+    /// Returns `true` if the set contains no elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut v = BTreeSet::new();
+    /// assert!(v.is_empty());
+    /// v.insert(1);
+    /// assert!(!v.is_empty());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> FromIterator<T> for BTreeSet<T> {
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index b2bd9d7..37af9ea 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -232,7 +232,7 @@
 ///
 /// This preserves the non-null invariant for types like `Box<T>`. The address
 /// may overlap with non-zero-size memory allocations.
-#[rustc_deprecated(since = "1.19", reason = "Use Unique/Shared::empty() instead")]
+#[rustc_deprecated(since = "1.19", reason = "Use Unique/NonNull::empty() instead")]
 #[unstable(feature = "heap_api", issue = "27700")]
 pub const EMPTY: *mut () = 1 as *mut ();
 
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 3cc3ea4..5139e54 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -15,7 +15,7 @@
 //!
 //! This library, like libcore, is not intended for general usage, but rather as
 //! a building block of other libraries. The types and interfaces in this
-//! library are reexported through the [standard library](../std/index.html),
+//! library are re-exported through the [standard library](../std/index.html),
 //! and should not be used through this library.
 //!
 //! ## Boxed values
@@ -52,7 +52,7 @@
 //! ## Collections
 //!
 //! Implementations of the most common general purpose data structures are
-//! defined in this library. They are reexported through the
+//! defined in this library. They are re-exported through the
 //! [standard collections library](../std/collections/index.html).
 //!
 //! ## Heap interfaces
@@ -84,6 +84,7 @@
 #![cfg_attr(test, feature(rand, test))]
 #![feature(allow_internal_unstable)]
 #![feature(ascii_ctype)]
+#![feature(box_into_raw_non_null)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
@@ -109,8 +110,8 @@
 #![feature(pattern)]
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
+#![feature(ptr_internals)]
 #![feature(rustc_attrs)]
-#![feature(shared)]
 #![feature(slice_get_slice)]
 #![feature(slice_patterns)]
 #![feature(slice_rsplit)]
@@ -120,10 +121,10 @@
 #![feature(trusted_len)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unique)]
 #![feature(unsize)]
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
+#![feature(exact_chunks)]
 
 #![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
 #![cfg_attr(test, feature(test, box_heap))]
diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs
index 3ac5a85..3cc810a 100644
--- a/src/liballoc/linked_list.rs
+++ b/src/liballoc/linked_list.rs
@@ -29,7 +29,7 @@
 use core::marker::PhantomData;
 use core::mem;
 use core::ops::{BoxPlace, InPlace, Place, Placer};
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
 
 use boxed::{Box, IntermediateBox};
 use super::SpecExtend;
@@ -44,15 +44,15 @@
 /// more memory efficient and make better use of CPU cache.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LinkedList<T> {
-    head: Option<Shared<Node<T>>>,
-    tail: Option<Shared<Node<T>>>,
+    head: Option<NonNull<Node<T>>>,
+    tail: Option<NonNull<Node<T>>>,
     len: usize,
     marker: PhantomData<Box<Node<T>>>,
 }
 
 struct Node<T> {
-    next: Option<Shared<Node<T>>>,
-    prev: Option<Shared<Node<T>>>,
+    next: Option<NonNull<Node<T>>>,
+    prev: Option<NonNull<Node<T>>>,
     element: T,
 }
 
@@ -65,8 +65,8 @@
 /// [`LinkedList`]: struct.LinkedList.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
-    head: Option<Shared<Node<T>>>,
-    tail: Option<Shared<Node<T>>>,
+    head: Option<NonNull<Node<T>>>,
+    tail: Option<NonNull<Node<T>>>,
     len: usize,
     marker: PhantomData<&'a Node<T>>,
 }
@@ -98,8 +98,8 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     list: &'a mut LinkedList<T>,
-    head: Option<Shared<Node<T>>>,
-    tail: Option<Shared<Node<T>>>,
+    head: Option<NonNull<Node<T>>>,
+    tail: Option<NonNull<Node<T>>>,
     len: usize,
 }
 
@@ -157,7 +157,7 @@
         unsafe {
             node.next = self.head;
             node.prev = None;
-            let node = Some(Shared::from(Box::into_unique(node)));
+            let node = Some(Box::into_raw_non_null(node));
 
             match self.head {
                 None => self.tail = node,
@@ -192,7 +192,7 @@
         unsafe {
             node.next = None;
             node.prev = self.tail;
-            let node = Some(Shared::from(Box::into_unique(node)));
+            let node = Some(Box::into_raw_non_null(node));
 
             match self.tail {
                 None => self.head = node,
@@ -225,7 +225,7 @@
     ///
     /// Warning: this will not check that the provided node belongs to the current list.
     #[inline]
-    unsafe fn unlink_node(&mut self, mut node: Shared<Node<T>>) {
+    unsafe fn unlink_node(&mut self, mut node: NonNull<Node<T>>) {
         let node = node.as_mut();
 
         match node.prev {
@@ -986,11 +986,11 @@
                     Some(prev) => prev,
                 };
 
-                let node = Some(Shared::from(Box::into_unique(box Node {
+                let node = Some(Box::into_raw_non_null(box Node {
                     next: Some(head),
                     prev: Some(prev),
                     element,
-                })));
+                }));
 
                 prev.as_mut().next = node;
                 head.as_mut().prev = node;
@@ -1038,7 +1038,7 @@
     where F: FnMut(&mut T) -> bool,
 {
     list: &'a mut LinkedList<T>,
-    it: Option<Shared<Node<T>>>,
+    it: Option<NonNull<Node<T>>>,
     pred: F,
     idx: usize,
     old_len: usize,
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index dbf1fb1..621e190 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -322,7 +322,7 @@
                     // would cause overflow
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
-                        Ok(ptr) => (new_cap, ptr),
+                        Ok(ptr) => (new_cap, ptr.into()),
                         Err(e) => self.a.oom(e),
                     }
                 }
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 358b593..1fa5d34 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -256,7 +256,7 @@
 use core::mem::{self, align_of_val, forget, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
 use core::convert::From;
 
 use heap::{Heap, Alloc, Layout, box_free};
@@ -282,7 +282,7 @@
 /// [get_mut]: #method.get_mut
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T: ?Sized> {
-    ptr: Shared<RcBox<T>>,
+    ptr: NonNull<RcBox<T>>,
     phantom: PhantomData<T>,
 }
 
@@ -311,11 +311,11 @@
             // pointers, which ensures that the weak destructor never frees
             // the allocation while the strong destructor is running, even
             // if the weak pointer is stored inside the strong one.
-            ptr: Shared::from(Box::into_unique(box RcBox {
+            ptr: Box::into_raw_non_null(box RcBox {
                 strong: Cell::new(1),
                 weak: Cell::new(1),
                 value,
-            })),
+            }),
             phantom: PhantomData,
         }
     }
@@ -428,7 +428,7 @@
         let rc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
 
         Rc {
-            ptr: Shared::new_unchecked(rc_ptr),
+            ptr: NonNull::new_unchecked(rc_ptr),
             phantom: PhantomData,
         }
     }
@@ -649,7 +649,7 @@
                 let raw: *const RcBox<Any> = self.ptr.as_ptr();
                 forget(self);
                 Ok(Rc {
-                    ptr: Shared::new_unchecked(raw as *const RcBox<T> as *mut _),
+                    ptr: NonNull::new_unchecked(raw as *const RcBox<T> as *mut _),
                     phantom: PhantomData,
                 })
             }
@@ -695,7 +695,7 @@
             // Free the allocation without dropping its contents
             box_free(bptr);
 
-            Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -722,7 +722,7 @@
             &mut (*ptr).value as *mut [T] as *mut T,
             v.len());
 
-        Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+        Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
     }
 }
 
@@ -781,7 +781,7 @@
             // All clear. Forget the guard so it doesn't free the new RcBox.
             forget(guard);
 
-            Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -1099,7 +1099,8 @@
 impl<'a> From<&'a str> for Rc<str> {
     #[inline]
     fn from(v: &str) -> Rc<str> {
-        unsafe { mem::transmute(<Rc<[u8]>>::from(v.as_bytes())) }
+        let rc = Rc::<[u8]>::from(v.as_bytes());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const str) }
     }
 }
 
@@ -1159,7 +1160,7 @@
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "rc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
-    ptr: Shared<RcBox<T>>,
+    ptr: NonNull<RcBox<T>>,
 }
 
 #[stable(feature = "rc_weak", since = "1.4.0")]
@@ -1189,11 +1190,11 @@
     pub fn new() -> Weak<T> {
         unsafe {
             Weak {
-                ptr: Shared::from(Box::into_unique(box RcBox {
+                ptr: Box::into_raw_non_null(box RcBox {
                     strong: Cell::new(0),
                     weak: Cell::new(1),
                     value: uninitialized(),
-                })),
+                }),
             }
         }
     }
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 18bb13d..028983d 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -123,6 +123,8 @@
 pub use core::slice::{from_ref, from_ref_mut};
 #[unstable(feature = "slice_get_slice", issue = "35729")]
 pub use core::slice::SliceIndex;
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub use core::slice::{ExactChunks, ExactChunksMut};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Basic slice extension methods
@@ -606,14 +608,17 @@
         core_slice::SliceExt::windows(self, size)
     }
 
-    /// Returns an iterator over `size` elements of the slice at a
-    /// time. The chunks are slices and do not overlap. If `size` does
+    /// Returns an iterator over `chunk_size` elements of the slice at a
+    /// time. The chunks are slices and do not overlap. If `chunk_size` does
     /// not divide the length of the slice, then the last chunk will
-    /// not have length `size`.
+    /// not have length `chunk_size`.
+    ///
+    /// See [`exact_chunks`] for a variant of this iterator that returns chunks
+    /// of always exactly `chunk_size` elements.
     ///
     /// # Panics
     ///
-    /// Panics if `size` is 0.
+    /// Panics if `chunk_size` is 0.
     ///
     /// # Examples
     ///
@@ -625,10 +630,44 @@
     /// assert_eq!(iter.next().unwrap(), &['m']);
     /// assert!(iter.next().is_none());
     /// ```
+    ///
+    /// [`exact_chunks`]: #method.exact_chunks
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn chunks(&self, size: usize) -> Chunks<T> {
-        core_slice::SliceExt::chunks(self, size)
+    pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
+        core_slice::SliceExt::chunks(self, chunk_size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a
+    /// time. The chunks are slices and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last up to `chunk_size-1`
+    /// elements will be omitted.
+    ///
+    /// Due to each chunk having exactly `chunk_size` elements, the compiler
+    /// can often optimize the resulting code better than in the case of
+    /// [`chunks`].
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(exact_chunks)]
+    ///
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.exact_chunks(2);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// [`chunks`]: #method.chunks
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    #[inline]
+    pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+        core_slice::SliceExt::exact_chunks(self, chunk_size)
     }
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
@@ -636,6 +675,9 @@
     /// not divide the length of the slice, then the last chunk will not
     /// have length `chunk_size`.
     ///
+    /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
+    /// of always exactly `chunk_size` elements.
+    ///
     /// # Panics
     ///
     /// Panics if `chunk_size` is 0.
@@ -654,12 +696,52 @@
     /// }
     /// assert_eq!(v, &[1, 1, 2, 2, 3]);
     /// ```
+    ///
+    /// [`exact_chunks_mut`]: #method.exact_chunks_mut
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
         core_slice::SliceExt::chunks_mut(self, chunk_size)
     }
 
+    /// Returns an iterator over `chunk_size` elements of the slice at a time.
+    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last up to `chunk_size-1`
+    /// elements will be omitted.
+    ///
+    ///
+    /// Due to each chunk having exactly `chunk_size` elements, the compiler
+    /// can often optimize the resulting code better than in the case of
+    /// [`chunks_mut`].
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(exact_chunks)]
+    ///
+    /// let v = &mut [0, 0, 0, 0, 0];
+    /// let mut count = 1;
+    ///
+    /// for chunk in v.exact_chunks_mut(2) {
+    ///     for elem in chunk.iter_mut() {
+    ///         *elem += count;
+    ///     }
+    ///     count += 1;
+    /// }
+    /// assert_eq!(v, &[1, 1, 2, 2, 0]);
+    /// ```
+    ///
+    /// [`chunks_mut`]: #method.chunks_mut
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    #[inline]
+    pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+        core_slice::SliceExt::exact_chunks_mut(self, chunk_size)
+    }
+
     /// Divides one slice into two at an index.
     ///
     /// The first will contain all indices from `[0, mid)` (excluding
@@ -699,7 +781,7 @@
         core_slice::SliceExt::split_at(self, mid)
     }
 
-    /// Divides one `&mut` into two at an index.
+    /// Divides one mutable slice into two at an index.
     ///
     /// The first will contain all indices from `[0, mid)` (excluding
     /// the index `mid` itself) and the second will contain all
@@ -1360,24 +1442,16 @@
         core_slice::SliceExt::sort_unstable_by_key(self, f);
     }
 
-    /// Permutes the slice in-place such that `self[mid..]` moves to the
-    /// beginning of the slice while `self[..mid]` moves to the end of the
-    /// slice.  Equivalently, rotates the slice `mid` places to the left
-    /// or `k = self.len() - mid` places to the right.
-    ///
-    /// This is a "k-rotation", a permutation in which item `i` moves to
-    /// position `i + k`, modulo the length of the slice.  See _Elements
-    /// of Programming_ [§10.4][eop].
-    ///
-    /// Rotation by `mid` and rotation by `k` are inverse operations.
-    ///
-    /// [eop]: https://books.google.com/books?id=CO9ULZGINlsC&pg=PA178&q=k-rotation
+    /// Rotates the slice in-place such that the first `mid` elements of the
+    /// slice move to the end while the last `self.len() - mid` elements move to
+    /// the front. After calling `rotate_left`, the element previously at index
+    /// `mid` will become the first element in the slice.
     ///
     /// # Panics
     ///
     /// This function will panic if `mid` is greater than the length of the
-    /// slice.  (Note that `mid == self.len()` does _not_ panic; it's a nop
-    /// rotation with `k == 0`, the inverse of a rotation with `mid == 0`.)
+    /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op
+    /// rotation.
     ///
     /// # Complexity
     ///
@@ -1388,31 +1462,68 @@
     /// ```
     /// #![feature(slice_rotate)]
     ///
-    /// let mut a = [1, 2, 3, 4, 5, 6, 7];
-    /// let mid = 2;
-    /// a.rotate(mid);
-    /// assert_eq!(&a, &[3, 4, 5, 6, 7, 1, 2]);
-    /// let k = a.len() - mid;
-    /// a.rotate(k);
-    /// assert_eq!(&a, &[1, 2, 3, 4, 5, 6, 7]);
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a.rotate_left(2);
+    /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
+    /// ```
     ///
-    /// use std::ops::Range;
-    /// fn slide<T>(slice: &mut [T], range: Range<usize>, to: usize) {
-    ///     if to < range.start {
-    ///         slice[to..range.end].rotate(range.start-to);
-    ///     } else if to > range.end {
-    ///         slice[range.start..to].rotate(range.end-range.start);
-    ///     }
-    /// }
-    /// let mut v: Vec<_> = (0..10).collect();
-    /// slide(&mut v, 1..4, 7);
-    /// assert_eq!(&v, &[0, 4, 5, 6, 1, 2, 3, 7, 8, 9]);
-    /// slide(&mut v, 6..8, 1);
-    /// assert_eq!(&v, &[0, 3, 7, 4, 5, 6, 1, 2, 8, 9]);
+    /// Rotating a subslice:
+    ///
+    /// ```
+    /// #![feature(slice_rotate)]
+    ///
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a[1..5].rotate_left(1);
+    /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
     /// ```
     #[unstable(feature = "slice_rotate", issue = "41891")]
+    pub fn rotate_left(&mut self, mid: usize) {
+        core_slice::SliceExt::rotate_left(self, mid);
+    }
+
+    #[unstable(feature = "slice_rotate", issue = "41891")]
+    #[rustc_deprecated(since = "", reason = "renamed to `rotate_left`")]
     pub fn rotate(&mut self, mid: usize) {
-        core_slice::SliceExt::rotate(self, mid);
+        core_slice::SliceExt::rotate_left(self, mid);
+    }
+
+    /// Rotates the slice in-place such that the first `self.len() - k`
+    /// elements of the slice move to the end while the last `k` elements move
+    /// to the front. After calling `rotate_right`, the element previously at
+    /// index `self.len() - k` will become the first element in the slice.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `k` is greater than the length of the
+    /// slice. Note that `k == self.len()` does _not_ panic and is a no-op
+    /// rotation.
+    ///
+    /// # Complexity
+    ///
+    /// Takes linear (in `self.len()`) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_rotate)]
+    ///
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a.rotate_right(2);
+    /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
+    /// ```
+    ///
+    /// Rotate a subslice:
+    ///
+    /// ```
+    /// #![feature(slice_rotate)]
+    ///
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a[1..5].rotate_right(1);
+    /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
+    /// ```
+    #[unstable(feature = "slice_rotate", issue = "41891")]
+    pub fn rotate_right(&mut self, k: usize) {
+        core_slice::SliceExt::rotate_right(self, k);
     }
 
     /// Copies the elements from `src` into `self`.
@@ -1595,6 +1706,7 @@
     /// let x = s.to_vec();
     /// // Here, `s` and `x` can be modified independently.
     /// ```
+    #[rustc_conversion_suggestion]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_vec(&self) -> Vec<T>
@@ -1725,6 +1837,14 @@
            reason = "trait should not have to exist",
            issue = "27747")]
 /// An extension trait for concatenating slices
+///
+/// While this trait is unstable, the methods are stable. `SliceConcatExt` is
+/// included in the [standard library prelude], so you can use [`join()`] and
+/// [`concat()`] as if they existed on `[T]` itself.
+///
+/// [standard library prelude]: ../../std/prelude/index.html
+/// [`join()`]: #tymethod.join
+/// [`concat()`]: #tymethod.concat
 pub trait SliceConcatExt<T: ?Sized> {
     #[unstable(feature = "slice_concat_ext",
                reason = "trait should not have to exist",
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 7fa872f..a00e3d1 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -719,13 +719,17 @@
     /// Remember, [`char`]s may not match your human intuition about characters:
     ///
     /// ```
-    /// let y = "y̆";
+    /// let yes = "y̆es";
     ///
-    /// let mut char_indices = y.char_indices();
+    /// let mut char_indices = yes.char_indices();
     ///
     /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
     /// assert_eq!(Some((1, '\u{0306}')), char_indices.next());
     ///
+    /// // note the 3 here - the last character took up two bytes
+    /// assert_eq!(Some((3, 'e')), char_indices.next());
+    /// assert_eq!(Some((4, 's')), char_indices.next());
+    ///
     /// assert_eq!(None, char_indices.next());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index ca493ab..8d99d0b 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -2034,6 +2034,7 @@
     ///
     /// assert_eq!(five, i.to_string());
     /// ```
+    #[rustc_conversion_suggestion]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn to_string(&self) -> String;
 }
diff --git a/src/liballoc/tests/cow_str.rs b/src/liballoc/tests/cow_str.rs
index aa87ee8..6393968 100644
--- a/src/liballoc/tests/cow_str.rs
+++ b/src/liballoc/tests/cow_str.rs
@@ -148,4 +148,4 @@
     let c2: Cow<str> = Cow::Owned(s);
     c1.clone_from(&c2);
     assert!(c1.into_owned().capacity() >= 25);
-}
\ No newline at end of file
+}
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index f1e9588..eee229b 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -30,6 +30,7 @@
 #![feature(string_retain)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
+#![feature(exact_chunks)]
 
 extern crate alloc_system;
 extern crate std_unicode;
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index 85d5ce3..1a9d26f 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -494,37 +494,72 @@
 }
 
 #[test]
-fn test_rotate() {
+fn test_rotate_left() {
     let expected: Vec<_> = (0..13).collect();
     let mut v = Vec::new();
 
     // no-ops
     v.clone_from(&expected);
-    v.rotate(0);
+    v.rotate_left(0);
     assert_eq!(v, expected);
-    v.rotate(expected.len());
+    v.rotate_left(expected.len());
     assert_eq!(v, expected);
     let mut zst_array = [(), (), ()];
-    zst_array.rotate(2);
+    zst_array.rotate_left(2);
 
     // happy path
     v = (5..13).chain(0..5).collect();
-    v.rotate(8);
+    v.rotate_left(8);
     assert_eq!(v, expected);
 
     let expected: Vec<_> = (0..1000).collect();
 
     // small rotations in large slice, uses ptr::copy
     v = (2..1000).chain(0..2).collect();
-    v.rotate(998);
+    v.rotate_left(998);
     assert_eq!(v, expected);
     v = (998..1000).chain(0..998).collect();
-    v.rotate(2);
+    v.rotate_left(2);
     assert_eq!(v, expected);
 
     // non-small prime rotation, has a few rounds of swapping
     v = (389..1000).chain(0..389).collect();
-    v.rotate(1000-389);
+    v.rotate_left(1000-389);
+    assert_eq!(v, expected);
+}
+
+#[test]
+fn test_rotate_right() {
+    let expected: Vec<_> = (0..13).collect();
+    let mut v = Vec::new();
+
+    // no-ops
+    v.clone_from(&expected);
+    v.rotate_right(0);
+    assert_eq!(v, expected);
+    v.rotate_right(expected.len());
+    assert_eq!(v, expected);
+    let mut zst_array = [(), (), ()];
+    zst_array.rotate_right(2);
+
+    // happy path
+    v = (5..13).chain(0..5).collect();
+    v.rotate_right(5);
+    assert_eq!(v, expected);
+
+    let expected: Vec<_> = (0..1000).collect();
+
+    // small rotations in large slice, uses ptr::copy
+    v = (2..1000).chain(0..2).collect();
+    v.rotate_right(2);
+    assert_eq!(v, expected);
+    v = (998..1000).chain(0..998).collect();
+    v.rotate_right(998);
+    assert_eq!(v, expected);
+
+    // non-small prime rotation, has a few rounds of swapping
+    v = (389..1000).chain(0..389).collect();
+    v.rotate_right(389);
     assert_eq!(v, expected);
 }
 
@@ -911,6 +946,30 @@
 }
 
 #[test]
+fn test_exact_chunksator() {
+    let v = &[1, 2, 3, 4, 5];
+
+    assert_eq!(v.exact_chunks(2).len(), 2);
+
+    let chunks: &[&[_]] = &[&[1, 2], &[3, 4]];
+    assert_eq!(v.exact_chunks(2).collect::<Vec<_>>(), chunks);
+    let chunks: &[&[_]] = &[&[1, 2, 3]];
+    assert_eq!(v.exact_chunks(3).collect::<Vec<_>>(), chunks);
+    let chunks: &[&[_]] = &[];
+    assert_eq!(v.exact_chunks(6).collect::<Vec<_>>(), chunks);
+
+    let chunks: &[&[_]] = &[&[3, 4], &[1, 2]];
+    assert_eq!(v.exact_chunks(2).rev().collect::<Vec<_>>(), chunks);
+}
+
+#[test]
+#[should_panic]
+fn test_exact_chunksator_0() {
+    let v = &[1, 2, 3, 4];
+    let _it = v.exact_chunks(0);
+}
+
+#[test]
 fn test_reverse_part() {
     let mut values = [1, 2, 3, 4, 5];
     values[1..4].reverse();
@@ -1124,7 +1183,7 @@
         }
     }
     let result = [0, 0, 0, 1, 1, 1, 2];
-    assert!(v == result);
+    assert_eq!(v, result);
 }
 
 #[test]
@@ -1136,7 +1195,7 @@
         }
     }
     let result = [2, 2, 2, 1, 1, 1, 0];
-    assert!(v == result);
+    assert_eq!(v, result);
 }
 
 #[test]
@@ -1147,6 +1206,38 @@
 }
 
 #[test]
+fn test_mut_exact_chunks() {
+    let mut v = [0, 1, 2, 3, 4, 5, 6];
+    assert_eq!(v.exact_chunks_mut(2).len(), 3);
+    for (i, chunk) in v.exact_chunks_mut(3).enumerate() {
+        for x in chunk {
+            *x = i as u8;
+        }
+    }
+    let result = [0, 0, 0, 1, 1, 1, 6];
+    assert_eq!(v, result);
+}
+
+#[test]
+fn test_mut_exact_chunks_rev() {
+    let mut v = [0, 1, 2, 3, 4, 5, 6];
+    for (i, chunk) in v.exact_chunks_mut(3).rev().enumerate() {
+        for x in chunk {
+            *x = i as u8;
+        }
+    }
+    let result = [1, 1, 1, 0, 0, 0, 6];
+    assert_eq!(v, result);
+}
+
+#[test]
+#[should_panic]
+fn test_mut_exact_chunks_0() {
+    let mut v = [1, 2, 3, 4];
+    let _it = v.exact_chunks_mut(0);
+}
+
+#[test]
 fn test_mut_last() {
     let mut x = [1, 2, 3, 4, 5];
     let h = x.last_mut();
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 93d7e66..b14b9d7 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -78,7 +78,7 @@
 use core::ops::{InPlace, Index, IndexMut, Place, Placer};
 use core::ops;
 use core::ptr;
-use core::ptr::Shared;
+use core::ptr::NonNull;
 use core::slice;
 
 use borrow::ToOwned;
@@ -715,7 +715,7 @@
     ///
     /// # Panics
     ///
-    /// Panics if `index` is out of bounds.
+    /// Panics if `index > len`.
     ///
     /// # Examples
     ///
@@ -1124,7 +1124,7 @@
                 tail_start: end,
                 tail_len: len - end,
                 iter: range_slice.iter(),
-                vec: Shared::from(self),
+                vec: NonNull::from(self),
             }
         }
     }
@@ -1745,7 +1745,7 @@
             let cap = self.buf.cap();
             mem::forget(self);
             IntoIter {
-                buf: Shared::new_unchecked(begin),
+                buf: NonNull::new_unchecked(begin),
                 phantom: PhantomData,
                 cap,
                 ptr: begin,
@@ -2267,7 +2267,7 @@
 /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
-    buf: Shared<T>,
+    buf: NonNull<T>,
     phantom: PhantomData<T>,
     cap: usize,
     ptr: *const T,
@@ -2442,7 +2442,7 @@
     tail_len: usize,
     /// Current remaining range to remove
     iter: slice::Iter<'a, T>,
-    vec: Shared<Vec<T>>,
+    vec: NonNull<Vec<T>>,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs
index f56aa23..9259138 100644
--- a/src/liballoc/vec_deque.rs
+++ b/src/liballoc/vec_deque.rs
@@ -23,7 +23,7 @@
 use core::mem;
 use core::ops::{Index, IndexMut, Place, Placer, InPlace};
 use core::ptr;
-use core::ptr::Shared;
+use core::ptr::NonNull;
 use core::slice;
 
 use core::hash::{Hash, Hasher};
@@ -895,7 +895,7 @@
         self.head = drain_tail;
 
         Drain {
-            deque: Shared::from(&mut *self),
+            deque: NonNull::from(&mut *self),
             after_tail: drain_head,
             after_head: head,
             iter: Iter {
@@ -906,7 +906,7 @@
         }
     }
 
-    /// Clears the buffer, removing all values.
+    /// Clears the `VecDeque`, removing all values.
     ///
     /// # Examples
     ///
@@ -1624,10 +1624,10 @@
         return elem;
     }
 
-    /// Splits the collection into two at the given index.
+    /// Splits the `VecDeque` into two at the given index.
     ///
-    /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
-    /// and the returned `Self` contains elements `[at, len)`.
+    /// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`,
+    /// and the returned `VecDeque` contains elements `[at, len)`.
     ///
     /// Note that the capacity of `self` does not change.
     ///
@@ -1635,7 +1635,7 @@
     ///
     /// # Panics
     ///
-    /// Panics if `at > len`
+    /// Panics if `at > len`.
     ///
     /// # Examples
     ///
@@ -1815,7 +1815,8 @@
 
 impl<T: Clone> VecDeque<T> {
     /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len,
-    /// either by removing excess elements or by appending clones of `value` to the back.
+    /// either by removing excess elements from the back or by appending clones of `value`
+    /// to the back.
     ///
     /// # Examples
     ///
@@ -2154,7 +2155,7 @@
     after_tail: usize,
     after_head: usize,
     iter: Iter<'a, T>,
-    deque: Shared<VecDeque<T>>,
+    deque: NonNull<VecDeque<T>>,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
@@ -2390,7 +2391,7 @@
     type Item = T;
     type IntoIter = IntoIter<T>;
 
-    /// Consumes the list into a front-to-back iterator yielding elements by
+    /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by
     /// value.
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { inner: self }
@@ -2480,7 +2481,7 @@
             if other.is_contiguous() {
                 ptr::copy(buf.offset(tail as isize), buf, len);
             } else {
-                if (tail - head) >= cmp::min((cap - tail), head) {
+                if (tail - head) >= cmp::min(cap - tail, head) {
                     // There is enough free space in the centre for the shortest block so we can
                     // do this in at most three copy moves.
                     if (cap - tail) > head {
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index de5006a..0aa46dc 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -16,7 +16,7 @@
 use std::env;
 use std::path::PathBuf;
 use std::process::Command;
-use build_helper::{run, native_lib_boilerplate, BuildExpectation};
+use build_helper::{run, native_lib_boilerplate};
 
 fn main() {
     // FIXME: This is a hack to support building targets that don't
@@ -29,13 +29,20 @@
     // for targets like emscripten, even if we don't use it.
     let target = env::var("TARGET").expect("TARGET was not set");
     let host = env::var("HOST").expect("HOST was not set");
-    if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
-       target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") ||
-       target.contains("redox") || target.contains("wasm32") {
+    if target.contains("bitrig") || target.contains("emscripten") || target.contains("fuchsia") ||
+       target.contains("msvc") || target.contains("openbsd") || target.contains("redox") ||
+       target.contains("rumprun") || target.contains("wasm32") {
         println!("cargo:rustc-cfg=dummy_jemalloc");
         return;
     }
 
+    // CloudABI ships with a copy of jemalloc that has been patched to
+    // work well with sandboxing. Don't attempt to build our own copy,
+    // as it won't build.
+    if target.contains("cloudabi") {
+        return;
+    }
+
     if target.contains("android") {
         println!("cargo:rustc-link-lib=gcc");
     } else if !target.contains("windows") && !target.contains("musl") {
@@ -113,7 +120,7 @@
         cmd.arg("--with-lg-quantum=4");
     }
 
-    run(&mut cmd, BuildExpectation::None);
+    run(&mut cmd);
 
     let mut make = Command::new(build_helper::make(&host));
     make.current_dir(&native.out_dir)
@@ -130,7 +137,7 @@
             .arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set"));
     }
 
-    run(&mut make, BuildExpectation::None);
+    run(&mut make);
 
     // The pthread_atfork symbols is used by jemalloc on android but the really
     // old android we're building on doesn't have them defined, so just make
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index 27259cc..1d5e7b7 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -21,7 +21,7 @@
 #![feature(core_intrinsics)]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
-#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
+#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
 #![rustc_alloc_kind = "lib"]
 
 // The minimum alignment guaranteed by the architecture. This value is used to
@@ -116,7 +116,7 @@
     }
 }
 
-#[cfg(any(unix, target_os = "redox"))]
+#[cfg(any(unix, target_os = "cloudabi", target_os = "redox"))]
 mod platform {
     extern crate libc;
 
@@ -213,6 +213,16 @@
             struct Stderr;
 
             impl Write for Stderr {
+                #[cfg(target_os = "cloudabi")]
+                fn write_str(&mut self, _: &str) -> fmt::Result {
+                    // CloudABI does not have any reserved file descriptor
+                    // numbers. We should not attempt to write to file
+                    // descriptor #2, as it may be associated with any kind of
+                    // resource.
+                    Ok(())
+                }
+
+                #[cfg(not(target_os = "cloudabi"))]
                 fn write_str(&mut self, s: &str) -> fmt::Result {
                     unsafe {
                         libc::write(libc::STDERR_FILENO,
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 2be7b1b..72fa314 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -69,7 +69,9 @@
 impl<T> TypedArenaChunk<T> {
     #[inline]
     unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
-        TypedArenaChunk { storage: RawVec::with_capacity(capacity) }
+        TypedArenaChunk {
+            storage: RawVec::with_capacity(capacity),
+        }
     }
 
     /// Destroys this arena chunk.
@@ -132,7 +134,9 @@
 
         unsafe {
             if mem::size_of::<T>() == 0 {
-                self.ptr.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T);
+                self.ptr
+                    .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1)
+                        as *mut T);
                 let ptr = mem::align_of::<T>() as *mut T;
                 // Don't drop the object. This `write` is equivalent to `forget`.
                 ptr::write(ptr, object);
@@ -148,15 +152,18 @@
         }
     }
 
-    /// Allocates a slice of objects that are copy into the `TypedArena`, returning a mutable
+    /// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable
     /// reference to it. Will panic if passed a zero-sized types.
     ///
     /// Panics:
+    ///
     ///  - Zero-sized types
     ///  - Zero-length slices
     #[inline]
     pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
-        where T: Copy {
+    where
+        T: Copy,
+    {
         assert!(mem::size_of::<T>() != 0);
         assert!(slice.len() != 0);
 
@@ -320,7 +327,10 @@
             let (chunk, mut new_capacity);
             if let Some(last_chunk) = chunks.last_mut() {
                 let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
-                if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) {
+                if last_chunk
+                    .storage
+                    .reserve_in_place(used_bytes, needed_bytes)
+                {
                     self.end.set(last_chunk.end());
                     return;
                 } else {
@@ -356,9 +366,9 @@
 
             let ptr = self.ptr.get();
             // Set the pointer past ourselves
-            self.ptr.set(intrinsics::arith_offset(
-                    self.ptr.get(), mem::size_of::<T>() as isize
-            ) as *mut u8);
+            self.ptr.set(
+                intrinsics::arith_offset(self.ptr.get(), mem::size_of::<T>() as isize) as *mut u8,
+            );
             // Write into uninitialized memory.
             ptr::write(ptr as *mut T, object);
             &mut *(ptr as *mut T)
@@ -369,11 +379,14 @@
     /// reference to it. Will panic if passed a zero-sized type.
     ///
     /// Panics:
+    ///
     ///  - Zero-sized types
     ///  - Zero-length slices
     #[inline]
     pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
-        where T: Copy {
+    where
+        T: Copy,
+    {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
         assert!(slice.len() != 0);
@@ -389,7 +402,8 @@
         unsafe {
             let arena_slice = slice::from_raw_parts_mut(self.ptr.get() as *mut T, slice.len());
             self.ptr.set(intrinsics::arith_offset(
-                    self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize
+                self.ptr.get(),
+                (slice.len() * mem::size_of::<T>()) as isize,
             ) as *mut u8);
             arena_slice.copy_from_slice(slice);
             arena_slice
@@ -454,8 +468,9 @@
 
         let arena = Wrap(TypedArena::new());
 
-        let result =
-            arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
+        let result = arena.alloc_outer(|| Outer {
+            inner: arena.alloc_inner(|| Inner { value: 10 }),
+        });
 
         assert_eq!(result.inner.value, 10);
     }
diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins
index 000d06a..0ba07e4 160000
--- a/src/libcompiler_builtins
+++ b/src/libcompiler_builtins
@@ -1 +1 @@
-Subproject commit 000d06a57a622eb4db4a15d0f76db48571f4d8e4
+Subproject commit 0ba07e49264a54cb5bbd4856fcea083bb3fbec15
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 0f541a4..65aacb2 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -83,9 +83,12 @@
 /// some other means.
 ///
 /// An important thing to remember is that the type `fmt::Error` should not be
-/// confused with `std::io::Error` or `std::error::Error`, which you may also
+/// confused with [`std::io::Error`] or [`std::error::Error`], which you may also
 /// have in scope.
 ///
+/// [`std::io::Error`]: ../../std/io/struct.Error.html
+/// [`std::error::Error`]: ../../std/error/trait.Error.html
+///
 /// # Examples
 ///
 /// ```rust
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index f1e51e9..a611dc0 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1390,6 +1390,5 @@
 
     /// Emits a `!nontemporal` store according to LLVM (see their docs).
     /// Probably will never become stable.
-    #[cfg(not(stage0))]
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
 }
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index e9aee4a..66a76a2 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -251,6 +251,21 @@
         self.start = self.end.clone();
         None
     }
+
+    #[inline]
+    fn last(mut self) -> Option<A> {
+        self.next_back()
+    }
+
+    #[inline]
+    fn min(mut self) -> Option<A> {
+        self.next()
+    }
+
+    #[inline]
+    fn max(mut self) -> Option<A> {
+        self.next_back()
+    }
 }
 
 // These macros generate `ExactSizeIterator` impls for various range types.
@@ -367,6 +382,21 @@
         self.end.replace_zero();
         None
     }
+
+    #[inline]
+    fn last(mut self) -> Option<A> {
+        self.next_back()
+    }
+
+    #[inline]
+    fn min(mut self) -> Option<A> {
+        self.next()
+    }
+
+    #[inline]
+    fn max(mut self) -> Option<A> {
+        self.next_back()
+    }
 }
 
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 948ad10..f00128a 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -330,6 +330,7 @@
 /// // The prefered method of quick returning Errors
 /// fn write_to_file_question() -> Result<(), MyError> {
 ///     let mut file = File::create("my_best_friends.txt")?;
+///     file.write_all(b"This is a list of my best friends.")?;
 ///     Ok(())
 /// }
 ///
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 17e7765..3032fb2 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -40,16 +40,11 @@
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
-pub unsafe trait Send {
+pub unsafe auto trait Send {
     // empty.
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Send for .. { }
-
-#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !Send for *const T { }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !Send for *mut T { }
@@ -345,16 +340,11 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "sync"]
 #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
-pub unsafe trait Sync {
+pub unsafe auto trait Sync {
     // Empty
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Sync for .. { }
-
-#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !Sync for *const T { }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !Sync for *mut T { }
@@ -563,11 +553,7 @@
 /// This affects, for example, whether a `static` of that type is
 /// placed in read-only static memory or writable static memory.
 #[lang = "freeze"]
-unsafe trait Freeze {}
-
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-unsafe impl Freeze for .. {}
+unsafe auto trait Freeze {}
 
 impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
 unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 5b1a939..93f6a02 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -1024,7 +1024,7 @@
     }
 }
 
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
 impl<T: Clone> Clone for ManuallyDrop<T> {
     fn clone(&self) -> Self {
         ManuallyDrop::new(self.deref().clone())
@@ -1035,14 +1035,14 @@
     }
 }
 
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
 impl<T: Default> Default for ManuallyDrop<T> {
     fn default() -> Self {
         ManuallyDrop::new(Default::default())
     }
 }
 
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
 impl<T: PartialEq> PartialEq for ManuallyDrop<T> {
     fn eq(&self, other: &Self) -> bool {
         self.deref().eq(other)
@@ -1053,10 +1053,10 @@
     }
 }
 
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
 impl<T: Eq> Eq for ManuallyDrop<T> {}
 
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
 impl<T: PartialOrd> PartialOrd for ManuallyDrop<T> {
     fn partial_cmp(&self, other: &Self) -> Option<::cmp::Ordering> {
         self.deref().partial_cmp(other)
@@ -1079,14 +1079,14 @@
     }
 }
 
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
 impl<T: Ord> Ord for ManuallyDrop<T> {
     fn cmp(&self, other: &Self) -> ::cmp::Ordering {
         self.deref().cmp(other)
     }
 }
 
-#[stable(feature = "manually_drop", since = "1.20.0")]
+#[stable(feature = "manually_drop_impls", since = "1.22.0")]
 impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> {
     fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
         self.deref().hash(state);
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index dc37bce..207df84 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -8,7 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Operations and constants for 32-bits floats (`f32` type)
+//! This module provides constants which are specific to the implementation
+//! of the `f32` floating point data type.
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -255,7 +260,7 @@
         // Since we do not support sNaN in Rust yet, we do not need to handle them.
         // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
         // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if self < other || self.is_nan() { other } else { self }) * 1.0
+        (if self.is_nan() || self < other { other } else { self }) * 1.0
     }
 
     /// Returns the minimum of the two numbers.
@@ -269,7 +274,7 @@
         // Since we do not support sNaN in Rust yet, we do not need to handle them.
         // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
         // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if self < other || other.is_nan() { self } else { other }) * 1.0
+        (if other.is_nan() || self < other { self } else { other }) * 1.0
     }
 
     /// Raw transmutation to `u32`.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 5c21716..9206132 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -8,7 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Operations and constants for 64-bits floats (`f64` type)
+//! This module provides constants which are specific to the implementation
+//! of the `f64` floating point data type.
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -253,7 +258,7 @@
         // Since we do not support sNaN in Rust yet, we do not need to handle them.
         // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
         // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if self < other || self.is_nan() { other } else { self }) * 1.0
+        (if self.is_nan() || self < other { other } else { self }) * 1.0
     }
 
     /// Returns the minimum of the two numbers.
@@ -267,7 +272,7 @@
         // Since we do not support sNaN in Rust yet, we do not need to handle them.
         // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
         // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if self < other || other.is_nan() { self } else { other }) * 1.0
+        (if other.is_nan() || self < other { self } else { other }) * 1.0
     }
 
     /// Raw transmutation to `u64`.
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index ebf8a95..1fae88b 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -103,6 +103,8 @@
         ///
         /// # Examples
         ///
+        /// Basic usage:
+        ///
         /// ```
         /// assert_eq!(i8::min_value(), -128);
         /// ```
@@ -116,6 +118,8 @@
         ///
         /// # Examples
         ///
+        /// Basic usage:
+        ///
         /// ```
         /// assert_eq!(i8::max_value(), 127);
         /// ```
@@ -435,7 +439,7 @@
         }
 
         /// Checked integer division. Computes `self / rhs`, returning `None`
-        /// if `rhs == 0` or the operation results in overflow.
+        /// if `rhs == 0` or the division results in overflow.
         ///
         /// # Examples
         ///
@@ -457,7 +461,7 @@
         }
 
         /// Checked integer remainder. Computes `self % rhs`, returning `None`
-        /// if `rhs == 0` or the operation results in overflow.
+        /// if `rhs == 0` or the division results in overflow.
         ///
         /// # Examples
         ///
@@ -1252,6 +1256,8 @@
         ///
         /// # Examples
         ///
+        /// Basic usage:
+        ///
         /// ```
         /// assert_eq!(u8::min_value(), 0);
         /// ```
@@ -1263,6 +1269,8 @@
         ///
         /// # Examples
         ///
+        /// Basic usage:
+        ///
         /// ```
         /// assert_eq!(u8::max_value(), 255);
         /// ```
@@ -1599,7 +1607,7 @@
         }
 
         /// Checked integer division. Computes `self / rhs`, returning `None`
-        /// if `rhs == 0` or the operation results in overflow.
+        /// if `rhs == 0`.
         ///
         /// # Examples
         ///
@@ -1619,7 +1627,7 @@
         }
 
         /// Checked integer remainder. Computes `self % rhs`, returning `None`
-        /// if `rhs == 0` or the operation results in overflow.
+        /// if `rhs == 0`.
         ///
         /// # Examples
         ///
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index d8f3ec3..b8fe28d 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -407,9 +407,7 @@
     }
 
     /// Applies a function to the contained value (if any),
-    /// or returns a [`default`][] (if not).
-    ///
-    /// [`default`]: ../default/trait.Default.html#tymethod.default
+    /// or returns the provided default (if not).
     ///
     /// # Examples
     ///
@@ -430,9 +428,7 @@
     }
 
     /// Applies a function to the contained value (if any),
-    /// or computes a [`default`][] (if not).
-    ///
-    /// [`default`]: ../default/trait.Default.html#tymethod.default
+    /// or computes a default (if not).
     ///
     /// # Examples
     ///
@@ -850,7 +846,7 @@
     /// Returns the contained value or a default
     ///
     /// Consumes the `self` argument then, if [`Some`], returns the contained
-    /// value, otherwise if [`None`], returns the default value for that
+    /// value, otherwise if [`None`], returns the [default value] for that
     /// type.
     ///
     /// # Examples
@@ -872,6 +868,7 @@
     ///
     /// [`Some`]: #variant.Some
     /// [`None`]: #variant.None
+    /// [default value]: ../default/trait.Default.html#tymethod.default
     /// [`parse`]: ../../std/primitive.str.html#method.parse
     /// [`FromStr`]: ../../std/str/trait.FromStr.html
     #[inline]
@@ -884,6 +881,35 @@
     }
 }
 
+impl<T, E> Option<Result<T, E>> {
+    /// Transposes an `Option` of a `Result` into a `Result` of an `Option`.
+    ///
+    /// `None` will be mapped to `Ok(None)`.
+    /// `Some(Ok(_))` and `Some(Err(_))` will be mapped to `Ok(Some(_))` and `Err(_)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(transpose_result)]
+    ///
+    /// #[derive(Debug, Eq, PartialEq)]
+    /// struct SomeErr;
+    ///
+    /// let x: Result<Option<i32>, SomeErr> = Ok(Some(5));
+    /// let y: Option<Result<i32, SomeErr>> = Some(Ok(5));
+    /// assert_eq!(x, y.transpose());
+    /// ```
+    #[inline]
+    #[unstable(feature = "transpose_result", issue = "47338")]
+    pub fn transpose(self) -> Result<Option<T>, E> {
+        match self {
+            Some(Ok(x)) => Ok(Some(x)),
+            Some(Err(e)) => Err(e),
+            None => Ok(None),
+        }
+    }
+}
+
 // This is a separate function to reduce the code size of .expect() itself.
 #[inline(never)]
 #[cold]
diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs
index 3fa6a97..d43496c 100644
--- a/src/libcore/prelude/v1.rs
+++ b/src/libcore/prelude/v1.rs
@@ -16,7 +16,7 @@
 
 #![stable(feature = "core_prelude", since = "1.4.0")]
 
-// Reexported core operators
+// Re-exported core operators
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use marker::{Copy, Send, Sized, Sync};
@@ -24,12 +24,12 @@
 #[doc(no_inline)]
 pub use ops::{Drop, Fn, FnMut, FnOnce};
 
-// Reexported functions
+// Re-exported functions
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use mem::drop;
 
-// Reexported types and traits
+// Re-exported types and traits
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use clone::Clone;
@@ -55,7 +55,7 @@
 #[doc(no_inline)]
 pub use result::Result::{self, Ok, Err};
 
-// Reexported extension traits for primitive types
+// Re-exported extension traits for primitive types
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use slice::SliceExt;
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 85bdeae..fab5832 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -1829,7 +1829,7 @@
     ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
+    ///     let mut dst: Vec<T> = Vec::with_capacity(elts);
     ///     dst.set_len(elts);
     ///     dst.as_mut_ptr().copy_from(ptr, elts);
     ///     dst
@@ -1868,7 +1868,7 @@
     ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
+    ///     let mut dst: Vec<T> = Vec::with_capacity(elts);
     ///     dst.set_len(elts);
     ///     dst.as_mut_ptr().copy_from_nonoverlapping(ptr, elts);
     ///     dst
@@ -2321,7 +2321,7 @@
 /// its owning Unique.
 ///
 /// If you're uncertain of whether it's correct to use `Unique` for your purposes,
-/// consider using `Shared`, which has weaker semantics.
+/// consider using `NonNull`, which has weaker semantics.
 ///
 /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
 /// is never dereferenced. This is so that enums may use this forbidden value
@@ -2330,9 +2330,9 @@
 ///
 /// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
 /// for any type which upholds Unique's aliasing requirements.
-#[allow(missing_debug_implementations)]
-#[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
-           issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0",
+           reason = "use NonNull instead and consider PhantomData<T> \
+                     (if you also use #[may_dangle]), Send, and/or Sync")]
 pub struct Unique<T: ?Sized> {
     pointer: NonZero<*const T>,
     // NOTE: this marker has no consequences for variance, but is necessary
@@ -2343,26 +2343,34 @@
     _marker: PhantomData<T>,
 }
 
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> fmt::Debug for Unique<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Pointer::fmt(&self.as_ptr(), f)
+    }
+}
+
 /// `Unique` pointers are `Send` if `T` is `Send` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
 
 /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: Sized> Unique<T> {
     /// Creates a new `Unique` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
     /// `Vec::new` does.
+    // FIXME: rename to dangling() to match NonNull?
     pub fn empty() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
@@ -2371,14 +2379,13 @@
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> Unique<T> {
     /// Creates a new `Unique`.
     ///
     /// # Safety
     ///
     /// `ptr` must be non-null.
-    #[unstable(feature = "unique", issue = "27730")]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
     }
@@ -2397,7 +2404,7 @@
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
+    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
     pub unsafe fn as_ref(&self) -> &T {
         &*self.as_ptr()
     }
@@ -2406,112 +2413,130 @@
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&mut *my_ptr.ptr()`.
+    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
     pub unsafe fn as_mut(&mut self) -> &mut T {
         &mut *self.as_ptr()
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> Clone for Unique<T> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> Copy for Unique<T> { }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> fmt::Pointer for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Pointer::fmt(&self.as_ptr(), f)
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
     fn from(reference: &'a mut T) -> Self {
         Unique { pointer: NonZero::from(reference), _marker: PhantomData }
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
     fn from(reference: &'a T) -> Self {
         Unique { pointer: NonZero::from(reference), _marker: PhantomData }
     }
 }
 
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
+    fn from(p: NonNull<T>) -> Self {
+        Unique { pointer: p.pointer, _marker: PhantomData }
+    }
+}
+
+/// Previous name of `NonNull`.
+#[rustc_deprecated(since = "1.24", reason = "renamed to `NonNull`")]
+#[unstable(feature = "shared", issue = "27730")]
+pub type Shared<T> = NonNull<T>;
+
 /// `*mut T` but non-zero and covariant.
 ///
 /// This is often the correct thing to use when building data structures using
 /// raw pointers, but is ultimately more dangerous to use because of its additional
-/// properties. If you're not sure if you should use `Shared<T>`, just use `*mut T`!
+/// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
 ///
 /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
 /// is never dereferenced. This is so that enums may use this forbidden value
-/// as a discriminant -- `Option<Shared<T>>` has the same size as `Shared<T>`.
+/// as a discriminant -- `Option<NonNull<T>>` has the same size as `NonNull<T>`.
 /// However the pointer may still dangle if it isn't dereferenced.
 ///
-/// Unlike `*mut T`, `Shared<T>` is covariant over `T`. If this is incorrect
+/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
 /// for your use case, you should include some PhantomData in your type to
 /// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
 /// Usually this won't be necessary; covariance is correct for most safe abstractions,
 /// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they
 /// provide a public API that follows the normal shared XOR mutable rules of Rust.
-#[allow(missing_debug_implementations)]
-#[unstable(feature = "shared", reason = "needs an RFC to flesh out design",
-           issue = "27730")]
-pub struct Shared<T: ?Sized> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+pub struct NonNull<T: ?Sized> {
     pointer: NonZero<*const T>,
 }
 
-/// `Shared` pointers are not `Send` because the data they reference may be aliased.
-// NB: This impl is unnecessary, but should provide better error messages.
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> !Send for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> fmt::Debug for NonNull<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Pointer::fmt(&self.as_ptr(), f)
+    }
+}
 
-/// `Shared` pointers are not `Sync` because the data they reference may be aliased.
+/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
 // NB: This impl is unnecessary, but should provide better error messages.
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> !Sync for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> !Send for NonNull<T> { }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: Sized> Shared<T> {
-    /// Creates a new `Shared` that is dangling, but well-aligned.
+/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
+// NB: This impl is unnecessary, but should provide better error messages.
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> !Sync for NonNull<T> { }
+
+impl<T: Sized> NonNull<T> {
+    /// Creates a new `NonNull` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
     /// `Vec::new` does.
-    pub fn empty() -> Self {
+    #[stable(feature = "nonnull", since = "1.24.0")]
+    pub fn dangling() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
-            Shared::new_unchecked(ptr)
+            NonNull::new_unchecked(ptr)
         }
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Shared<T> {
-    /// Creates a new `Shared`.
+impl<T: ?Sized> NonNull<T> {
+    /// Creates a new `NonNull`.
     ///
     /// # Safety
     ///
     /// `ptr` must be non-null.
-    #[unstable(feature = "shared", issue = "27730")]
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
-        Shared { pointer: NonZero::new_unchecked(ptr) }
+        NonNull { pointer: NonZero::new_unchecked(ptr) }
     }
 
-    /// Creates a new `Shared` if `ptr` is non-null.
+    /// Creates a new `NonNull` if `ptr` is non-null.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub fn new(ptr: *mut T) -> Option<Self> {
-        NonZero::new(ptr as *const T).map(|nz| Shared { pointer: nz })
+        NonZero::new(ptr as *const T).map(|nz| NonNull { pointer: nz })
     }
 
     /// Acquires the underlying `*mut` pointer.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub fn as_ptr(self) -> *mut T {
         self.pointer.get() as *mut T
     }
@@ -2520,7 +2545,8 @@
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
+    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub unsafe fn as_ref(&self) -> &T {
         &*self.as_ptr()
     }
@@ -2529,56 +2555,50 @@
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&mut *my_ptr.ptr_mut()`.
+    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub unsafe fn as_mut(&mut self) -> &mut T {
         &mut *self.as_ptr()
     }
-
-    /// Acquires the underlying pointer as a `*mut` pointer.
-    #[rustc_deprecated(since = "1.19", reason = "renamed to `as_ptr` for ergonomics/consistency")]
-    #[unstable(feature = "shared", issue = "27730")]
-    pub unsafe fn as_mut_ptr(&self) -> *mut T {
-        self.as_ptr()
-    }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Clone for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> Clone for NonNull<T> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Copy for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> Copy for NonNull<T> { }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> fmt::Pointer for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> fmt::Pointer for NonNull<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Pointer::fmt(&self.as_ptr(), f)
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> From<Unique<T>> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
     fn from(unique: Unique<T>) -> Self {
-        Shared { pointer: unique.pointer }
+        NonNull { pointer: unique.pointer }
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<'a, T: ?Sized> From<&'a mut T> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
     fn from(reference: &'a mut T) -> Self {
-        Shared { pointer: NonZero::from(reference) }
+        NonNull { pointer: NonZero::from(reference) }
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<'a, T: ?Sized> From<&'a T> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
     fn from(reference: &'a T) -> Self {
-        Shared { pointer: NonZero::from(reference) }
+        NonNull { pointer: NonZero::from(reference) }
     }
 }
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 2ace3d2..3801db9 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -909,6 +909,35 @@
     }
 }
 
+impl<T, E> Result<Option<T>, E> {
+    /// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
+    ///
+    /// `Ok(None)` will be mapped to `None`.
+    /// `Ok(Some(_))` and `Err(_)` will be mapped to `Some(Ok(_))` and `Some(Err(_))`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(transpose_result)]
+    ///
+    /// #[derive(Debug, Eq, PartialEq)]
+    /// struct SomeErr;
+    ///
+    /// let x: Result<Option<i32>, SomeErr> = Ok(Some(5));
+    /// let y: Option<Result<i32, SomeErr>> = Some(Ok(5));
+    /// assert_eq!(x.transpose(), y);
+    /// ```
+    #[inline]
+    #[unstable(feature = "transpose_result", issue = "47338")]
+    pub fn transpose(self) -> Option<Result<T, E>> {
+        match self {
+            Ok(Some(x)) => Some(Ok(x)),
+            Ok(None) => None,
+            Err(e) => Some(Err(e)),
+        }
+    }
+}
+
 // This is a separate function to reduce the code size of the methods
 #[inline(never)]
 #[cold]
diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs
new file mode 100644
index 0000000..69c9cb3
--- /dev/null
+++ b/src/libcore/slice/memchr.rs
@@ -0,0 +1,230 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// Original implementation taken from rust-memchr
+// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
+
+use cmp;
+use mem;
+
+const LO_U64: u64 = 0x0101010101010101;
+const HI_U64: u64 = 0x8080808080808080;
+
+// use truncation
+const LO_USIZE: usize = LO_U64 as usize;
+const HI_USIZE: usize = HI_U64 as usize;
+
+/// Return `true` if `x` contains any zero byte.
+///
+/// From *Matters Computational*, J. Arndt
+///
+/// "The idea is to subtract one from each of the bytes and then look for
+/// bytes where the borrow propagated all the way to the most significant
+/// bit."
+#[inline]
+fn contains_zero_byte(x: usize) -> bool {
+    x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
+}
+
+#[cfg(target_pointer_width = "16")]
+#[inline]
+fn repeat_byte(b: u8) -> usize {
+    (b as usize) << 8 | b as usize
+}
+
+#[cfg(target_pointer_width = "32")]
+#[inline]
+fn repeat_byte(b: u8) -> usize {
+    let mut rep = (b as usize) << 8 | b as usize;
+    rep = rep << 16 | rep;
+    rep
+}
+
+#[cfg(target_pointer_width = "64")]
+#[inline]
+fn repeat_byte(b: u8) -> usize {
+    let mut rep = (b as usize) << 8 | b as usize;
+    rep = rep << 16 | rep;
+    rep = rep << 32 | rep;
+    rep
+}
+
+/// Return the first index matching the byte `x` in `text`.
+pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
+    // Scan for a single byte value by reading two `usize` words at a time.
+    //
+    // Split `text` in three parts
+    // - unaligned initial part, before the first word aligned address in text
+    // - body, scan by 2 words at a time
+    // - the last remaining part, < 2 word size
+    let len = text.len();
+    let ptr = text.as_ptr();
+    let usize_bytes = mem::size_of::<usize>();
+
+    // search up to an aligned boundary
+    let mut offset = ptr.align_offset(usize_bytes);
+    if offset > 0 {
+        offset = cmp::min(offset, len);
+        if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
+            return Some(index);
+        }
+    }
+
+    // search the body of the text
+    let repeated_x = repeat_byte(x);
+
+    if len >= 2 * usize_bytes {
+        while offset <= len - 2 * usize_bytes {
+            unsafe {
+                let u = *(ptr.offset(offset as isize) as *const usize);
+                let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
+
+                // break if there is a matching byte
+                let zu = contains_zero_byte(u ^ repeated_x);
+                let zv = contains_zero_byte(v ^ repeated_x);
+                if zu || zv {
+                    break;
+                }
+            }
+            offset += usize_bytes * 2;
+        }
+    }
+
+    // find the byte after the point the body loop stopped
+    text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
+}
+
+/// Return the last index matching the byte `x` in `text`.
+pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
+    // Scan for a single byte value by reading two `usize` words at a time.
+    //
+    // Split `text` in three parts
+    // - unaligned tail, after the last word aligned address in text
+    // - body, scan by 2 words at a time
+    // - the first remaining bytes, < 2 word size
+    let len = text.len();
+    let ptr = text.as_ptr();
+    let usize_bytes = mem::size_of::<usize>();
+
+    // search to an aligned boundary
+    let end_align = (ptr as usize + len) & (usize_bytes - 1);
+    let mut offset;
+    if end_align > 0 {
+        offset = if end_align >= len { 0 } else { len - end_align };
+        if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
+            return Some(offset + index);
+        }
+    } else {
+        offset = len;
+    }
+
+    // search the body of the text
+    let repeated_x = repeat_byte(x);
+
+    while offset >= 2 * usize_bytes {
+        unsafe {
+            let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
+            let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
+
+            // break if there is a matching byte
+            let zu = contains_zero_byte(u ^ repeated_x);
+            let zv = contains_zero_byte(v ^ repeated_x);
+            if zu || zv {
+                break;
+            }
+        }
+        offset -= 2 * usize_bytes;
+    }
+
+    // find the byte before the point the body loop stopped
+    text[..offset].iter().rposition(|elt| *elt == x)
+}
+
+// test fallback implementations on all platforms
+#[test]
+fn matches_one() {
+    assert_eq!(Some(0), memchr(b'a', b"a"));
+}
+
+#[test]
+fn matches_begin() {
+    assert_eq!(Some(0), memchr(b'a', b"aaaa"));
+}
+
+#[test]
+fn matches_end() {
+    assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
+}
+
+#[test]
+fn matches_nul() {
+    assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
+}
+
+#[test]
+fn matches_past_nul() {
+    assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
+}
+
+#[test]
+fn no_match_empty() {
+    assert_eq!(None, memchr(b'a', b""));
+}
+
+#[test]
+fn no_match() {
+    assert_eq!(None, memchr(b'a', b"xyz"));
+}
+
+#[test]
+fn matches_one_reversed() {
+    assert_eq!(Some(0), memrchr(b'a', b"a"));
+}
+
+#[test]
+fn matches_begin_reversed() {
+    assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
+}
+
+#[test]
+fn matches_end_reversed() {
+    assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
+}
+
+#[test]
+fn matches_nul_reversed() {
+    assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
+}
+
+#[test]
+fn matches_past_nul_reversed() {
+    assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
+}
+
+#[test]
+fn no_match_empty_reversed() {
+    assert_eq!(None, memrchr(b'a', b""));
+}
+
+#[test]
+fn no_match_reversed() {
+    assert_eq!(None, memrchr(b'a', b"xyz"));
+}
+
+#[test]
+fn each_alignment_reversed() {
+    let mut data = [1u8; 64];
+    let needle = 2;
+    let pos = 40;
+    data[pos] = needle;
+    for start in 0..16 {
+        assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
+    }
+}
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index ca5cf04..244bf47 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -22,7 +22,7 @@
 // a lot of stuff defined here. Let's keep it clean.
 //
 // Since slices don't support inherent methods; all operations
-// on them are defined on traits, which are then reexported from
+// on them are defined on traits, which are then re-exported from
 // the prelude for convenience. So there are a lot of traits here.
 //
 // The layout of this file is thus:
@@ -50,6 +50,11 @@
 use marker::{Copy, Send, Sync, Sized, self};
 use iter_private::TrustedRandomAccess;
 
+#[unstable(feature = "slice_internals", issue = "0",
+           reason = "exposed from core to be reused in std; use the memchr crate")]
+/// Pure rust memchr implementation, taken from rust-memchr
+pub mod memchr;
+
 mod rotate;
 mod sort;
 
@@ -99,6 +104,9 @@
     #[stable(feature = "core", since = "1.6.0")]
     fn chunks(&self, size: usize) -> Chunks<Self::Item>;
 
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    fn exact_chunks(&self, size: usize) -> ExactChunks<Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn get<I>(&self, index: I) -> Option<&I::Output>
         where I: SliceIndex<Self>;
@@ -176,6 +184,9 @@
     #[stable(feature = "core", since = "1.6.0")]
     fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<Self::Item>;
 
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    fn exact_chunks_mut(&mut self, size: usize) -> ExactChunksMut<Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn swap(&mut self, a: usize, b: usize);
 
@@ -201,7 +212,10 @@
     fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
 
     #[unstable(feature = "slice_rotate", issue = "41891")]
-    fn rotate(&mut self, mid: usize);
+    fn rotate_left(&mut self, mid: usize);
+
+    #[unstable(feature = "slice_rotate", issue = "41891")]
+    fn rotate_right(&mut self, k: usize);
 
     #[stable(feature = "clone_from_slice", since = "1.7.0")]
     fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
@@ -343,9 +357,17 @@
     }
 
     #[inline]
-    fn chunks(&self, size: usize) -> Chunks<T> {
-        assert!(size != 0);
-        Chunks { v: self, size: size }
+    fn chunks(&self, chunk_size: usize) -> Chunks<T> {
+        assert!(chunk_size != 0);
+        Chunks { v: self, chunk_size: chunk_size }
+    }
+
+    #[inline]
+    fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+        assert!(chunk_size != 0);
+        let rem = self.len() % chunk_size;
+        let len = self.len() - rem;
+        ExactChunks { v: &self[..len], chunk_size: chunk_size}
     }
 
     #[inline]
@@ -527,11 +549,19 @@
 
     #[inline]
     fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
-        assert!(chunk_size > 0);
+        assert!(chunk_size != 0);
         ChunksMut { v: self, chunk_size: chunk_size }
     }
 
     #[inline]
+    fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+        assert!(chunk_size != 0);
+        let rem = self.len() % chunk_size;
+        let len = self.len() - rem;
+        ExactChunksMut { v: &mut self[..len], chunk_size: chunk_size}
+    }
+
+    #[inline]
     fn swap(&mut self, a: usize, b: usize) {
         unsafe {
             // Can't take two mutable loans from one vector, so instead just cast
@@ -619,7 +649,7 @@
 
     #[inline]
     fn contains(&self, x: &T) -> bool where T: PartialEq {
-        self.iter().any(|elt| *x == *elt)
+        x.slice_contains(self)
     }
 
     #[inline]
@@ -640,7 +670,7 @@
         self.binary_search_by(|p| p.cmp(x))
     }
 
-    fn rotate(&mut self, mid: usize) {
+    fn rotate_left(&mut self, mid: usize) {
         assert!(mid <= self.len());
         let k = self.len() - mid;
 
@@ -650,6 +680,16 @@
         }
     }
 
+    fn rotate_right(&mut self, k: usize) {
+        assert!(k <= self.len());
+        let mid = self.len() - k;
+
+        unsafe {
+            let p = self.as_mut_ptr();
+            rotate::ptr_rotate(mid, p.offset(mid as isize), k);
+        }
+    }
+
     #[inline]
     fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
         assert!(self.len() == src.len(),
@@ -1197,6 +1237,43 @@
                 }
                 accum
             }
+
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
+                Self: Sized,
+                P: FnMut(Self::Item) -> bool,
+            {
+                // The addition might panic on overflow
+                let n = self.len();
+                self.try_fold(0, move |i, x| {
+                    if predicate(x) { Err(i) }
+                    else { Ok(i + 1) }
+                }).err()
+                    .map(|i| {
+                        unsafe { assume(i < n) };
+                        i
+                    })
+            }
+
+            #[inline]
+            fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
+                P: FnMut(Self::Item) -> bool,
+                Self: Sized + ExactSizeIterator + DoubleEndedIterator
+            {
+                // No need for an overflow check here, because `ExactSizeIterator`
+                // implies that the number of elements fits into a `usize`.
+                let n = self.len();
+                self.try_rfold(n, move |i, x| {
+                    let i = i - 1;
+                    if predicate(x) { Err(i) }
+                    else { Ok(i) }
+                }).err()
+                    .map(|i| {
+                        unsafe { assume(i < n) };
+                        i
+                    })
+            }
         }
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -2112,7 +2189,15 @@
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T> FusedIterator for Windows<'a, T> {}
 
-/// An iterator over a slice in (non-overlapping) chunks (`size` elements at a
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
+        from_raw_parts(self.v.as_ptr().offset(i as isize), self.size)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
+
+/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
 /// time).
 ///
 /// When the slice len is not evenly divided by the chunk size, the last slice
@@ -2126,7 +2211,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chunks<'a, T:'a> {
     v: &'a [T],
-    size: usize
+    chunk_size: usize
 }
 
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
@@ -2135,7 +2220,7 @@
     fn clone(&self) -> Chunks<'a, T> {
         Chunks {
             v: self.v,
-            size: self.size,
+            chunk_size: self.chunk_size,
         }
     }
 }
@@ -2149,7 +2234,7 @@
         if self.v.is_empty() {
             None
         } else {
-            let chunksz = cmp::min(self.v.len(), self.size);
+            let chunksz = cmp::min(self.v.len(), self.chunk_size);
             let (fst, snd) = self.v.split_at(chunksz);
             self.v = snd;
             Some(fst)
@@ -2161,8 +2246,8 @@
         if self.v.is_empty() {
             (0, Some(0))
         } else {
-            let n = self.v.len() / self.size;
-            let rem = self.v.len() % self.size;
+            let n = self.v.len() / self.chunk_size;
+            let rem = self.v.len() % self.chunk_size;
             let n = if rem > 0 { n+1 } else { n };
             (n, Some(n))
         }
@@ -2175,12 +2260,12 @@
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<Self::Item> {
-        let (start, overflow) = n.overflowing_mul(self.size);
+        let (start, overflow) = n.overflowing_mul(self.chunk_size);
         if start >= self.v.len() || overflow {
             self.v = &[];
             None
         } else {
-            let end = match start.checked_add(self.size) {
+            let end = match start.checked_add(self.chunk_size) {
                 Some(sum) => cmp::min(self.v.len(), sum),
                 None => self.v.len(),
             };
@@ -2195,7 +2280,7 @@
         if self.v.is_empty() {
             None
         } else {
-            let start = (self.v.len() - 1) / self.size * self.size;
+            let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size;
             Some(&self.v[start..])
         }
     }
@@ -2208,8 +2293,8 @@
         if self.v.is_empty() {
             None
         } else {
-            let remainder = self.v.len() % self.size;
-            let chunksz = if remainder != 0 { remainder } else { self.size };
+            let remainder = self.v.len() % self.chunk_size;
+            let chunksz = if remainder != 0 { remainder } else { self.chunk_size };
             let (fst, snd) = self.v.split_at(self.v.len() - chunksz);
             self.v = fst;
             Some(snd)
@@ -2223,7 +2308,20 @@
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T> FusedIterator for Chunks<'a, T> {}
 
-/// An iterator over a slice in (non-overlapping) mutable chunks (`size`
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
+        let start = i * self.chunk_size;
+        let end = match start.checked_add(self.chunk_size) {
+            None => self.v.len(),
+            Some(end) => cmp::min(end, self.v.len()),
+        };
+        from_raw_parts(self.v.as_ptr().offset(start as isize), end - start)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
+
+/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
 /// elements at a time). When the slice len is not evenly divided by the chunk
 /// size, the last slice of the iteration will be the remainder.
 ///
@@ -2326,6 +2424,222 @@
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T> FusedIterator for ChunksMut<'a, T> {}
 
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
+        let start = i * self.chunk_size;
+        let end = match start.checked_add(self.chunk_size) {
+            None => self.v.len(),
+            Some(end) => cmp::min(end, self.v.len()),
+        };
+        from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), end - start)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
+
+/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
+/// time).
+///
+/// When the slice len is not evenly divided by the chunk size, the last
+/// up to `chunk_size-1` elements will be omitted.
+///
+/// This struct is created by the [`exact_chunks`] method on [slices].
+///
+/// [`exact_chunks`]: ../../std/primitive.slice.html#method.exact_chunks
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub struct ExactChunks<'a, T:'a> {
+    v: &'a [T],
+    chunk_size: usize
+}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Clone for ExactChunks<'a, T> {
+    fn clone(&self) -> ExactChunks<'a, T> {
+        ExactChunks {
+            v: self.v,
+            chunk_size: self.chunk_size,
+        }
+    }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Iterator for ExactChunks<'a, T> {
+    type Item = &'a [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.v.len() < self.chunk_size {
+            None
+        } else {
+            let (fst, snd) = self.v.split_at(self.chunk_size);
+            self.v = snd;
+            Some(fst)
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let n = self.v.len() / self.chunk_size;
+        (n, Some(n))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        let (start, overflow) = n.overflowing_mul(self.chunk_size);
+        if start >= self.v.len() || overflow {
+            self.v = &[];
+            None
+        } else {
+            let (_, snd) = self.v.split_at(start);
+            self.v = snd;
+            self.next()
+        }
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<Self::Item> {
+        self.next_back()
+    }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> DoubleEndedIterator for ExactChunks<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        if self.v.len() < self.chunk_size {
+            None
+        } else {
+            let (fst, snd) = self.v.split_at(self.v.len() - self.chunk_size);
+            self.v = fst;
+            Some(snd)
+        }
+    }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> {
+    fn is_empty(&self) -> bool {
+        self.v.is_empty()
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for ExactChunks<'a, T> {}
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ExactChunks<'a, T> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
+        let start = i * self.chunk_size;
+        from_raw_parts(self.v.as_ptr().offset(start as isize), self.chunk_size)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
+
+/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
+/// elements at a time). When the slice len is not evenly divided by the chunk
+/// size, the last up to `chunk_size-1` elements will be omitted.
+///
+/// This struct is created by the [`exact_chunks_mut`] method on [slices].
+///
+/// [`exact_chunks_mut`]: ../../std/primitive.slice.html#method.exact_chunks_mut
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[unstable(feature = "exact_chunks", issue = "47115")]
+pub struct ExactChunksMut<'a, T:'a> {
+    v: &'a mut [T],
+    chunk_size: usize
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> Iterator for ExactChunksMut<'a, T> {
+    type Item = &'a mut [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a mut [T]> {
+        if self.v.len() < self.chunk_size {
+            None
+        } else {
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let (head, tail) = tmp.split_at_mut(self.chunk_size);
+            self.v = tail;
+            Some(head)
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let n = self.v.len() / self.chunk_size;
+        (n, Some(n))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
+        let (start, overflow) = n.overflowing_mul(self.chunk_size);
+        if start >= self.v.len() || overflow {
+            self.v = &mut [];
+            None
+        } else {
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let (_, snd) = tmp.split_at_mut(start);
+            self.v = snd;
+            self.next()
+        }
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<Self::Item> {
+        self.next_back()
+    }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> DoubleEndedIterator for ExactChunksMut<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a mut [T]> {
+        if self.v.len() < self.chunk_size {
+            None
+        } else {
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let tmp_len = tmp.len();
+            let (head, tail) = tmp.split_at_mut(tmp_len - self.chunk_size);
+            self.v = head;
+            Some(tail)
+        }
+    }
+}
+
+#[unstable(feature = "exact_chunks", issue = "47115")]
+impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> {
+    fn is_empty(&self) -> bool {
+        self.v.is_empty()
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {}
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
+        let start = i * self.chunk_size;
+        from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), self.chunk_size)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
+
 //
 // Free functions
 //
@@ -2614,3 +2928,27 @@
     }
     fn may_have_side_effect() -> bool { false }
 }
+
+trait SliceContains: Sized {
+    fn slice_contains(&self, x: &[Self]) -> bool;
+}
+
+impl<T> SliceContains for T where T: PartialEq {
+    default fn slice_contains(&self, x: &[Self]) -> bool {
+        x.iter().any(|y| *y == *self)
+    }
+}
+
+impl SliceContains for u8 {
+    fn slice_contains(&self, x: &[Self]) -> bool {
+        memchr::memchr(*self, x).is_some()
+    }
+}
+
+impl SliceContains for i8 {
+    fn slice_contains(&self, x: &[Self]) -> bool {
+        let byte = *self as u8;
+        let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr() as *const u8, x.len()) };
+        memchr::memchr(byte, bytes).is_some()
+    }
+}
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 1ca995c..765b369 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1997,7 +1997,9 @@
         }
     }
 
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
+    #[unstable(feature = "inclusive_range",
+               reason = "recently added, follows RFC",
+               issue = "28237")]
     impl SliceIndex<str> for ops::RangeInclusive<usize> {
         type Output = str;
         #[inline]
@@ -2040,7 +2042,9 @@
 
 
 
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
+    #[unstable(feature = "inclusive_range",
+               reason = "recently added, follows RFC",
+               issue = "28237")]
     impl SliceIndex<str> for ops::RangeToInclusive<usize> {
         type Output = str;
         #[inline]
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index edb7bed..089d691 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -19,6 +19,7 @@
 
 use cmp;
 use fmt;
+use slice::memchr;
 use usize;
 
 // Pattern
@@ -127,6 +128,11 @@
     fn next(&mut self) -> SearchStep;
 
     /// Find the next `Match` result. See `next()`
+    ///
+    /// Unlike next(), there is no guarantee that the returned ranges
+    /// of this and next_reject will overlap. This will return (start_match, end_match),
+    /// where start_match is the index of where the match begins, and end_match is
+    /// the index after the end of the match.
     #[inline]
     fn next_match(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -138,7 +144,10 @@
         }
     }
 
-    /// Find the next `Reject` result. See `next()`
+    /// Find the next `Reject` result. See `next()` and `next_match()`
+    ///
+    /// Unlike next(), there is no guarantee that the returned ranges
+    /// of this and next_match will overlap.
     #[inline]
     fn next_reject(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -234,62 +243,276 @@
 /// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched.
 pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
 
+
 /////////////////////////////////////////////////////////////////////////////
-// Impl for a CharEq wrapper
+// Impl for char
+/////////////////////////////////////////////////////////////////////////////
+
+/// Associated type for `<char as Pattern<'a>>::Searcher`.
+#[derive(Clone, Debug)]
+pub struct CharSearcher<'a> {
+    haystack: &'a str,
+    // safety invariant: `finger`/`finger_back` must be a valid utf8 byte index of `haystack`
+    // This invariant can be broken *within* next_match and next_match_back, however
+    // they must exit with fingers on valid code point boundaries.
+
+    /// `finger` is the current byte index of the forward search.
+    /// Imagine that it exists before the byte at its index, i.e.
+    /// haystack[finger] is the first byte of the slice we must inspect during
+    /// forward searching
+    finger: usize,
+    /// `finger_back` is the current byte index of the reverse search.
+    /// Imagine that it exists after the byte at its index, i.e.
+    /// haystack[finger_back - 1] is the last byte of the slice we must inspect during
+    /// forward searching (and thus the first byte to be inspected when calling next_back())
+    finger_back: usize,
+    /// The character being searched for
+    needle: char,
+
+    // safety invariant: `utf8_size` must be less than 5
+    /// The number of bytes `needle` takes up when encoded in utf8
+    utf8_size: usize,
+    /// A utf8 encoded copy of the `needle`
+    utf8_encoded: [u8; 4],
+}
+
+unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
+    #[inline]
+    fn haystack(&self) -> &'a str {
+        self.haystack
+    }
+    #[inline]
+    fn next(&mut self) -> SearchStep {
+        let old_finger = self.finger;
+        let slice = unsafe { self.haystack.get_unchecked(old_finger..self.finger_back) };
+        let mut iter = slice.chars();
+        let old_len = iter.iter.len();
+        if let Some(ch) = iter.next() {
+            // add byte offset of current character
+            // without re-encoding as utf-8
+            self.finger += old_len - iter.iter.len();
+            if ch == self.needle {
+                SearchStep::Match(old_finger, self.finger)
+            } else {
+                SearchStep::Reject(old_finger, self.finger)
+            }
+        } else {
+            SearchStep::Done
+        }
+    }
+    #[inline]
+    fn next_match(&mut self) -> Option<(usize, usize)> {
+        loop {
+            // get the haystack after the last character found
+            let bytes = if let Some(slice) = self.haystack.as_bytes()
+                                                 .get(self.finger..self.finger_back) {
+                slice
+            } else {
+                return None;
+            };
+            // the last byte of the utf8 encoded needle
+            let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
+            if let Some(index) = memchr::memchr(last_byte, bytes) {
+                // The new finger is the index of the byte we found,
+                // plus one, since we memchr'd for the last byte of the character.
+                //
+                // Note that this doesn't always give us a finger on a UTF8 boundary.
+                // If we *didn't* find our character
+                // we may have indexed to the non-last byte of a 3-byte or 4-byte character.
+                // We can't just skip to the next valid starting byte because a character like
+                // ꁁ (U+A041 YI SYLLABLE PA), utf-8 `EA 81 81` will have us always find
+                // the second byte when searching for the third.
+                //
+                // However, this is totally okay. While we have the invariant that
+                // self.finger is on a UTF8 boundary, this invariant is not relid upon
+                // within this method (it is relied upon in CharSearcher::next()).
+                //
+                // We only exit this method when we reach the end of the string, or if we
+                // find something. When we find something the `finger` will be set
+                // to a UTF8 boundary.
+                self.finger += index + 1;
+                if self.finger >= self.utf8_size {
+                    let found_char = self.finger - self.utf8_size;
+                    if let Some(slice) = self.haystack.as_bytes().get(found_char..self.finger) {
+                        if slice == &self.utf8_encoded[0..self.utf8_size] {
+                            return Some((found_char, self.finger));
+                        }
+                    }
+                }
+            } else {
+                // found nothing, exit
+                self.finger = self.finger_back;
+                return None;
+            }
+        }
+    }
+
+    // let next_reject use the default implementation from the Searcher trait
+}
+
+unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
+    #[inline]
+    fn next_back(&mut self) -> SearchStep {
+        let old_finger = self.finger_back;
+        let slice = unsafe { self.haystack.slice_unchecked(self.finger, old_finger) };
+        let mut iter = slice.chars();
+        let old_len = iter.iter.len();
+        if let Some(ch) = iter.next_back() {
+            // subtract byte offset of current character
+            // without re-encoding as utf-8
+            self.finger_back -= old_len - iter.iter.len();
+            if ch == self.needle {
+                SearchStep::Match(self.finger_back, old_finger)
+            } else {
+                SearchStep::Reject(self.finger_back, old_finger)
+            }
+        } else {
+            SearchStep::Done
+        }
+    }
+    #[inline]
+    fn next_match_back(&mut self) -> Option<(usize, usize)> {
+        let haystack = self.haystack.as_bytes();
+        loop {
+            // get the haystack up to but not including the last character searched
+            let bytes = if let Some(slice) = haystack.get(self.finger..self.finger_back) {
+                slice
+            } else {
+                return None;
+            };
+            // the last byte of the utf8 encoded needle
+            let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
+            if let Some(index) = memchr::memrchr(last_byte, bytes) {
+                // we searched a slice that was offset by self.finger,
+                // add self.finger to recoup the original index
+                let index = self.finger + index;
+                // memrchr will return the index of the byte we wish to
+                // find. In case of an ASCII character, this is indeed
+                // were we wish our new finger to be ("after" the found
+                // char in the paradigm of reverse iteration). For
+                // multibyte chars we need to skip down by the number of more
+                // bytes they have than ASCII
+                let shift = self.utf8_size - 1;
+                if index >= shift {
+                    let found_char = index - shift;
+                    if let Some(slice) = haystack.get(found_char..(found_char + self.utf8_size)) {
+                        if slice == &self.utf8_encoded[0..self.utf8_size] {
+                            // move finger to before the character found (i.e. at its start index)
+                            self.finger_back = found_char;
+                            return Some((self.finger_back, self.finger_back + self.utf8_size));
+                        }
+                    }
+                }
+                // We can't use finger_back = index - size + 1 here. If we found the last char
+                // of a different-sized character (or the middle byte of a different character)
+                // we need to bump the finger_back down to `index`. This similarly makes
+                // `finger_back` have the potential to no longer be on a boundary,
+                // but this is OK since we only exit this function on a boundary
+                // or when the haystack has been searched completely.
+                //
+                // Unlike next_match this does not
+                // have the problem of repeated bytes in utf-8 because
+                // we're searching for the last byte, and we can only have
+                // found the last byte when searching in reverse.
+                self.finger_back = index;
+            } else {
+                self.finger_back = self.finger;
+                // found nothing, exit
+                return None;
+            }
+        }
+    }
+
+    // let next_reject_back use the default implementation from the Searcher trait
+}
+
+impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
+
+/// Searches for chars that are equal to a given char
+impl<'a> Pattern<'a> for char {
+    type Searcher = CharSearcher<'a>;
+
+    #[inline]
+    fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
+        let mut utf8_encoded = [0; 4];
+        self.encode_utf8(&mut utf8_encoded);
+        let utf8_size = self.len_utf8();
+        CharSearcher {
+            haystack,
+            finger: 0,
+            finger_back: haystack.len(),
+            needle: self,
+            utf8_size,
+            utf8_encoded
+        }
+    }
+
+    #[inline]
+    fn is_contained_in(self, haystack: &'a str) -> bool {
+        if (self as u32) < 128 {
+            haystack.as_bytes().contains(&(self as u8))
+        } else {
+            let mut buffer = [0u8; 4];
+            self.encode_utf8(&mut buffer).is_contained_in(haystack)
+        }
+    }
+
+    #[inline]
+    fn is_prefix_of(self, haystack: &'a str) -> bool {
+        if let Some(ch) = haystack.chars().next() {
+            self == ch
+        } else {
+            false
+        }
+    }
+
+    #[inline]
+    fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a>
+    {
+        if let Some(ch) = haystack.chars().next_back() {
+            self == ch
+        } else {
+            false
+        }
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Impl for a MultiCharEq wrapper
 /////////////////////////////////////////////////////////////////////////////
 
 #[doc(hidden)]
-trait CharEq {
+trait MultiCharEq {
     fn matches(&mut self, c: char) -> bool;
-    fn only_ascii(&self) -> bool;
 }
 
-impl CharEq for char {
-    #[inline]
-    fn matches(&mut self, c: char) -> bool { *self == c }
-
-    #[inline]
-    fn only_ascii(&self) -> bool { (*self as u32) < 128 }
-}
-
-impl<F> CharEq for F where F: FnMut(char) -> bool {
+impl<F> MultiCharEq for F where F: FnMut(char) -> bool {
     #[inline]
     fn matches(&mut self, c: char) -> bool { (*self)(c) }
-
-    #[inline]
-    fn only_ascii(&self) -> bool { false }
 }
 
-impl<'a> CharEq for &'a [char] {
+impl<'a> MultiCharEq for &'a [char] {
     #[inline]
     fn matches(&mut self, c: char) -> bool {
-        self.iter().any(|&m| { let mut m = m; m.matches(c) })
-    }
-
-    #[inline]
-    fn only_ascii(&self) -> bool {
-        self.iter().all(|m| m.only_ascii())
+        self.iter().any(|&m| { m == c })
     }
 }
 
-struct CharEqPattern<C: CharEq>(C);
+struct MultiCharEqPattern<C: MultiCharEq>(C);
 
 #[derive(Clone, Debug)]
-struct CharEqSearcher<'a, C: CharEq> {
+struct MultiCharEqSearcher<'a, C: MultiCharEq> {
     char_eq: C,
     haystack: &'a str,
     char_indices: super::CharIndices<'a>,
-    #[allow(dead_code)]
-    ascii_only: bool,
 }
 
-impl<'a, C: CharEq> Pattern<'a> for CharEqPattern<C> {
-    type Searcher = CharEqSearcher<'a, C>;
+impl<'a, C: MultiCharEq> Pattern<'a> for MultiCharEqPattern<C> {
+    type Searcher = MultiCharEqSearcher<'a, C>;
 
     #[inline]
-    fn into_searcher(self, haystack: &'a str) -> CharEqSearcher<'a, C> {
-        CharEqSearcher {
-            ascii_only: self.0.only_ascii(),
+    fn into_searcher(self, haystack: &'a str) -> MultiCharEqSearcher<'a, C> {
+        MultiCharEqSearcher {
             haystack,
             char_eq: self.0,
             char_indices: haystack.char_indices(),
@@ -297,7 +520,7 @@
     }
 }
 
-unsafe impl<'a, C: CharEq> Searcher<'a> for CharEqSearcher<'a, C> {
+unsafe impl<'a, C: MultiCharEq> Searcher<'a> for MultiCharEqSearcher<'a, C> {
     #[inline]
     fn haystack(&self) -> &'a str {
         self.haystack
@@ -322,7 +545,7 @@
     }
 }
 
-unsafe impl<'a, C: CharEq> ReverseSearcher<'a> for CharEqSearcher<'a, C> {
+unsafe impl<'a, C: MultiCharEq> ReverseSearcher<'a> for MultiCharEqSearcher<'a, C> {
     #[inline]
     fn next_back(&mut self) -> SearchStep {
         let s = &mut self.char_indices;
@@ -342,7 +565,7 @@
     }
 }
 
-impl<'a, C: CharEq> DoubleEndedSearcher<'a> for CharEqSearcher<'a, C> {}
+impl<'a, C: MultiCharEq> DoubleEndedSearcher<'a> for MultiCharEqSearcher<'a, C> {}
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -410,55 +633,6 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////
-// Impl for char
-/////////////////////////////////////////////////////////////////////////////
-
-/// Associated type for `<char as Pattern<'a>>::Searcher`.
-#[derive(Clone, Debug)]
-pub struct CharSearcher<'a>(<CharEqPattern<char> as Pattern<'a>>::Searcher);
-
-unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
-    searcher_methods!(forward);
-}
-
-unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
-    searcher_methods!(reverse);
-}
-
-impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
-
-/// Searches for chars that are equal to a given char
-impl<'a> Pattern<'a> for char {
-    type Searcher = CharSearcher<'a>;
-
-    #[inline]
-    fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
-        CharSearcher(CharEqPattern(self).into_searcher(haystack))
-    }
-
-    #[inline]
-    fn is_contained_in(self, haystack: &'a str) -> bool {
-        if (self as u32) < 128 {
-            haystack.as_bytes().contains(&(self as u8))
-        } else {
-            let mut buffer = [0u8; 4];
-            self.encode_utf8(&mut buffer).is_contained_in(haystack)
-        }
-    }
-
-    #[inline]
-    fn is_prefix_of(self, haystack: &'a str) -> bool {
-        CharEqPattern(self).is_prefix_of(haystack)
-    }
-
-    #[inline]
-    fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a>
-    {
-        CharEqPattern(self).is_suffix_of(haystack)
-    }
-}
-
-/////////////////////////////////////////////////////////////////////////////
 // Impl for &[char]
 /////////////////////////////////////////////////////////////////////////////
 
@@ -466,7 +640,7 @@
 
 /// Associated type for `<&[char] as Pattern<'a>>::Searcher`.
 #[derive(Clone, Debug)]
-pub struct CharSliceSearcher<'a, 'b>(<CharEqPattern<&'b [char]> as Pattern<'a>>::Searcher);
+pub struct CharSliceSearcher<'a, 'b>(<MultiCharEqPattern<&'b [char]> as Pattern<'a>>::Searcher);
 
 unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> {
     searcher_methods!(forward);
@@ -480,7 +654,7 @@
 
 /// Searches for chars that are equal to any of the chars in the array
 impl<'a, 'b> Pattern<'a> for &'b [char] {
-    pattern_methods!(CharSliceSearcher<'a, 'b>, CharEqPattern, CharSliceSearcher);
+    pattern_methods!(CharSliceSearcher<'a, 'b>, MultiCharEqPattern, CharSliceSearcher);
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -489,7 +663,7 @@
 
 /// Associated type for `<F as Pattern<'a>>::Searcher`.
 #[derive(Clone)]
-pub struct CharPredicateSearcher<'a, F>(<CharEqPattern<F> as Pattern<'a>>::Searcher)
+pub struct CharPredicateSearcher<'a, F>(<MultiCharEqPattern<F> as Pattern<'a>>::Searcher)
     where F: FnMut(char) -> bool;
 
 impl<'a, F> fmt::Debug for CharPredicateSearcher<'a, F>
@@ -499,7 +673,6 @@
         f.debug_struct("CharPredicateSearcher")
             .field("haystack", &self.0.haystack)
             .field("char_indices", &self.0.char_indices)
-            .field("ascii_only", &self.0.ascii_only)
             .finish()
     }
 }
@@ -520,7 +693,7 @@
 
 /// Searches for chars that match the given predicate
 impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
-    pattern_methods!(CharPredicateSearcher<'a, F>, CharEqPattern, CharPredicateSearcher);
+    pattern_methods!(CharPredicateSearcher<'a, F>, MultiCharEqPattern, CharPredicateSearcher);
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index e334d20..3da9e9c 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -944,6 +944,7 @@
      $stable_cxchg:meta,
      $stable_debug:meta,
      $stable_access:meta,
+     $stable_from:meta,
      $s_int_type:expr, $int_ref:expr,
      $int_type:ident $atomic_type:ident $atomic_init:ident) => {
         /// An integer type which can be safely shared between threads.
@@ -978,7 +979,7 @@
             }
         }
 
-        #[stable(feature = "atomic_from", since = "1.23.0")]
+        #[$stable_from]
         impl From<$int_type> for $atomic_type {
             #[inline]
             fn from(v: $int_type) -> Self { Self::new(v) }
@@ -1375,6 +1376,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i8", "../../../std/primitive.i8.html",
     i8 AtomicI8 ATOMIC_I8_INIT
 }
@@ -1384,6 +1386,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u8", "../../../std/primitive.u8.html",
     u8 AtomicU8 ATOMIC_U8_INIT
 }
@@ -1393,6 +1396,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i16", "../../../std/primitive.i16.html",
     i16 AtomicI16 ATOMIC_I16_INIT
 }
@@ -1402,6 +1406,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u16", "../../../std/primitive.u16.html",
     u16 AtomicU16 ATOMIC_U16_INIT
 }
@@ -1411,6 +1416,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i32", "../../../std/primitive.i32.html",
     i32 AtomicI32 ATOMIC_I32_INIT
 }
@@ -1420,6 +1426,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u32", "../../../std/primitive.u32.html",
     u32 AtomicU32 ATOMIC_U32_INIT
 }
@@ -1429,6 +1436,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "i64", "../../../std/primitive.i64.html",
     i64 AtomicI64 ATOMIC_I64_INIT
 }
@@ -1438,6 +1446,7 @@
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    unstable(feature = "integer_atomics", issue = "32976"),
     "u64", "../../../std/primitive.u64.html",
     u64 AtomicU64 ATOMIC_U64_INIT
 }
@@ -1447,6 +1456,7 @@
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
+    stable(feature = "atomic_from", since = "1.23.0"),
     "isize", "../../../std/primitive.isize.html",
     isize AtomicIsize ATOMIC_ISIZE_INIT
 }
@@ -1456,6 +1466,7 @@
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
+    stable(feature = "atomic_from", since = "1.23.0"),
     "usize", "../../../std/primitive.usize.html",
     usize AtomicUsize ATOMIC_USIZE_INIT
 }
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 5cac5b2..8997cf9 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1353,6 +1353,51 @@
 }
 
 #[test]
+fn test_range_last_max() {
+    assert_eq!((0..20).last(), Some(19));
+    assert_eq!((-20..0).last(), Some(-1));
+    assert_eq!((5..5).last(), None);
+
+    assert_eq!((0..20).max(), Some(19));
+    assert_eq!((-20..0).max(), Some(-1));
+    assert_eq!((5..5).max(), None);
+}
+
+#[test]
+fn test_range_inclusive_last_max() {
+    assert_eq!((0..=20).last(), Some(20));
+    assert_eq!((-20..=0).last(), Some(0));
+    assert_eq!((5..=5).last(), Some(5));
+    let mut r = 10..=10;
+    r.next();
+    assert_eq!(r.last(), None);
+
+    assert_eq!((0..=20).max(), Some(20));
+    assert_eq!((-20..=0).max(), Some(0));
+    assert_eq!((5..=5).max(), Some(5));
+    let mut r = 10..=10;
+    r.next();
+    assert_eq!(r.max(), None);
+}
+
+#[test]
+fn test_range_min() {
+    assert_eq!((0..20).min(), Some(0));
+    assert_eq!((-20..0).min(), Some(-20));
+    assert_eq!((5..5).min(), None);
+}
+
+#[test]
+fn test_range_inclusive_min() {
+    assert_eq!((0..=20).min(), Some(0));
+    assert_eq!((-20..=0).min(), Some(-20));
+    assert_eq!((5..=5).min(), Some(5));
+    let mut r = 10..=10;
+    r.next();
+    assert_eq!(r.min(), None);
+}
+
+#[test]
 fn test_repeat() {
     let mut it = repeat(42);
     assert_eq!(it.next(), Some(42));
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 0e445cd..1c32452 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -28,6 +28,7 @@
 #![feature(iter_rfind)]
 #![feature(iter_rfold)]
 #![feature(nonzero)]
+#![feature(pattern)]
 #![feature(raw)]
 #![feature(refcell_replace_swap)]
 #![feature(sip_hash_13)]
@@ -40,7 +41,7 @@
 #![feature(trusted_len)]
 #![feature(try_from)]
 #![feature(try_trait)]
-#![feature(unique)]
+#![feature(exact_chunks)]
 
 extern crate core;
 extern crate test;
@@ -61,6 +62,7 @@
 mod num;
 mod ops;
 mod option;
+mod pattern;
 mod ptr;
 mod result;
 mod slice;
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
index 7eb5ff9..587dcbe 100644
--- a/src/libcore/tests/num/mod.rs
+++ b/src/libcore/tests/num/mod.rs
@@ -197,7 +197,6 @@
 test_impl_from! { test_u32f64, u32, f64 }
 
 // Float -> Float
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn test_f32f64() {
     use core::f32;
diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs
index b81b387..9d2fa1a 100644
--- a/src/libcore/tests/ops.rs
+++ b/src/libcore/tests/ops.rs
@@ -67,4 +67,4 @@
     r = RangeInclusive { start: 1, end: -1 };
     assert_eq!(r.size_hint(), (0, Some(0)));
     assert_eq!(r.next(), None);
-}
\ No newline at end of file
+}
diff --git a/src/libcore/tests/pattern.rs b/src/libcore/tests/pattern.rs
new file mode 100644
index 0000000..cfa3b7e
--- /dev/null
+++ b/src/libcore/tests/pattern.rs
@@ -0,0 +1,302 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::str::pattern::*;
+
+// This macro makes it easier to write
+// tests that do a series of iterations
+macro_rules! search_asserts {
+    ($haystack:expr, $needle:expr, $testname:expr, [$($func:ident),*], $result:expr) => {
+        let mut searcher = $needle.into_searcher($haystack);
+        let arr = [$( Step::from(searcher.$func()) ),+];
+        assert_eq!(&arr[..], &$result, $testname);
+    }
+}
+
+/// Combined enum for the results of next() and next_match()/next_reject()
+#[derive(Debug, PartialEq, Eq)]
+enum Step {
+    // variant names purposely chosen to
+    // be the same length for easy alignment
+    Matches(usize, usize),
+    Rejects(usize, usize),
+    InRange(usize, usize),
+    Done
+}
+
+use self::Step::*;
+
+impl From<SearchStep> for Step {
+    fn from(x: SearchStep) -> Self {
+        match x {
+            SearchStep::Match(a, b) => Matches(a, b),
+            SearchStep::Reject(a, b) => Rejects(a, b),
+            SearchStep::Done => Done
+        }
+    }
+}
+
+impl From<Option<(usize, usize)>> for Step {
+    fn from(x: Option<(usize, usize)>) -> Self {
+        match x {
+            Some((a, b)) => InRange(a, b),
+            None => Done
+        }
+    }
+}
+
+// ignore-tidy-linelength
+
+// FIXME(Manishearth) these tests focus on single-character searching  (CharSearcher)
+// and on next()/next_match(), not next_reject(). This is because
+// the memchr changes make next_match() for single chars complex, but next_reject()
+// continues to use next() under the hood. We should add more test cases for all
+// of these, as well as tests for StrSearcher and higher level tests for str::find() (etc)
+
+#[test]
+fn test_simple_iteration() {
+    search_asserts! ("abcdeabcd", 'a', "forward iteration for ASCII string",
+        // a            b              c              d              e              a              b              c              d              EOF
+        [next,          next,          next,          next,          next,          next,          next,          next,          next,          next],
+        [Matches(0, 1), Rejects(1, 2), Rejects(2, 3), Rejects(3, 4), Rejects(4, 5), Matches(5, 6), Rejects(6, 7), Rejects(7, 8), Rejects(8, 9), Done]
+    );
+
+    search_asserts! ("abcdeabcd", 'a', "reverse iteration for ASCII string",
+        // d            c              b              a            e                d              c              b              a             EOF
+        [next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back,     next_back],
+        [Rejects(8, 9), Rejects(7, 8), Rejects(6, 7), Matches(5, 6), Rejects(4, 5), Rejects(3, 4), Rejects(2, 3), Rejects(1, 2), Matches(0, 1), Done]
+    );
+
+    search_asserts! ("我爱我的猫", '我', "forward iteration for Chinese string",
+        // 我           愛             我             的              貓               EOF
+        [next,          next,          next,          next,           next,            next],
+        [Matches(0, 3), Rejects(3, 6), Matches(6, 9), Rejects(9, 12), Rejects(12, 15), Done]
+    );
+
+    search_asserts! ("我的猫说meow", 'm', "forward iteration for mixed string",
+        // 我           的             猫             说              m                e                o                w                EOF
+        [next,          next,          next,          next,           next,            next,            next,            next,            next],
+        [Rejects(0, 3), Rejects(3, 6), Rejects(6, 9), Rejects(9, 12), Matches(12, 13), Rejects(13, 14), Rejects(14, 15), Rejects(15, 16), Done]
+    );
+
+    search_asserts! ("我的猫说meow", '猫', "reverse iteration for mixed string",
+        // w             o                 e                m                说              猫             的             我             EOF
+        [next_back,       next_back,       next_back,       next_back,       next_back,      next_back,      next_back,    next_back,     next_back],
+        [Rejects(15, 16), Rejects(14, 15), Rejects(13, 14), Rejects(12, 13), Rejects(9, 12), Matches(6, 9), Rejects(3, 6), Rejects(0, 3), Done]
+    );
+}
+
+#[test]
+fn test_simple_search() {
+    search_asserts!("abcdeabcdeabcde", 'a', "next_match for ASCII string",
+        [next_match,    next_match,    next_match,      next_match],
+        [InRange(0, 1), InRange(5, 6), InRange(10, 11), Done]
+    );
+
+    search_asserts!("abcdeabcdeabcde", 'a', "next_match_back for ASCII string",
+        [next_match_back, next_match_back, next_match_back, next_match_back],
+        [InRange(10, 11), InRange(5, 6),   InRange(0, 1),   Done]
+    );
+
+    search_asserts!("abcdeab", 'a', "next_reject for ASCII string",
+        [next_reject,   next_reject,   next_match,    next_reject,   next_reject],
+        [InRange(1, 2), InRange(2, 3), InRange(5, 6), InRange(6, 7), Done]
+    );
+
+    search_asserts!("abcdeabcdeabcde", 'a', "next_reject_back for ASCII string",
+        [next_reject_back, next_reject_back, next_match_back, next_reject_back, next_reject_back, next_reject_back],
+        [InRange(14, 15),  InRange(13, 14),  InRange(10, 11), InRange(9, 10),   InRange(8, 9),    InRange(7, 8)]
+    );
+}
+
+// Á, 각, ก, 😀 all end in 0x81
+// 🁀, ᘀ do not end in 0x81 but contain the byte
+// ꁁ has 0x81 as its second and third bytes.
+//
+// The memchr-using implementation of next_match
+// and next_match_back temporarily violate
+// the property that the search is always on a unicode boundary,
+// which is fine as long as this never reaches next() or next_back().
+// So we test if next() is correct after each next_match() as well.
+const STRESS: &str = "Áa🁀bÁꁁfg😁각กᘀ각aÁ각ꁁก😁a";
+
+#[test]
+fn test_stress_indices() {
+    // this isn't really a test, more of documentation on the indices of each character in the stresstest string
+
+    search_asserts!(STRESS, 'x', "Indices of characters in stress test",
+        [next, next, next, next, next, next, next, next, next, next, next, next, next, next, next, next, next, next, next, next, next],
+        [Rejects(0, 2), // Á
+         Rejects(2, 3), // a
+         Rejects(3, 7), // 🁀
+         Rejects(7, 8), // b
+         Rejects(8, 10), // Á
+         Rejects(10, 13), // ꁁ
+         Rejects(13, 14), // f
+         Rejects(14, 15), // g
+         Rejects(15, 19), // 😀
+         Rejects(19, 22), // 각
+         Rejects(22, 25), // ก
+         Rejects(25, 28), // ᘀ
+         Rejects(28, 31), // 각
+         Rejects(31, 32), // a
+         Rejects(32, 34), // Á
+         Rejects(34, 37), // 각
+         Rejects(37, 40), // ꁁ
+         Rejects(40, 43), // ก
+         Rejects(43, 47), // 😀
+         Rejects(47, 48), // a
+         Done]
+    );
+}
+
+#[test]
+fn test_forward_search_shared_bytes() {
+    search_asserts!(STRESS, 'Á', "Forward search for two-byte Latin character",
+        [next_match,    next_match,     next_match,      next_match],
+        [InRange(0, 2), InRange(8, 10), InRange(32, 34), Done]
+    );
+
+    search_asserts!(STRESS, 'Á', "Forward search for two-byte Latin character; check if next() still works",
+        [next_match,    next,          next_match,     next,             next_match,     next,            next_match],
+        [InRange(0, 2), Rejects(2, 3), InRange(8, 10), Rejects(10, 13), InRange(32, 34), Rejects(34, 37), Done]
+    );
+
+    search_asserts!(STRESS, '각', "Forward search for three-byte Hangul character",
+        [next_match,      next,            next_match,      next_match,      next_match],
+        [InRange(19, 22), Rejects(22, 25), InRange(28, 31), InRange(34, 37), Done]
+    );
+
+    search_asserts!(STRESS, '각', "Forward search for three-byte Hangul character; check if next() still works",
+        [next_match,      next,            next_match,      next,            next_match,      next,            next_match],
+        [InRange(19, 22), Rejects(22, 25), InRange(28, 31), Rejects(31, 32), InRange(34, 37), Rejects(37, 40), Done]
+    );
+
+    search_asserts!(STRESS, 'ก', "Forward search for three-byte Thai character",
+        [next_match,      next,            next_match,      next,            next_match],
+        [InRange(22, 25), Rejects(25, 28), InRange(40, 43), Rejects(43, 47), Done]
+    );
+
+    search_asserts!(STRESS, 'ก', "Forward search for three-byte Thai character; check if next() still works",
+        [next_match,      next,            next_match,      next,            next_match],
+        [InRange(22, 25), Rejects(25, 28), InRange(40, 43), Rejects(43, 47), Done]
+    );
+
+    search_asserts!(STRESS, '😁', "Forward search for four-byte emoji",
+        [next_match,      next,            next_match,      next,            next_match],
+        [InRange(15, 19), Rejects(19, 22), InRange(43, 47), Rejects(47, 48), Done]
+    );
+
+    search_asserts!(STRESS, '😁', "Forward search for four-byte emoji; check if next() still works",
+        [next_match,      next,            next_match,      next,            next_match],
+        [InRange(15, 19), Rejects(19, 22), InRange(43, 47), Rejects(47, 48), Done]
+    );
+
+    search_asserts!(STRESS, 'ꁁ', "Forward search for three-byte Yi character with repeated bytes",
+        [next_match,      next,            next_match,      next,            next_match],
+        [InRange(10, 13), Rejects(13, 14), InRange(37, 40), Rejects(40, 43), Done]
+    );
+
+    search_asserts!(STRESS, 'ꁁ', "Forward search for three-byte Yi character with repeated bytes; check if next() still works",
+        [next_match,      next,            next_match,      next,            next_match],
+        [InRange(10, 13), Rejects(13, 14), InRange(37, 40), Rejects(40, 43), Done]
+    );
+}
+
+#[test]
+fn test_reverse_search_shared_bytes() {
+    search_asserts!(STRESS, 'Á', "Reverse search for two-byte Latin character",
+        [next_match_back, next_match_back, next_match_back, next_match_back],
+        [InRange(32, 34), InRange(8, 10),  InRange(0, 2),   Done]
+    );
+
+    search_asserts!(STRESS, 'Á', "Reverse search for two-byte Latin character; check if next_back() still works",
+        [next_match_back, next_back,       next_match_back, next_back,     next_match_back, next_back],
+        [InRange(32, 34), Rejects(31, 32), InRange(8, 10),  Rejects(7, 8), InRange(0, 2),   Done]
+    );
+
+    search_asserts!(STRESS, '각', "Reverse search for three-byte Hangul character",
+        [next_match_back, next_back,        next_match_back, next_match_back, next_match_back],
+        [InRange(34, 37), Rejects(32, 34), InRange(28, 31),  InRange(19, 22), Done]
+    );
+
+    search_asserts!(STRESS, '각', "Reverse search for three-byte Hangul character; check if next_back() still works",
+        [next_match_back, next_back,       next_match_back, next_back,       next_match_back, next_back,       next_match_back],
+        [InRange(34, 37), Rejects(32, 34), InRange(28, 31), Rejects(25, 28), InRange(19, 22), Rejects(15, 19), Done]
+    );
+
+    search_asserts!(STRESS, 'ก', "Reverse search for three-byte Thai character",
+        [next_match_back, next_back,       next_match_back, next_back,       next_match_back],
+        [InRange(40, 43), Rejects(37, 40), InRange(22, 25), Rejects(19, 22), Done]
+    );
+
+    search_asserts!(STRESS, 'ก', "Reverse search for three-byte Thai character; check if next_back() still works",
+        [next_match_back, next_back,       next_match_back, next_back,       next_match_back],
+        [InRange(40, 43), Rejects(37, 40), InRange(22, 25), Rejects(19, 22), Done]
+    );
+
+    search_asserts!(STRESS, '😁', "Reverse search for four-byte emoji",
+        [next_match_back, next_back,       next_match_back, next_back,       next_match_back],
+        [InRange(43, 47), Rejects(40, 43), InRange(15, 19), Rejects(14, 15), Done]
+    );
+
+    search_asserts!(STRESS, '😁', "Reverse search for four-byte emoji; check if next_back() still works",
+        [next_match_back, next_back,       next_match_back, next_back,       next_match_back],
+        [InRange(43, 47), Rejects(40, 43), InRange(15, 19), Rejects(14, 15), Done]
+    );
+
+    search_asserts!(STRESS, 'ꁁ', "Reverse search for three-byte Yi character with repeated bytes",
+        [next_match_back, next_back,       next_match_back, next_back,      next_match_back],
+        [InRange(37, 40), Rejects(34, 37), InRange(10, 13), Rejects(8, 10), Done]
+    );
+
+    search_asserts!(STRESS, 'ꁁ', "Reverse search for three-byte Yi character with repeated bytes; check if next_back() still works",
+        [next_match_back, next_back,       next_match_back, next_back,      next_match_back],
+        [InRange(37, 40), Rejects(34, 37), InRange(10, 13), Rejects(8, 10), Done]
+    );
+}
+
+#[test]
+fn double_ended_regression_test() {
+    // https://github.com/rust-lang/rust/issues/47175
+    // Ensures that double ended searching comes to a convergence
+    search_asserts!("abcdeabcdeabcde", 'a', "alternating double ended search",
+        [next_match,    next_match_back,    next_match,      next_match_back],
+        [InRange(0, 1), InRange(10, 11), InRange(5, 6), Done]
+    );
+    search_asserts!("abcdeabcdeabcde", 'a', "triple double ended search for a",
+        [next_match,    next_match_back,    next_match_back,      next_match_back],
+        [InRange(0, 1), InRange(10, 11), InRange(5, 6), Done]
+    );
+    search_asserts!("abcdeabcdeabcde", 'd', "triple double ended search for d",
+        [next_match,    next_match_back,    next_match_back,      next_match_back],
+        [InRange(3, 4), InRange(13, 14), InRange(8, 9), Done]
+    );
+    search_asserts!(STRESS, 'Á', "Double ended search for two-byte Latin character",
+        [next_match,    next_match_back,     next_match,      next_match_back],
+        [InRange(0, 2), InRange(32, 34), InRange(8, 10), Done]
+    );
+    search_asserts!(STRESS, '각', "Reverse double ended search for three-byte Hangul character",
+        [next_match_back, next_back,       next_match,      next,            next_match_back, next_match],
+        [InRange(34, 37), Rejects(32, 34), InRange(19, 22), Rejects(22, 25), InRange(28, 31), Done]
+    );
+    search_asserts!(STRESS, 'ก', "Double ended search for three-byte Thai character",
+        [next_match,      next_back,       next,            next_match_back, next_match],
+        [InRange(22, 25), Rejects(47, 48), Rejects(25, 28), InRange(40, 43), Done]
+    );
+    search_asserts!(STRESS, '😁', "Double ended search for four-byte emoji",
+        [next_match_back, next,          next_match,      next_back,       next_match],
+        [InRange(43, 47), Rejects(0, 2), InRange(15, 19), Rejects(40, 43), Done]
+    );
+    search_asserts!(STRESS, 'ꁁ', "Double ended search for three-byte Yi character with repeated bytes",
+        [next_match,      next,            next_match_back, next_back,       next_match],
+        [InRange(10, 13), Rejects(13, 14), InRange(37, 40), Rejects(34, 37), Done]
+    );
+}
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index 98436f0..00f8733 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -249,9 +249,9 @@
 }
 
 #[test]
-fn test_unsized_unique() {
+fn test_unsized_nonnull() {
     let xs: &[i32] = &[1, 2, 3];
-    let ptr = unsafe { Unique::new_unchecked(xs as *const [i32] as *mut [i32]) };
+    let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
     let ys = unsafe { ptr.as_ref() };
     let zs: &[i32] = &[1, 2, 3];
     assert!(ys == zs);
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index fa4c2e9..13740b9 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -10,6 +10,25 @@
 
 use core::result::Result::{Ok, Err};
 
+
+#[test]
+fn test_position() {
+    let b = [1, 2, 3, 5, 5];
+    assert!(b.iter().position(|&v| v == 9) == None);
+    assert!(b.iter().position(|&v| v == 5) == Some(3));
+    assert!(b.iter().position(|&v| v == 3) == Some(2));
+    assert!(b.iter().position(|&v| v == 0) == None);
+}
+
+#[test]
+fn test_rposition() {
+    let b = [1, 2, 3, 5, 5];
+    assert!(b.iter().rposition(|&v| v == 9) == None);
+    assert!(b.iter().rposition(|&v| v == 5) == Some(4));
+    assert!(b.iter().rposition(|&v| v == 3) == Some(2));
+    assert!(b.iter().rposition(|&v| v == 0) == None);
+}
+
 #[test]
 fn test_binary_search() {
     let b: [i32; 0] = [];
@@ -117,12 +136,12 @@
 fn test_chunks_nth() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
     let mut c = v.chunks(2);
-    assert_eq!(c.nth(1).unwrap()[1], 3);
-    assert_eq!(c.next().unwrap()[0], 4);
+    assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[4, 5]);
 
     let v2: &[i32] = &[0, 1, 2, 3, 4];
     let mut c2 = v2.chunks(3);
-    assert_eq!(c2.nth(1).unwrap()[1], 4);
+    assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
     assert_eq!(c2.next(), None);
 }
 
@@ -138,6 +157,18 @@
 }
 
 #[test]
+fn test_chunks_zip() {
+    let v1: &[i32] = &[0, 1, 2, 3, 4];
+    let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+    let res = v1.chunks(2)
+        .zip(v2.chunks(2))
+        .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
+        .collect::<Vec<_>>();
+    assert_eq!(res, vec![14, 22, 14]);
+}
+
+#[test]
 fn test_chunks_mut_count() {
     let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
     let c = v.chunks_mut(3);
@@ -156,12 +187,12 @@
 fn test_chunks_mut_nth() {
     let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
     let mut c = v.chunks_mut(2);
-    assert_eq!(c.nth(1).unwrap()[1], 3);
-    assert_eq!(c.next().unwrap()[0], 4);
+    assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[4, 5]);
 
     let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
     let mut c2 = v2.chunks_mut(3);
-    assert_eq!(c2.nth(1).unwrap()[1], 4);
+    assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
     assert_eq!(c2.next(), None);
 }
 
@@ -169,11 +200,129 @@
 fn test_chunks_mut_last() {
     let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
     let c = v.chunks_mut(2);
-    assert_eq!(c.last().unwrap()[1], 5);
+    assert_eq!(c.last().unwrap(), &[4, 5]);
 
     let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
     let c2 = v2.chunks_mut(2);
-    assert_eq!(c2.last().unwrap()[0], 4);
+    assert_eq!(c2.last().unwrap(), &[4]);
+}
+
+#[test]
+fn test_chunks_mut_zip() {
+    let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+    for (a, b) in v1.chunks_mut(2).zip(v2.chunks(2)) {
+        let sum = b.iter().sum::<i32>();
+        for v in a {
+            *v += sum;
+        }
+    }
+    assert_eq!(v1, [13, 14, 19, 20, 14]);
+}
+
+#[test]
+fn test_exact_chunks_count() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.exact_chunks(3);
+    assert_eq!(c.count(), 2);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.exact_chunks(2);
+    assert_eq!(c2.count(), 2);
+
+    let v3: &[i32] = &[];
+    let c3 = v3.exact_chunks(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_exact_chunks_nth() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.exact_chunks(2);
+    assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[4, 5]);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
+    let mut c2 = v2.exact_chunks(3);
+    assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_exact_chunks_last() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.exact_chunks(2);
+    assert_eq!(c.last().unwrap(), &[4, 5]);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.exact_chunks(2);
+    assert_eq!(c2.last().unwrap(), &[2, 3]);
+}
+
+#[test]
+fn test_exact_chunks_zip() {
+    let v1: &[i32] = &[0, 1, 2, 3, 4];
+    let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+    let res = v1.exact_chunks(2)
+        .zip(v2.exact_chunks(2))
+        .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
+        .collect::<Vec<_>>();
+    assert_eq!(res, vec![14, 22]);
+}
+
+#[test]
+fn test_exact_chunks_mut_count() {
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let c = v.exact_chunks_mut(3);
+    assert_eq!(c.count(), 2);
+
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let c2 = v2.exact_chunks_mut(2);
+    assert_eq!(c2.count(), 2);
+
+    let v3: &mut [i32] = &mut [];
+    let c3 = v3.exact_chunks_mut(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_exact_chunks_mut_nth() {
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let mut c = v.exact_chunks_mut(2);
+    assert_eq!(c.nth(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[4, 5]);
+
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6];
+    let mut c2 = v2.exact_chunks_mut(3);
+    assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_exact_chunks_mut_last() {
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let c = v.exact_chunks_mut(2);
+    assert_eq!(c.last().unwrap(), &[4, 5]);
+
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let c2 = v2.exact_chunks_mut(2);
+    assert_eq!(c2.last().unwrap(), &[2, 3]);
+}
+
+#[test]
+fn test_exact_chunks_mut_zip() {
+    let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+    for (a, b) in v1.exact_chunks_mut(2).zip(v2.exact_chunks(2)) {
+        let sum = b.iter().sum::<i32>();
+        for v in a {
+            *v += sum;
+        }
+    }
+    assert_eq!(v1, [13, 14, 19, 20, 4]);
 }
 
 #[test]
@@ -216,6 +365,19 @@
 }
 
 #[test]
+fn test_windows_zip() {
+    let v1: &[i32] = &[0, 1, 2, 3, 4];
+    let v2: &[i32] = &[6, 7, 8, 9, 10];
+
+    let res = v1.windows(2)
+        .zip(v2.windows(2))
+        .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
+        .collect::<Vec<_>>();
+
+    assert_eq!(res, [14, 18, 22, 26]);
+}
+
+#[test]
 fn get_range() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
     assert_eq!(v.get(..), Some(&[0, 1, 2, 3, 4, 5][..]));
@@ -290,17 +452,32 @@
 }
 
 #[test]
-fn test_rotate() {
+fn test_rotate_left() {
     const N: usize = 600;
     let a: &mut [_] = &mut [0; N];
     for i in 0..N {
         a[i] = i;
     }
 
-    a.rotate(42);
+    a.rotate_left(42);
     let k = N - 42;
 
     for i in 0..N {
-        assert_eq!(a[(i+k)%N], i);
+        assert_eq!(a[(i + k) % N], i);
+    }
+}
+
+#[test]
+fn test_rotate_right() {
+    const N: usize = 600;
+    let a: &mut [_] = &mut [0; N];
+    for i in 0..N {
+        a[i] = i;
+    }
+
+    a.rotate_right(42);
+
+    for i in 0..N {
+        assert_eq!(a[(i + 42) % N], i);
     }
 }
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index 110493b..cd893b9 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -306,7 +306,7 @@
     LabelStr(Cow<'a, str>),
 
     /// This kind of label uses the graphviz label escString type:
-    /// http://www.graphviz.org/content/attrs#kescString
+    /// <http://www.graphviz.org/content/attrs#kescString>
     ///
     /// Occurrences of backslashes (`\`) are not escaped; instead they
     /// are interpreted as initiating an escString escape sequence.
@@ -326,7 +326,7 @@
 }
 
 /// The style for a node or edge.
-/// See http://www.graphviz.org/doc/info/attrs.html#k:style for descriptions.
+/// See <http://www.graphviz.org/doc/info/attrs.html#k:style> for descriptions.
 /// Note that some of these are not valid for edges.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum Style {
diff --git a/src/liblibc b/src/liblibc
index ef9eefb..2b4cd10 160000
--- a/src/liblibc
+++ b/src/liblibc
@@ -1 +1 @@
-Subproject commit ef9eefb6df3f3a2cb989e8050519661faa7d7118
+Subproject commit 2b4cd1016bdba92becb4f982a4dcb18fe6653bc4
diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs
index 29a9e1a..c3bd6a2 100644
--- a/src/libpanic_abort/lib.rs
+++ b/src/libpanic_abort/lib.rs
@@ -53,7 +53,7 @@
 pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
     abort();
 
-    #[cfg(unix)]
+    #[cfg(any(unix, target_os = "cloudabi"))]
     unsafe fn abort() -> ! {
         extern crate libc;
         libc::abort();
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 6b8da7a..92e40e8 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -68,6 +68,7 @@
 
 // i686-pc-windows-gnu and all others
 #[cfg(any(all(unix, not(target_os = "emscripten")),
+          target_os = "cloudabi",
           target_os = "redox",
           all(windows, target_arch = "x86", target_env = "gnu")))]
 #[path = "gcc.rs"]
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 41ccd88..b9e816b 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -95,7 +95,7 @@
             // notify the expansion info that it is unhygienic
             let mark = Mark::fresh(mark);
             mark.set_expn_info(expn_info);
-            let span = call_site.with_ctxt(call_site.ctxt().apply_mark(mark));
+            let span = call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark));
             let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span));
             Ok(__internal::token_stream_wrap(stream))
         })
@@ -221,6 +221,21 @@
         }
     }
 
+    /// The `Span` for the tokens in the previous macro expansion from which
+    /// `self` was generated from, if any.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn parent(&self) -> Option<Span> {
+        self.0.ctxt().outer().expn_info().map(|i| Span(i.call_site))
+    }
+
+    /// The span for the origin source code that `self` was generated from. If
+    /// this `Span` wasn't generated from other macro expansions then the return
+    /// value is the same as `*self`.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn source(&self) -> Span {
+        Span(self.0.source_callsite())
+    }
+
     /// Get the starting line/column in the source file for this span.
     #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn start(&self) -> LineColumn {
@@ -247,13 +262,27 @@
     #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn join(&self, other: Span) -> Option<Span> {
         let self_loc = __internal::lookup_char_pos(self.0.lo());
-        let other_loc = __internal::lookup_char_pos(self.0.lo());
+        let other_loc = __internal::lookup_char_pos(other.0.lo());
 
         if self_loc.file.name != other_loc.file.name { return None }
 
         Some(Span(self.0.to(other.0)))
     }
 
+    /// Creates a new span with the same line/column information as `self` but
+    /// that resolves symbols as though it were at `other`.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn resolved_at(&self, other: Span) -> Span {
+        Span(self.0.with_ctxt(other.0.ctxt()))
+    }
+
+    /// Creates a new span with the same name resolution behavior as `self` but
+    /// with the line/column information of `other`.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn located_at(&self, other: Span) -> Span {
+        other.resolved_at(*self)
+    }
+
     diagnostic_method!(error, Level::Error);
     diagnostic_method!(warning, Level::Warning);
     diagnostic_method!(note, Level::Note);
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 3a4b302..f95dbcf 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -14,7 +14,7 @@
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
-log = "0.3"
+log = "0.4"
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
@@ -54,4 +54,4 @@
 # tl;dr; this is not needed to get `rustc` to compile, but if you remove it then
 #        later crate stop compiling. If you can remove this and everything
 #        compiles, then please feel free to do so!
-flate2 = "0.2"
+flate2 = "1.0"
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 1f65df2..14f54fb 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -279,7 +279,7 @@
 
                             DepNode {
                                 kind: DepKind::$variant,
-                                hash: Fingerprint::zero(),
+                                hash: Fingerprint::ZERO,
                             }
                         }
                     )*
@@ -308,7 +308,7 @@
                 assert!(!kind.has_params());
                 DepNode {
                     kind,
-                    hash: Fingerprint::zero(),
+                    hash: Fingerprint::ZERO,
                 }
             }
 
@@ -496,7 +496,6 @@
     [] SuperPredicatesOfItem(DefId),
     [] TraitDefOfItem(DefId),
     [] AdtDefOfItem(DefId),
-    [] IsAutoImpl(DefId),
     [] ImplTraitRef(DefId),
     [] ImplPolarity(DefId),
     [] FnSignature(DefId),
@@ -633,6 +632,12 @@
     [anon] NormalizeTy,
     // We use this for most things when incr. comp. is turned off.
     [] Null,
+
+    [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
+
+    [input] TargetFeaturesWhitelist,
+    [] TargetFeaturesEnabled(DefId),
+
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs
index 2d19b34..7e46c20 100644
--- a/src/librustc/dep_graph/dep_tracking_map.rs
+++ b/src/librustc/dep_graph/dep_tracking_map.rs
@@ -56,7 +56,7 @@
     /// map; and `CurrentTask` represents the current task when
     /// `memoize` is invoked.
     ///
-    /// **Important:* when `op` is invoked, the current task will be
+    /// **Important:** when `op` is invoked, the current task will be
     /// switched to `Map(key)`. Therefore, if `op` makes use of any
     /// HIR nodes or shared state accessed through its closure
     /// environment, it must explicitly register a read of that
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 96d6b0f..55ec8ad 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -34,14 +34,11 @@
 pub struct DepGraph {
     data: Option<Rc<DepGraphData>>,
 
-    // At the moment we are using DepNode as key here. In the future it might
-    // be possible to use an IndexVec<DepNodeIndex, _> here. At the moment there
-    // are a few problems with that:
-    // - Some fingerprints are needed even if incr. comp. is disabled -- yet
-    //   we need to have a dep-graph to generate DepNodeIndices.
-    // - The architecture is still in flux and it's not clear what how to best
-    //   implement things.
-    fingerprints: Rc<RefCell<FxHashMap<DepNode, Fingerprint>>>
+    // A vector mapping depnodes from the current graph to their associated
+    // result value fingerprints. Do not rely on the length of this vector
+    // being the same as the number of nodes in the graph. The vector can
+    // contain an arbitrary number of zero-entries at the end.
+    fingerprints: Rc<RefCell<IndexVec<DepNodeIndex, Fingerprint>>>
 }
 
 
@@ -97,6 +94,11 @@
 impl DepGraph {
 
     pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
+        // Pre-allocate the fingerprints array. We over-allocate a little so
+        // that we hopefully don't have to re-allocate during this compilation
+        // session.
+        let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO,
+                                                 (prev_graph.node_count() * 115) / 100);
         DepGraph {
             data: Some(Rc::new(DepGraphData {
                 previous_work_products: RefCell::new(FxHashMap()),
@@ -107,14 +109,14 @@
                 colors: RefCell::new(FxHashMap()),
                 loaded_from_cache: RefCell::new(FxHashMap()),
             })),
-            fingerprints: Rc::new(RefCell::new(FxHashMap())),
+            fingerprints: Rc::new(RefCell::new(fingerprints)),
         }
     }
 
     pub fn new_disabled() -> DepGraph {
         DepGraph {
             data: None,
-            fingerprints: Rc::new(RefCell::new(FxHashMap())),
+            fingerprints: Rc::new(RefCell::new(IndexVec::new())),
         }
     }
 
@@ -139,14 +141,22 @@
         DepGraphQuery::new(&nodes[..], &edges[..])
     }
 
-    pub fn in_ignore<'graph>(&'graph self) -> Option<raii::IgnoreTask<'graph>> {
-        self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current))
+    pub fn assert_ignored(&self)
+    {
+        if let Some(ref data) = self.data {
+            match data.current.borrow().task_stack.last() {
+                Some(&OpenTask::Ignore) | None => {
+                    // ignored
+                }
+                _ => panic!("expected an ignore context")
+            }
+        }
     }
 
     pub fn with_ignore<OP,R>(&self, op: OP) -> R
         where OP: FnOnce() -> R
     {
-        let _task = self.in_ignore();
+        let _task = self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current));
         op()
     }
 
@@ -156,8 +166,8 @@
     /// what state they have access to. In particular, we want to
     /// prevent implicit 'leaks' of tracked state into the task (which
     /// could then be read without generating correct edges in the
-    /// dep-graph -- see the [README] for more details on the
-    /// dep-graph). To this end, the task function gets exactly two
+    /// dep-graph -- see the module-level [README] for more details on
+    /// the dep-graph). To this end, the task function gets exactly two
     /// pieces of state: the context `cx` and an argument `arg`. Both
     /// of these bits of state must be of some type that implements
     /// `DepGraphSafe` and hence does not leak.
@@ -176,7 +186,7 @@
     /// - If you need 3+ arguments, use a tuple for the
     ///   `arg` parameter.
     ///
-    /// [README]: README.md
+    /// [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/dep_graph/README.md
     pub fn with_task<C, A, R, HCX>(&self,
                                    key: DepNode,
                                    cx: C,
@@ -231,12 +241,16 @@
 
             // Store the current fingerprint
             {
-                let old_value = self.fingerprints
-                                    .borrow_mut()
-                                    .insert(key, current_fingerprint);
-                debug_assert!(old_value.is_none(),
+                let mut fingerprints = self.fingerprints.borrow_mut();
+
+                if dep_node_index.index() >= fingerprints.len() {
+                    fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
+                }
+
+                debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
                               "DepGraph::with_task() - Duplicate fingerprint \
                                insertion for {:?}", key);
+                fingerprints[dep_node_index] = current_fingerprint;
             }
 
             // Determine the color of the new DepNode.
@@ -262,13 +276,15 @@
                 let result = task(cx, arg);
                 let mut stable_hasher = StableHasher::new();
                 result.hash_stable(&mut hcx, &mut stable_hasher);
-                let old_value = self.fingerprints
-                                    .borrow_mut()
-                                    .insert(key, stable_hasher.finish());
-                debug_assert!(old_value.is_none(),
-                              "DepGraph::with_task() - Duplicate fingerprint \
-                               insertion for {:?}", key);
-                (result, DepNodeIndex::INVALID)
+                let fingerprint = stable_hasher.finish();
+
+                let mut fingerprints = self.fingerprints.borrow_mut();
+                let dep_node_index = DepNodeIndex::new(fingerprints.len());
+                fingerprints.push(fingerprint);
+                debug_assert!(fingerprints[dep_node_index] == fingerprint,
+                              "DepGraph::with_task() - Assigned fingerprint to \
+                               unexpected index for {:?}", key);
+                (result, dep_node_index)
             } else {
                 (task(cx, arg), DepNodeIndex::INVALID)
             }
@@ -328,11 +344,29 @@
     }
 
     #[inline]
-    pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
-        match self.fingerprints.borrow().get(dep_node) {
+    pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex {
+        self.data
+            .as_ref()
+            .unwrap()
+            .current
+            .borrow_mut()
+            .node_to_node_index
+            .get(dep_node)
+            .cloned()
+            .unwrap()
+    }
+
+    #[inline]
+    pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
+        match self.fingerprints.borrow().get(dep_node_index) {
             Some(&fingerprint) => fingerprint,
             None => {
-                bug!("Could not find current fingerprint for {:?}", dep_node)
+                if let Some(ref data) = self.data {
+                    let dep_node = data.current.borrow().nodes[dep_node_index];
+                    bug!("Could not find current fingerprint for {:?}", dep_node)
+                } else {
+                    bug!("Could not find current fingerprint for {:?}", dep_node_index)
+                }
             }
         }
     }
@@ -420,14 +454,17 @@
     }
 
     pub fn serialize(&self) -> SerializedDepGraph {
-        let fingerprints = self.fingerprints.borrow();
+        let mut fingerprints = self.fingerprints.borrow_mut();
         let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
 
-        let nodes: IndexVec<_, _> = current_dep_graph.nodes.iter().map(|dep_node| {
-            let fingerprint = fingerprints.get(dep_node)
-                                          .cloned()
-                                          .unwrap_or(Fingerprint::zero());
-            (*dep_node, fingerprint)
+        // Make sure we don't run out of bounds below.
+        if current_dep_graph.nodes.len() > fingerprints.len() {
+            fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO);
+        }
+
+        let nodes: IndexVec<_, (DepNode, Fingerprint)> =
+            current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| {
+            (dep_node, fingerprints[idx])
         }).collect();
 
         let total_edge_count: usize = current_dep_graph.edges.iter()
@@ -610,13 +647,20 @@
 
         // ... copying the fingerprint from the previous graph too, so we don't
         // have to recompute it ...
-        let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
-        let old_fingerprint = self.fingerprints
-                                  .borrow_mut()
-                                  .insert(*dep_node, fingerprint);
-        debug_assert!(old_fingerprint.is_none(),
-                      "DepGraph::try_mark_green() - Duplicate fingerprint \
-                      insertion for {:?}", dep_node);
+        {
+            let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
+            let mut fingerprints = self.fingerprints.borrow_mut();
+
+            if dep_node_index.index() >= fingerprints.len() {
+                fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
+            }
+
+            debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
+                "DepGraph::try_mark_green() - Duplicate fingerprint \
+                insertion for {:?}", dep_node);
+
+            fingerprints[dep_node_index] = fingerprint;
+        }
 
         // ... emitting any stored diagnostic ...
         {
diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs
index 6c43b5c..50e1ee8 100644
--- a/src/librustc/dep_graph/prev.rs
+++ b/src/librustc/dep_graph/prev.rs
@@ -62,4 +62,8 @@
                                 -> Fingerprint {
         self.data.nodes[dep_node_index].1
     }
+
+    pub fn node_count(&self) -> usize {
+        self.index.len()
+    }
 }
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 7b48e78..8bd89b8 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -2003,7 +2003,69 @@
 invoking itself via a virtual call, and hence does not directly
 reference its own *type*.
 
-"##, }
+"##,
+
+E0692: r##"
+A `repr(transparent)` type was also annotated with other, incompatible
+representation hints.
+
+Erroneous code example:
+
+```compile_fail,E0692
+#![feature(repr_transparent)]
+
+#[repr(transparent, C)] // error: incompatible representation hints
+struct Grams(f32);
+```
+
+A type annotated as `repr(transparent)` delegates all representation concerns to
+another type, so adding more representation hints is contradictory. Remove
+either the `transparent` hint or the other hints, like this:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Grams(f32);
+```
+
+Alternatively, move the other attributes to the contained type:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(C)]
+struct Foo {
+    x: i32,
+    // ...
+}
+
+#[repr(transparent)]
+struct FooWrapper(Foo);
+```
+
+Note that introducing another `struct` just to have a place for the other
+attributes may have unintended side effects on the representation:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Grams(f32);
+
+#[repr(C)]
+struct Float(f32);
+
+#[repr(transparent)]
+struct Grams2(Float); // this is not equivalent to `Grams` above
+```
+
+Here, `Grams2` is a not equivalent to `Grams` -- the former transparently wraps
+a (non-transparent) struct containing a single float, while `Grams` is a
+transparent wrapper around a float. This can make a difference for the ABI.
+"##,
+
+}
 
 
 register_diagnostics! {
@@ -2056,4 +2118,6 @@
     E0657, // `impl Trait` can only capture lifetimes bound at the fn level
     E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
     E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
+
+    E0906, // closures cannot be static
 }
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 003255f..a073910 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -14,11 +14,10 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-use session::Session;
+use ty::TyCtxt;
 
-use syntax::ast;
-use syntax::visit;
-use syntax::visit::Visitor;
+use hir;
+use hir::intravisit::{self, Visitor, NestedVisitorMap};
 
 #[derive(Copy, Clone, PartialEq)]
 enum Target {
@@ -30,81 +29,95 @@
 }
 
 impl Target {
-    fn from_item(item: &ast::Item) -> Target {
+    fn from_item(item: &hir::Item) -> Target {
         match item.node {
-            ast::ItemKind::Fn(..) => Target::Fn,
-            ast::ItemKind::Struct(..) => Target::Struct,
-            ast::ItemKind::Union(..) => Target::Union,
-            ast::ItemKind::Enum(..) => Target::Enum,
+            hir::ItemFn(..) => Target::Fn,
+            hir::ItemStruct(..) => Target::Struct,
+            hir::ItemUnion(..) => Target::Union,
+            hir::ItemEnum(..) => Target::Enum,
             _ => Target::Other,
         }
     }
 }
 
-struct CheckAttrVisitor<'a> {
-    sess: &'a Session,
+struct CheckAttrVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
-impl<'a> CheckAttrVisitor<'a> {
+impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     /// Check any attribute.
-    fn check_attribute(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
-        if let Some(name) = attr.name() {
-            match &*name.as_str() {
-                "inline" => self.check_inline(attr, item, target),
-                "repr" => self.check_repr(attr, item, target),
-                _ => (),
+    fn check_attributes(&self, item: &hir::Item, target: Target) {
+        self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id));
+
+        for attr in &item.attrs {
+            if let Some(name) = attr.name() {
+                if name == "inline" {
+                    self.check_inline(attr, item, target)
+                }
             }
         }
+
+        self.check_repr(item, target);
     }
 
     /// Check if an `#[inline]` is applied to a function.
-    fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
+    fn check_inline(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
         if target != Target::Fn {
-            struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
+            struct_span_err!(self.tcx.sess,
+                             attr.span,
+                             E0518,
+                             "attribute should be applied to function")
                 .span_label(item.span, "not a function")
                 .emit();
         }
     }
 
-    /// Check if an `#[repr]` attr is valid.
-    fn check_repr(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
-        let words = match attr.meta_item_list() {
-            Some(words) => words,
-            None => {
-                return;
-            }
-        };
+    /// Check if the `#[repr]` attributes on `item` are valid.
+    fn check_repr(&self, item: &hir::Item, target: Target) {
+        // Extract the names of all repr hints, e.g., [foo, bar, align] for:
+        // ```
+        // #[repr(foo)]
+        // #[repr(bar, align(8))]
+        // ```
+        let hints: Vec<_> = item.attrs
+            .iter()
+            .filter(|attr| match attr.name() {
+                Some(name) => name == "repr",
+                None => false,
+            })
+            .filter_map(|attr| attr.meta_item_list())
+            .flat_map(|hints| hints)
+            .collect();
 
         let mut int_reprs = 0;
         let mut is_c = false;
         let mut is_simd = false;
+        let mut is_transparent = false;
 
-        for word in words {
-
-            let name = match word.name() {
-                Some(word) => word,
-                None => continue,
+        for hint in &hints {
+            let name = if let Some(name) = hint.name() {
+                name
+            } else {
+                // Invalid repr hint like repr(42). We don't check for unrecognized hints here
+                // (libsyntax does that), so just ignore it.
+                continue;
             };
 
-            let (message, label) = match &*name.as_str() {
+            let (article, allowed_targets) = match &*name.as_str() {
                 "C" => {
                     is_c = true;
                     if target != Target::Struct &&
                             target != Target::Union &&
                             target != Target::Enum {
-                                ("attribute should be applied to struct, enum or union",
-                                 "a struct, enum or union")
+                                ("a", "struct, enum or union")
                     } else {
                         continue
                     }
                 }
                 "packed" => {
-                    // Do not increment conflicting_reprs here, because "packed"
-                    // can be used to modify another repr hint
                     if target != Target::Struct &&
                             target != Target::Union {
-                                ("attribute should be applied to struct or union",
-                                 "a struct or union")
+                                ("a", "struct or union")
                     } else {
                         continue
                     }
@@ -112,8 +125,7 @@
                 "simd" => {
                     is_simd = true;
                     if target != Target::Struct {
-                        ("attribute should be applied to struct",
-                         "a struct")
+                        ("a", "struct")
                     } else {
                         continue
                     }
@@ -121,8 +133,15 @@
                 "align" => {
                     if target != Target::Struct &&
                             target != Target::Union {
-                        ("attribute should be applied to struct or union",
-                         "a struct or union")
+                        ("a", "struct or union")
+                    } else {
+                        continue
+                    }
+                }
+                "transparent" => {
+                    is_transparent = true;
+                    if target != Target::Struct {
+                        ("a", "struct")
                     } else {
                         continue
                     }
@@ -132,48 +151,62 @@
                 "isize" | "usize" => {
                     int_reprs += 1;
                     if target != Target::Enum {
-                        ("attribute should be applied to enum",
-                         "an enum")
+                        ("an", "enum")
                     } else {
                         continue
                     }
                 }
                 _ => continue,
             };
-            struct_span_err!(self.sess, attr.span, E0517, "{}", message)
-                .span_label(item.span, format!("not {}", label))
+            struct_span_err!(self.tcx.sess, hint.span, E0517,
+                             "attribute should be applied to {}", allowed_targets)
+                .span_label(item.span, format!("not {} {}", article, allowed_targets))
                 .emit();
         }
 
+        // Just point at all repr hints if there are any incompatibilities.
+        // This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
+        let hint_spans = hints.iter().map(|hint| hint.span);
+
+        // Error on repr(transparent, <anything else>).
+        if is_transparent && hints.len() > 1 {
+            let hint_spans: Vec<_> = hint_spans.clone().collect();
+            span_err!(self.tcx.sess, hint_spans, E0692,
+                      "transparent struct cannot have other repr hints");
+        }
         // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
         if (int_reprs > 1)
            || (is_simd && is_c)
            || (int_reprs == 1 && is_c && is_c_like_enum(item)) {
-            span_warn!(self.sess, attr.span, E0566,
+            let hint_spans: Vec<_> = hint_spans.collect();
+            span_warn!(self.tcx.sess, hint_spans, E0566,
                        "conflicting representation hints");
         }
     }
 }
 
-impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
-    fn visit_item(&mut self, item: &'a ast::Item) {
+impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
         let target = Target::from_item(item);
-        for attr in &item.attrs {
-            self.check_attribute(attr, item, target);
-        }
-        visit::walk_item(self, item);
+        self.check_attributes(item, target);
+        intravisit::walk_item(self, item);
     }
 }
 
-pub fn check_crate(sess: &Session, krate: &ast::Crate) {
-    visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate);
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    let mut checker = CheckAttrVisitor { tcx };
+    tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor());
 }
 
-fn is_c_like_enum(item: &ast::Item) -> bool {
-    if let ast::ItemKind::Enum(ref def, _) = item.node {
+fn is_c_like_enum(item: &hir::Item) -> bool {
+    if let hir::ItemEnum(ref def, _) = item.node {
         for variant in &def.variants {
             match variant.node.data {
-                ast::VariantData::Unit(_) => { /* continue */ }
+                hir::VariantData::Unit(_) => { /* continue */ }
                 _ => { return false; }
             }
         }
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 19a37b6..8e4a4d3 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -71,13 +71,16 @@
 /// `base_def` is definition of resolved part of the
 /// path, `unresolved_segments` is the number of unresolved
 /// segments.
-///     module::Type::AssocX::AssocY::MethodOrAssocType
-///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-///     base_def      unresolved_segments = 3
 ///
-///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
-///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
-///           base_def        unresolved_segments = 2
+/// ```text
+/// module::Type::AssocX::AssocY::MethodOrAssocType
+/// ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/// base_def      unresolved_segments = 3
+///
+/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
+///       ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
+///       base_def        unresolved_segments = 2
+/// ```
 #[derive(Copy, Clone, Debug)]
 pub struct PathResolution {
     base_def: Def,
@@ -132,6 +135,7 @@
     /// We include non-`pub` exports for hygienic macros that get used from extern crates.
     pub vis: ty::Visibility,
     /// True if from a `use` or and `extern crate`.
+    /// Used in rustdoc.
     pub is_import: bool,
 }
 
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index 8858023..637b156 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -71,27 +71,23 @@
 /// particular definition. It should really be considered an interned
 /// shorthand for a particular DefPath.
 ///
-/// At the moment we are allocating the numerical values of DefIndexes into two
-/// ranges: the "low" range (starting at zero) and the "high" range (starting at
-/// DEF_INDEX_HI_START). This allows us to allocate the DefIndexes of all
-/// item-likes (Items, TraitItems, and ImplItems) into one of these ranges and
+/// At the moment we are allocating the numerical values of DefIndexes from two
+/// address spaces: DefIndexAddressSpace::Low and DefIndexAddressSpace::High.
+/// This allows us to allocate the DefIndexes of all item-likes
+/// (Items, TraitItems, and ImplItems) into one of these spaces and
 /// consequently use a simple array for lookup tables keyed by DefIndex and
 /// known to be densely populated. This is especially important for the HIR map.
 ///
 /// Since the DefIndex is mostly treated as an opaque ID, you probably
-/// don't have to care about these ranges.
-newtype_index!(DefIndex
-    {
-        ENCODABLE = custom
-        DEBUG_FORMAT = custom,
+/// don't have to care about these address spaces.
 
-        /// The start of the "high" range of DefIndexes.
-        const DEF_INDEX_HI_START = 1 << 31,
+#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, Hash, Copy)]
+pub struct DefIndex(u32);
 
-        /// The crate root is always assigned index 0 by the AST Map code,
-        /// thanks to `NodeCollector::new`.
-        const CRATE_DEF_INDEX = 0,
-    });
+/// The crate root is always assigned index 0 by the AST Map code,
+/// thanks to `NodeCollector::new`.
+pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
+
 
 impl fmt::Debug for DefIndex {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -104,40 +100,50 @@
 
 impl DefIndex {
     #[inline]
-    pub fn from_u32(x: u32) -> DefIndex {
-        DefIndex(x)
-    }
-
-    #[inline]
-    pub fn as_usize(&self) -> usize {
-        self.0 as usize
-    }
-
-    #[inline]
-    pub fn as_u32(&self) -> u32 {
-        self.0
-    }
-
-    #[inline]
     pub fn address_space(&self) -> DefIndexAddressSpace {
-        if self.0 < DEF_INDEX_HI_START.0 {
-            DefIndexAddressSpace::Low
-        } else {
-            DefIndexAddressSpace::High
+        match self.0 & 1 {
+            0 => DefIndexAddressSpace::Low,
+            1 => DefIndexAddressSpace::High,
+            _ => unreachable!()
         }
     }
 
     /// Converts this DefIndex into a zero-based array index.
-    /// This index is the offset within the given "range" of the DefIndex,
-    /// that is, if the DefIndex is part of the "high" range, the resulting
-    /// index will be (DefIndex - DEF_INDEX_HI_START).
+    /// This index is the offset within the given DefIndexAddressSpace.
     #[inline]
     pub fn as_array_index(&self) -> usize {
-        (self.0 & !DEF_INDEX_HI_START.0) as usize
+        (self.0 >> 1) as usize
     }
 
+    #[inline]
     pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefIndex {
-        DefIndex::new(address_space.start() + i)
+        DefIndex::from_raw_u32(((i << 1) | (address_space as usize)) as u32)
+    }
+
+    // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This
+    // function maps the index of the macro within the crate (which is also the
+    // index of the macro in the CrateMetadata::proc_macros array) to the
+    // corresponding DefIndex.
+    pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
+        let def_index = DefIndex::from_array_index(proc_macro_index,
+                                                   DefIndexAddressSpace::High);
+        assert!(def_index != CRATE_DEF_INDEX);
+        def_index
+    }
+
+    // This function is the reverse of from_proc_macro_index() above.
+    pub fn to_proc_macro_index(self: DefIndex) -> usize {
+        self.as_array_index()
+    }
+
+    // Don't use this if you don't know about the DefIndex encoding.
+    pub fn from_raw_u32(x: u32) -> DefIndex {
+        DefIndex(x)
+    }
+
+    // Don't use this if you don't know about the DefIndex encoding.
+    pub fn as_raw_u32(&self) -> u32 {
+        self.0
     }
 }
 
@@ -155,11 +161,6 @@
     pub fn index(&self) -> usize {
         *self as usize
     }
-
-    #[inline]
-    pub fn start(&self) -> usize {
-        self.index() * DEF_INDEX_HI_START.as_usize()
-    }
 }
 
 /// A DefId identifies a particular *definition*, by combining a crate
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 74714ed..ce35e65 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -498,10 +498,6 @@
             // visit_enum_def() takes care of visiting the Item's NodeId
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
-        ItemAutoImpl(_, ref trait_ref) => {
-            visitor.visit_id(item.id);
-            visitor.visit_trait_ref(trait_ref)
-        }
         ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_item_refs) => {
             visitor.visit_id(item.id);
             visitor.visit_generics(type_parameters);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 6fc35e5..e76f39a 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -151,6 +151,11 @@
     /// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
     /// This should only return `None` during testing.
     fn definitions(&mut self) -> &mut Definitions;
+
+    /// Given suffix ["b","c","d"], creates a HIR path for `[::crate_root]::b::c::d` and resolves
+    /// it based on `is_value`.
+    fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
+                components: &[&str], is_value: bool) -> hir::Path;
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -180,7 +185,7 @@
     // We're constructing the HIR here; we don't care what we will
     // read, since we haven't even constructed the *input* to
     // incr. comp. yet.
-    let _ignore = dep_graph.in_ignore();
+    dep_graph.assert_ignored();
 
     LoweringContext {
         crate_root: std_inject::injected_crate_name(),
@@ -995,9 +1000,10 @@
                         );
 
                         let hir_bounds = self.lower_bounds(bounds, itctx);
+                        // Set the name to `impl Bound1 + Bound2`
+                        let name = Symbol::intern(&pprust::ty_to_string(t));
                         self.in_band_ty_params.push(hir::TyParam {
-                            // Set the name to `impl Bound1 + Bound2`
-                            name: Symbol::intern(&pprust::ty_to_string(t)),
+                            name,
                             id: def_node_id,
                             bounds: hir_bounds,
                             default: None,
@@ -1009,7 +1015,7 @@
                         hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
                             span,
                             def: Def::TyParam(DefId::local(def_index)),
-                            segments: vec![].into(),
+                            segments: hir_vec![hir::PathSegment::from_name(name)],
                         })))
                     },
                     ImplTraitContext::Disallowed => {
@@ -1501,8 +1507,8 @@
                      fn_def_id: Option<DefId>,
                      impl_trait_return_allow: bool)
                      -> P<hir::FnDecl> {
-        // NOTE: The two last paramters here have to do with impl Trait. If fn_def_id is Some,
-        //       then impl Trait arguments are lowered into generic paramters on the given
+        // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
+        //       then impl Trait arguments are lowered into generic parameters on the given
         //       fn_def_id, otherwise impl Trait is disallowed. (for now)
         //
         //       Furthermore, if impl_trait_return_allow is true, then impl Trait may be used in
@@ -1571,7 +1577,7 @@
             bounds,
             default: tp.default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)),
             span: tp.span,
-            pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
+            pure_wrt_drop: attr::contains_name(&tp.attrs, "may_dangle"),
             synthetic: tp.attrs.iter()
                                .filter(|attr| attr.check_name("rustc_synthetic"))
                                .map(|_| hir::SyntheticTyParamKind::ImplTrait)
@@ -1611,7 +1617,7 @@
         let def = hir::LifetimeDef {
             lifetime: self.lower_lifetime(&l.lifetime),
             bounds: self.lower_lifetimes(&l.bounds),
-            pure_wrt_drop: l.attrs.iter().any(|attr| attr.check_name("may_dangle")),
+            pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"),
             in_band: false,
         };
 
@@ -1951,16 +1957,6 @@
                 let vdata = self.lower_variant_data(vdata);
                 hir::ItemUnion(vdata, self.lower_generics(generics))
             }
-            ItemKind::AutoImpl(unsafety, ref trait_ref) => {
-                let trait_ref = self.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed);
-
-                if let Def::Trait(def_id) = trait_ref.path.def {
-                    self.trait_auto_impl.insert(def_id, id);
-                }
-
-                hir::ItemAutoImpl(self.lower_unsafety(unsafety),
-                                     trait_ref)
-            }
             ItemKind::Impl(unsafety,
                            polarity,
                            defaultness,
@@ -2051,11 +2047,12 @@
                         .chain(path.segments.iter())
                         .cloned()
                         .collect(),
-                    span: path.span.to(prefix.span),
+                    span: path.span
                 };
 
                 // Correctly resolve `self` imports
-                if path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
+                if path.segments.len() > 1 &&
+                   path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
                     let _ = path.segments.pop();
                     if ident.name == keywords::SelfValue.name() {
                         *name = path.segments.last().unwrap().identifier.name;
@@ -2128,7 +2125,7 @@
 
                 // Privatize the degenerate import base, used only to check
                 // the stability of `use a::{};`, to avoid it showing up as
-                // a reexport by accident when `pub`, e.g. in documentation.
+                // a re-export by accident when `pub`, e.g. in documentation.
                 let path = P(self.lower_path(id, &prefix, ParamMode::Explicit, true));
                 *vis = hir::Inherited;
                 hir::ItemUse(path, hir::UseKind::ListStem)
@@ -2331,7 +2328,7 @@
         let mut vis = self.lower_visibility(&i.vis, None);
         let attrs = self.lower_attrs(&i.attrs);
         if let ItemKind::MacroDef(ref def) = i.node {
-            if !def.legacy || i.attrs.iter().any(|attr| attr.path == "macro_export") {
+            if !def.legacy || attr::contains_name(&i.attrs, "macro_export") {
                 let body = self.lower_token_stream(def.stream());
                 self.exported_macros.push(hir::MacroDef {
                     name,
@@ -2776,7 +2773,7 @@
                                arms.iter().map(|x| self.lower_arm(x)).collect(),
                                hir::MatchSource::Normal)
             }
-            ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
+            ExprKind::Closure(capture_clause, movability, ref decl, ref body, fn_decl_span) => {
                 self.with_new_scopes(|this| {
                     this.with_parent_def(e.id, |this| {
                         let mut is_generator = false;
@@ -2785,16 +2782,28 @@
                             is_generator = this.is_generator;
                             e
                         });
-                        if is_generator && !decl.inputs.is_empty() {
-                            span_err!(this.sess, fn_decl_span, E0628,
-                                      "generators cannot have explicit arguments");
-                            this.sess.abort_if_errors();
-                        }
+                        let generator_option = if is_generator {
+                            if !decl.inputs.is_empty() {
+                                span_err!(this.sess, fn_decl_span, E0628,
+                                        "generators cannot have explicit arguments");
+                                this.sess.abort_if_errors();
+                            }
+                            Some(match movability {
+                                Movability::Movable => hir::GeneratorMovability::Movable,
+                                Movability::Static => hir::GeneratorMovability::Static,
+                            })
+                        } else {
+                            if movability == Movability::Static {
+                                span_err!(this.sess, fn_decl_span, E0906,
+                                        "closures cannot be static");
+                            }
+                            None
+                        };
                         hir::ExprClosure(this.lower_capture_clause(capture_clause),
                                          this.lower_fn_decl(decl, None, false),
                                          body_id,
                                          fn_decl_span,
-                                         is_generator)
+                                         generator_option)
                     })
                 })
             }
@@ -3633,16 +3642,7 @@
     /// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
     /// The path is also resolved according to `is_value`.
     fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
-        let mut path = hir::Path {
-            span,
-            def: Def::Err,
-            segments: iter::once(keywords::CrateRoot.name()).chain({
-                self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
-            }).map(hir::PathSegment::from_name).collect(),
-        };
-
-        self.resolver.resolve_hir_path(&mut path, is_value);
-        path
+        self.resolver.resolve_str_path(span, self.crate_root, components, is_value)
     }
 
     fn signal_block_expr(&mut self,
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index d2888dc..1eaacdb 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -33,6 +33,7 @@
 /// and a body (as well as a NodeId, a span, etc).
 ///
 /// More specifically, it is one of either:
+///
 ///   - A function item,
 ///   - A closure expr (i.e. an ExprClosure), or
 ///   - The default implementation for a trait method.
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index e3ca6f1..0e1c662 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -12,6 +12,7 @@
 
 use dep_graph::{DepGraph, DepKind, DepNodeIndex};
 use hir::intravisit::{Visitor, NestedVisitorMap};
+use hir::svh::Svh;
 use middle::cstore::CrateStore;
 use session::CrateDisambiguator;
 use std::iter::repeat;
@@ -44,7 +45,7 @@
 
     // We are collecting DepNode::HirBody hashes here so we can compute the
     // crate hash from then later on.
-    hir_body_nodes: Vec<DefPathHash>,
+    hir_body_nodes: Vec<(DefPathHash, DepNodeIndex)>,
 }
 
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
@@ -99,7 +100,7 @@
             );
         }
 
-        let hir_body_nodes = vec![root_mod_def_path_hash];
+        let hir_body_nodes = vec![(root_mod_def_path_hash, root_mod_full_dep_index)];
 
         let mut collector = NodeCollector {
             krate,
@@ -123,13 +124,12 @@
                                                   crate_disambiguator: CrateDisambiguator,
                                                   cstore: &CrateStore,
                                                   commandline_args_hash: u64)
-                                                  -> Vec<MapEntry<'hir>> {
+                                                  -> (Vec<MapEntry<'hir>>, Svh) {
         let mut node_hashes: Vec<_> = self
             .hir_body_nodes
             .iter()
-            .map(|&def_path_hash| {
-                let dep_node = def_path_hash.to_dep_node(DepKind::HirBody);
-                (def_path_hash, self.dep_graph.fingerprint_of(&dep_node))
+            .map(|&(def_path_hash, dep_node_index)| {
+                (def_path_hash, self.dep_graph.fingerprint_of(dep_node_index))
             })
             .collect();
 
@@ -147,13 +147,19 @@
             (name1, dis1).cmp(&(name2, dis2))
         });
 
-        self.dep_graph.with_task(DepNode::new_no_params(DepKind::Krate),
-                                 &self.hcx,
-                                 ((node_hashes, upstream_crates),
-                                  (commandline_args_hash,
-                                   crate_disambiguator.to_fingerprint())),
-                                 identity_fn);
-        self.map
+        let (_, crate_dep_node_index) = self
+            .dep_graph
+            .with_task(DepNode::new_no_params(DepKind::Krate),
+                       &self.hcx,
+                       ((node_hashes, upstream_crates),
+                        (commandline_args_hash,
+                         crate_disambiguator.to_fingerprint())),
+                       identity_fn);
+
+        let svh = Svh::new(self.dep_graph
+                               .fingerprint_of(crate_dep_node_index)
+                               .to_smaller_hash());
+        (self.map, svh)
     }
 
     fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
@@ -255,7 +261,7 @@
             identity_fn
         ).1;
 
-        self.hir_body_nodes.push(def_path_hash);
+        self.hir_body_nodes.push((def_path_hash, self.current_full_dep_index));
 
         self.current_dep_node_owner = dep_node_owner;
         self.currently_in_body = false;
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 002849c..d68b18d 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -104,8 +104,7 @@
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into
         let def_data = match i.node {
-            ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
-                DefPathData::Impl,
+            ItemKind::Impl(..) => DefPathData::Impl,
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
             ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 7c2f0bc..43cc437 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -19,7 +19,7 @@
                   CRATE_DEF_INDEX};
 use ich::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::{IndexVec};
 use rustc_data_structures::stable_hasher::StableHasher;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use session::CrateDisambiguator;
@@ -61,7 +61,7 @@
                 -> DefIndex {
         let index = {
             let index_to_key = &mut self.index_to_key[address_space.index()];
-            let index = DefIndex::new(index_to_key.len() + address_space.start());
+            let index = DefIndex::from_array_index(index_to_key.len(), address_space);
             debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
             index_to_key.push(key);
             index
@@ -89,8 +89,7 @@
     pub fn add_def_path_hashes_to(&self,
                                   cnum: CrateNum,
                                   out: &mut FxHashMap<DefPathHash, DefId>) {
-        for address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
-            let start_index = address_space.start();
+        for &address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
             out.extend(
                 (&self.def_path_hashes[address_space.index()])
                     .iter()
@@ -98,7 +97,7 @@
                     .map(|(index, &hash)| {
                         let def_id = DefId {
                             krate: cnum,
-                            index: DefIndex::new(index + start_index),
+                            index: DefIndex::from_array_index(index, address_space),
                         };
                         (hash, def_id)
                     })
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index e6af075..a4c9311 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -20,16 +20,16 @@
         errors: vec![],
     };
 
-    hir_map.dep_graph.with_ignore(|| {
-        hir_map.krate().visit_all_item_likes(&mut outer_visitor);
-        if !outer_visitor.errors.is_empty() {
-            let message = outer_visitor
-                .errors
-                .iter()
-                .fold(String::new(), |s1, s2| s1 + "\n" + s2);
-            bug!("{}", message);
-        }
-    });
+    hir_map.dep_graph.assert_ignored();
+
+    hir_map.krate().visit_all_item_likes(&mut outer_visitor);
+    if !outer_visitor.errors.is_empty() {
+        let message = outer_visitor
+            .errors
+            .iter()
+            .fold(String::new(), |s1, s2| s1 + "\n" + s2);
+        bug!("{}", message);
+    }
 }
 
 struct HirIdValidator<'a, 'hir: 'a> {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 014e577..5feea60 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -26,6 +26,7 @@
 
 use hir::*;
 use hir::print::Nested;
+use hir::svh::Svh;
 use util::nodemap::{DefIdMap, FxHashMap};
 
 use arena::TypedArena;
@@ -241,6 +242,9 @@
     /// deref. This is a gratuitous micro-optimization.
     pub dep_graph: DepGraph,
 
+    /// The SVH of the local crate.
+    pub crate_hash: Svh,
+
     /// NodeIds are sequential integers from 0, so we can be
     /// super-compact by storing them in a vector. Not everything with
     /// a NodeId is in the map, but empirically the occupancy is about
@@ -1048,7 +1052,7 @@
                        forest: &'hir mut Forest,
                        definitions: &'hir Definitions)
                        -> Map<'hir> {
-    let map = {
+    let (map, crate_hash) = {
         let hcx = ::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
 
         let mut collector = NodeCollector::root(&forest.krate,
@@ -1064,7 +1068,7 @@
                                                   cmdline_args)
     };
 
-    if log_enabled!(::log::LogLevel::Debug) {
+    if log_enabled!(::log::Level::Debug) {
         // This only makes sense for ordered stores; note the
         // enumerate to count the number of entries.
         let (entries_less_1, _) = map.iter().filter(|&x| {
@@ -1087,6 +1091,7 @@
     let map = Map {
         forest,
         dep_graph: forest.dep_graph.clone(),
+        crate_hash,
         map,
         hir_to_node_id,
         definitions,
@@ -1187,7 +1192,6 @@
                 ItemTrait(..) => "trait",
                 ItemTraitAlias(..) => "trait alias",
                 ItemImpl(..) => "impl",
-                ItemAutoImpl(..) => "default impl",
             };
             format!("{} {}{}", item_str, path_str(), id_str)
         }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 9ab3b5c..8921fec 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -34,13 +34,14 @@
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::codemap::{self, Spanned};
 use syntax::abi::Abi;
-use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
+use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::TokenStream;
 use syntax::util::ThinVec;
+use syntax::util::parser::ExprPrecedence;
 use ty::AdtKind;
 
 use rustc_data_structures::indexed_vec;
@@ -241,7 +242,7 @@
 }
 
 /// A "Path" is essentially Rust's notion of a name; for instance:
-/// std::cmp::PartialEq  .  It's represented as a sequence of identifiers,
+/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
 /// along with a bunch of supporting information.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Path {
@@ -588,7 +589,9 @@
 /// The top-level data structure that stores the entire contents of
 /// the crate currently being compiled.
 ///
-/// For more details, see [the module-level README](README.md).
+/// For more details, see the module-level [README].
+///
+/// [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/hir/README.md.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate {
     pub module: Mod,
@@ -956,6 +959,31 @@
     }
 }
 
+impl Into<ast::BinOpKind> for BinOp_ {
+    fn into(self) -> ast::BinOpKind {
+        match self {
+            BiAdd => ast::BinOpKind::Add,
+            BiSub => ast::BinOpKind::Sub,
+            BiMul => ast::BinOpKind::Mul,
+            BiDiv => ast::BinOpKind::Div,
+            BiRem => ast::BinOpKind::Rem,
+            BiAnd => ast::BinOpKind::And,
+            BiOr => ast::BinOpKind::Or,
+            BiBitXor => ast::BinOpKind::BitXor,
+            BiBitAnd => ast::BinOpKind::BitAnd,
+            BiBitOr => ast::BinOpKind::BitOr,
+            BiShl => ast::BinOpKind::Shl,
+            BiShr => ast::BinOpKind::Shr,
+            BiEq => ast::BinOpKind::Eq,
+            BiLt => ast::BinOpKind::Lt,
+            BiLe => ast::BinOpKind::Le,
+            BiNe => ast::BinOpKind::Ne,
+            BiGe => ast::BinOpKind::Ge,
+            BiGt => ast::BinOpKind::Gt,
+        }
+    }
+}
+
 pub type BinOp = Spanned<BinOp_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1164,6 +1192,42 @@
     pub hir_id: HirId,
 }
 
+impl Expr {
+    pub fn precedence(&self) -> ExprPrecedence {
+        match self.node {
+            ExprBox(_) => ExprPrecedence::Box,
+            ExprArray(_) => ExprPrecedence::Array,
+            ExprCall(..) => ExprPrecedence::Call,
+            ExprMethodCall(..) => ExprPrecedence::MethodCall,
+            ExprTup(_) => ExprPrecedence::Tup,
+            ExprBinary(op, ..) => ExprPrecedence::Binary(op.node.into()),
+            ExprUnary(..) => ExprPrecedence::Unary,
+            ExprLit(_) => ExprPrecedence::Lit,
+            ExprType(..) | ExprCast(..) => ExprPrecedence::Cast,
+            ExprIf(..) => ExprPrecedence::If,
+            ExprWhile(..) => ExprPrecedence::While,
+            ExprLoop(..) => ExprPrecedence::Loop,
+            ExprMatch(..) => ExprPrecedence::Match,
+            ExprClosure(..) => ExprPrecedence::Closure,
+            ExprBlock(..) => ExprPrecedence::Block,
+            ExprAssign(..) => ExprPrecedence::Assign,
+            ExprAssignOp(..) => ExprPrecedence::AssignOp,
+            ExprField(..) => ExprPrecedence::Field,
+            ExprTupField(..) => ExprPrecedence::TupField,
+            ExprIndex(..) => ExprPrecedence::Index,
+            ExprPath(..) => ExprPrecedence::Path,
+            ExprAddrOf(..) => ExprPrecedence::AddrOf,
+            ExprBreak(..) => ExprPrecedence::Break,
+            ExprAgain(..) => ExprPrecedence::Continue,
+            ExprRet(..) => ExprPrecedence::Ret,
+            ExprInlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprStruct(..) => ExprPrecedence::Struct,
+            ExprRepeat(..) => ExprPrecedence::Repeat,
+            ExprYield(..) => ExprPrecedence::Yield,
+        }
+    }
+}
+
 impl fmt::Debug for Expr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "expr({}: {})", self.id,
@@ -1226,7 +1290,7 @@
     ///
     /// This may also be a generator literal, indicated by the final boolean,
     /// in that case there is an GeneratorClause.
-    ExprClosure(CaptureClause, P<FnDecl>, BodyId, Span, bool),
+    ExprClosure(CaptureClause, P<FnDecl>, BodyId, Span, Option<GeneratorMovability>),
     /// A block (`{ ... }`)
     ExprBlock(P<Block>),
 
@@ -1403,6 +1467,12 @@
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum GeneratorMovability {
+    Static,
+    Movable,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum CaptureClause {
     CaptureByValue,
     CaptureByRef,
@@ -1963,10 +2033,6 @@
     /// Represents a Trait Alias Declaration
     ItemTraitAlias(Generics, TyParamBounds),
 
-    /// Auto trait implementations
-    ///
-    /// `impl Trait for .. {}`
-    ItemAutoImpl(Unsafety, TraitRef),
     /// An implementation, eg `impl<A> Trait for Foo { .. }`
     ItemImpl(Unsafety,
              ImplPolarity,
@@ -1994,8 +2060,7 @@
             ItemUnion(..) => "union",
             ItemTrait(..) => "trait",
             ItemTraitAlias(..) => "trait alias",
-            ItemImpl(..) |
-            ItemAutoImpl(..) => "item",
+            ItemImpl(..) => "item",
         }
     }
 
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 2f9fc70..4cfa7a4 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -652,18 +652,6 @@
                 self.head(&visibility_qualified(&item.vis, "union"))?;
                 self.print_struct(struct_def, generics, item.name, item.span, true)?;
             }
-            hir::ItemAutoImpl(unsafety, ref trait_ref) => {
-                self.head("")?;
-                self.print_visibility(&item.vis)?;
-                self.print_unsafety(unsafety)?;
-                self.word_nbsp("impl")?;
-                self.print_trait_ref(trait_ref)?;
-                self.s.space()?;
-                self.word_space("for")?;
-                self.word_space("..")?;
-                self.bopen()?;
-                self.bclose(item.span)?;
-            }
             hir::ItemImpl(unsafety,
                           polarity,
                           defaultness,
@@ -1116,7 +1104,7 @@
     }
 
     pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr, prec: i8) -> io::Result<()> {
-        let needs_par = expr_precedence(expr) < prec;
+        let needs_par = expr.precedence().order() < prec;
         if needs_par {
             self.popen()?;
         }
@@ -2330,55 +2318,6 @@
     }
 }
 
-
-fn expr_precedence(expr: &hir::Expr) -> i8 {
-    use syntax::util::parser::*;
-
-    match expr.node {
-        hir::ExprClosure(..) => PREC_CLOSURE,
-
-        hir::ExprBreak(..) |
-        hir::ExprAgain(..) |
-        hir::ExprRet(..) |
-        hir::ExprYield(..) => PREC_JUMP,
-
-        // Binop-like expr kinds, handled by `AssocOp`.
-        hir::ExprBinary(op, _, _) => bin_op_to_assoc_op(op.node).precedence() as i8,
-
-        hir::ExprCast(..) => AssocOp::As.precedence() as i8,
-        hir::ExprType(..) => AssocOp::Colon.precedence() as i8,
-
-        hir::ExprAssign(..) |
-        hir::ExprAssignOp(..) => AssocOp::Assign.precedence() as i8,
-
-        // Unary, prefix
-        hir::ExprBox(..) |
-        hir::ExprAddrOf(..) |
-        hir::ExprUnary(..) => PREC_PREFIX,
-
-        // Unary, postfix
-        hir::ExprCall(..) |
-        hir::ExprMethodCall(..) |
-        hir::ExprField(..) |
-        hir::ExprTupField(..) |
-        hir::ExprIndex(..) |
-        hir::ExprInlineAsm(..) => PREC_POSTFIX,
-
-        // Never need parens
-        hir::ExprArray(..) |
-        hir::ExprRepeat(..) |
-        hir::ExprTup(..) |
-        hir::ExprLit(..) |
-        hir::ExprPath(..) |
-        hir::ExprIf(..) |
-        hir::ExprWhile(..) |
-        hir::ExprLoop(..) |
-        hir::ExprMatch(..) |
-        hir::ExprBlock(..) |
-        hir::ExprStruct(..) => PREC_PAREN,
-    }
-}
-
 fn bin_op_to_assoc_op(op: hir::BinOp_) -> AssocOp {
     use hir::BinOp_::*;
     match op {
diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs
index 3d089d8..a7adf28 100644
--- a/src/librustc/ich/fingerprint.rs
+++ b/src/librustc/ich/fingerprint.rs
@@ -8,16 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::mem;
 use rustc_data_structures::stable_hasher;
+use serialize;
+use serialize::opaque::{EncodeResult, Encoder, Decoder};
 
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
 pub struct Fingerprint(u64, u64);
 
 impl Fingerprint {
-    #[inline]
-    pub fn zero() -> Fingerprint {
-        Fingerprint(0, 0)
-    }
+
+    pub const ZERO: Fingerprint = Fingerprint(0, 0);
 
     #[inline]
     pub fn from_smaller_hash(hash: u64) -> Fingerprint {
@@ -48,6 +49,21 @@
         format!("{:x}{:x}", self.0, self.1)
     }
 
+    pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
+        let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
+
+        encoder.emit_raw_bytes(&bytes)
+    }
+
+    pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
+        let mut bytes = [0; 16];
+
+        decoder.read_raw_bytes(&mut bytes)?;
+
+        let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
+
+        Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
+    }
 }
 
 impl ::std::fmt::Display for Fingerprint {
@@ -71,3 +87,19 @@
         ::std::hash::Hash::hash(self, hasher);
     }
 }
+
+impl serialize::UseSpecializedEncodable for Fingerprint { }
+
+impl serialize::UseSpecializedDecodable for Fingerprint { }
+
+impl<'a> serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder<'a> {
+    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+        f.encode_opaque(self)
+    }
+}
+
+impl<'a> serialize::SpecializedDecoder<Fingerprint> for serialize::opaque::Decoder<'a> {
+    fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+        Fingerprint::decode_opaque(self)
+    }
+}
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 2945b1a..67f6c0c 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -19,8 +19,8 @@
 
 use std::cmp::Ord;
 use std::hash as std_hash;
-use std::cell::RefCell;
 use std::collections::HashMap;
+use std::cell::RefCell;
 
 use syntax::ast;
 
@@ -36,8 +36,10 @@
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 
-thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> =
-    RefCell::new(FxHashSet()));
+pub fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
+    debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
+    ich::IGNORED_ATTRIBUTES.iter().map(|&s| Symbol::intern(s)).collect()
+}
 
 /// This is the context state available during incr. comp. hashing. It contains
 /// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
@@ -90,15 +92,6 @@
                -> Self {
         let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans;
 
-        debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
-        IGNORED_ATTR_NAMES.with(|names| {
-            let mut names = names.borrow_mut();
-            if names.is_empty() {
-                names.extend(ich::IGNORED_ATTRIBUTES.iter()
-                                                    .map(|&s| Symbol::intern(s)));
-            }
-        });
-
         StableHashingContext {
             sess,
             body_resolver: BodyResolver(krate),
@@ -186,9 +179,7 @@
 
     #[inline]
     pub fn is_ignored_attr(&self, name: Symbol) -> bool {
-        IGNORED_ATTR_NAMES.with(|names| {
-            names.borrow().contains(&name)
-        })
+        self.sess.ignored_attr_names.contains(&name)
     }
 
     pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 125b82a..59d9db4 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -606,6 +606,11 @@
     }
 }
 
+impl_stable_hash_for!(enum hir::GeneratorMovability {
+    Static,
+    Movable
+});
+
 impl_stable_hash_for!(enum hir::CaptureClause {
     CaptureByValue,
     CaptureByRef
@@ -854,7 +859,6 @@
     ItemUnion(variant_data, generics),
     ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
     ItemTraitAlias(generics, bounds),
-    ItemAutoImpl(unsafety, trait_ref),
     ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
 });
 
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index df67c3a..f46b590 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -28,7 +28,7 @@
     name,
     source_info,
     internal,
-    lexical_scope,
+    syntactic_scope,
     is_user_variable
 });
 impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref, mutability });
@@ -150,6 +150,7 @@
                 targets.hash_stable(hcx, hasher);
             }
             mir::TerminatorKind::Resume |
+            mir::TerminatorKind::Abort |
             mir::TerminatorKind::Return |
             mir::TerminatorKind::GeneratorDrop |
             mir::TerminatorKind::Unreachable => {}
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 57120d6..c31a5c9 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -155,8 +155,8 @@
     Bool(value)
 });
 
-impl_stable_hash_for!(enum ::syntax::ast::IntTy { Is, I8, I16, I32, I64, I128 });
-impl_stable_hash_for!(enum ::syntax::ast::UintTy { Us, U8, U16, U32, U64, U128 });
+impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
+impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
 impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index ea3a107..107779e 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -11,9 +11,11 @@
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::ty in no particular order.
 
-use ich::{StableHashingContext, NodeIdHashingMode};
+use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                            StableHasher, StableHasherResult};
+use std::cell::RefCell;
 use std::hash as std_hash;
 use std::mem;
 use middle::region;
@@ -26,7 +28,26 @@
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        (&self[..]).hash_stable(hcx, hasher);
+        thread_local! {
+            static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
+                RefCell::new(FxHashMap());
+        }
+
+        let hash = CACHE.with(|cache| {
+            let key = (self.as_ptr() as usize, self.len());
+            if let Some(&hash) = cache.borrow().get(&key) {
+                return hash;
+            }
+
+            let mut hasher = StableHasher::new();
+            (&self[..]).hash_stable(hcx, &mut hasher);
+
+            let hash: Fingerprint = hasher.finish();
+            cache.borrow_mut().insert(key, hash);
+            hash
+        });
+
+        hash.hash_stable(hcx, hasher);
     }
 }
 
@@ -410,7 +431,7 @@
 
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
 
-impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
+impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness, movable });
 
 impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
     parent,
@@ -635,6 +656,9 @@
                 closure_substs.hash_stable(hcx, hasher);
                 interior.hash_stable(hcx, hasher);
             }
+            TyGeneratorWitness(types) => {
+                types.hash_stable(hcx, hasher)
+            }
             TyTuple(inner_tys, from_diverging_type_var) => {
                 inner_tys.hash_stable(hcx, hasher);
                 from_diverging_type_var.hash_stable(hcx, hasher);
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index cbd76ee..ce1bd07 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -13,7 +13,7 @@
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
 pub use self::hcx::{StableHashingContext, NodeIdHashingMode,
-                    hash_stable_trait_impls};
+                    hash_stable_trait_impls, compute_ignored_attr_names};
 mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/anon_types/mod.rs
index be5314a..f5b88db 100644
--- a/src/librustc/infer/anon_types/mod.rs
+++ b/src/librustc/infer/anon_types/mod.rs
@@ -147,7 +147,9 @@
     /// Let's work through an example to explain how it works.  Assume
     /// the current function is as follows:
     ///
-    ///     fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
+    /// ```text
+    /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
+    /// ```
     ///
     /// Here, we have two `impl Trait` types whose values are being
     /// inferred (the `impl Bar<'a>` and the `impl
@@ -155,13 +157,15 @@
     /// define underlying abstract types (`Foo1`, `Foo2`) and then, in
     /// the return type of `foo`, we *reference* those definitions:
     ///
-    ///     abstract type Foo1<'x>: Bar<'x>;
-    ///     abstract type Foo2<'x>: Bar<'x>;
-    ///     fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
-    ///                        //  ^^^^ ^^
-    ///                        //  |    |
-    ///                        //  |    substs
-    ///                        //  def_id
+    /// ```text
+    /// abstract type Foo1<'x>: Bar<'x>;
+    /// abstract type Foo2<'x>: Bar<'x>;
+    /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
+    ///                    //  ^^^^ ^^
+    ///                    //  |    |
+    ///                    //  |    substs
+    ///                    //  def_id
+    /// ```
     ///
     /// As indicating in the comments above, each of those references
     /// is (in the compiler) basically a substitution (`substs`)
@@ -175,8 +179,10 @@
     /// `Foo2`.  That is, this gives rise to higher-order (pattern) unification
     /// constraints like:
     ///
-    ///     for<'a> (Foo1<'a> = C1)
-    ///     for<'b> (Foo1<'b> = C2)
+    /// ```text
+    /// for<'a> (Foo1<'a> = C1)
+    /// for<'b> (Foo1<'b> = C2)
+    /// ```
     ///
     /// For these equation to be satisfiable, the types `C1` and `C2`
     /// can only refer to a limited set of regions. For example, `C1`
@@ -189,15 +195,19 @@
     /// regions. In fact, it is fairly likely that they do! Consider
     /// this possible definition of `foo`:
     ///
-    ///     fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
+    /// ```text
+    /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
     ///         (&*x, &*y)
     ///     }
+    /// ```
     ///
     /// Here, the values for the concrete types of the two impl
     /// traits will include inference variables:
     ///
-    ///     &'0 i32
-    ///     &'1 i32
+    /// ```text
+    /// &'0 i32
+    /// &'1 i32
+    /// ```
     ///
     /// Ordinarily, the subtyping rules would ensure that these are
     /// sufficiently large. But since `impl Bar<'a>` isn't a specific
@@ -207,7 +217,7 @@
     /// inferred type are regions that could validly appear.
     ///
     /// This is actually a bit of a tricky constraint in general. We
-    /// want to say that each variable (e.g., `'0``) can only take on
+    /// want to say that each variable (e.g., `'0`) can only take on
     /// values that were supplied as arguments to the abstract type
     /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
     /// scope. We don't have a constraint quite of this kind in the current
@@ -225,7 +235,9 @@
     ///
     /// In some cases, there is no minimum. Consider this example:
     ///
-    ///    fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
+    /// ```text
+    /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
+    /// ```
     ///
     /// Here we would report an error, because `'a` and `'b` have no
     /// relation to one another.
@@ -245,8 +257,10 @@
     /// which is the current function. It also means that we can
     /// take "implied bounds" into account in some cases:
     ///
-    ///     trait SomeTrait<'a, 'b> { }
-    ///     fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
+    /// ```text
+    /// trait SomeTrait<'a, 'b> { }
+    /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
+    /// ```
     ///
     /// Here, the fact that `'b: 'a` is known only because of the
     /// implied bounds from the `&'a &'b u32` parameter, and is not
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index cae7bf5..541c135 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -437,10 +437,20 @@
         match cause.code {
             ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
                 hir::MatchSource::IfLetDesugar {..} => {
-                    err.span_note(arm_span, "`if let` arm with an incompatible type");
+                    let msg = "`if let` arm with an incompatible type";
+                    if self.tcx.sess.codemap().is_multiline(arm_span) {
+                        err.span_note(arm_span, msg);
+                    } else {
+                        err.span_label(arm_span, msg);
+                    }
                 }
                 _ => {
-                    err.span_note(arm_span, "match arm with an incompatible type");
+                    let msg = "match arm with an incompatible type";
+                    if self.tcx.sess.codemap().is_multiline(arm_span) {
+                        err.span_note(arm_span, msg);
+                    } else {
+                        err.span_label(arm_span, msg);
+                    }
                 }
             },
             _ => ()
@@ -1057,6 +1067,7 @@
                                sub_region: Region<'tcx>,
                                sup_origin: SubregionOrigin<'tcx>,
                                sup_region: Region<'tcx>) {
+
         let mut err = self.report_inference_failure(var_origin);
 
         self.tcx.note_and_explain_region(region_scope_tree, &mut err,
diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
index d4ea899..7b0f293 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -53,7 +53,7 @@
     ///
     /// It will later be extended to trait objects.
     pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
-        let NiceRegionError { span, sub, sup, .. } = *self;
+        let (span, sub, sup) = self.get_regions();
 
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
         let anon_reg_sup = self.is_suitable_region(sup)?;
diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
index edc38b6..59b36a5 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
@@ -18,46 +18,64 @@
 mod different_lifetimes;
 mod find_anon_type;
 mod named_anon_conflict;
+mod outlives_closure;
 mod util;
 
 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool {
-        let (span, sub, sup) = match *error {
-            ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
-            SubSupConflict(_, ref origin, sub, _, sup) => (origin.span(), sub, sup),
-            _ => return false, // inapplicable
-        };
+        match *error {
+            ConcreteFailure(..) | SubSupConflict(..) => {}
+            _ => return false,  // inapplicable
+        }
 
         if let Some(tables) = self.in_progress_tables {
             let tables = tables.borrow();
-            NiceRegionError::new(self.tcx, span, sub, sup, Some(&tables)).try_report().is_some()
+            NiceRegionError::new(self.tcx, error.clone(), Some(&tables)).try_report().is_some()
         } else {
-            NiceRegionError::new(self.tcx, span, sub, sup, None).try_report().is_some()
+            NiceRegionError::new(self.tcx, error.clone(), None).try_report().is_some()
         }
     }
 }
 
 pub struct NiceRegionError<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-    span: Span,
-    sub: ty::Region<'tcx>,
-    sup: ty::Region<'tcx>,
+    error: Option<RegionResolutionError<'tcx>>,
+    regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
     tables: Option<&'cx ty::TypeckTables<'tcx>>,
 }
 
 impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> {
     pub fn new(
         tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+        error: RegionResolutionError<'tcx>,
+        tables: Option<&'cx ty::TypeckTables<'tcx>>,
+    ) -> Self {
+        Self { tcx, error: Some(error), regions: None, tables }
+    }
+
+    pub fn new_from_span(
+        tcx: TyCtxt<'cx, 'gcx, 'tcx>,
         span: Span,
         sub: ty::Region<'tcx>,
         sup: ty::Region<'tcx>,
         tables: Option<&'cx ty::TypeckTables<'tcx>>,
     ) -> Self {
-        Self { tcx, span, sub, sup, tables }
+        Self { tcx, error: None, regions: Some((span, sub, sup)), tables }
     }
 
     pub fn try_report(&self) -> Option<ErrorReported> {
         self.try_report_named_anon_conflict()
             .or_else(|| self.try_report_anon_anon_conflict())
+            .or_else(|| self.try_report_outlives_closure())
+    }
+
+    pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
+        match (&self.error, self.regions) {
+            (&Some(ConcreteFailure(ref origin, sub, sup)), None) => (origin.span(), sub, sup),
+            (&Some(SubSupConflict(_, ref origin, sub, _, sup)), None) => (origin.span(), sub, sup),
+            (None, Some((span, sub, sup))) => (span, sub, sup),
+            (Some(_), Some(_)) => panic!("incorrectly built NiceRegionError"),
+            _ => panic!("trying to report on an incorrect lifetime failure"),
+        }
     }
 }
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 9d0ddfd..c106fd0 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -18,7 +18,7 @@
     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
     /// an anonymous region, emit an descriptive diagnostic error.
     pub(super) fn try_report_named_anon_conflict(&self) -> Option<ErrorReported> {
-        let NiceRegionError { span, sub, sup, .. } = *self;
+        let (span, sub, sup) = self.get_regions();
 
         debug!(
             "try_report_named_anon_conflict(sub={:?}, sup={:?})",
@@ -118,4 +118,17 @@
             .emit();
         return Some(ErrorReported);
     }
+
+    // This method returns whether the given Region is Named
+    pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
+        match *region {
+            ty::ReStatic => true,
+            ty::ReFree(ref free_region) => match free_region.bound_region {
+                ty::BrNamed(..) => true,
+                _ => false,
+            },
+            ty::ReEarlyBound(_) => true,
+            _ => false,
+        }
+    }
 }
diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
new file mode 100644
index 0000000..18b8c70
--- /dev/null
+++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
@@ -0,0 +1,124 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Error Reporting for Anonymous Region Lifetime Errors
+//! where both the regions are anonymous.
+
+use infer::error_reporting::nice_region_error::NiceRegionError;
+use infer::SubregionOrigin;
+use ty::RegionKind;
+use hir::{Expr, ExprClosure};
+use hir::map::NodeExpr;
+use util::common::ErrorReported;
+use infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
+
+impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
+    /// Print the error message for lifetime errors when binding excapes a closure.
+    ///
+    /// Consider a case where we have
+    ///
+    /// ```no_run
+    /// fn with_int<F>(f: F) where F: FnOnce(&isize) {
+    ///     let x = 3;
+    ///     f(&x);
+    /// }
+    /// fn main() {
+    ///     let mut x = None;
+    ///     with_int(|y| x = Some(y));
+    /// }
+    /// ```
+    ///
+    /// the output will be
+    ///
+    /// ```text
+    ///     let mut x = None;
+    ///         ----- borrowed data cannot be stored into here...
+    ///     with_int(|y| x = Some(y));
+    ///              ---          ^ cannot be stored outside of its closure
+    ///              |
+    ///              ...because it cannot outlive this closure
+    /// ```
+    pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> {
+        if let Some(SubSupConflict(origin,
+                                   ref sub_origin,
+                                   _,
+                                   ref sup_origin,
+                                   sup_region)) = self.error {
+
+            // #45983: when trying to assign the contents of an argument to a binding outside of a
+            // closure, provide a specific message pointing this out.
+            if let (&SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span),
+                    &RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) {
+                let hir = &self.tcx.hir;
+                if let Some(node_id) = hir.as_local_node_id(free_region.scope) {
+                    match hir.get(node_id) {
+                        NodeExpr(Expr {
+                            node: ExprClosure(_, _, _, closure_span, None),
+                            ..
+                        }) => {
+                            let sup_sp = sup_origin.span();
+                            let origin_sp = origin.span();
+                            let mut err = self.tcx.sess.struct_span_err(
+                                sup_sp,
+                                "borrowed data cannot be stored outside of its closure");
+                            err.span_label(sup_sp, "cannot be stored outside of its closure");
+                            if origin_sp == sup_sp || origin_sp.contains(sup_sp) {
+// // sup_sp == origin.span():
+//
+// let mut x = None;
+//     ----- borrowed data cannot be stored into here...
+// with_int(|y| x = Some(y));
+//          ---          ^ cannot be stored outside of its closure
+//          |
+//          ...because it cannot outlive this closure
+//
+// // origin.contains(&sup_sp):
+//
+// let mut f: Option<&u32> = None;
+//     ----- borrowed data cannot be stored into here...
+// closure_expecting_bound(|x: &'x u32| {
+//                         ------------ ... because it cannot outlive this closure
+//     f = Some(x);
+//              ^ cannot be stored outside of its closure
+                                err.span_label(*external_span,
+                                               "borrowed data cannot be stored into here...");
+                                err.span_label(*closure_span,
+                                               "...because it cannot outlive this closure");
+                            } else {
+// FIXME: the wording for this case could be much improved
+//
+// let mut lines_to_use: Vec<&CrateId> = Vec::new();
+//                           - cannot infer an appropriate lifetime...
+// let push_id = |installed_id: &CrateId| {
+//     -------   ------------------------ borrowed data cannot outlive this closure
+//     |
+//     ...so that variable is valid at time of its declaration
+//     lines_to_use.push(installed_id);
+//                       ^^^^^^^^^^^^ cannot be stored outside of its closure
+                                err.span_label(origin_sp,
+                                               "cannot infer an appropriate lifetime...");
+                                err.span_label(*external_span,
+                                               "...so that variable is valid at time of its \
+                                                declaration");
+                                err.span_label(*closure_span,
+                                               "borrowed data cannot outlive this closure");
+                            }
+                            err.emit();
+                            return Some(ErrorReported);
+                        }
+                        _ => {}
+                    }
+                }
+            }
+        }
+        None
+    }
+}
+
diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs
index f8b6f7d..8aadec6 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/util.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs
@@ -198,16 +198,4 @@
         }
         false
     }
-
-    // This method returns whether the given Region is Named
-    pub(super) fn is_named_region(&self, region: Region<'tcx>) -> bool {
-        match *region {
-            ty::ReFree(ref free_region) => match free_region.bound_region {
-                ty::BrNamed(..) => true,
-                _ => false,
-            },
-            ty::ReEarlyBound(_) => true,
-            _ => false,
-        }
-    }
 }
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index 1783d5a..8b61fcf 100644
--- a/src/librustc/infer/freshen.rs
+++ b/src/librustc/infer/freshen.rs
@@ -192,6 +192,7 @@
             ty::TyForeign(..) |
             ty::TyParam(..) |
             ty::TyClosure(..) |
+            ty::TyGeneratorWitness(..) |
             ty::TyAnon(..) => {
                 t.super_fold_with(self)
             }
diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs
index 4120948..d9d0829 100644
--- a/src/librustc/infer/lexical_region_resolve/graphviz.rs
+++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs
@@ -19,7 +19,6 @@
 use graphviz as dot;
 
 use hir::def_id::DefIndex;
-use rustc_data_structures::indexed_vec::Idx;
 use ty;
 use middle::free_region::RegionRelations;
 use middle::region;
@@ -68,7 +67,7 @@
     }
 
     let requested_node = env::var("RUST_REGION_GRAPH_NODE")
-        .ok().and_then(|s| s.parse().map(DefIndex::new).ok());
+        .ok().and_then(|s| s.parse().map(DefIndex::from_raw_u32).ok());
 
     if requested_node.is_some() && requested_node != Some(context.index) {
         return;
@@ -102,7 +101,7 @@
             let mut new_str = String::new();
             for c in output_template.chars() {
                 if c == '%' {
-                    new_str.push_str(&context.index.as_usize().to_string());
+                    new_str.push_str(&context.index.as_raw_u32().to_string());
                 } else {
                     new_str.push(c);
                 }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index becaf78..d727dfb 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -44,10 +44,12 @@
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
 #![feature(const_fn)]
+#![feature(copy_closures, clone_closures)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![feature(dyn_trait)]
 #![feature(from_ref)]
+#![feature(fs_read_write)]
 #![feature(i128)]
 #![feature(i128_type)]
 #![feature(inclusive_range)]
@@ -175,4 +177,5 @@
 
 
 // Build the diagnostics array at the end so that the metadata includes error use sites.
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc, DIAGNOSTICS }
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index de0bd9d..143d2c2 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -127,7 +127,7 @@
 declare_lint! {
     pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
     Deny,
-    "detect public reexports of private extern crates"
+    "detect public re-exports of private extern crates"
 }
 
 declare_lint! {
@@ -240,6 +240,12 @@
    "detects single use lifetimes"
 }
 
+declare_lint! {
+    pub TYVAR_BEHIND_RAW_POINTER,
+    Warn,
+    "raw pointer to an inference variable"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -284,7 +290,8 @@
             UNUSED_UNSAFE,
             UNUSED_MUT,
             COERCE_NEVER,
-            SINGLE_USE_LIFETIME
+            SINGLE_USE_LIFETIME,
+            TYVAR_BEHIND_RAW_POINTER
         )
     }
 }
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 32ab458..5336c19 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -1046,7 +1046,7 @@
     // calculated the lint levels for all AST nodes.
     for (_id, lints) in cx.buffered.map {
         for early_lint in lints {
-            span_bug!(early_lint.span, "failed to process bufferd lint here");
+            span_bug!(early_lint.span, "failed to process buffered lint here");
         }
     }
 }
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index f4abc54..b2a9859 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -97,12 +97,13 @@
 
 /// Declare a static `LintArray` and return it as an expression.
 #[macro_export]
-macro_rules! lint_array { ($( $lint:expr ),*) => (
-    {
-        static ARRAY: LintArray = &[ $( &$lint ),* ];
-        ARRAY
-    }
-) }
+macro_rules! lint_array {
+    ($( $lint:expr ),*,) => { lint_array!( $( $lint ),* ) };
+    ($( $lint:expr ),*) => {{
+         static ARRAY: LintArray = &[ $( &$lint ),* ];
+         ARRAY
+    }}
+}
 
 pub type LintArray = &'static [&'static &'static Lint];
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 21eb772..1ff9c7a 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -50,7 +50,7 @@
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
     live_symbols: Box<FxHashSet<ast::NodeId>>,
-    struct_has_extern_repr: bool,
+    repr_has_repr_c: bool,
     in_pat: bool,
     inherited_pub_visibility: bool,
     ignore_variant_stack: Vec<DefId>,
@@ -102,7 +102,7 @@
     fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
         match self.tables.expr_ty_adjusted(lhs).sty {
             ty::TyAdt(def, _) => {
-                self.insert_def_id(def.struct_variant().field_named(name).did);
+                self.insert_def_id(def.non_enum_variant().field_named(name).did);
             }
             _ => span_bug!(lhs.span, "named field access on non-ADT"),
         }
@@ -111,7 +111,7 @@
     fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
         match self.tables.expr_ty_adjusted(lhs).sty {
             ty::TyAdt(def, _) => {
-                self.insert_def_id(def.struct_variant().fields[idx].did);
+                self.insert_def_id(def.non_enum_variant().fields[idx].did);
             }
             ty::TyTuple(..) => {}
             _ => span_bug!(lhs.span, "numeric field access on non-ADT"),
@@ -149,8 +149,8 @@
     }
 
     fn visit_node(&mut self, node: &hir_map::Node<'tcx>) {
-        let had_extern_repr = self.struct_has_extern_repr;
-        self.struct_has_extern_repr = false;
+        let had_repr_c = self.repr_has_repr_c;
+        self.repr_has_repr_c = false;
         let had_inherited_pub_visibility = self.inherited_pub_visibility;
         self.inherited_pub_visibility = false;
         match *node {
@@ -159,7 +159,7 @@
                     hir::ItemStruct(..) | hir::ItemUnion(..) => {
                         let def_id = self.tcx.hir.local_def_id(item.id);
                         let def = self.tcx.adt_def(def_id);
-                        self.struct_has_extern_repr = def.repr.c();
+                        self.repr_has_repr_c = def.repr.c();
 
                         intravisit::walk_item(self, &item);
                     }
@@ -187,7 +187,7 @@
             }
             _ => ()
         }
-        self.struct_has_extern_repr = had_extern_repr;
+        self.repr_has_repr_c = had_repr_c;
         self.inherited_pub_visibility = had_inherited_pub_visibility;
     }
 
@@ -223,10 +223,10 @@
 
     fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name,
                         _: &hir::Generics, _: ast::NodeId, _: syntax_pos::Span) {
-        let has_extern_repr = self.struct_has_extern_repr;
+        let has_repr_c = self.repr_has_repr_c;
         let inherited_pub_visibility = self.inherited_pub_visibility;
         let live_fields = def.fields().iter().filter(|f| {
-            has_extern_repr || inherited_pub_visibility || f.vis == hir::Public
+            has_repr_c || inherited_pub_visibility || f.vis == hir::Public
         });
         self.live_symbols.extend(live_fields.map(|f| f.id));
 
@@ -428,7 +428,7 @@
         tcx,
         tables: &ty::TypeckTables::empty(None),
         live_symbols: box FxHashSet(),
-        struct_has_extern_repr: false,
+        repr_has_repr_c: false,
         in_pat: false,
         inherited_pub_visibility: false,
         ignore_variant_stack: vec![],
@@ -564,7 +564,6 @@
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
                 hir::ItemTrait(..) |
-                hir::ItemAutoImpl(..) |
                 hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span),
                 _ => item.span,
             };
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 3bcde93..c690051 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -663,7 +663,7 @@
         match with_cmt.ty.sty {
             ty::TyAdt(adt, substs) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
-                for with_field in &adt.struct_variant().fields {
+                for with_field in &adt.non_enum_variant().fields {
                     if !contains_field_named(with_field, fields) {
                         let cmt_field = self.mc.cat_field(
                             &*with_expr,
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index f8933d0..dca6761 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -338,6 +338,8 @@
     U128ShloFnLangItem,              "u128_shlo",               u128_shlo_fn;
     I128ShroFnLangItem,              "i128_shro",               i128_shro_fn;
     U128ShroFnLangItem,              "u128_shro",               u128_shro_fn;
+
+    TerminationTraitLangItem,        "termination",             termination;
 }
 
 impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 0d4429d..a895572 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1248,7 +1248,7 @@
                 Def::StructCtor(_, CtorKind::Fn) => {
                     match self.pat_ty(&pat)?.sty {
                         ty::TyAdt(adt_def, _) => {
-                            (cmt, adt_def.struct_variant().fields.len())
+                            (cmt, adt_def.non_enum_variant().fields.len())
                         }
                         ref ty => {
                             span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 1376886..e2de0b6 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -26,9 +26,9 @@
     // public, then type `T` is reachable. Its values can be obtained by other crates
     // even if the type itself is not nameable.
     Reachable,
-    // Public items + items accessible to other crates with help of `pub use` reexports
+    // Public items + items accessible to other crates with help of `pub use` re-exports
     Exported,
-    // Items accessible to other crates directly, without help of reexports
+    // Items accessible to other crates directly, without help of re-exports
     Public,
 }
 
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 6f457c9..e11609e 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -270,8 +270,7 @@
                     hir::ItemMod(..) | hir::ItemForeignMod(..) |
                     hir::ItemImpl(..) | hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
                     hir::ItemStruct(..) | hir::ItemEnum(..) |
-                    hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
-                    hir::ItemGlobalAsm(..) => {}
+                    hir::ItemUnion(..) |  hir::ItemGlobalAsm(..) => {}
                 }
             }
             hir_map::NodeTraitItem(trait_method) => {
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index d3aa80e..66b3adb 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -53,9 +53,9 @@
 /// expression for the indexed statement, until the end of the block.
 ///
 /// So: the following code can be broken down into the scopes beneath:
-/// ```
+///
+/// ```text
 /// let a = f().g( 'b: { let x = d(); let y = d(); x.h(y)  }   ) ;
-/// ```
 ///
 ///                                                              +-+ (D12.)
 ///                                                        +-+       (D11.)
@@ -82,6 +82,7 @@
 /// (R10.): Remainder scope for block `'b:`, stmt 1 (let y = ...).
 /// (D11.): DestructionScope for temporaries and bindings from block `'b:`.
 /// (D12.): DestructionScope for temporaries created during M1 (e.g. f()).
+/// ```
 ///
 /// Note that while the above picture shows the destruction scopes
 /// as following their corresponding node scopes, in the internal
@@ -452,6 +453,43 @@
     terminating_scopes: FxHashSet<hir::ItemLocalId>,
 }
 
+struct ExprLocatorVisitor {
+    id: ast::NodeId,
+    result: Option<usize>,
+    expr_and_pat_count: usize,
+}
+
+// This visitor has to have the same visit_expr calls as RegionResolutionVisitor
+// since `expr_count` is compared against the results there.
+impl<'tcx> Visitor<'tcx> for ExprLocatorVisitor {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_pat(&mut self, pat: &'tcx Pat) {
+        self.expr_and_pat_count += 1;
+
+        intravisit::walk_pat(self, pat);
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr) {
+        debug!("ExprLocatorVisitor - pre-increment {} expr = {:?}",
+               self.expr_and_pat_count,
+               expr);
+
+        intravisit::walk_expr(self, expr);
+
+        self.expr_and_pat_count += 1;
+
+        debug!("ExprLocatorVisitor - post-increment {} expr = {:?}",
+               self.expr_and_pat_count,
+               expr);
+
+        if expr.id == self.id {
+            self.result = Some(self.expr_and_pat_count);
+        }
+    }
+}
 
 impl<'tcx> ScopeTree {
     pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
@@ -611,6 +649,20 @@
         return true;
     }
 
+    /// Returns the id of the innermost containing body
+    pub fn containing_body(&self, mut scope: Scope)-> Option<hir::ItemLocalId> {
+        loop {
+            if let ScopeData::CallSite(id) = scope.data() {
+                return Some(id);
+            }
+
+            match self.opt_encl_scope(scope) {
+                None => return None,
+                Some(parent) => scope = parent,
+            }
+        }
+    }
+
     /// Finds the nearest common ancestor (if any) of two scopes.  That is, finds the smallest
     /// scope which is greater than or equal to both `scope_a` and `scope_b`.
     pub fn nearest_common_ancestor(&self,
@@ -767,6 +819,28 @@
         self.yield_in_scope.get(&scope).cloned()
     }
 
+    /// Checks whether the given scope contains a `yield` and if that yield could execute
+    /// after `expr`. If so, it returns the span of that `yield`.
+    /// `scope` must be inside the body.
+    pub fn yield_in_scope_for_expr(&self,
+                                   scope: Scope,
+                                   expr: ast::NodeId,
+                                   body: &'tcx hir::Body) -> Option<Span> {
+        self.yield_in_scope(scope).and_then(|(span, count)| {
+            let mut visitor = ExprLocatorVisitor {
+                id: expr,
+                result: None,
+                expr_and_pat_count: 0,
+            };
+            visitor.visit_body(body);
+            if count >= visitor.result.unwrap() {
+                Some(span)
+            } else {
+                None
+            }
+        })
+    }
+
     /// Gives the number of expressions visited in a body.
     /// Used to sanity check visit_expr call count when
     /// calculating generator interiors.
@@ -871,9 +945,13 @@
         record_var_lifetime(visitor, pat.hir_id.local_id, pat.span);
     }
 
+    debug!("resolve_pat - pre-increment {} pat = {:?}", visitor.expr_and_pat_count, pat);
+
     intravisit::walk_pat(visitor, pat);
 
     visitor.expr_and_pat_count += 1;
+
+    debug!("resolve_pat - post-increment {} pat = {:?}", visitor.expr_and_pat_count, pat);
 }
 
 fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt: &'tcx hir::Stmt) {
@@ -896,7 +974,7 @@
 }
 
 fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &'tcx hir::Expr) {
-    debug!("resolve_expr(expr.id={:?})", expr.id);
+    debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr);
 
     let prev_cx = visitor.cx;
     visitor.enter_node_scope_with_dtor(expr.hir_id.local_id);
@@ -981,6 +1059,8 @@
 
     visitor.expr_and_pat_count += 1;
 
+    debug!("resolve_expr post-increment {}, expr = {:?}", visitor.expr_and_pat_count, expr);
+
     if let hir::ExprYield(..) = expr.node {
         // Mark this expr's scope and all parent scopes as containing `yield`.
         let mut scope = Scope::Node(expr.hir_id.local_id);
@@ -1076,12 +1156,13 @@
         }
     }
 
-    if let Some(pat) = pat {
-        visitor.visit_pat(pat);
-    }
+    // Make sure we visit the initializer first, so expr_and_pat_count remains correct
     if let Some(expr) = init {
         visitor.visit_expr(expr);
     }
+    if let Some(pat) = pat {
+        visitor.visit_pat(pat);
+    }
 
     /// True if `pat` match the `P&` nonterminal:
     ///
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 8b302db..935dfd7 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -461,10 +461,10 @@
                                           intravisit::walk_item(this, item);
                 });
             }
+
             hir::ItemExternCrate(_)
             | hir::ItemUse(..)
             | hir::ItemMod(..)
-            | hir::ItemAutoImpl(..)
             | hir::ItemForeignMod(..)
             | hir::ItemGlobalAsm(..) => {
                 // These sorts of items have no lifetime parameters at all.
diff --git a/src/librustc/mir/README.md b/src/librustc/mir/README.md
index fb0c7ce..cac86be 100644
--- a/src/librustc/mir/README.md
+++ b/src/librustc/mir/README.md
@@ -59,7 +59,7 @@
 pipeline is stolen, anyone who may want to read from it has already
 done so. Concretely, this means that if you have some query `foo(D)`
 that wants to access the result of `mir_const(D)` or
-`mir_validated(D)`, you need to have the successor pass either "force"
+`mir_validated(D)`, you need to have the successor pass "force"
 `foo(D)` using `ty::queries::foo::force(...)`. This will force a query
 to execute even though you don't directly require its result.
 
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 054cb23..8ffea62 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -145,7 +145,7 @@
 }
 
 
-#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
+#[derive(Copy, Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
 pub struct AllocId(pub u64);
 
 impl fmt::Display for AllocId {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index f410865..3aa94b3 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! MIR datatypes and passes. See [the README](README.md) for details.
+//! MIR datatypes and passes. See the module-level [README] for details.
+//!
+//! [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/mir/README.md
 
 use graphviz::IntoCow;
 use middle::const_val::ConstVal;
@@ -481,11 +483,86 @@
     /// Source info of the local.
     pub source_info: SourceInfo,
 
-    /// The *lexical* visibility scope the local is defined
+    /// The *syntactic* visibility scope the local is defined
     /// in. If the local was defined in a let-statement, this
     /// is *within* the let-statement, rather than outside
     /// of it.
-    pub lexical_scope: VisibilityScope,
+    ///
+    /// This is needed because visibility scope of locals within a let-statement
+    /// is weird.
+    ///
+    /// The reason is that we want the local to be *within* the let-statement
+    /// for lint purposes, but we want the local to be *after* the let-statement
+    /// for names-in-scope purposes.
+    ///
+    /// That's it, if we have a let-statement like the one in this
+    /// function:
+    ///
+    /// ```
+    /// fn foo(x: &str) {
+    ///     #[allow(unused_mut)]
+    ///     let mut x: u32 = { // <- one unused mut
+    ///         let mut y: u32 = x.parse().unwrap();
+    ///         y + 2
+    ///     };
+    ///     drop(x);
+    /// }
+    /// ```
+    ///
+    /// Then, from a lint point of view, the declaration of `x: u32`
+    /// (and `y: u32`) are within the `#[allow(unused_mut)]` scope - the
+    /// lint scopes are the same as the AST/HIR nesting.
+    ///
+    /// However, from a name lookup point of view, the scopes look more like
+    /// as if the let-statements were `match` expressions:
+    ///
+    /// ```
+    /// fn foo(x: &str) {
+    ///     match {
+    ///         match x.parse().unwrap() {
+    ///             y => y + 2
+    ///         }
+    ///     } {
+    ///         x => drop(x)
+    ///     };
+    /// }
+    /// ```
+    ///
+    /// We care about the name-lookup scopes for debuginfo - if the
+    /// debuginfo instruction pointer is at the call to `x.parse()`, we
+    /// want `x` to refer to `x: &str`, but if it is at the call to
+    /// `drop(x)`, we want it to refer to `x: u32`.
+    ///
+    /// To allow both uses to work, we need to have more than a single scope
+    /// for a local. We have the `syntactic_scope` represent the
+    /// "syntactic" lint scope (with a variable being under its let
+    /// block) while the source-info scope represents the "local variable"
+    /// scope (where the "rest" of a block is under all prior let-statements).
+    ///
+    /// The end result looks like this:
+    ///
+    /// ```text
+    /// ROOT SCOPE
+    ///  │{ argument x: &str }
+    ///  │
+    ///  │ │{ #[allow(unused_mut] } // this is actually split into 2 scopes
+    ///  │ │                        // in practice because I'm lazy.
+    ///  │ │
+    ///  │ │← x.syntactic_scope
+    ///  │ │← `x.parse().unwrap()`
+    ///  │ │
+    ///  │ │ │← y.syntactic_scope
+    ///  │ │
+    ///  │ │ │{ let y: u32 }
+    ///  │ │ │
+    ///  │ │ │← y.source_info.scope
+    ///  │ │ │← `y + 2`
+    ///  │
+    ///  │ │{ let x: u32 }
+    ///  │ │← x.source_info.scope
+    ///  │ │← `drop(x)` // this accesses `x: u32`
+    /// ```
+    pub syntactic_scope: VisibilityScope,
 }
 
 impl<'tcx> LocalDecl<'tcx> {
@@ -500,7 +577,7 @@
                 span,
                 scope: ARGUMENT_VISIBILITY_SCOPE
             },
-            lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+            syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
             internal: false,
             is_user_variable: false
         }
@@ -517,7 +594,7 @@
                 span,
                 scope: ARGUMENT_VISIBILITY_SCOPE
             },
-            lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+            syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
             internal: true,
             is_user_variable: false
         }
@@ -535,7 +612,7 @@
                 span,
                 scope: ARGUMENT_VISIBILITY_SCOPE
             },
-            lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+            syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
             internal: false,
             name: None,     // FIXME maybe we do want some name here?
             is_user_variable: false
@@ -637,6 +714,10 @@
     /// continue. Emitted by build::scope::diverge_cleanup.
     Resume,
 
+    /// Indicates that the landing pad is finished and that the process
+    /// should abort. Used to prevent unwinding for foreign items.
+    Abort,
+
     /// Indicates a normal return. The return place should have
     /// been filled in by now. This should occur at most once.
     Return,
@@ -759,7 +840,7 @@
         match *self {
             Goto { target: ref b } => slice::from_ref(b).into_cow(),
             SwitchInt { targets: ref b, .. } => b[..].into_cow(),
-            Resume | GeneratorDrop => (&[]).into_cow(),
+            Resume | Abort | GeneratorDrop => (&[]).into_cow(),
             Return => (&[]).into_cow(),
             Unreachable => (&[]).into_cow(),
             Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
@@ -794,7 +875,7 @@
         match *self {
             Goto { target: ref mut b } => vec![b],
             SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
-            Resume | GeneratorDrop => Vec::new(),
+            Resume | Abort | GeneratorDrop => Vec::new(),
             Return => Vec::new(),
             Unreachable => Vec::new(),
             Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
@@ -823,6 +904,7 @@
         match *self {
             TerminatorKind::Goto { .. } |
             TerminatorKind::Resume |
+            TerminatorKind::Abort |
             TerminatorKind::Return |
             TerminatorKind::Unreachable |
             TerminatorKind::GeneratorDrop |
@@ -918,6 +1000,7 @@
             Return => write!(fmt, "return"),
             GeneratorDrop => write!(fmt, "generator_drop"),
             Resume => write!(fmt, "resume"),
+            Abort => write!(fmt, "abort"),
             Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
             Unreachable => write!(fmt, "unreachable"),
             Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
@@ -970,7 +1053,7 @@
     pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
         use self::TerminatorKind::*;
         match *self {
-            Return | Resume | Unreachable | GeneratorDrop => vec![],
+            Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
             SwitchInt { ref values, .. } => {
                 values.iter()
@@ -1818,7 +1901,7 @@
 ///
 /// Example: If type check produces a closure with the closure substs:
 ///
-/// ```
+/// ```text
 /// ClosureSubsts = [
 ///     i8,                                  // the "closure kind"
 ///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
@@ -1829,7 +1912,7 @@
 /// here, there is one unique free region (`'a`) but it appears
 /// twice. We would "renumber" each occurence to a unique vid, as follows:
 ///
-/// ```
+/// ```text
 /// ClosureSubsts = [
 ///     i8,                                  // the "closure kind"
 ///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
@@ -2102,6 +2185,7 @@
             },
             GeneratorDrop => GeneratorDrop,
             Resume => Resume,
+            Abort => Abort,
             Return => Return,
             Unreachable => Unreachable,
             FalseEdges { real_target, ref imaginary_targets } =>
@@ -2143,6 +2227,7 @@
             },
             Goto { .. } |
             Resume |
+            Abort |
             Return |
             GeneratorDrop |
             Unreachable |
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 5f74f08..efdf406 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -12,9 +12,11 @@
 use syntax::symbol::InternedString;
 use ty::Instance;
 use util::nodemap::FxHashMap;
+use rustc_data_structures::base_n;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
                                            StableHasher};
 use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
+use std::hash::Hash;
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum MonoItem<'tcx> {
@@ -119,6 +121,16 @@
     {
         &mut self.items
     }
+
+    pub fn mangle_name(human_readable_name: &str) -> String {
+        // We generate a 80 bit hash from the name. This should be enough to
+        // avoid collisions and is still reasonably short for filenames.
+        let mut hasher = StableHasher::new();
+        human_readable_name.hash(&mut hasher);
+        let hash: u128 = hasher.finish();
+        let hash = hash & ((1u128 << 80) - 1);
+        base_n::encode(hash, base_n::CASE_INSENSITIVE)
+    }
 }
 
 impl<'tcx> HashStable<StableHashingContext<'tcx>> for CodegenUnit<'tcx> {
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 0e6c14a..57ed41f 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -277,6 +277,13 @@
 
             fn super_mir(&mut self,
                          mir: & $($mutability)* Mir<'tcx>) {
+                if let Some(yield_ty) = &$($mutability)* mir.yield_ty {
+                    self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
+                        span: mir.span,
+                        scope: ARGUMENT_VISIBILITY_SCOPE,
+                    }));
+                }
+
                 // for best performance, we want to use an iterator rather
                 // than a for-loop, to avoid calling Mir::invalidate for
                 // each basic block.
@@ -432,6 +439,7 @@
                     }
 
                     TerminatorKind::Resume |
+                    TerminatorKind::Abort |
                     TerminatorKind::Return |
                     TerminatorKind::GeneratorDrop |
                     TerminatorKind::Unreachable => {
@@ -702,7 +710,7 @@
                     name: _,
                     ref $($mutability)* source_info,
                     internal: _,
-                    ref $($mutability)* lexical_scope,
+                    ref $($mutability)* syntactic_scope,
                     is_user_variable: _,
                 } = *local_decl;
 
@@ -711,7 +719,7 @@
                     source_info: *source_info,
                 });
                 self.visit_source_info(source_info);
-                self.visit_visibility_scope(lexical_scope);
+                self.visit_visibility_scope(syntactic_scope);
             }
 
             fn super_visibility_scope(&mut self,
@@ -851,6 +859,8 @@
     /// The return type of the function.
     ReturnTy(SourceInfo),
 
+    YieldTy(SourceInfo),
+
     /// A type found at some location.
     Location(Location),
 }
diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs
index 118b841..64f405e 100644
--- a/src/librustc/session/code_stats.rs
+++ b/src/librustc/session/code_stats.rs
@@ -155,11 +155,19 @@
 
                     // Include field alignment in output only if it caused padding injection
                     if min_offset != offset {
-                        let pad = offset - min_offset;
-                        println!("print-type-size {}padding: {} bytes",
-                                 indent, pad);
-                        println!("print-type-size {}field `.{}`: {} bytes, alignment: {} bytes",
-                                 indent, name, size, align);
+                        if offset > min_offset {
+                            let pad = offset - min_offset;
+                            println!("print-type-size {}padding: {} bytes",
+                                     indent, pad);
+                            println!("print-type-size {}field `.{}`: {} bytes, \
+                                      alignment: {} bytes",
+                                     indent, name, size, align);
+                        } else {
+                            println!("print-type-size {}field `.{}`: {} bytes, \
+                                      offset: {} bytes, \
+                                      alignment: {} bytes",
+                                     indent, name, size, offset, align);
+                        }
                     } else {
                         println!("print-type-size {}field `.{}`: {} bytes",
                                  indent, name, size);
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 6ad9bd9..da119ba 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -778,6 +778,8 @@
             Some(::rustc_back::LinkerFlavor::one_of());
         pub const parse_optimization_fuel: Option<&'static str> =
             Some("crate=integer");
+        pub const parse_unpretty: Option<&'static str> =
+            Some("`string` or `string=string`");
     }
 
     #[allow(dead_code)]
@@ -965,6 +967,17 @@
                 }
             }
         }
+
+        fn parse_unpretty(slot: &mut Option<String>, v: Option<&str>) -> bool {
+            match v {
+                None => false,
+                Some(s) if s.split('=').count() <= 2 => {
+                    *slot = Some(s.to_string());
+                    true
+                }
+                _ => false,
+            }
+        }
     }
 ) }
 
@@ -1045,6 +1058,8 @@
 options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
          build_debugging_options, "Z", "debugging",
          DB_OPTIONS, db_type_desc, dbsetters,
+    codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
+        "the backend to use"),
     verbose: bool = (false, parse_bool, [UNTRACKED],
         "in general, enable more debug printouts"),
     span_free_formats: bool = (false, parse_bool, [UNTRACKED],
@@ -1082,8 +1097,8 @@
         "gather borrowck statistics"),
     no_landing_pads: bool = (false, parse_bool, [TRACKED],
         "omit landing pads for unwinding"),
-    debug_llvm: bool = (false, parse_bool, [UNTRACKED],
-        "enable debug output from LLVM"),
+    fewer_names: bool = (false, parse_bool, [TRACKED],
+        "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR)"),
     meta_stats: bool = (false, parse_bool, [UNTRACKED],
         "gather metadata statistics"),
     print_link_args: bool = (false, parse_bool, [UNTRACKED],
@@ -1102,13 +1117,13 @@
         "write syntax and type analysis (in JSON format) information, in \
          addition to normal output"),
     flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED],
-        "include loan analysis data in --unpretty flowgraph output"),
+        "include loan analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_moves: bool = (false, parse_bool, [UNTRACKED],
-        "include move analysis data in --unpretty flowgraph output"),
+        "include move analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_assigns: bool = (false, parse_bool, [UNTRACKED],
-        "include assignment analysis data in --unpretty flowgraph output"),
+        "include assignment analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_all: bool = (false, parse_bool, [UNTRACKED],
-        "include all dataflow analysis data in --unpretty flowgraph output"),
+        "include all dataflow analysis data in -Z unpretty flowgraph output"),
     print_region_graph: bool = (false, parse_bool, [UNTRACKED],
          "prints region inference graph. \
           Use with RUST_REGION_GRAPH=help for more info"),
@@ -1172,7 +1187,7 @@
           "emit noalias metadata for mutable references"),
     dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
           "dump MIR state at various points in translation"),
-    dump_mir_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
+    dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED],
           "the directory the MIR is dumped into"),
     dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
           "in addition to `.mir` files, create graphviz `.dot` files"),
@@ -1234,6 +1249,18 @@
         "rewrite operators on i128 and u128 into lang item calls (typically provided \
          by compiler-builtins) so translation doesn't need to support them,
          overriding the default for the current target"),
+    human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
+        "generate human-readable, predictable names for codegen units"),
+    dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
+        "in dep-info output, omit targets for tracking dependencies of the dep-info files \
+         themselves"),
+    unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
+        "Present the input source, unstable (and less-pretty) variants;
+        valid types are any of the types for `--pretty`, as well as:
+        `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+        `everybody_loops` (all function bodies replaced with `loop {}`),
+        `hir` (the HIR), `hir,identified`, or
+        `hir,typed` (HIR with types for each node)."),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1507,14 +1534,6 @@
                   `expanded` (crates expanded), or
                   `expanded,identified` (fully parenthesized, AST nodes with IDs).",
                  "TYPE"),
-        opt::opt("", "unpretty",
-                 "Present the input source, unstable (and less-pretty) variants;
-                  valid types are any of the types for `--pretty`, as well as:
-                  `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
-                  `everybody_loops` (all function bodies replaced with `loop {}`),
-                  `hir` (the HIR), `hir,identified`, or
-                  `hir,typed` (HIR with types for each node).",
-                 "TYPE"),
     ]);
     opts
 }
@@ -2745,8 +2764,6 @@
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
         opts.debugging_opts.borrowck_stats = true;
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
-        opts.debugging_opts.debug_llvm = true;
-        assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
         opts.debugging_opts.meta_stats = true;
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
         opts.debugging_opts.print_link_args = true;
@@ -2793,7 +2810,7 @@
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
         opts.debugging_opts.dump_mir = Some(String::from("abc"));
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
-        opts.debugging_opts.dump_mir_dir = Some(String::from("abc"));
+        opts.debugging_opts.dump_mir_dir = String::from("abc");
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
         opts.debugging_opts.dump_mir_graphviz = true;
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
@@ -2812,6 +2829,10 @@
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
         opts = reference.clone();
+        opts.debugging_opts.fewer_names = true;
+        assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
+        opts = reference.clone();
         opts.debugging_opts.no_trans = true;
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 0de1c20..36f716a 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -11,14 +11,15 @@
 pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
 pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
 
-use hir::def_id::{CrateNum, DefIndex};
+use hir::def_id::CrateNum;
 use ich::Fingerprint;
 
+use ich;
 use lint;
 use middle::allocator::AllocatorKind;
 use middle::dependency_format;
 use session::search_paths::PathKind;
-use session::config::{BorrowckMode, DebugInfoLevel};
+use session::config::{BorrowckMode, DebugInfoLevel, OutputType};
 use ty::tls;
 use util::nodemap::{FxHashMap, FxHashSet};
 use util::common::{duration_to_secs_str, ErrorReported};
@@ -28,6 +29,7 @@
 use errors::emitter::{Emitter, EmitterWriter};
 use syntax::json::JsonEmitter;
 use syntax::feature_gate;
+use syntax::symbol::Symbol;
 use syntax::parse;
 use syntax::parse::ParseSess;
 use syntax::{ast, codemap};
@@ -112,6 +114,9 @@
 
     incr_comp_session: RefCell<IncrCompSession>,
 
+    /// A cache of attributes ignored by StableHashingContext
+    pub ignored_attr_names: FxHashSet<Symbol>,
+
     /// Some measurements that are being gathered during compilation.
     pub perf_stats: PerfStats,
 
@@ -504,6 +509,13 @@
     pub fn linker_flavor(&self) -> LinkerFlavor {
         self.opts.debugging_opts.linker_flavor.unwrap_or(self.target.target.linker_flavor)
     }
+
+    pub fn fewer_names(&self) -> bool {
+        let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) ||
+                         self.opts.output_types.contains_key(&OutputType::Bitcode);
+        self.opts.debugging_opts.fewer_names || !more_names
+    }
+
     pub fn no_landing_pads(&self) -> bool {
         self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort
     }
@@ -551,18 +563,16 @@
 
     /// Returns the symbol name for the registrar function,
     /// given the crate Svh and the function DefIndex.
-    pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator,
-                                            index: DefIndex)
+    pub fn generate_plugin_registrar_symbol(&self,
+                                            disambiguator: CrateDisambiguator)
                                             -> String {
-        format!("__rustc_plugin_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
-                                                   index.as_usize())
+        format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
-    pub fn generate_derive_registrar_symbol(&self, disambiguator: CrateDisambiguator,
-                                            index: DefIndex)
+    pub fn generate_derive_registrar_symbol(&self,
+                                            disambiguator: CrateDisambiguator)
                                             -> String {
-        format!("__rustc_derive_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
-                                                   index.as_usize())
+        format!("__rustc_derive_registrar_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
     pub fn sysroot<'a>(&'a self) -> &'a Path {
@@ -642,6 +652,7 @@
             IncrCompSession::Active { ref session_directory, .. } => {
                 session_directory.clone()
             }
+            IncrCompSession::InvalidBecauseOfErrors { .. } => return,
             _ => bug!("Trying to invalidate IncrCompSession `{:?}`",
                       *incr_comp_session),
         };
@@ -791,10 +802,7 @@
         // As a result 16 was chosen here! Mostly because it was a power of 2
         // and most benchmarks agreed it was roughly a local optimum. Not very
         // scientific.
-        match self.opts.optimize {
-            config::OptLevel::No => 16,
-            _ => 1, // FIXME(#46346) this should be 16
-        }
+        16
     }
 
     /// Returns whether ThinLTO is enabled for this compilation
@@ -972,6 +980,7 @@
         injected_panic_runtime: Cell::new(None),
         imported_macro_spans: RefCell::new(HashMap::new()),
         incr_comp_session: RefCell::new(IncrCompSession::NotInitialized),
+        ignored_attr_names: ich::compute_ignored_attr_names(),
         perf_stats: PerfStats {
             svh_time: Cell::new(Duration::from_secs(0)),
             incr_comp_hashes_time: Cell::new(Duration::from_secs(0)),
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 7d1f3b3..ae68e3f 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -451,7 +451,10 @@
             true
         }
 
-        ty::TyClosure(..) | ty::TyGenerator(..) | ty::TyAnon(..) => {
+        ty::TyClosure(..) |
+        ty::TyGenerator(..) |
+        ty::TyGeneratorWitness(..) |
+        ty::TyAnon(..) => {
             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
         }
     }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 54da238..067340e 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -262,6 +262,7 @@
                 },
                 ty::TyGenerator(..) => Some(18),
                 ty::TyForeign(..) => Some(19),
+                ty::TyGeneratorWitness(..) => Some(20),
                 ty::TyInfer(..) | ty::TyError => None
             }
         }
@@ -717,93 +718,40 @@
                     self.tcx.hir.span_if_local(did)
                 }).map(|sp| self.tcx.sess.codemap().def_span(sp)); // the sp could be an fn def
 
-                let found_ty_count =
-                    match found_trait_ref.skip_binder().substs.type_at(1).sty {
-                        ty::TyTuple(ref tys, _) => tys.len(),
-                        _ => 1,
-                    };
-                let (expected_tys, expected_ty_count) =
-                    match expected_trait_ref.skip_binder().substs.type_at(1).sty {
-                        ty::TyTuple(ref tys, _) =>
-                            (tys.iter().map(|t| &t.sty).collect(), tys.len()),
-                        ref sty => (vec![sty], 1),
-                    };
-                if found_ty_count == expected_ty_count {
+                let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
+                    ty::TyTuple(ref tys, _) => tys.iter()
+                        .map(|_| ArgKind::empty()).collect::<Vec<_>>(),
+                    _ => vec![ArgKind::empty()],
+                };
+                let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
+                    ty::TyTuple(ref tys, _) => tys.iter()
+                        .map(|t| match t.sty {
+                            ty::TypeVariants::TyTuple(ref tys, _) => ArgKind::Tuple(
+                                span,
+                                tys.iter()
+                                    .map(|ty| ("_".to_owned(), format!("{}", ty.sty)))
+                                    .collect::<Vec<_>>()
+                            ),
+                            _ => ArgKind::Arg("_".to_owned(), format!("{}", t.sty)),
+                        }).collect(),
+                    ref sty => vec![ArgKind::Arg("_".to_owned(), format!("{}", sty))],
+                };
+                if found.len()== expected.len() {
                     self.report_closure_arg_mismatch(span,
                                                      found_span,
                                                      found_trait_ref,
                                                      expected_trait_ref)
                 } else {
-                    let expected_tuple = if expected_ty_count == 1 {
-                        expected_tys.first().and_then(|t| {
-                            if let &&ty::TyTuple(ref tuptys, _) = t {
-                                Some(tuptys.len())
-                            } else {
-                                None
-                            }
-                        })
-                    } else {
-                        None
-                    };
-
-                    // FIXME(#44150): Expand this to "N args expected but a N-tuple found."
-                    // Type of the 1st expected argument is somehow provided as type of a
-                    // found one in that case.
-                    //
-                    // ```
-                    // [1i32, 2, 3].sort_by(|(a, b)| ..)
-                    // //           ^^^^^^^ --------
-                    // // expected_trait_ref:  std::ops::FnMut<(&i32, &i32)>
-                    // //    found_trait_ref:  std::ops::FnMut<(&i32,)>
-                    // ```
-
-                    let (closure_span, closure_args) = found_did
+                    let (closure_span, found) = found_did
                         .and_then(|did| self.tcx.hir.get_if_local(did))
-                        .and_then(|node| {
-                            if let hir::map::NodeExpr(
-                                &hir::Expr {
-                                    node: hir::ExprClosure(_, ref decl, id, span, _),
-                                    ..
-                                }) = node
-                            {
-                                let ty_snips = decl.inputs.iter()
-                                    .map(|ty| {
-                                        self.tcx.sess.codemap().span_to_snippet(ty.span).ok()
-                                            .and_then(|snip| {
-                                                // filter out dummy spans
-                                                if snip == "," || snip == "|" {
-                                                    None
-                                                } else {
-                                                    Some(snip)
-                                                }
-                                            })
-                                    })
-                                    .collect::<Vec<Option<String>>>();
+                        .map(|node| self.get_fn_like_arguments(node))
+                        .unwrap_or((found_span.unwrap(), found));
 
-                                let body = self.tcx.hir.body(id);
-                                let pat_snips = body.arguments.iter()
-                                    .map(|arg|
-                                        self.tcx.sess.codemap().span_to_snippet(arg.pat.span).ok())
-                                    .collect::<Option<Vec<String>>>();
-
-                                Some((span, pat_snips, ty_snips))
-                            } else {
-                                None
-                            }
-                        })
-                        .map(|(span, pat, ty)| (Some(span), Some((pat, ty))))
-                        .unwrap_or((None, None));
-                    let closure_args = closure_args.and_then(|(pat, ty)| Some((pat?, ty)));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span.or(found_span),
-                        expected_ty_count,
-                        expected_tuple,
-                        found_ty_count,
-                        closure_args,
-                        found_trait_ty.is_closure()
-                    )
+                    self.report_arg_count_mismatch(span,
+                                                   closure_span,
+                                                   expected,
+                                                   found,
+                                                   found_trait_ty.is_closure())
                 }
             }
 
@@ -845,94 +793,135 @@
         }
     }
 
+    fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>) {
+        if let hir::map::NodeExpr(&hir::Expr {
+            node: hir::ExprClosure(_, ref _decl, id, span, _),
+            ..
+        }) = node {
+            (self.tcx.sess.codemap().def_span(span), self.tcx.hir.body(id).arguments.iter()
+                .map(|arg| {
+                    if let hir::Pat {
+                        node: hir::PatKind::Tuple(args, _),
+                        span,
+                        ..
+                    } = arg.pat.clone().into_inner() {
+                        ArgKind::Tuple(
+                            span,
+                            args.iter().map(|pat| {
+                                let snippet = self.tcx.sess.codemap()
+                                    .span_to_snippet(pat.span).unwrap();
+                                (snippet, "_".to_owned())
+                            }).collect::<Vec<_>>(),
+                        )
+                    } else {
+                        let name = self.tcx.sess.codemap().span_to_snippet(arg.pat.span).unwrap();
+                        ArgKind::Arg(name, "_".to_owned())
+                    }
+                })
+                .collect::<Vec<ArgKind>>())
+        } else if let hir::map::NodeItem(&hir::Item {
+            span,
+            node: hir::ItemFn(ref decl, ..),
+            ..
+        }) = node {
+            (self.tcx.sess.codemap().def_span(span), decl.inputs.iter()
+                    .map(|arg| match arg.clone().into_inner().node {
+                hir::TyTup(ref tys) => ArgKind::Tuple(
+                    arg.span,
+                    tys.iter()
+                        .map(|_| ("_".to_owned(), "_".to_owned()))
+                        .collect::<Vec<_>>(),
+                ),
+                _ => ArgKind::Arg("_".to_owned(), "_".to_owned())
+            }).collect::<Vec<ArgKind>>())
+        } else {
+            panic!("non-FnLike node found: {:?}", node);
+        }
+    }
+
     fn report_arg_count_mismatch(
         &self,
         span: Span,
-        found_span: Option<Span>,
-        expected: usize,
-        expected_tuple: Option<usize>,
-        found: usize,
-        closure_args: Option<(Vec<String>, Vec<Option<String>>)>,
-        is_closure: bool
+        found_span: Span,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
     ) -> DiagnosticBuilder<'tcx> {
-        use std::borrow::Cow;
-
         let kind = if is_closure { "closure" } else { "function" };
 
-        let args_str = |n, distinct| format!(
-                "{} {}argument{}",
-                n,
-                if distinct && n >= 2 { "distinct " } else { "" },
-                if n == 1 { "" } else { "s" },
-            );
-
-        let expected_str = if let Some(n) = expected_tuple {
-            assert!(expected == 1);
-            if closure_args.as_ref().map(|&(ref pats, _)| pats.len()) == Some(n) {
-                Cow::from("a single tuple as argument")
-            } else {
-                // be verbose when numbers differ
-                Cow::from(format!("a single {}-tuple as argument", n))
+        let args_str = |arguments: &Vec<ArgKind>, other: &Vec<ArgKind>| {
+            let arg_length = arguments.len();
+            let distinct = match &other[..] {
+                &[ArgKind::Tuple(..)] => true,
+                _ => false,
+            };
+            match (arg_length, arguments.get(0)) {
+                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!("{} {}argument{}",
+                             arg_length,
+                             if distinct && arg_length > 1 { "distinct " } else { "" },
+                             if arg_length == 1 { "" } else { "s" }),
             }
-        } else {
-            Cow::from(args_str(expected, false))
         };
 
-        let found_str = if expected_tuple.is_some() {
-            args_str(found, true)
-        } else {
-            args_str(found, false)
-        };
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
 
-
-        let mut err = struct_span_err!(self.tcx.sess, span, E0593,
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
             "{} is expected to take {}, but it takes {}",
             kind,
             expected_str,
             found_str,
         );
 
-        err.span_label(
-            span,
-            format!(
-                "expected {} that takes {}",
-                kind,
-                expected_str,
-            )
-        );
+        err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
+        err.span_label(found_span, format!("takes {}", found_str));
 
-        if let Some(span) = found_span {
-            if let (Some(expected_tuple), Some((pats, tys))) = (expected_tuple, closure_args) {
-                if expected_tuple != found || pats.len() != found {
-                    err.span_label(span, format!("takes {}", found_str));
-                } else {
-                    let sugg = format!(
-                        "|({}){}|",
-                        pats.join(", "),
-
-                        // add type annotations if available
-                        if tys.iter().any(|ty| ty.is_some()) {
-                            Cow::from(format!(
-                                ": ({})",
-                                tys.into_iter().map(|ty| if let Some(ty) = ty {
-                                    ty
-                                } else {
-                                    "_".to_string()
-                                }).collect::<Vec<String>>().join(", ")
-                            ))
-                        } else {
-                            Cow::from("")
-                        },
-                    );
-
-                    err.span_suggestion(
-                        span,
-                        "consider changing the closure to accept a tuple",
-                        sugg
-                    );
-                }
-            } else {
-                err.span_label(span, format!("takes {}", found_str));
+        if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+            if fields.len() == expected_args.len() {
+                let sugg = fields.iter()
+                    .map(|(name, _)| name.to_owned())
+                    .collect::<Vec<String>>().join(", ");
+                err.span_suggestion(found_span,
+                                    "change the closure to take multiple arguments instead of \
+                                     a single tuple",
+                                    format!("|{}|", sugg));
+            }
+        }
+        if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
+            if fields.len() == found_args.len() && is_closure {
+                let sugg = format!(
+                    "|({}){}|",
+                    found_args.iter()
+                        .map(|arg| match arg {
+                            ArgKind::Arg(name, _) => name.to_owned(),
+                            _ => "_".to_owned(),
+                        })
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    // add type annotations if available
+                    if found_args.iter().any(|arg| match arg {
+                        ArgKind::Arg(_, ty) => ty != "_",
+                        _ => false,
+                    }) {
+                        format!(": ({})",
+                                fields.iter()
+                                    .map(|(_, ty)| ty.to_owned())
+                                    .collect::<Vec<String>>()
+                                    .join(", "))
+                    } else {
+                        "".to_owned()
+                    },
+                );
+                err.span_suggestion(found_span,
+                                    "change the closure to accept a tuple instead of individual \
+                                     arguments",
+                                    sugg);
             }
         }
 
@@ -1241,7 +1230,13 @@
             }
             ObligationCauseCode::ItemObligation(item_def_id) => {
                 let item_name = tcx.item_path_str(item_def_id);
-                err.note(&format!("required by `{}`", item_name));
+                let msg = format!("required by `{}`", item_name);
+                if let Some(sp) = tcx.hir.span_if_local(item_def_id) {
+                    let sp = tcx.sess.codemap().def_span(sp);
+                    err.span_note(sp, &msg);
+                } else {
+                    err.note(&msg);
+                }
             }
             ObligationCauseCode::ObjectCastObligation(object_ty) => {
                 err.note(&format!("required for the cast to the object type `{}`",
@@ -1325,3 +1320,14 @@
                           suggested_limit));
     }
 }
+
+enum ArgKind {
+    Arg(String, String),
+    Tuple(Span, Vec<(String, String)>),
+}
+
+impl ArgKind {
+    fn empty() -> ArgKind {
+        ArgKind::Arg("_".to_owned(), "_".to_owned())
+    }
+}
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 94605d8..fd47e09 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -658,9 +658,9 @@
 /// environment. If this returns false, then either normalize
 /// encountered an error or one of the predicates did not hold. Used
 /// when creating vtables to check for unsatisfiable methods.
-pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                               predicates: Vec<ty::Predicate<'tcx>>)
-                                               -> bool
+fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                           predicates: Vec<ty::Predicate<'tcx>>)
+                                           -> bool
 {
     debug!("normalize_and_test_predicates(predicates={:?})",
            predicates);
@@ -687,6 +687,22 @@
     result
 }
 
+fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                      key: (DefId, &'tcx Substs<'tcx>))
+                                                      -> bool
+{
+    use ty::subst::Subst;
+    debug!("substitute_normalize_and_test_predicates(key={:?})",
+           key);
+
+    let predicates = tcx.predicates_of(key.0).predicates.subst(tcx, key.1);
+    let result = normalize_and_test_predicates(tcx, predicates);
+
+    debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}",
+           key, result);
+    result
+}
+
 /// Given a trait `trait_ref`, iterates the vtable entries
 /// that come from `trait_ref`, including its supertraits.
 #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
@@ -879,6 +895,7 @@
         specializes: specialize::specializes,
         trans_fulfill_obligation: trans::trans_fulfill_obligation,
         vtable_methods,
+        substitute_normalize_and_test_predicates,
         ..*providers
     };
 }
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 16e200d..757b078 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -140,9 +140,7 @@
     {
         let attrs = tcx.get_attrs(impl_def_id);
 
-        let attr = if let Some(item) =
-            attrs.into_iter().find(|a| a.check_name("rustc_on_unimplemented"))
-        {
+        let attr = if let Some(item) = attr::find_by_name(&attrs, "rustc_on_unimplemented") {
             item
         } else {
             return Ok(None);
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index e70de0e..55cbc89 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -906,6 +906,7 @@
     /// For defaulted traits, we use a co-inductive strategy to solve, so
     /// that recursion is ok. This routine returns true if the top of the
     /// stack (`cycle[0]`):
+    ///
     /// - is a defaulted trait, and
     /// - it also appears in the backtrace at some position `X`; and,
     /// - all the predicates at positions `X..` between `X` an the top are
@@ -2043,8 +2044,8 @@
             ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
             ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
             ty::TyChar | ty::TyRef(..) | ty::TyGenerator(..) |
-            ty::TyArray(..) | ty::TyClosure(..) | ty::TyNever |
-            ty::TyError => {
+            ty::TyGeneratorWitness(..) | ty::TyArray(..) | ty::TyClosure(..) |
+            ty::TyNever | ty::TyError => {
                 // safe for everything
                 Where(ty::Binder(Vec::new()))
             }
@@ -2094,7 +2095,7 @@
             }
 
             ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
-            ty::TyGenerator(..) | ty::TyForeign(..) |
+            ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | ty::TyForeign(..) |
             ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 Never
             }
@@ -2205,8 +2206,14 @@
             }
 
             ty::TyGenerator(def_id, ref substs, interior) => {
-                let witness = iter::once(interior.witness);
-                substs.upvar_tys(def_id, self.tcx()).chain(witness).collect()
+                substs.upvar_tys(def_id, self.tcx()).chain(iter::once(interior.witness)).collect()
+            }
+
+            ty::TyGeneratorWitness(types) => {
+                // This is sound because no regions in the witness can refer to
+                // the binder outside the witness. So we'll effectivly reuse
+                // the implicit binder around the witness.
+                types.skip_binder().to_vec()
             }
 
             // for `PhantomData<T>`, we pass `T`
@@ -2433,7 +2440,7 @@
         VtableBuiltinData { nested: obligations }
     }
 
-    /// This handles the case where a `impl Foo for ..` impl is being used.
+    /// This handles the case where a `auto trait Foo` impl is being used.
     /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
     ///
     /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
@@ -3275,7 +3282,7 @@
         /*!
          * Creates a cause for obligations that are derived from
          * `obligation` by a recursive search (e.g., for a builtin
-         * bound, or eventually a `impl Foo for ..`). If `obligation`
+         * bound, or eventually a `auto trait Foo`). If `obligation`
          * is itself a derived obligation, this is just a clone, but
          * otherwise we create a "derived obligation" cause so as to
          * keep track of the original root obligation for error
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index 349d77c..6df6bb9 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -22,38 +22,38 @@
 /// Here are some common scenarios:
 ///
 /// 1. The simplest cases are where a pointer is not adjusted fat vs thin.
-/// Here the pointer will be dereferenced N times (where a dereference can
-/// happen to raw or borrowed pointers or any smart pointer which implements
-/// Deref, including Box<_>). The types of dereferences is given by
-/// `autoderefs`.  It can then be auto-referenced zero or one times, indicated
-/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
-/// `false`.
+///    Here the pointer will be dereferenced N times (where a dereference can
+///    happen to raw or borrowed pointers or any smart pointer which implements
+///    Deref, including Box<_>). The types of dereferences is given by
+///    `autoderefs`.  It can then be auto-referenced zero or one times, indicated
+///    by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
+///    `false`.
 ///
 /// 2. A thin-to-fat coercion involves unsizing the underlying data. We start
-/// with a thin pointer, deref a number of times, unsize the underlying data,
-/// then autoref. The 'unsize' phase may change a fixed length array to a
-/// dynamically sized one, a concrete object to a trait object, or statically
-/// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
-/// represented by:
+///    with a thin pointer, deref a number of times, unsize the underlying data,
+///    then autoref. The 'unsize' phase may change a fixed length array to a
+///    dynamically sized one, a concrete object to a trait object, or statically
+///    sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
+///    represented by:
 ///
-/// ```
-/// Deref(None) -> [i32; 4],
-/// Borrow(AutoBorrow::Ref) -> &[i32; 4],
-/// Unsize -> &[i32],
-/// ```
+///    ```
+///    Deref(None) -> [i32; 4],
+///    Borrow(AutoBorrow::Ref) -> &[i32; 4],
+///    Unsize -> &[i32],
+///    ```
 ///
-/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
-/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
-/// The autoderef and -ref are the same as in the above example, but the type
-/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
-/// the underlying conversions from `[i32; 4]` to `[i32]`.
+///    Note that for a struct, the 'deep' unsizing of the struct is not recorded.
+///    E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
+///    The autoderef and -ref are the same as in the above example, but the type
+///    stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
+///    the underlying conversions from `[i32; 4]` to `[i32]`.
 ///
 /// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case.  In
-/// that case, we have the pointer we need coming in, so there are no
-/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
-/// At some point, of course, `Box` should move out of the compiler, in which
-/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
-/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
+///    that case, we have the pointer we need coming in, so there are no
+///    autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
+///    At some point, of course, `Box` should move out of the compiler, in which
+///    case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
+///    Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct Adjustment<'tcx> {
     pub kind: Adjust<'tcx>,
diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs
index 0badb85..c118b7a 100644
--- a/src/librustc/ty/cast.rs
+++ b/src/librustc/ty/cast.rs
@@ -20,6 +20,7 @@
 pub enum IntTy {
     U(ast::UintTy),
     I,
+    Ivar,
     CEnum,
     Bool,
     Char
@@ -63,6 +64,8 @@
             ty::TyBool => Some(CastTy::Int(IntTy::Bool)),
             ty::TyChar => Some(CastTy::Int(IntTy::Char)),
             ty::TyInt(_) => Some(CastTy::Int(IntTy::I)),
+            ty::TyInfer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::Ivar)),
+            ty::TyInfer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float),
             ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))),
             ty::TyFloat(_) => Some(CastTy::Float),
             ty::TyAdt(d,_) if d.is_enum() && d.is_payloadfree() =>
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index b233156..e4e0745 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -754,13 +754,13 @@
             char: mk(TyChar),
             never: mk(TyNever),
             err: mk(TyError),
-            isize: mk(TyInt(ast::IntTy::Is)),
+            isize: mk(TyInt(ast::IntTy::Isize)),
             i8: mk(TyInt(ast::IntTy::I8)),
             i16: mk(TyInt(ast::IntTy::I16)),
             i32: mk(TyInt(ast::IntTy::I32)),
             i64: mk(TyInt(ast::IntTy::I64)),
             i128: mk(TyInt(ast::IntTy::I128)),
-            usize: mk(TyUint(ast::UintTy::Us)),
+            usize: mk(TyUint(ast::UintTy::Usize)),
             u8: mk(TyUint(ast::UintTy::U8)),
             u16: mk(TyUint(ast::UintTy::U16)),
             u32: mk(TyUint(ast::UintTy::U32)),
@@ -778,8 +778,10 @@
 
 /// The central data structure of the compiler. It stores references
 /// to the various **arenas** and also houses the results of the
-/// various **compiler queries** that have been performed. See [the
-/// README](README.md) for more deatils.
+/// various **compiler queries** that have been performed. See the
+/// module-level [README] for more details.
+///
+/// [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/ty/README.md
 #[derive(Copy, Clone)]
 pub struct TyCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     gcx: &'a GlobalCtxt<'gcx>,
@@ -893,31 +895,29 @@
     allocs: FxHashSet<&'tcx interpret::Allocation>,
 
     /// Allows obtaining function instance handles via a unique identifier
-    functions: FxHashMap<u64, Instance<'tcx>>,
+    functions: FxHashMap<interpret::AllocId, Instance<'tcx>>,
 
     /// Inverse map of `interpret_functions`.
     /// Used so we don't allocate a new pointer every time we need one
-    function_cache: FxHashMap<Instance<'tcx>, u64>,
+    function_cache: FxHashMap<Instance<'tcx>, interpret::AllocId>,
 
     /// Allows obtaining const allocs via a unique identifier
-    alloc_by_id: FxHashMap<u64, &'tcx interpret::Allocation>,
+    alloc_by_id: FxHashMap<interpret::AllocId, &'tcx interpret::Allocation>,
 
     /// The AllocId to assign to the next new regular allocation.
     /// Always incremented, never gets smaller.
-    next_id: u64,
+    next_id: interpret::AllocId,
 
     /// Allows checking whether a constant already has an allocation
-    ///
-    /// The pointers are to the beginning of an `alloc_by_id` allocation
-    alloc_cache: FxHashMap<interpret::GlobalId<'tcx>, interpret::Pointer>,
+    alloc_cache: FxHashMap<interpret::GlobalId<'tcx>, interpret::AllocId>,
 
     /// A cache for basic byte allocations keyed by their contents. This is used to deduplicate
     /// allocations for string and bytestring literals.
-    literal_alloc_cache: FxHashMap<Vec<u8>, u64>,
+    literal_alloc_cache: FxHashMap<Vec<u8>, interpret::AllocId>,
 }
 
 impl<'tcx> InterpretInterner<'tcx> {
-    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> u64 {
+    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> interpret::AllocId {
         if let Some(&alloc_id) = self.function_cache.get(&instance) {
             return alloc_id;
         }
@@ -930,14 +930,14 @@
 
     pub fn get_fn(
         &self,
-        id: u64,
+        id: interpret::AllocId,
     ) -> Option<Instance<'tcx>> {
         self.functions.get(&id).cloned()
     }
 
     pub fn get_alloc(
         &self,
-        id: u64,
+        id: interpret::AllocId,
     ) -> Option<&'tcx interpret::Allocation> {
         self.alloc_by_id.get(&id).cloned()
     }
@@ -945,14 +945,14 @@
     pub fn get_cached(
         &self,
         global_id: interpret::GlobalId<'tcx>,
-    ) -> Option<interpret::Pointer> {
+    ) -> Option<interpret::AllocId> {
         self.alloc_cache.get(&global_id).cloned()
     }
 
     pub fn cache(
         &mut self,
         global_id: interpret::GlobalId<'tcx>,
-        ptr: interpret::Pointer,
+        ptr: interpret::AllocId,
     ) {
         if let Some(old) = self.alloc_cache.insert(global_id, ptr) {
             bug!("tried to cache {:?}, but was already existing as {:#?}", global_id, old);
@@ -961,7 +961,7 @@
 
     pub fn intern_at_reserved(
         &mut self,
-        id: u64,
+        id: interpret::AllocId,
         alloc: &'tcx interpret::Allocation,
     ) {
         if let Some(old) = self.alloc_by_id.insert(id, alloc) {
@@ -973,9 +973,9 @@
     /// yet have an allocation backing it.
     pub fn reserve(
         &mut self,
-    ) -> u64 {
+    ) -> interpret::AllocId {
         let next = self.next_id;
-        self.next_id = self.next_id
+        self.next_id.0 = self.next_id.0
             .checked_add(1)
             .expect("You overflowed a u64 by incrementing by 1... \
                      You've just earned yourself a free drink if we ever meet. \
@@ -1067,7 +1067,7 @@
     }
 
     /// Allocates a byte or string literal for `mir::interpret`
-    pub fn allocate_cached(self, bytes: &[u8]) -> u64 {
+    pub fn allocate_cached(self, bytes: &[u8]) -> interpret::AllocId {
         // check whether we already allocated this literal or a constant with the same memory
         if let Some(&alloc_id) = self.interpret_interner.borrow().literal_alloc_cache.get(bytes) {
             return alloc_id;
@@ -1672,8 +1672,9 @@
     pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
-            TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyGenerator, TyForeign,
-            TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
+            TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
+            TyGenerator, TyGeneratorWitness, TyDynamic, TyClosure, TyTuple,
+            TyParam, TyInfer, TyProjection, TyAnon, TyForeign);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("Region interner: #{}", self.interners.region.borrow().len());
@@ -1910,7 +1911,7 @@
 
     pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {
         match tm {
-            ast::IntTy::Is   => self.types.isize,
+            ast::IntTy::Isize   => self.types.isize,
             ast::IntTy::I8   => self.types.i8,
             ast::IntTy::I16  => self.types.i16,
             ast::IntTy::I32  => self.types.i32,
@@ -1921,7 +1922,7 @@
 
     pub fn mk_mach_uint(self, tm: ast::UintTy) -> Ty<'tcx> {
         match tm {
-            ast::UintTy::Us   => self.types.usize,
+            ast::UintTy::Usize   => self.types.usize,
             ast::UintTy::U8   => self.types.u8,
             ast::UintTy::U16  => self.types.u16,
             ast::UintTy::U32  => self.types.u32,
@@ -2079,6 +2080,10 @@
         self.mk_ty(TyGenerator(id, closure_substs, interior))
     }
 
+    pub fn mk_generator_witness(self, types: ty::Binder<&'tcx Slice<Ty<'tcx>>>) -> Ty<'tcx> {
+        self.mk_ty(TyGeneratorWitness(types))
+    }
+
     pub fn mk_var(self, v: TyVid) -> Ty<'tcx> {
         self.mk_infer(TyVar(v))
     }
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index cb68e57..583612f 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -227,6 +227,7 @@
             }
             ty::TyClosure(..) => "closure".to_string(),
             ty::TyGenerator(..) => "generator".to_string(),
+            ty::TyGeneratorWitness(..) => "generator witness".to_string(),
             ty::TyTuple(..) => "tuple".to_string(),
             ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
             ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(),
@@ -260,10 +261,8 @@
                 let expected_str = values.expected.sort_string(self);
                 let found_str = values.found.sort_string(self);
                 if expected_str == found_str && expected_str == "closure" {
-                    db.span_note(sp,
-                        "no two closures, even if identical, have the same type");
-                    db.span_help(sp,
-                        "consider boxing your closure and/or using it as a trait object");
+                    db.note("no two closures, even if identical, have the same type");
+                    db.help("consider boxing your closure and/or using it as a trait object");
                 }
             },
             TyParamDefaultMismatch(values) => {
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 138f6af..97c259e6 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -46,6 +46,7 @@
     TraitSimplifiedType(D),
     ClosureSimplifiedType(D),
     GeneratorSimplifiedType(D),
+    GeneratorWitnessSimplifiedType(usize),
     AnonSimplifiedType(D),
     FunctionSimplifiedType(usize),
     ParameterSimplifiedType,
@@ -92,6 +93,9 @@
         ty::TyGenerator(def_id, _, _) => {
             Some(GeneratorSimplifiedType(def_id))
         }
+        ty::TyGeneratorWitness(ref tys) => {
+            Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len()))
+        }
         ty::TyNever => Some(NeverSimplifiedType),
         ty::TyTuple(ref tys, _) => {
             Some(TupleSimplifiedType(tys.len()))
@@ -141,6 +145,7 @@
             TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
             ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
             GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
+            GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
             AnonSimplifiedType(d) => AnonSimplifiedType(map(d)),
             FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
             ParameterSimplifiedType => ParameterSimplifiedType,
@@ -175,6 +180,7 @@
             TraitSimplifiedType(d) => d.hash_stable(hcx, hasher),
             ClosureSimplifiedType(d) => d.hash_stable(hcx, hasher),
             GeneratorSimplifiedType(d) => d.hash_stable(hcx, hasher),
+            GeneratorWitnessSimplifiedType(n) => n.hash_stable(hcx, hasher),
             AnonSimplifiedType(d) => d.hash_stable(hcx, hasher),
             FunctionSimplifiedType(n) => n.hash_stable(hcx, hasher),
             ForeignSimplifiedType(d) => d.hash_stable(hcx, hasher),
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 63c646d..2889322 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -94,6 +94,12 @@
                 self.add_ty(interior.witness);
             }
 
+            &ty::TyGeneratorWitness(ref ts) => {
+                let mut computation = FlagComputation::new();
+                computation.add_tys(&ts.skip_binder()[..]);
+                self.add_bound_computation(&computation);
+            }
+
             &ty::TyClosure(_, ref substs) => {
                 self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                 self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 5b87273..63bf52a 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -28,7 +28,7 @@
     Item(DefId),
     Intrinsic(DefId),
 
-    /// <fn() as FnTrait>::call_*
+    /// \<fn() as FnTrait>::call_*
     /// def-id is FnTrait::call_*
     FnPtrShim(DefId, Ty<'tcx>),
 
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 0fecb53..fefd11e 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -232,11 +232,11 @@
 
         // Always use types for non-local impls, where types are always
         // available, and filename/line-number is mostly uninteresting.
-        let use_types = !self.is_auto_impl(impl_def_id) && (!impl_def_id.is_local() || {
+        let use_types = !impl_def_id.is_local() || {
             // Otherwise, use filename/line-number if forced.
             let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
             !force_no_types
-        });
+        };
 
         if !use_types {
             return self.push_impl_path_fallback(buffer, impl_def_id);
@@ -375,6 +375,7 @@
         ty::TyAnon(..) |
         ty::TyInfer(_) |
         ty::TyError |
+        ty::TyGeneratorWitness(..) |
         ty::TyNever |
         ty::TyFloat(_) => None,
     }
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 978c6c7..69d07ea 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -340,8 +340,8 @@
 
 /// Alignment of a type in bytes, both ABI-mandated and preferred.
 /// Each field is a power of two, giving the alignment a maximum
-/// value of 2^(2^8 - 1), which is limited by LLVM to a i32, with
-/// a maximum capacity of 2^31 - 1 or 2147483647.
+/// value of 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a i32, with
+/// a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct Align {
     abi: u8,
@@ -520,7 +520,7 @@
             attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
             attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
             attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
-            attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => {
+            attr::SignedInt(IntTy::Isize) | attr::UnsignedInt(UintTy::Usize) => {
                 dl.ptr_sized_integer()
             }
         }
@@ -651,11 +651,13 @@
 }
 
 /// The first half of a fat pointer.
+///
 /// - For a trait object, this is the address of the box.
 /// - For a slice, this is the base address.
 pub const FAT_PTR_ADDR: usize = 0;
 
 /// The second half of a fat pointer.
+///
 /// - For a trait object, this is the address of the vtable.
 /// - For a slice, this is the length.
 pub const FAT_PTR_EXTRA: usize = 1;
@@ -1352,17 +1354,6 @@
                     }).collect::<Result<Vec<_>, _>>()
                 }).collect::<Result<Vec<_>, _>>()?;
 
-                let (inh_first, inh_second) = {
-                    let mut inh_variants = (0..variants.len()).filter(|&v| {
-                        variants[v].iter().all(|f| f.abi != Abi::Uninhabited)
-                    });
-                    (inh_variants.next(), inh_variants.next())
-                };
-                if inh_first.is_none() {
-                    // Uninhabited because it has no variants, or only uninhabited ones.
-                    return Ok(tcx.intern_layout(LayoutDetails::uninhabited(0)));
-                }
-
                 if def.is_union() {
                     let packed = def.repr.packed();
                     if packed && def.repr.align > 0 {
@@ -1400,6 +1391,17 @@
                     }));
                 }
 
+                let (inh_first, inh_second) = {
+                    let mut inh_variants = (0..variants.len()).filter(|&v| {
+                        variants[v].iter().all(|f| f.abi != Abi::Uninhabited)
+                    });
+                    (inh_variants.next(), inh_variants.next())
+                };
+                if inh_first.is_none() {
+                    // Uninhabited because it has no variants, or only uninhabited ones.
+                    return Ok(tcx.intern_layout(LayoutDetails::uninhabited(0)));
+                }
+
                 let is_struct = !def.is_enum() ||
                     // Only one variant is inhabited.
                     (inh_second.is_none() &&
@@ -1655,10 +1657,10 @@
                         discr,
                         variants
                     },
-                    // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results
-                    // in lost optimizations, specifically around allocations, see
-                    // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`.
-                    fields: FieldPlacement::Union(1),
+                    fields: FieldPlacement::Arbitrary {
+                        offsets: vec![Size::from_bytes(0)],
+                        memory_index: vec![0]
+                    },
                     abi,
                     align,
                     size
@@ -1676,7 +1678,7 @@
             ty::TyParam(_) => {
                 return Err(LayoutError::Unknown(ty));
             }
-            ty::TyInfer(_) | ty::TyError => {
+            ty::TyGeneratorWitness(..) | ty::TyInfer(_) | ty::TyError => {
                 bug!("LayoutDetails::compute: unexpected type `{}`", ty)
             }
         })
@@ -2149,8 +2151,9 @@
             ty::TyFnPtr(_) |
             ty::TyNever |
             ty::TyFnDef(..) |
-            ty::TyDynamic(..) |
-            ty::TyForeign(..) => {
+            ty::TyGeneratorWitness(..) |
+            ty::TyForeign(..) |
+            ty::TyDynamic(..) => {
                 bug!("TyLayout::field_type({:?}): not applicable", self)
             }
 
@@ -2293,6 +2296,13 @@
             }, niche_start))
         };
 
+        // Locals variables which live across yields are stored
+        // in the generator type as fields. These may be uninitialized
+        // so we don't look for niches there.
+        if let ty::TyGenerator(..) = self.ty.sty {
+            return Ok(None);
+        }
+
         match self.abi {
             Abi::Scalar(ref scalar) => {
                 return Ok(scalar_component(scalar, Size::from_bytes(0)));
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index a556861..8dedcb2 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -102,7 +102,7 @@
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::coherent_trait<'tcx> {
-    fn describe(tcx: TyCtxt, (_, def_id): (CrateNum, DefId)) -> String {
+    fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("coherence checking all impls of trait `{}`",
                 tcx.item_path_str(def_id))
     }
@@ -625,6 +625,18 @@
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
+    fn describe(tcx: TyCtxt, key: (DefId, &'tcx Substs<'tcx>)) -> String {
+        format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0))
+    }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the whitelist of target features")
+    }
+}
+
 macro_rules! impl_disk_cacheable_query(
     ($query_name:ident, |$key:tt| $cond:expr) => {
         impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
@@ -647,5 +659,6 @@
 impl_disk_cacheable_query!(borrowck, |def_id| def_id.is_local());
 impl_disk_cacheable_query!(mir_borrowck, |def_id| def_id.is_local());
 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!(contains_extern_indicator, |_| true);
 impl_disk_cacheable_query!(def_symbol_name, |_| true);
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 23531b7..e7e92b8 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -112,9 +112,6 @@
     /// True if this is a foreign item (i.e., linked via `extern { ... }`).
     [] fn is_foreign_item: IsForeignItem(DefId) -> bool,
 
-    /// True if this is an auto impl (aka impl Foo for ..)
-    [] fn is_auto_impl: IsAutoImpl(DefId) -> bool,
-
     /// Get a map with the variance of every item; use `item_variance`
     /// instead.
     [] fn crate_variances: crate_variances(CrateNum) -> Rc<ty::CrateVariancesMap>,
@@ -187,7 +184,7 @@
 
     [] fn has_typeck_tables: HasTypeckTables(DefId) -> bool,
 
-    [] fn coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
+    [] fn coherent_trait: CoherenceCheckTrait(DefId) -> (),
 
     [] fn borrowck: BorrowCheck(DefId) -> Rc<BorrowCheckResult>,
 
@@ -360,6 +357,14 @@
     // however, which uses this query as a kind of cache.
     [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>,
     [] fn fully_normalize_monormophic_ty: normalize_ty_node(Ty<'tcx>) -> Ty<'tcx>,
+
+    [] fn substitute_normalize_and_test_predicates:
+        substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
+
+    [] fn target_features_whitelist:
+        target_features_whitelist_node(CrateNum) -> Rc<FxHashSet<String>>,
+    [] fn target_features_enabled: TargetFeaturesEnabled(DefId) -> Rc<Vec<String>>,
+
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -385,10 +390,6 @@
     }
 }
 
-fn coherent_trait_dep_node<'tcx>((_, def_id): (CrateNum, DefId)) -> DepConstructor<'tcx> {
-    DepConstructor::CoherenceCheckTrait(def_id)
-}
-
 fn crate_inherent_impls_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::Coherence
 }
@@ -504,3 +505,12 @@
 fn normalize_ty_node<'tcx>(_: Ty<'tcx>) -> DepConstructor<'tcx> {
     DepConstructor::NormalizeTy
 }
+
+fn substitute_normalize_and_test_predicates_node<'tcx>(key: (DefId, &'tcx Substs<'tcx>))
+                                            -> DepConstructor<'tcx> {
+    DepConstructor::SubstituteNormalizeAndTestPredicates { key }
+}
+
+fn target_features_whitelist_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::TargetFeaturesWhitelist
+}
diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs
index 079b518..4e2421d 100644
--- a/src/librustc/ty/maps/on_disk_cache.rs
+++ b/src/librustc/ty/maps/on_disk_cache.rs
@@ -14,7 +14,7 @@
 use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId,
                   RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE};
 use hir::map::definitions::DefPathHash;
-use ich::CachingCodemapView;
+use ich::{CachingCodemapView, Fingerprint};
 use mir;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -165,112 +165,113 @@
         where E: ty_codec::TyEncoder
      {
         // Serializing the DepGraph should not modify it:
-        let _in_ignore = tcx.dep_graph.in_ignore();
+        tcx.dep_graph.with_ignore(|| {
+            // Allocate FileMapIndices
+            let (file_to_file_index, file_index_to_stable_id) = {
+                let mut file_to_file_index = FxHashMap();
+                let mut file_index_to_stable_id = FxHashMap();
 
-        // Allocate FileMapIndices
-        let (file_to_file_index, file_index_to_stable_id) = {
-            let mut file_to_file_index = FxHashMap();
-            let mut file_index_to_stable_id = FxHashMap();
+                for (index, file) in tcx.sess.codemap().files().iter().enumerate() {
+                    let index = FileMapIndex(index as u32);
+                    let file_ptr: *const FileMap = &**file as *const _;
+                    file_to_file_index.insert(file_ptr, index);
+                    file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
+                }
 
-            for (index, file) in tcx.sess.codemap().files().iter().enumerate() {
-                let index = FileMapIndex(index as u32);
-                let file_ptr: *const FileMap = &**file as *const _;
-                file_to_file_index.insert(file_ptr, index);
-                file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
+                (file_to_file_index, file_index_to_stable_id)
+            };
+
+            let mut encoder = CacheEncoder {
+                tcx,
+                encoder,
+                type_shorthands: FxHashMap(),
+                predicate_shorthands: FxHashMap(),
+                expn_info_shorthands: FxHashMap(),
+                codemap: CachingCodemapView::new(tcx.sess.codemap()),
+                file_to_file_index,
+            };
+
+            // Load everything into memory so we can write it out to the on-disk
+            // cache. The vast majority of cacheable query results should already
+            // be in memory, so this should be a cheap operation.
+            tcx.dep_graph.exec_cache_promotions(tcx);
+
+            // Encode query results
+            let mut query_result_index = EncodedQueryResultIndex::new();
+
+            {
+                use ty::maps::queries::*;
+                let enc = &mut encoder;
+                let qri = &mut query_result_index;
+
+                // Encode TypeckTables
+                encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
+                encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
+                encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
+                encode_query_results::<borrowck, _>(tcx, enc, qri)?;
+                encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
+                encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
+                encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
+                encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
+                encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
+                encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
+                encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
+                encode_query_results::<check_match, _>(tcx, enc, qri)?;
             }
 
-            (file_to_file_index, file_index_to_stable_id)
-        };
+            // Encode diagnostics
+            let diagnostics_index = {
+                let mut diagnostics_index = EncodedDiagnosticsIndex::new();
 
-        let mut encoder = CacheEncoder {
-            tcx,
-            encoder,
-            type_shorthands: FxHashMap(),
-            predicate_shorthands: FxHashMap(),
-            expn_info_shorthands: FxHashMap(),
-            codemap: CachingCodemapView::new(tcx.sess.codemap()),
-            file_to_file_index,
-        };
+                for (dep_node_index, diagnostics) in self.current_diagnostics
+                                                        .borrow()
+                                                        .iter() {
+                    let pos = AbsoluteBytePos::new(encoder.position());
+                    // Let's make sure we get the expected type here:
+                    let diagnostics: &EncodedDiagnostics = diagnostics;
+                    let dep_node_index =
+                        SerializedDepNodeIndex::new(dep_node_index.index());
+                    encoder.encode_tagged(dep_node_index, diagnostics)?;
+                    diagnostics_index.push((dep_node_index, pos));
+                }
 
-        // Load everything into memory so we can write it out to the on-disk
-        // cache. The vast majority of cacheable query results should already
-        // be in memory, so this should be a cheap operation.
-        tcx.dep_graph.exec_cache_promotions(tcx);
+                diagnostics_index
+            };
 
-        // Encode query results
-        let mut query_result_index = EncodedQueryResultIndex::new();
+            let sorted_cnums = sorted_cnums_including_local_crate(tcx);
+            let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
+                let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
+                let crate_disambiguator = tcx.crate_disambiguator(cnum);
+                (cnum.as_u32(), crate_name, crate_disambiguator)
+            }).collect();
 
-        {
-            use ty::maps::queries::*;
-            let enc = &mut encoder;
-            let qri = &mut query_result_index;
+            // Encode the file footer
+            let footer_pos = encoder.position() as u64;
+            encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
+                file_index_to_stable_id,
+                prev_cnums,
+                query_result_index,
+                diagnostics_index,
+            })?;
 
-            // Encode TypeckTables
-            encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
-            encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
-            encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
-            encode_query_results::<borrowck, _>(tcx, enc, qri)?;
-            encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
-            encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
-            encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
-            encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
-            encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
-            encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
-            encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
-        }
+            // Encode the position of the footer as the last 8 bytes of the
+            // file so we know where to look for it.
+            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
 
-        // Encode diagnostics
-        let diagnostics_index = {
-            let mut diagnostics_index = EncodedDiagnosticsIndex::new();
+            // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
+            // of the footer must be the last thing in the data stream.
 
-            for (dep_node_index, diagnostics) in self.current_diagnostics
-                                                     .borrow()
-                                                     .iter() {
-                let pos = AbsoluteBytePos::new(encoder.position());
-                // Let's make sure we get the expected type here:
-                let diagnostics: &EncodedDiagnostics = diagnostics;
-                let dep_node_index =
-                    SerializedDepNodeIndex::new(dep_node_index.index());
-                encoder.encode_tagged(dep_node_index, diagnostics)?;
-                diagnostics_index.push((dep_node_index, pos));
+            return Ok(());
+
+            fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
+                let mut cnums = vec![LOCAL_CRATE];
+                cnums.extend_from_slice(&tcx.crates()[..]);
+                cnums.sort_unstable();
+                // Just to be sure...
+                cnums.dedup();
+                cnums
             }
-
-            diagnostics_index
-        };
-
-        let sorted_cnums = sorted_cnums_including_local_crate(tcx);
-        let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
-            let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
-            let crate_disambiguator = tcx.crate_disambiguator(cnum);
-            (cnum.as_u32(), crate_name, crate_disambiguator)
-        }).collect();
-
-        // Encode the file footer
-        let footer_pos = encoder.position() as u64;
-        encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
-            file_index_to_stable_id,
-            prev_cnums,
-            query_result_index,
-            diagnostics_index,
-        })?;
-
-        // Encode the position of the footer as the last 8 bytes of the
-        // file so we know where to look for it.
-        IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
-
-        // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
-        // of the footer must be the last thing in the data stream.
-
-        return Ok(());
-
-        fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
-            let mut cnums = vec![LOCAL_CRATE];
-            cnums.extend_from_slice(&tcx.crates()[..]);
-            cnums.sort_unstable();
-            // Just to be sure...
-            cnums.dedup();
-            cnums
-        }
+        })
     }
 
     /// Load a diagnostic emitted during the previous compilation session.
@@ -379,30 +380,30 @@
                         prev_cnums: &[(u32, String, CrateDisambiguator)])
                         -> IndexVec<CrateNum, Option<CrateNum>>
     {
-        let _in_ignore = tcx.dep_graph.in_ignore();
+        tcx.dep_graph.with_ignore(|| {
+            let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
+                let crate_name = tcx.original_crate_name(cnum)
+                                    .as_str()
+                                    .to_string();
+                let crate_disambiguator = tcx.crate_disambiguator(cnum);
+                ((crate_name, crate_disambiguator), cnum)
+            }).collect::<FxHashMap<_,_>>();
 
-        let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
-            let crate_name = tcx.original_crate_name(cnum)
-                                .as_str()
-                                .to_string();
-            let crate_disambiguator = tcx.crate_disambiguator(cnum);
-            ((crate_name, crate_disambiguator), cnum)
-        }).collect::<FxHashMap<_,_>>();
+            let map_size = prev_cnums.iter()
+                                    .map(|&(cnum, ..)| cnum)
+                                    .max()
+                                    .unwrap_or(0) + 1;
+            let mut map = IndexVec::new();
+            map.resize(map_size as usize, None);
 
-        let map_size = prev_cnums.iter()
-                                 .map(|&(cnum, ..)| cnum)
-                                 .max()
-                                 .unwrap_or(0) + 1;
-        let mut map = IndexVec::new();
-        map.resize(map_size as usize, None);
+            for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
+                let key = (crate_name.clone(), crate_disambiguator);
+                map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
+            }
 
-        for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
-            let key = (crate_name.clone(), crate_disambiguator);
-            map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
-        }
-
-        map[LOCAL_CRATE] = Some(LOCAL_CRATE);
-        map
+            map[LOCAL_CRATE] = Some(LOCAL_CRATE);
+            map
+        })
     }
 }
 
@@ -659,6 +660,12 @@
     }
 }
 
+impl<'a, 'tcx, 'x> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx, 'x> {
+    fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+        Fingerprint::decode_opaque(&mut self.opaque)
+    }
+}
+
 impl<'a, 'tcx, 'x, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
 for CacheDecoder<'a, 'tcx, 'x> {
     #[inline]
@@ -878,6 +885,14 @@
     }
 }
 
+impl<'enc, 'a, 'tcx> SpecializedEncoder<Fingerprint>
+for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder<'enc>>
+{
+    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+        f.encode_opaque(&mut self.encoder)
+    }
+}
+
 impl<'enc, 'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>>
 for CacheEncoder<'enc, 'a, 'tcx, E>
     where E: 'enc + ty_codec::TyEncoder,
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 8875439..d670ecc 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -438,7 +438,7 @@
                     use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
                     use ich::Fingerprint;
 
-                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node)) ==
+                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node_index)) ==
                             tcx.dep_graph.prev_fingerprint_of(dep_node),
                             "Fingerprint for green query instance not loaded \
                              from cache: {:?}", dep_node);
@@ -452,7 +452,7 @@
                     let new_hash: Fingerprint = hasher.finish();
                     debug!("END verify_ich({:?})", dep_node);
 
-                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node);
+                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node_index);
 
                     assert!(new_hash == old_hash, "Found unstable fingerprints \
                         for {:?}", dep_node);
@@ -760,6 +760,7 @@
         DepKind::VtableMethods |
         DepKind::EraseRegionsTy |
         DepKind::NormalizeTy |
+        DepKind::SubstituteNormalizeAndTestPredicates |
 
         // This one should never occur in this context
         DepKind::Null => {
@@ -800,7 +801,6 @@
         DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
         DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
         DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
-        DepKind::IsAutoImpl => { force!(is_auto_impl, def_id!()); }
         DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
         DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
         DepKind::FnSignature => { force!(fn_sig, def_id!()); }
@@ -917,6 +917,9 @@
         }
         DepKind::IsTranslatedFunction => { force!(is_translated_function, def_id!()); }
         DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
+
+        DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
+        DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
     }
 
     true
@@ -978,4 +981,5 @@
     SymbolName => def_symbol_name,
     ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
     ContainsExternIndicator => contains_extern_indicator,
+    CheckMatch => check_match,
 );
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index e03e123..b3acfb7 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -19,6 +19,8 @@
 use hir::def::{Def, CtorKind, ExportMap};
 use hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use hir::map::DefPathData;
+use hir::svh::Svh;
+use ich::Fingerprint;
 use ich::StableHashingContext;
 use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
@@ -36,6 +38,7 @@
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
 
 use serialize::{self, Encodable, Encoder};
+use std::cell::RefCell;
 use std::collections::BTreeMap;
 use std::cmp;
 use std::fmt;
@@ -1097,8 +1100,8 @@
 /// In particular, form #1 is "desugared" to the combination of a
 /// normal trait predicate (`T : TraitRef<...>`) and one of these
 /// predicates. Form #2 is a broader form in that it also permits
-/// equality between arbitrary types. Processing an instance of Form
-/// #2 eventually yields one of these `ProjectionPredicate`
+/// equality between arbitrary types. Processing an instance of
+/// Form #2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct ProjectionPredicate<'tcx> {
@@ -1400,7 +1403,7 @@
         /// fields/variants) and as such, whether downstream crates must match exhaustively on the
         /// fields/variants of this data type.
         ///
-        /// See RFC 2008 (https://github.com/rust-lang/rfcs/pull/2008).
+        /// See RFC 2008 (<https://github.com/rust-lang/rfcs/pull/2008>).
         const IS_NON_EXHAUSTIVE   = 1 << 5;
     }
 }
@@ -1475,17 +1478,32 @@
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        let ty::AdtDef {
-            did,
-            ref variants,
-            ref flags,
-            ref repr,
-        } = *self;
+        thread_local! {
+            static CACHE: RefCell<FxHashMap<usize, Fingerprint>> =
+                RefCell::new(FxHashMap());
+        }
 
-        did.hash_stable(hcx, hasher);
-        variants.hash_stable(hcx, hasher);
-        flags.hash_stable(hcx, hasher);
-        repr.hash_stable(hcx, hasher);
+        let hash: Fingerprint = CACHE.with(|cache| {
+            let addr = self as *const AdtDef as usize;
+            *cache.borrow_mut().entry(addr).or_insert_with(|| {
+                let ty::AdtDef {
+                    did,
+                    ref variants,
+                    ref flags,
+                    ref repr,
+                } = *self;
+
+                let mut hasher = StableHasher::new();
+                did.hash_stable(hcx, &mut hasher);
+                variants.hash_stable(hcx, &mut hasher);
+                flags.hash_stable(hcx, &mut hasher);
+                repr.hash_stable(hcx, &mut hasher);
+
+                hasher.finish()
+           })
+        });
+
+        hash.hash_stable(hcx, hasher);
     }
 }
 
@@ -1498,8 +1516,9 @@
         const IS_C               = 1 << 0;
         const IS_PACKED          = 1 << 1;
         const IS_SIMD            = 1 << 2;
+        const IS_TRANSPARENT     = 1 << 3;
         // Internal only for now. If true, don't reorder fields.
-        const IS_LINEAR          = 1 << 3;
+        const IS_LINEAR          = 1 << 4;
 
         // Any of these flags being set prevent field reordering optimisation.
         const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits |
@@ -1537,8 +1556,9 @@
         for attr in tcx.get_attrs(did).iter() {
             for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
                 flags.insert(match r {
-                    attr::ReprExtern => ReprFlags::IS_C,
+                    attr::ReprC => ReprFlags::IS_C,
                     attr::ReprPacked => ReprFlags::IS_PACKED,
+                    attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
                     attr::ReprSimd => ReprFlags::IS_SIMD,
                     attr::ReprInt(i) => {
                         size = Some(i);
@@ -1552,11 +1572,6 @@
             }
         }
 
-        // FIXME(eddyb) This is deprecated and should be removed.
-        if tcx.has_attr(did, "simd") {
-            flags.insert(ReprFlags::IS_SIMD);
-        }
-
         // This is here instead of layout because the choice must make it into metadata.
         if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) {
             flags.insert(ReprFlags::IS_LINEAR);
@@ -1571,10 +1586,12 @@
     #[inline]
     pub fn packed(&self) -> bool { self.flags.contains(ReprFlags::IS_PACKED) }
     #[inline]
+    pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) }
+    #[inline]
     pub fn linear(&self) -> bool { self.flags.contains(ReprFlags::IS_LINEAR) }
 
     pub fn discr_type(&self) -> attr::IntType {
-        self.int.unwrap_or(attr::SignedInt(ast::IntTy::Is))
+        self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
     }
 
     /// Returns true if this `#[repr()]` should inhabit "smart enum
@@ -1690,10 +1707,9 @@
         self.destructor(tcx).is_some()
     }
 
-    /// Asserts this is a struct and returns the struct's unique
-    /// variant.
-    pub fn struct_variant(&self) -> &VariantDef {
-        assert!(!self.is_enum());
+    /// Asserts this is a struct or union and returns its unique variant.
+    pub fn non_enum_variant(&self) -> &VariantDef {
+        assert!(self.is_struct() || self.is_union());
         &self.variants[0]
     }
 
@@ -1732,7 +1748,7 @@
         match def {
             Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.struct_variant(),
+            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(),
             _ => bug!("unexpected def {:?} in variant_of_def", def)
         }
     }
@@ -1864,7 +1880,12 @@
                 vec![]
             }
 
-            TyStr | TyDynamic(..) | TySlice(_) | TyForeign(..) | TyError => {
+            TyStr |
+            TyDynamic(..) |
+            TySlice(_) |
+            TyForeign(..) |
+            TyError |
+            TyGeneratorWitness(..) => {
                 // these are never sized - return the target type
                 vec![ty]
             }
@@ -2318,11 +2339,11 @@
                 self.adt_def(enum_did).variant_with_id(did)
             }
             Def::Struct(did) | Def::Union(did) => {
-                self.adt_def(did).struct_variant()
+                self.adt_def(did).non_enum_variant()
             }
             Def::StructCtor(ctor_did, ..) => {
                 let did = self.parent_def_id(ctor_did).expect("struct ctor has no parent");
-                self.adt_def(did).struct_variant()
+                self.adt_def(did).non_enum_variant()
             }
             _ => bug!("expect_variant_def used with unexpected def {:?}", def)
         }
@@ -2401,12 +2422,10 @@
 
     /// Determine whether an item is annotated with an attribute
     pub fn has_attr(self, did: DefId, attr: &str) -> bool {
-        self.get_attrs(did).iter().any(|item| item.check_name(attr))
+        attr::contains_name(&self.get_attrs(did), attr)
     }
 
     /// Returns true if this is an `auto trait`.
-    ///
-    /// NB. For a limited time, also returns true if `impl Trait for .. { }` is in the code-base.
     pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
         self.trait_def(trait_def_id).has_auto_impl
     }
@@ -2669,6 +2688,13 @@
     tcx.crate_name.clone()
 }
 
+fn crate_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        crate_num: CrateNum)
+                        -> Svh {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.hir.crate_hash
+}
+
 pub fn provide(providers: &mut ty::maps::Providers) {
     context::provide(providers);
     erase_regions::provide(providers);
@@ -2684,6 +2710,7 @@
         trait_of_item,
         crate_disambiguator,
         original_crate_name,
+        crate_hash,
         trait_impls_of: trait_def::trait_impls_of_provider,
         ..*providers
     };
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 7071376..ff99a4b 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -79,16 +79,19 @@
                 }
             }
 
-            ty::TyGenerator(def_id, ref substs, ref interior) => {
+            ty::TyGenerator(def_id, ref substs, _) => {
                 // Same as the closure case
                 for upvar_ty in substs.upvar_tys(def_id, *self) {
                     self.compute_components(upvar_ty, out);
                 }
 
-                // But generators can have additional interior types
-                self.compute_components(interior.witness, out);
+                // We ignore regions in the generator interior as we don't
+                // want these to affect region inference
             }
 
+            // All regions are bound inside a witness
+            ty::TyGeneratorWitness(..) => (),
+
             // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
             // is implied by the environment is done in regionck.
             ty::TyParam(p) => {
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 376cdc4..a6c7272 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -18,6 +18,7 @@
 use traits::Reveal;
 use ty::subst::{Kind, Substs};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::fold::{TypeVisitor, TypeFolder};
 use ty::error::{ExpectedFound, TypeError};
 use util::common::ErrorReported;
 use std::rc::Rc;
@@ -319,6 +320,33 @@
     }
 }
 
+#[derive(Debug, Clone)]
+struct GeneratorWitness<'tcx>(&'tcx ty::Slice<Ty<'tcx>>);
+
+impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        GeneratorWitness(self.0.fold_with(folder))
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.0.visit_with(visitor)
+    }
+}
+
+impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
+    fn relate<'a, 'gcx, R>(relation: &mut R,
+                           a: &GeneratorWitness<'tcx>,
+                           b: &GeneratorWitness<'tcx>)
+                           -> RelateResult<'tcx, GeneratorWitness<'tcx>>
+        where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
+    {
+        assert!(a.0.len() == b.0.len());
+        let tcx = relation.tcx();
+        let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
+        Ok(GeneratorWitness(types))
+    }
+}
+
 impl<'tcx> Relate<'tcx> for Ty<'tcx> {
     fn relate<'a, 'gcx, R>(relation: &mut R,
                            a: &Ty<'tcx>,
@@ -410,6 +438,17 @@
             Ok(tcx.mk_generator(a_id, substs, interior))
         }
 
+        (&ty::TyGeneratorWitness(a_types), &ty::TyGeneratorWitness(b_types)) =>
+        {
+            // Wrap our types with a temporary GeneratorWitness struct
+            // inside the binder so we can related them
+            let a_types = ty::Binder(GeneratorWitness(*a_types.skip_binder()));
+            let b_types = ty::Binder(GeneratorWitness(*b_types.skip_binder()));
+            // Then remove the GeneratorWitness for the result
+            let types = ty::Binder(relation.relate(&a_types, &b_types)?.skip_binder().0);
+            Ok(tcx.mk_generator_witness(types))
+        }
+
         (&ty::TyClosure(a_id, a_substs),
          &ty::TyClosure(b_id, b_substs))
             if a_id == b_id =>
@@ -575,8 +614,9 @@
                            -> RelateResult<'tcx, ty::GeneratorInterior<'tcx>>
         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
     {
-        let interior = relation.relate(&a.witness, &b.witness)?;
-        Ok(ty::GeneratorInterior::new(interior))
+        assert_eq!(a.movable, b.movable);
+        let witness = relation.relate(&a.witness, &b.witness)?;
+        Ok(ty::GeneratorInterior { witness, movable: a.movable })
     }
 }
 
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 4385112..0dc1338 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -438,7 +438,7 @@
     type Lifted = ty::GeneratorInterior<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&self.witness).map(|witness| {
-            ty::GeneratorInterior { witness }
+            ty::GeneratorInterior { witness, movable: self.movable }
         })
     }
 }
@@ -798,6 +798,7 @@
             ty::TyGenerator(did, substs, interior) => {
                 ty::TyGenerator(did, substs.fold_with(folder), interior.fold_with(folder))
             }
+            ty::TyGeneratorWitness(types) => ty::TyGeneratorWitness(types.fold_with(folder)),
             ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)),
             ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
             ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
@@ -832,6 +833,7 @@
             ty::TyGenerator(_did, ref substs, ref interior) => {
                 substs.visit_with(visitor) || interior.visit_with(visitor)
             }
+            ty::TyGeneratorWitness(ref types) => types.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
             ty::TyProjection(ref data) => data.visit_with(visitor),
             ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
@@ -928,7 +930,10 @@
 
 impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorInterior<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        ty::GeneratorInterior::new(self.witness.fold_with(folder))
+        ty::GeneratorInterior {
+           witness: self.witness.fold_with(folder),
+           movable: self.movable,
+        }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 02729c6..b6ba789 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -141,6 +141,10 @@
     /// `|a| yield a`.
     TyGenerator(DefId, ClosureSubsts<'tcx>, GeneratorInterior<'tcx>),
 
+    /// A type representin the types stored inside a generator.
+    /// This should only appear in GeneratorInteriors.
+    TyGeneratorWitness(Binder<&'tcx Slice<Ty<'tcx>>>),
+
     /// The never type `!`
     TyNever,
 
@@ -405,19 +409,7 @@
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct GeneratorInterior<'tcx> {
     pub witness: Ty<'tcx>,
-}
-
-impl<'tcx> GeneratorInterior<'tcx> {
-    pub fn new(witness: Ty<'tcx>) -> GeneratorInterior<'tcx> {
-        GeneratorInterior { witness }
-    }
-
-    pub fn as_slice(&self) -> &'tcx Slice<Ty<'tcx>> {
-        match self.witness.sty {
-            ty::TyTuple(s, _) => s,
-            _ => bug!(),
-        }
-    }
+    pub movable: bool,
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@@ -673,6 +665,7 @@
     /// accounting.
     ///
     /// Some examples where `skip_binder` is reasonable:
+    ///
     /// - extracting the def-id from a PolyTraitRef;
     /// - comparing the self type of a PolyTraitRef to see if it is equal to
     ///   a type parameter `X`, since the type `X`  does not reference any regions
@@ -992,8 +985,8 @@
 /// happen, you can use `leak_check`. This is more clearly explained
 /// by infer/higher_ranked/README.md.
 ///
-/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
-/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
+/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
+/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
 #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
     // Region bound in a type or fn declaration which will be
@@ -1350,7 +1343,7 @@
     pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
         match self.sty {
             TyAdt(def, substs) => {
-                def.struct_variant().fields[0].ty(tcx, substs)
+                def.non_enum_variant().fields[0].ty(tcx, substs)
             }
             _ => bug!("simd_type called on invalid type")
         }
@@ -1358,7 +1351,7 @@
 
     pub fn simd_size(&self, _cx: TyCtxt) -> usize {
         match self.sty {
-            TyAdt(def, _) => def.struct_variant().fields.len(),
+            TyAdt(def, _) => def.non_enum_variant().fields.len(),
             _ => bug!("simd_size called on invalid type")
         }
     }
@@ -1477,13 +1470,6 @@
         }
     }
 
-    pub fn is_uint(&self) -> bool {
-        match self.sty {
-            TyInfer(IntVar(_)) | TyUint(ast::UintTy::Us) => true,
-            _ => false
-        }
-    }
-
     pub fn is_char(&self) -> bool {
         match self.sty {
             TyChar => true,
@@ -1511,7 +1497,7 @@
 
     pub fn is_machine(&self) -> bool {
         match self.sty {
-            TyInt(ast::IntTy::Is) | TyUint(ast::UintTy::Us) => false,
+            TyInt(ast::IntTy::Isize) | TyUint(ast::UintTy::Usize) => false,
             TyInt(..) | TyUint(..) | TyFloat(..) => true,
             _ => false,
         }
@@ -1617,6 +1603,7 @@
             }
             TyFnDef(..) |
             TyFnPtr(_) |
+            TyGeneratorWitness(..) |
             TyBool |
             TyChar |
             TyInt(_) |
@@ -1647,10 +1634,8 @@
     ///
     /// Note that during type checking, we use an inference variable
     /// to represent the closure kind, because it has not yet been
-    /// inferred. Once [upvar inference] is complete, that type varibale
-    /// will be unified.
-    ///
-    /// [upvar inference]: src/librustc_typeck/check/upvar.rs
+    /// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`)
+    /// is complete, that type variable will be unified.
     pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
         match self.sty {
             TyInt(int_ty) => match int_ty {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 9b93023..34f0523 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -11,7 +11,7 @@
 //! misc. type-system utilities too small to deserve their own file
 
 use hir::def::Def;
-use hir::def_id::{DefId, LOCAL_CRATE};
+use hir::def_id::DefId;
 use hir::map::{DefPathData, Node};
 use hir;
 use ich::NodeIdHashingMode;
@@ -29,7 +29,6 @@
                                            HashStable};
 use rustc_data_structures::fx::FxHashMap;
 use std::cmp;
-use std::iter;
 use std::hash::Hash;
 use std::intrinsics;
 use syntax::ast::{self, Name};
@@ -55,7 +54,7 @@
             SignedInt(ast::IntTy::I32)   => ConstInt::I32($lit),
             SignedInt(ast::IntTy::I64)   => ConstInt::I64($lit),
             SignedInt(ast::IntTy::I128)   => ConstInt::I128($lit),
-            SignedInt(ast::IntTy::Is) => match $tcx.sess.target.isize_ty {
+            SignedInt(ast::IntTy::Isize) => match $tcx.sess.target.isize_ty {
                 ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16($lit)),
                 ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32($lit)),
                 ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64($lit)),
@@ -66,7 +65,7 @@
             UnsignedInt(ast::UintTy::U32) => ConstInt::U32($lit),
             UnsignedInt(ast::UintTy::U64) => ConstInt::U64($lit),
             UnsignedInt(ast::UintTy::U128) => ConstInt::U128($lit),
-            UnsignedInt(ast::UintTy::Us) => match $tcx.sess.target.usize_ty {
+            UnsignedInt(ast::UintTy::Usize) => match $tcx.sess.target.usize_ty {
                 ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16($lit)),
                 ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32($lit)),
                 ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64($lit)),
@@ -84,13 +83,13 @@
             SignedInt(ast::IntTy::I32)     => tcx.types.i32,
             SignedInt(ast::IntTy::I64)     => tcx.types.i64,
             SignedInt(ast::IntTy::I128)     => tcx.types.i128,
-            SignedInt(ast::IntTy::Is)   => tcx.types.isize,
+            SignedInt(ast::IntTy::Isize)   => tcx.types.isize,
             UnsignedInt(ast::UintTy::U8)    => tcx.types.u8,
             UnsignedInt(ast::UintTy::U16)   => tcx.types.u16,
             UnsignedInt(ast::UintTy::U32)   => tcx.types.u32,
             UnsignedInt(ast::UintTy::U64)   => tcx.types.u64,
             UnsignedInt(ast::UintTy::U128)   => tcx.types.u128,
-            UnsignedInt(ast::UintTy::Us) => tcx.types.usize,
+            UnsignedInt(ast::UintTy::Usize) => tcx.types.usize,
         }
     }
 
@@ -105,13 +104,13 @@
             (SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {},
             (SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {},
             (SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {},
-            (SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {},
+            (SignedInt(ast::IntTy::Isize), ConstInt::Isize(_)) => {},
             (UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {},
             (UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {},
             (UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
             (UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
             (UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {},
-            (UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
+            (UnsignedInt(ast::UintTy::Usize), ConstInt::Usize(_)) => {},
             _ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
         }
     }
@@ -258,7 +257,7 @@
                 adt.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
             }
             (&TyAdt(adt, substs), None) => {
-                // Don't use `struct_variant`, this may be a univariant enum.
+                // Don't use `non_enum_variant`, this may be a univariant enum.
                 adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
             }
             (&TyTuple(ref v, _), None) => v.get(i).cloned(),
@@ -277,7 +276,7 @@
                 adt.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
             }
             (&TyAdt(adt, substs), None) => {
-                adt.struct_variant().find_field_named(n).map(|f| f.ty(self, substs))
+                adt.non_enum_variant().find_field_named(n).map(|f| f.ty(self, substs))
             }
             _ => return None
         }
@@ -293,7 +292,7 @@
                     if !def.is_struct() {
                         break;
                     }
-                    match def.struct_variant().fields.last() {
+                    match def.non_enum_variant().fields.last() {
                         Some(f) => ty = f.ty(self, substs),
                         None => break,
                     }
@@ -329,7 +328,7 @@
             match (&a.sty, &b.sty) {
                 (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs))
                         if a_def == b_def && a_def.is_struct() => {
-                    if let Some(f) = a_def.struct_variant().fields.last() {
+                    if let Some(f) = a_def.non_enum_variant().fields.last() {
                         a = f.ty(self, a_substs);
                         b = f.ty(self, b_substs);
                     } else {
@@ -427,7 +426,7 @@
             return None;
         };
 
-        self.coherent_trait((LOCAL_CRATE, drop_trait));
+        ty::maps::queries::coherent_trait::ensure(self, drop_trait);
 
         let mut dtor_did = None;
         let ty = self.type_of(adt_did);
@@ -550,7 +549,8 @@
         let result = match ty.sty {
             ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
             ty::TyFloat(_) | ty::TyStr | ty::TyNever | ty::TyForeign(..) |
-            ty::TyRawPtr(..) | ty::TyRef(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+            ty::TyRawPtr(..) | ty::TyRef(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) |
+            ty::TyGeneratorWitness(..) => {
                 // these types never have a destructor
                 Ok(ty::DtorckConstraint::empty())
             }
@@ -572,8 +572,11 @@
                 }).collect()
             }
 
-            ty::TyGenerator(def_id, substs, interior) => {
-                substs.upvar_tys(def_id, self).chain(iter::once(interior.witness)).map(|ty| {
+            ty::TyGenerator(def_id, substs, _) => {
+                // Note that the interior types are ignored here.
+                // Any type reachable inside the interior must also be reachable
+                // through the upvars.
+                substs.upvar_tys(def_id, self).map(|ty| {
                     self.dtorck_constraint_for_ty(span, for_ty, depth+1, ty)
                 }).collect()
             }
@@ -783,6 +786,9 @@
                     self.def_id(d);
                 }
             }
+            TyGeneratorWitness(tys) => {
+                self.hash(tys.skip_binder().len());
+            }
             TyTuple(tys, defaulted) => {
                 self.hash(tys.len());
                 self.hash(defaulted);
@@ -1139,7 +1145,7 @@
         // Fast-path for primitive types
         ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
         ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
-        ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
+        ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar | ty::TyGeneratorWitness(..) |
         ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
 
         // Foreign types can never have destructors
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index 448ad4c..45f0ad1 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -119,8 +119,11 @@
             stack.extend(substs.substs.types().rev());
         }
         ty::TyGenerator(_, ref substs, ref interior) => {
-            stack.extend(substs.substs.types().rev());
             stack.push(interior.witness);
+            stack.extend(substs.substs.types().rev());
+        }
+        ty::TyGeneratorWitness(ts) => {
+            stack.extend(ts.skip_binder().iter().cloned().rev());
         }
         ty::TyTuple(ts, _) => {
             stack.extend(ts.iter().cloned().rev());
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index a851ccc..ce44448 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -283,6 +283,7 @@
                 ty::TyFloat(..) |
                 ty::TyError |
                 ty::TyStr |
+                ty::TyGeneratorWitness(..) |
                 ty::TyNever |
                 ty::TyParam(_) |
                 ty::TyForeign(..) => {
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 76d3494..2971f3e 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -29,7 +29,7 @@
 
 // Useful type to use with `Result<>` indicate that an error has already
 // been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)]
 pub struct ErrorReported;
 
 thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
@@ -218,13 +218,10 @@
 // Memory reporting
 #[cfg(unix)]
 fn get_resident() -> Option<usize> {
-    use std::fs::File;
-    use std::io::Read;
+    use std::fs;
 
     let field = 1;
-    let mut f = File::open("/proc/self/statm").ok()?;
-    let mut contents = String::new();
-    f.read_to_string(&mut contents).ok()?;
+    let contents = fs::read_string("/proc/self/statm").ok()?;
     let s = contents.split_whitespace().nth(field)?;
     let npages = s.parse::<usize>().ok()?;
     Some(npages * 4096)
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 5184183..37d1c56 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -17,7 +17,7 @@
 use ty::{TyBool, TyChar, TyAdt};
 use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
 use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
-use ty::{TyClosure, TyGenerator, TyForeign, TyProjection, TyAnon};
+use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon};
 use ty::{TyDynamic, TyInt, TyUint, TyInfer};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use util::nodemap::FxHashSet;
@@ -632,6 +632,22 @@
 }
 
 define_print! {
+    ('tcx) &'tcx ty::Slice<Ty<'tcx>>, (self, f, cx) {
+        display {
+            write!(f, "{{")?;
+            let mut tys = self.iter();
+            if let Some(&ty) = tys.next() {
+                print!(f, cx, print(ty))?;
+                for &ty in tys {
+                    print!(f, cx, write(", "), print(ty))?;
+                }
+            }
+            write!(f, "}}")
+        }
+    }
+}
+
+define_print! {
     ('tcx) ty::TypeAndMut<'tcx>, (self, f, cx) {
         display {
             print!(f, cx,
@@ -1066,7 +1082,11 @@
                 TyStr => write!(f, "str"),
                 TyGenerator(did, substs, interior) => ty::tls::with(|tcx| {
                     let upvar_tys = substs.upvar_tys(did, tcx);
-                    write!(f, "[generator")?;
+                    if interior.movable {
+                        write!(f, "[generator")?;
+                    } else {
+                        write!(f, "[static generator")?;
+                    }
 
                     if let Some(node_id) = tcx.hir.as_local_node_id(did) {
                         write!(f, "@{:?}", tcx.hir.span(node_id))?;
@@ -1097,6 +1117,9 @@
 
                     print!(f, cx, write(" "), print(interior), write("]"))
                 }),
+                TyGeneratorWitness(types) => {
+                    ty::tls::with(|tcx| cx.in_binder(f, tcx, &types, tcx.lift(&types)))
+                }
                 TyClosure(did, substs) => ty::tls::with(|tcx| {
                     let upvar_tys = substs.upvar_tys(did, tcx);
                     write!(f, "[closure")?;
diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs
index 124c840..7abd02b 100644
--- a/src/librustc_apfloat/ieee.rs
+++ b/src/librustc_apfloat/ieee.rs
@@ -65,11 +65,11 @@
     /// Number of bits in the significand. This includes the integer bit.
     const PRECISION: usize;
 
-    /// The largest E such that 2^E is representable; this matches the
+    /// The largest E such that 2<sup>E</sup> is representable; this matches the
     /// definition of IEEE 754.
     const MAX_EXP: ExpInt;
 
-    /// The smallest E such that 2^E is a normalized number; this
+    /// The smallest E such that 2<sup>E</sup> is a normalized number; this
     /// matches the definition of IEEE 754.
     const MIN_EXP: ExpInt = -Self::MAX_EXP + 1;
 
@@ -1434,7 +1434,7 @@
         let max_change = S::MAX_EXP as i32 - (S::MIN_EXP as i32 - sig_bits) + 1;
 
         // Clamp to one past the range ends to let normalize handle overflow.
-        let exp_change = cmp::min(cmp::max(exp as i32, (-max_change - 1)), max_change);
+        let exp_change = cmp::min(cmp::max(exp as i32, -max_change - 1), max_change);
         self.exp = self.exp.saturating_add(exp_change as ExpInt);
         self = self.normalize(round, Loss::ExactlyZero).value;
         if self.is_nan() {
@@ -2608,7 +2608,7 @@
     ///
     /// `(n - 1) * (n - 1) + 2 * (n - 1) == (n - 1) * (n + 1)`
     ///
-    /// which is less than n^2.
+    /// which is less than n<sup>2</sup>.
     pub(super) fn widening_mul(a: Limb, b: Limb) -> [Limb; 2] {
         let mut wide = [0, 0];
 
diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs
index 7dea3da..3afc2f6 100644
--- a/src/librustc_apfloat/lib.rs
+++ b/src/librustc_apfloat/lib.rs
@@ -10,7 +10,8 @@
 
 //! Port of LLVM's APFloat software floating-point implementation from the
 //! following C++ sources (please update commit hash when backporting):
-//! https://github.com/llvm-mirror/llvm/tree/23efab2bbd424ed13495a420ad8641cb2c6c28f9
+//! <https://github.com/llvm-mirror/llvm/tree/23efab2bbd424ed13495a420ad8641cb2c6c28f9>
+//!
 //! * `include/llvm/ADT/APFloat.h` -> `Float` and `FloatConvert` traits
 //! * `lib/Support/APFloat.cpp` -> `ieee` and `ppc` modules
 //! * `unittests/ADT/APFloatTest.cpp` -> `tests` directory
@@ -221,8 +222,8 @@
 ///
 /// `apfloat` does not provide any exception handling beyond default exception
 /// handling. We represent Signaling NaNs via IEEE-754R 2008 6.2.1 should clause
-/// by encoding Signaling NaNs with the first bit of its trailing significand as
-/// 0.
+/// by encoding Signaling NaNs with the first bit of its trailing significand
+/// as 0.
 ///
 /// Future work
 /// ===========
@@ -259,11 +260,11 @@
     /// Number of bits in the significand. This includes the integer bit.
     const PRECISION: usize;
 
-    /// The largest E such that 2^E is representable; this matches the
+    /// The largest E such that 2<sup>E</sup> is representable; this matches the
     /// definition of IEEE 754.
     const MAX_EXP: ExpInt;
 
-    /// The smallest E such that 2^E is a normalized number; this
+    /// The smallest E such that 2<sup>E</sup> is a normalized number; this
     /// matches the definition of IEEE 754.
     const MIN_EXP: ExpInt;
 
@@ -571,7 +572,7 @@
     ///
     fn ilogb(self) -> ExpInt;
 
-    /// Returns: self * 2^exp for integral exponents.
+    /// Returns: self * 2<sup>exp</sup> for integral exponents.
     fn scalbn_r(self, exp: ExpInt, round: Round) -> Self;
     fn scalbn(self, exp: ExpInt) -> Self {
         self.scalbn_r(exp, Round::NearestTiesToEven)
diff --git a/src/librustc_back/Cargo.toml b/src/librustc_back/Cargo.toml
index 92b024b..d864c5b 100644
--- a/src/librustc_back/Cargo.toml
+++ b/src/librustc_back/Cargo.toml
@@ -11,7 +11,7 @@
 [dependencies]
 syntax = { path = "../libsyntax" }
 serialize = { path = "../libserialize" }
-log = "0.3"
+log = "0.4"
 rand = "0.3"
 
 [features]
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index ccf1db7..8bf60b0 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -28,6 +28,7 @@
 
 #![feature(box_syntax)]
 #![feature(const_fn)]
+#![feature(fs_read_write)]
 
 extern crate syntax;
 extern crate rand;
diff --git a/src/librustc_back/target/aarch64_unknown_cloudabi.rs b/src/librustc_back/target/aarch64_unknown_cloudabi.rs
new file mode 100644
index 0000000..59c82e0
--- /dev/null
+++ b/src/librustc_back/target/aarch64_unknown_cloudabi.rs
@@ -0,0 +1,33 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::cloudabi_base::opts();
+    base.max_atomic_width = Some(128);
+    base.abi_blacklist = super::arm_base::abi_blacklist();
+    base.linker = "aarch64-unknown-cloudabi-cc".to_string();
+
+    Ok(Target {
+        llvm_target: "aarch64-unknown-cloudabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        target_os: "cloudabi".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/armv4t_unknown_linux_gnueabi.rs b/src/librustc_back/target/armv4t_unknown_linux_gnueabi.rs
new file mode 100644
index 0000000..33399a7
--- /dev/null
+++ b/src/librustc_back/target/armv4t_unknown_linux_gnueabi.rs
@@ -0,0 +1,36 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let base = super::linux_base::opts();
+    Ok(Target {
+        llvm_target: "armv4t-unknown-linux-gnueabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+
+        options: TargetOptions {
+            features: "+soft-float,+strict-align".to_string(),
+            // Atomic operations provided by compiler-builtins
+            max_atomic_width: Some(32),
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            .. base
+        }
+    })
+}
diff --git a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs b/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
index 97397ca..4efe669 100644
--- a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
+++ b/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
@@ -27,11 +27,7 @@
 
         options: TargetOptions {
             features: "+soft-float,+strict-align".to_string(),
-
-            // Atomic operations provided when linked with libgcc.
-            // FIXME: If the following PR is merged, the atomic operations would be
-            // provided by compiler-builtins instead with no change of behavior:
-            // https://github.com/rust-lang-nursery/compiler-builtins/pull/115/files
+            // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
diff --git a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs
new file mode 100644
index 0000000..faa2c4f
--- /dev/null
+++ b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::cloudabi_base::opts();
+    base.cpu = "cortex-a8".to_string();
+    base.max_atomic_width = Some(64);
+    base.features = "+v7,+vfp3,+neon".to_string();
+    base.abi_blacklist = super::arm_base::abi_blacklist();
+    base.linker = "armv7-unknown-cloudabi-eabihf-cc".to_string();
+
+    Ok(Target {
+        llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "cloudabi".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/cloudabi_base.rs b/src/librustc_back/target/cloudabi_base.rs
new file mode 100644
index 0000000..4cd52eb
--- /dev/null
+++ b/src/librustc_back/target/cloudabi_base.rs
@@ -0,0 +1,46 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions, RelroLevel};
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        "-Wl,-Bstatic".to_string(),
+        "-Wl,--no-dynamic-linker".to_string(),
+        "-Wl,--eh-frame-hdr".to_string(),
+        "-Wl,--gc-sections".to_string(),
+    ]);
+
+    TargetOptions {
+        executables: true,
+        target_family: None,
+        linker_is_gnu: true,
+        pre_link_args: args,
+        position_independent_executables: true,
+        // As CloudABI only supports static linkage, there is no need
+        // for dynamic TLS. The C library therefore does not provide
+        // __tls_get_addr(), which is normally used to perform dynamic
+        // TLS lookups by programs that make use of dlopen(). Only the
+        // "local-exec" and "initial-exec" TLS models can be used.
+        //
+        // "local-exec" is more efficient than "initial-exec", as the
+        // latter has one more level of indirection: it accesses the GOT
+        // (Global Offset Table) to obtain the effective address of a
+        // thread-local variable. Using a GOT is useful only when doing
+        // dynamic linking.
+        tls_model: "local-exec".to_string(),
+        relro_level: RelroLevel::Full,
+        exe_allocation_crate: super::maybe_jemalloc(),
+        .. Default::default()
+    }
+}
diff --git a/src/librustc_back/target/i586_unknown_linux_musl.rs b/src/librustc_back/target/i586_unknown_linux_musl.rs
new file mode 100644
index 0000000..416eacf
--- /dev/null
+++ b/src/librustc_back/target/i586_unknown_linux_musl.rs
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::TargetResult;
+
+pub fn target() -> TargetResult {
+    let mut base = super::i686_unknown_linux_musl::target()?;
+    base.options.cpu = "pentium".to_string();
+    base.llvm_target = "i586-unknown-linux-musl".to_string();
+    Ok(base)
+}
diff --git a/src/librustc_back/target/i686_unknown_cloudabi.rs b/src/librustc_back/target/i686_unknown_cloudabi.rs
new file mode 100644
index 0000000..e244f44
--- /dev/null
+++ b/src/librustc_back/target/i686_unknown_cloudabi.rs
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::cloudabi_base::opts();
+    base.cpu = "pentium4".to_string();
+    base.max_atomic_width = Some(64);
+    base.linker = "i686-unknown-cloudabi-cc".to_string();
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
+    base.stack_probes = true;
+
+    Ok(Target {
+        llvm_target: "i686-unknown-cloudabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        arch: "x86".to_string(),
+        target_os: "cloudabi".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 6f9ba5d..b65b18d 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -47,7 +47,6 @@
 use serialize::json::{Json, ToJson};
 use std::collections::BTreeMap;
 use std::default::Default;
-use std::io::prelude::*;
 use syntax::abi::{Abi, lookup as lookup_abi};
 
 use {LinkerFlavor, PanicStrategy, RelroLevel};
@@ -57,6 +56,7 @@
 mod apple_ios_base;
 mod arm_base;
 mod bitrig_base;
+mod cloudabi_base;
 mod dragonfly_base;
 mod emscripten_base;
 mod freebsd_base;
@@ -146,24 +146,27 @@
     ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
     ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
+    ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
     ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
     ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
     ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
     ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
+    ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
     ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
     ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
     ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
+
     ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
     ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
     ("i686-unknown-linux-musl", i686_unknown_linux_musl),
+    ("i586-unknown-linux-musl", i586_unknown_linux_musl),
     ("mips-unknown-linux-musl", mips_unknown_linux_musl),
     ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
+
     ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
     ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
 
-    ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
-
     ("i686-linux-android", i686_linux_android),
     ("x86_64-linux-android", x86_64_linux_android),
     ("arm-linux-androideabi", arm_linux_androideabi),
@@ -227,6 +230,11 @@
     ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
 
     ("msp430-none-elf", msp430_none_elf),
+
+    ("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi),
+    ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf),
+    ("i686-unknown-cloudabi", i686_unknown_cloudabi),
+    ("x86_64-unknown-cloudabi", x86_64_unknown_cloudabi),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
@@ -360,7 +368,7 @@
     /// Whether the linker support GNU-like arguments such as -O. Defaults to false.
     pub linker_is_gnu: bool,
     /// The MinGW toolchain has a known issue that prevents it from correctly
-    /// handling COFF object files with more than 2^15 sections. Since each weak
+    /// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
     /// symbol needs its own COMDAT section, weak linkage implies a large
     /// number sections that easily exceeds the given limit for larger
     /// codebases. Consequently we want a way to disallow weak linkage on some
@@ -802,14 +810,12 @@
     pub fn search(target: &str) -> Result<Target, String> {
         use std::env;
         use std::ffi::OsString;
-        use std::fs::File;
+        use std::fs;
         use std::path::{Path, PathBuf};
         use serialize::json;
 
         fn load_file(path: &Path) -> Result<Target, String> {
-            let mut f = File::open(path).map_err(|e| e.to_string())?;
-            let mut contents = Vec::new();
-            f.read_to_end(&mut contents).map_err(|e| e.to_string())?;
+            let contents = fs::read(path).map_err(|e| e.to_string())?;
             let obj = json::from_reader(&mut &contents[..])
                            .map_err(|e| e.to_string())?;
             Target::from_json(obj)
diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs
index e6aa745..cc40b8b 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_back/target/windows_base.rs
@@ -59,6 +59,15 @@
         "-lmingw32".to_string(),
         "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
         "-lmsvcrt".to_string(),
+        // mingw's msvcrt is a weird hybrid import library and static library.
+        // And it seems that the linker fails to use import symbols from msvcrt
+        // that are required from functions in msvcrt in certain cases. For example
+        // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
+        // Listing the library twice seems to fix that, and seems to also be done
+        // by mingw's gcc (Though not sure if it's done on purpose, or by mistake).
+        //
+        // See https://github.com/rust-lang/rust/pull/47483
+        "-lmsvcrt".to_string(),
         "-luser32".to_string(),
         "-lkernel32".to_string(),
     ]);
diff --git a/src/librustc_back/target/x86_64_unknown_cloudabi.rs b/src/librustc_back/target/x86_64_unknown_cloudabi.rs
new file mode 100644
index 0000000..1ce3c64
--- /dev/null
+++ b/src/librustc_back/target/x86_64_unknown_cloudabi.rs
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::cloudabi_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.max_atomic_width = Some(64);
+    base.linker = "x86_64-unknown-cloudabi-cc".to_string();
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+    base.stack_probes = true;
+
+    Ok(Target {
+        llvm_target: "x86_64-unknown-cloudabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "cloudabi".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_borrowck/Cargo.toml b/src/librustc_borrowck/Cargo.toml
index 25f0253..8522fe1 100644
--- a/src/librustc_borrowck/Cargo.toml
+++ b/src/librustc_borrowck/Cargo.toml
@@ -10,7 +10,7 @@
 test = false
 
 [dependencies]
-log = "0.3"
+log = "0.4"
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 graphviz = { path = "../libgraphviz" }
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 9087376..862ea0c 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -25,7 +25,7 @@
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
 use rustc::middle::region;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, TyCtxt, RegionKind};
 use syntax::ast;
 use syntax_pos::Span;
 use rustc::hir;
@@ -92,6 +92,7 @@
     move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
     all_loans: &'a [Loan<'tcx>],
     param_env: ty::ParamEnv<'tcx>,
+    movable_generator: bool,
 }
 
 impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
@@ -147,6 +148,8 @@
         }
 
         self.check_for_conflicting_loans(hir_id.local_id);
+
+        self.check_for_loans_across_yields(cmt, loan_region, borrow_span);
     }
 
     fn mutate(&mut self,
@@ -198,6 +201,16 @@
     debug!("check_loans(body id={})", body.value.id);
 
     let def_id = bccx.tcx.hir.body_owner_def_id(body.id());
+
+    let node_id = bccx.tcx.hir.as_local_node_id(def_id).unwrap();
+    let movable_generator = !match bccx.tcx.hir.get(node_id) {
+        hir::map::Node::NodeExpr(&hir::Expr {
+            node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)),
+            ..
+        }) => true,
+        _ => false,
+    };
+
     let param_env = bccx.tcx.param_env(def_id);
     let mut clcx = CheckLoanCtxt {
         bccx,
@@ -205,6 +218,7 @@
         move_data,
         all_loans,
         param_env,
+        movable_generator,
     };
     let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
     euv::ExprUseVisitor::new(&mut clcx,
@@ -348,6 +362,99 @@
         return result;
     }
 
+    pub fn check_for_loans_across_yields(&self,
+                                         cmt: mc::cmt<'tcx>,
+                                         loan_region: ty::Region<'tcx>,
+                                         borrow_span: Span) {
+        pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt<'tcx>) -> bool {
+            match cmt.cat {
+                // Borrows of static items is allowed
+                Categorization::StaticItem => false,
+                // Reborrow of already borrowed data is ignored
+                // Any errors will be caught on the initial borrow
+                Categorization::Deref(..) => false,
+
+                // By-ref upvars has Derefs so they will get ignored.
+                // Generators counts as FnOnce so this leaves only
+                // by-move upvars, which is local data for generators
+                Categorization::Upvar(..) => true,
+
+                Categorization::Rvalue(region) => {
+                    // Rvalues promoted to 'static are no longer local
+                    if let RegionKind::ReStatic = *region {
+                        false
+                    } else {
+                        true
+                    }
+                }
+
+                // Borrow of local data must be checked
+                Categorization::Local(..) => true,
+
+                // For interior references and downcasts, find out if the base is local
+                Categorization::Downcast(ref cmt_base, _) |
+                Categorization::Interior(ref cmt_base, _) => borrow_of_local_data(&cmt_base),
+            }
+        }
+
+        if !self.movable_generator {
+            return;
+        }
+
+        if !borrow_of_local_data(&cmt) {
+            return;
+        }
+
+        let scope = match *loan_region {
+            // A concrete region in which we will look for a yield expression
+            RegionKind::ReScope(scope) => scope,
+
+            // There cannot be yields inside an empty region
+            RegionKind::ReEmpty => return,
+
+            // Local data cannot have these lifetimes
+            RegionKind::ReEarlyBound(..) |
+            RegionKind::ReLateBound(..) |
+            RegionKind::ReFree(..) |
+            RegionKind::ReStatic => {
+                self.bccx
+                    .tcx
+                    .sess.delay_span_bug(borrow_span,
+                                         &format!("unexpected region for local data {:?}",
+                                                  loan_region));
+                return
+            }
+
+            // These cannot exist in borrowck
+            RegionKind::ReVar(..) |
+            RegionKind::ReSkolemized(..) |
+            RegionKind::ReClosureBound(..) |
+            RegionKind::ReErased => span_bug!(borrow_span,
+                                              "unexpected region in borrowck {:?}",
+                                              loan_region),
+        };
+
+        let body_id = self.bccx.body.value.hir_id.local_id;
+
+        if self.bccx.region_scope_tree.containing_body(scope) != Some(body_id) {
+            // We are borrowing local data longer than its storage.
+            // This should result in other borrowck errors.
+            self.bccx.tcx.sess.delay_span_bug(borrow_span,
+                                              "borrowing local data longer than its storage");
+            return;
+        }
+
+        if let Some(yield_span) = self.bccx
+                                      .region_scope_tree
+                                      .yield_in_scope_for_expr(scope,
+                                                               cmt.id,
+                                                               self.bccx.body) {
+            self.bccx.cannot_borrow_across_generator_yield(borrow_span,
+                                                           yield_span,
+                                                           Origin::Ast).emit();
+        }
+    }
+
     pub fn check_for_conflicting_loans(&self, node: hir::ItemLocalId) {
         //! Checks to see whether any of the loans that are issued
         //! on entrance to `node` conflict with loans that have already been
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index bc01f22..5cfbe49 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -107,7 +107,7 @@
                     ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
                         RestrictionResult::Safe => RestrictionResult::Safe,
                         RestrictionResult::SafeIf(base_lp, mut base_vec) => {
-                            for field in &adt_def.struct_variant().fields {
+                            for field in &adt_def.non_enum_variant().fields {
                                 let field = InteriorKind::InteriorField(mc::NamedField(field.name));
                                 let field_ty = if field == interior {
                                     cmt.ty
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index b124872..f755efc 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -346,6 +346,16 @@
     }
 
     fn to_type(&self) -> Ty<'tcx> { self.ty }
+
+    fn has_downcast(&self) -> bool {
+        match self.kind {
+            LpDowncast(_, _) => true,
+            LpExtend(ref lp, _, LpInterior(_, _)) => {
+                lp.has_downcast()
+            }
+            _ => false,
+        }
+    }
 }
 
 // FIXME (pnkfelix): See discussion here
@@ -484,54 +494,60 @@
     }
 }
 
-pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
-    //! Computes the `LoanPath` (if any) for a `cmt`.
-    //! Note that this logic is somewhat duplicated in
-    //! the method `compute()` found in `gather_loans::restrictions`,
-    //! which allows it to share common loan path pieces as it
-    //! traverses the CMT.
-
+// Avoid "cannot borrow immutable field `self.x` as mutable" as that implies that a field *can* be
+// mutable independently of the struct it belongs to. (#35937)
+pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option<Rc<LoanPath<'tcx>>>, bool) {
     let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
 
     match cmt.cat {
         Categorization::Rvalue(..) |
         Categorization::StaticItem => {
-            None
+            (None, false)
         }
 
         Categorization::Local(id) => {
-            Some(new_lp(LpVar(id)))
+            (Some(new_lp(LpVar(id))), false)
         }
 
         Categorization::Upvar(mc::Upvar { id, .. }) => {
-            Some(new_lp(LpUpvar(id)))
+            (Some(new_lp(LpUpvar(id))), false)
         }
 
         Categorization::Deref(ref cmt_base, pk) => {
-            opt_loan_path(cmt_base).map(|lp| {
+            let lp = opt_loan_path_is_field(cmt_base);
+            (lp.0.map(|lp| {
                 new_lp(LpExtend(lp, cmt.mutbl, LpDeref(pk)))
-            })
+            }), lp.1)
         }
 
         Categorization::Interior(ref cmt_base, ik) => {
-            opt_loan_path(cmt_base).map(|lp| {
+            (opt_loan_path(cmt_base).map(|lp| {
                 let opt_variant_id = match cmt_base.cat {
                     Categorization::Downcast(_, did) =>  Some(did),
                     _ => None
                 };
                 new_lp(LpExtend(lp, cmt.mutbl, LpInterior(opt_variant_id, ik.cleaned())))
-            })
+            }), true)
         }
 
-        Categorization::Downcast(ref cmt_base, variant_def_id) =>
-            opt_loan_path(cmt_base)
-            .map(|lp| {
+        Categorization::Downcast(ref cmt_base, variant_def_id) => {
+            let lp = opt_loan_path_is_field(cmt_base);
+            (lp.0.map(|lp| {
                 new_lp(LpDowncast(lp, variant_def_id))
-            }),
-
+            }), lp.1)
+        }
     }
 }
 
+/// Computes the `LoanPath` (if any) for a `cmt`.
+/// Note that this logic is somewhat duplicated in
+/// the method `compute()` found in `gather_loans::restrictions`,
+/// which allows it to share common loan path pieces as it
+/// traverses the CMT.
+pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
+    opt_loan_path_is_field(cmt).0
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Errors
 
@@ -715,16 +731,20 @@
                          move_note));
             err
         } else {
-            err.span_label(use_span, format!("value {} here after move", verb_participle))
-               .span_label(move_span, format!("value moved{} here", move_note));
+            err.span_label(use_span, format!("value {} here after move", verb_participle));
+            err.span_label(move_span, format!("value moved{} here", move_note));
             err
         };
 
         if need_note {
-            err.note(&format!("move occurs because `{}` has type `{}`, \
-                               which does not implement the `Copy` trait",
-                              self.loan_path_to_string(moved_lp),
-                              moved_lp.ty));
+            err.note(&format!(
+                "move occurs because {} has type `{}`, which does not implement the `Copy` trait",
+                if moved_lp.has_downcast() {
+                    "the value".to_string()
+                } else {
+                    format!("`{}`", self.loan_path_to_string(moved_lp))
+                },
+                moved_lp.ty));
         }
 
         // Note: we used to suggest adding a `ref binding` or calling
@@ -752,11 +772,12 @@
                                                 &move_data::Assignment) {
         let mut err = self.cannot_reassign_immutable(span,
                                                      &self.loan_path_to_string(lp),
+                                                     false,
                                                      Origin::Ast);
         err.span_label(span, "cannot assign twice to immutable variable");
         if span != assign.span {
             err.span_label(assign.span, format!("first assignment to `{}`",
-                                              self.loan_path_to_string(lp)));
+                                                self.loan_path_to_string(lp)));
         }
         err.emit();
     }
@@ -787,14 +808,26 @@
                     mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => {
                         self.cmt_to_string(&err.cmt)
                     }
-                    _ => match opt_loan_path(&err.cmt) {
-                        None => {
+                    _ => match opt_loan_path_is_field(&err.cmt) {
+                        (None, true) => {
+                            format!("{} of {} binding",
+                                    self.cmt_to_string(&err.cmt),
+                                    err.cmt.mutbl.to_user_str())
+
+                        }
+                        (None, false) => {
                             format!("{} {}",
                                     err.cmt.mutbl.to_user_str(),
                                     self.cmt_to_string(&err.cmt))
 
                         }
-                        Some(lp) => {
+                        (Some(lp), true) => {
+                            format!("{} `{}` of {} binding",
+                                    self.cmt_to_string(&err.cmt),
+                                    self.loan_path_to_string(&lp),
+                                    err.cmt.mutbl.to_user_str())
+                        }
+                        (Some(lp), false) => {
                             format!("{} {} `{}`",
                                     err.cmt.mutbl.to_user_str(),
                                     self.cmt_to_string(&err.cmt),
@@ -809,10 +842,32 @@
                         if let mc::NoteClosureEnv(upvar_id) = err.cmt.note {
                             let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
                             let sp = self.tcx.hir.span(node_id);
-                            match self.tcx.sess.codemap().span_to_snippet(sp) {
-                                Ok(snippet) => {
+                            let fn_closure_msg = "`Fn` closures cannot capture their enclosing \
+                                                  environment for modifications";
+                            match (self.tcx.sess.codemap().span_to_snippet(sp), &err.cmt.cat) {
+                                (_, &Categorization::Upvar(mc::Upvar {
+                                    kind: ty::ClosureKind::Fn, ..
+                                })) => {
+                                    db.note(fn_closure_msg);
+                                    // we should point at the cause for this closure being
+                                    // identified as `Fn` (like in signature of method this
+                                    // closure was passed into)
+                                }
+                                (Ok(ref snippet), ref cat) => {
                                     let msg = &format!("consider making `{}` mutable", snippet);
-                                    db.span_suggestion(sp, msg, format!("mut {}", snippet));
+                                    let suggestion = format!("mut {}", snippet);
+
+                                    if let &Categorization::Deref(ref cmt, _) = cat {
+                                        if let Categorization::Upvar(mc::Upvar {
+                                            kind: ty::ClosureKind::Fn, ..
+                                        }) = cmt.cat {
+                                            db.note(fn_closure_msg);
+                                        } else {
+                                            db.span_suggestion(sp, msg, suggestion);
+                                        }
+                                    } else {
+                                        db.span_suggestion(sp, msg, suggestion);
+                                    }
                                 }
                                 _ => {
                                     db.span_help(sp, "consider making this binding mutable");
@@ -851,73 +906,6 @@
                     }
                 };
 
-                // When you have a borrow that lives across a yield,
-                // that reference winds up captured in the generator
-                // type. Regionck then constraints it to live as long
-                // as the generator itself. If that borrow is borrowing
-                // data owned by the generator, this winds up resulting in
-                // an `err_out_of_scope` error:
-                //
-                // ```
-                // {
-                //     let g = || {
-                //         let a = &3; // this borrow is forced to ... -+
-                //         yield ();          //                        |
-                //         println!("{}", a); //                        |
-                //     };                     //                        |
-                // } <----------------------... live until here --------+
-                // ```
-                //
-                // To detect this case, we look for cases where the
-                // `super_scope` (lifetime of the value) is within the
-                // body, but the `sub_scope` is not.
-                debug!("err_out_of_scope: self.body.is_generator = {:?}",
-                       self.body.is_generator);
-                let maybe_borrow_across_yield = if self.body.is_generator {
-                    let body_scope = region::Scope::Node(self.body.value.hir_id.local_id);
-                    debug!("err_out_of_scope: body_scope = {:?}", body_scope);
-                    debug!("err_out_of_scope: super_scope = {:?}", super_scope);
-                    debug!("err_out_of_scope: sub_scope = {:?}", sub_scope);
-                    match (super_scope, sub_scope) {
-                        (&ty::RegionKind::ReScope(value_scope),
-                         &ty::RegionKind::ReScope(loan_scope)) => {
-                            if {
-                                // value_scope <= body_scope &&
-                                self.region_scope_tree.is_subscope_of(value_scope, body_scope) &&
-                                    // body_scope <= loan_scope
-                                    self.region_scope_tree.is_subscope_of(body_scope, loan_scope)
-                            } {
-                                // We now know that this is a case
-                                // that fits the bill described above:
-                                // a borrow of something whose scope
-                                // is within the generator, but the
-                                // borrow is for a scope outside the
-                                // generator.
-                                //
-                                // Now look within the scope of the of
-                                // the value being borrowed (in the
-                                // example above, that would be the
-                                // block remainder that starts with
-                                // `let a`) for a yield. We can cite
-                                // that for the user.
-                                self.region_scope_tree.yield_in_scope(value_scope)
-                            } else {
-                                None
-                            }
-                        }
-                        _ => None,
-                    }
-                } else {
-                    None
-                };
-
-                if let Some((yield_span, _)) = maybe_borrow_across_yield {
-                    debug!("err_out_of_scope: opt_yield_span = {:?}", yield_span);
-                    self.cannot_borrow_across_generator_yield(error_span, yield_span, Origin::Ast)
-                        .emit();
-                    return;
-                }
-
                 let mut db = self.path_does_not_live_long_enough(error_span, &msg, Origin::Ast);
                 let value_kind = match err.cmt.cat {
                     mc::Categorization::Rvalue(..) => "temporary value",
@@ -1080,15 +1068,20 @@
         };
 
         match cause {
-            mc::AliasableStatic |
+            mc::AliasableStatic => {
+                // This happens when we have an `&mut` or assignment to a
+                // static. We should have already reported a mutability
+                // violation first, but may have continued compiling.
+                self.tcx.sess.delay_span_bug(
+                    span,
+                    &format!("aliasability violation for static `{}`", prefix)
+                );
+                return;
+            }
             mc::AliasableStaticMut => {
-                // This path cannot occur. It happens when we have an
-                // `&mut` or assignment to a static. But in the case
-                // of `static X`, we get a mutability violation first,
-                // and never get here. In the case of `static mut X`,
-                // that is unsafe and hence the aliasability error is
-                // ignored.
-                span_bug!(span, "aliasability violation for static `{}`", prefix)
+                // This path cannot occur. `static mut X` is not checked
+                // for aliasability violations.
+                span_bug!(span, "aliasability violation for static mut `{}`", prefix)
             }
             mc::AliasableBorrowed => {}
         };
@@ -1326,7 +1319,7 @@
                 } else if let Categorization::Interior(ref cmt, _) = err.cmt.cat {
                     if let mc::MutabilityCategory::McImmutable = cmt.mutbl {
                         db.span_label(*error_span,
-                                      "cannot mutably borrow immutable field");
+                                      "cannot mutably borrow field of immutable binding");
                     }
                 }
             }
@@ -1391,7 +1384,7 @@
             LpDowncast(ref lp_base, variant_def_id) => {
                 out.push('(');
                 self.append_autoderefd_loan_path_to_string(&lp_base, out);
-                out.push(':');
+                out.push_str(DOWNCAST_PRINTED_OPERATOR);
                 out.push_str(&self.tcx.item_path_str(variant_def_id));
                 out.push(')');
             }
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index 7915ecc..98de394 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -343,7 +343,7 @@
             if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
                     = (&base_lp.ty.sty, lp_elem) {
                 if adt_def.is_union() {
-                    for field in &adt_def.struct_variant().fields {
+                    for field in &adt_def.non_enum_variant().fields {
                         let field = InteriorKind::InteriorField(mc::NamedField(field.name));
                         if field != interior {
                             let sibling_lp_kind =
@@ -395,7 +395,7 @@
         if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
             if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
                 if adt_def.is_union() {
-                    for field in &adt_def.struct_variant().fields {
+                    for field in &adt_def.non_enum_variant().fields {
                         let field = InteriorKind::InteriorField(mc::NamedField(field.name));
                         let field_ty = if field == interior {
                             lp.ty
diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml
index e8d404a..53b8402 100644
--- a/src/librustc_const_eval/Cargo.toml
+++ b/src/librustc_const_eval/Cargo.toml
@@ -10,7 +10,7 @@
 
 [dependencies]
 arena = { path = "../libarena" }
-log = "0.3"
+log = "0.4"
 rustc = { path = "../librustc" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index 33d9bfa..a7c382e 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -561,19 +561,25 @@
 ///   (1) all_constructors will only return constructors that are statically
 ///       possible. eg. it will only return Ok for Result<T, !>
 ///
-/// Whether a vector `v` of patterns is 'useful' in relation to a set of such
-/// vectors `m` is defined as there being a set of inputs that will match `v`
-/// but not any of the sets in `m`.
+/// This finds whether a (row) vector `v` of patterns is 'useful' in relation
+/// to a set of such vectors `m` - this is defined as there being a set of
+/// inputs that will match `v` but not any of the sets in `m`.
+///
+/// All the patterns at each column of the `matrix ++ v` matrix must
+/// have the same type, except that wildcard (PatternKind::Wild) patterns
+/// with type TyErr are also allowed, even if the "type of the column"
+/// is not TyErr. That is used to represent private fields, as using their
+/// real type would assert that they are inhabited.
 ///
 /// This is used both for reachability checking (if a pattern isn't useful in
 /// relation to preceding patterns, it is not reachable) and exhaustiveness
 /// checking (if a wildcard pattern is useful in relation to a matrix, the
 /// matrix isn't exhaustive).
 pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
-                           matrix: &Matrix<'p, 'tcx>,
-                           v: &[&'p Pattern<'tcx>],
-                           witness: WitnessPreference)
-                           -> Usefulness<'tcx> {
+                                       matrix: &Matrix<'p, 'tcx>,
+                                       v: &[&'p Pattern<'tcx>],
+                                       witness: WitnessPreference)
+                                       -> Usefulness<'tcx> {
     let &Matrix(ref rows) = matrix;
     debug!("is_useful({:?}, {:?})", matrix, v);
 
@@ -596,6 +602,25 @@
     assert!(rows.iter().all(|r| r.len() == v.len()));
 
     let pcx = PatternContext {
+        // TyErr is used to represent the type of wildcard patterns matching
+        // against inaccessible (private) fields of structs, so that we won't
+        // be able to observe whether the types of the struct's fields are
+        // inhabited.
+        //
+        // If the field is truely inaccessible, then all the patterns
+        // matching against it must be wildcard patterns, so its type
+        // does not matter.
+        //
+        // However, if we are matching against non-wildcard patterns, we
+        // need to know the real type of the field so we can specialize
+        // against it. This primarily occurs through constants - they
+        // can include contents for fields that are inaccessible at the
+        // location of the match. In that case, the field's type is
+        // inhabited - by the constant - so we can just use it.
+        //
+        // FIXME: this might lead to "unstable" behavior with macro hygiene
+        // introducing uninhabited patterns for inaccessible fields. We
+        // need to figure out how to model that.
         ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error())
             .unwrap_or(v[0].ty),
         max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0])))
@@ -861,13 +886,13 @@
                     if is_visible {
                         field.ty(cx.tcx, substs)
                     } else {
-                        // Treat all non-visible fields as nil. They
+                        // Treat all non-visible fields as TyErr. They
                         // can't appear in any other pattern from
                         // this match (because they are private),
                         // so their type does not matter - but
                         // we don't want to know they are
                         // uninhabited.
-                        cx.tcx.mk_nil()
+                        cx.tcx.types.err
                     }
                 }).collect()
             }
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index e22f7f1..fd171b8 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -402,8 +402,8 @@
                             );
                             // if we had a catchall pattern, hint at that
                             if let Some(catchall) = catchall {
-                                err.span_label(pat.span, "this is an unreachable pattern");
-                                err.span_note(catchall, "this pattern matches any value");
+                                err.span_label(pat.span, "unreachable pattern");
+                                err.span_label(catchall, "matches any value");
                             }
                             err.emit();
                         },
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 81cd63b..418bd4b 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -133,8 +133,8 @@
                 (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
                     Some(I128(i128::min_value()))
                 },
-                (&LitKind::Int(n, _), &ty::TyInt(IntTy::Is)) |
-                (&LitKind::Int(n, Signed(IntTy::Is)), _) => {
+                (&LitKind::Int(n, _), &ty::TyInt(IntTy::Isize)) |
+                (&LitKind::Int(n, Signed(IntTy::Isize)), _) => {
                     match tcx.sess.target.isize_ty {
                         IntTy::I16 => if n == I16_OVERFLOW {
                             Some(Isize(Is16(i16::min_value())))
@@ -478,7 +478,7 @@
         ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i128 as i32))),
         ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i128 as i64))),
         ty::TyInt(ast::IntTy::I128) => Ok(Integral(I128(v as i128))),
-        ty::TyInt(ast::IntTy::Is) => {
+        ty::TyInt(ast::IntTy::Isize) => {
             Ok(Integral(Isize(ConstIsize::new_truncating(v as i128, tcx.sess.target.isize_ty))))
         },
         ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
@@ -486,7 +486,7 @@
         ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
         ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
         ty::TyUint(ast::UintTy::U128) => Ok(Integral(U128(v as u128))),
-        ty::TyUint(ast::UintTy::Us) => {
+        ty::TyUint(ast::UintTy::Usize) => {
             Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.usize_ty))))
         },
         ty::TyFloat(fty) => {
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 9d636b4..b4563f6 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -56,4 +56,5 @@
 }
 
 // Build the diagnostics array at the end so that the metadata includes error use sites.
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_const_eval, DIAGNOSTICS }
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index cfbb962..3cfa1d6 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -280,7 +280,8 @@
         let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
         let result = pcx.lower_pattern(pat);
         if !pcx.errors.is_empty() {
-            span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
+            let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
+            tcx.sess.delay_span_bug(pat.span, &msg);
         }
         debug!("Pattern::from_hir({:?}) = {:?}", pat, result);
         result
diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs
index 1e9c2ba..bd0a332 100644
--- a/src/librustc_const_math/err.rs
+++ b/src/librustc_const_math/err.rs
@@ -75,13 +75,13 @@
             ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32",
             ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64",
             ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128",
-            ULitOutOfRange(ast::UintTy::Us) => "literal out of range for usize",
+            ULitOutOfRange(ast::UintTy::Usize) => "literal out of range for usize",
             LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8",
             LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16",
             LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32",
             LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64",
             LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128",
-            LitOutOfRange(ast::IntTy::Is) => "literal out of range for isize",
+            LitOutOfRange(ast::IntTy::Isize) => "literal out of range for isize",
         }
     }
 }
diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs
index 08473d7..4ec27d7 100644
--- a/src/librustc_const_math/int.rs
+++ b/src/librustc_const_math/int.rs
@@ -12,8 +12,8 @@
 use syntax::attr::IntType;
 use syntax::ast::{IntTy, UintTy};
 
-use super::is::*;
-use super::us::*;
+use super::isize::*;
+use super::usize::*;
 use super::err::*;
 
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
@@ -83,7 +83,7 @@
             UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)),
             UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)),
             UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)),
-            UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
+            UintTy::Usize if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
                 .map(Usize),
             UintTy::U128 => Some(U128(val)),
             _ => None
@@ -98,7 +98,7 @@
             IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)),
             IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)),
             IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)),
-            IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
+            IntTy::Isize if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
                 .map(Isize),
             IntTy::I128 => Some(I128(val)),
             _ => None
@@ -112,7 +112,7 @@
             UintTy::U16 => U16(val as u16),
             UintTy::U32 => U32(val as u32),
             UintTy::U64 => U64(val as u64),
-            UintTy::Us => Usize(ConstUsize::new_truncating(val, usize_ty)),
+            UintTy::Usize => Usize(ConstUsize::new_truncating(val, usize_ty)),
             UintTy::U128 => U128(val)
         }
     }
@@ -124,7 +124,7 @@
             IntTy::I16 => I16(val as i16),
             IntTy::I32 => I32(val as i32),
             IntTy::I64 => I64(val as i64),
-            IntTy::Is => Isize(ConstIsize::new_truncating(val, isize_ty)),
+            IntTy::Isize => Isize(ConstIsize::new_truncating(val, isize_ty)),
             IntTy::I128 => I128(val)
         }
     }
@@ -280,13 +280,13 @@
             ConstInt::I32(_) => IntType::SignedInt(IntTy::I32),
             ConstInt::I64(_) => IntType::SignedInt(IntTy::I64),
             ConstInt::I128(_) => IntType::SignedInt(IntTy::I128),
-            ConstInt::Isize(_) => IntType::SignedInt(IntTy::Is),
+            ConstInt::Isize(_) => IntType::SignedInt(IntTy::Isize),
             ConstInt::U8(_) => IntType::UnsignedInt(UintTy::U8),
             ConstInt::U16(_) => IntType::UnsignedInt(UintTy::U16),
             ConstInt::U32(_) => IntType::UnsignedInt(UintTy::U32),
             ConstInt::U64(_) => IntType::UnsignedInt(UintTy::U64),
             ConstInt::U128(_) => IntType::UnsignedInt(UintTy::U128),
-            ConstInt::Usize(_) => IntType::UnsignedInt(UintTy::Us),
+            ConstInt::Usize(_) => IntType::UnsignedInt(UintTy::Usize),
         }
     }
 }
diff --git a/src/librustc_const_math/is.rs b/src/librustc_const_math/isize.rs
similarity index 92%
rename from src/librustc_const_math/is.rs
rename to src/librustc_const_math/isize.rs
index 50dfb60..18acc78 100644
--- a/src/librustc_const_math/is.rs
+++ b/src/librustc_const_math/isize.rs
@@ -38,9 +38,9 @@
     pub fn new(i: i64, isize_ty: ast::IntTy) -> Result<Self, ConstMathErr> {
         match isize_ty {
             ast::IntTy::I16 if i as i16 as i64 == i => Ok(Is16(i as i16)),
-            ast::IntTy::I16 => Err(LitOutOfRange(ast::IntTy::Is)),
+            ast::IntTy::I16 => Err(LitOutOfRange(ast::IntTy::Isize)),
             ast::IntTy::I32 if i as i32 as i64 == i => Ok(Is32(i as i32)),
-            ast::IntTy::I32 => Err(LitOutOfRange(ast::IntTy::Is)),
+            ast::IntTy::I32 => Err(LitOutOfRange(ast::IntTy::Isize)),
             ast::IntTy::I64 => Ok(Is64(i)),
             _ => unreachable!(),
         }
diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs
index 095b8bb..2d98bc4 100644
--- a/src/librustc_const_math/lib.rs
+++ b/src/librustc_const_math/lib.rs
@@ -30,12 +30,12 @@
 
 mod float;
 mod int;
-mod us;
-mod is;
+mod usize;
+mod isize;
 mod err;
 
 pub use float::*;
 pub use int::*;
-pub use us::*;
-pub use is::*;
+pub use usize::*;
+pub use isize::*;
 pub use err::{ConstMathErr, Op};
diff --git a/src/librustc_const_math/us.rs b/src/librustc_const_math/usize.rs
similarity index 98%
rename from src/librustc_const_math/us.rs
rename to src/librustc_const_math/usize.rs
index 9876bc4..56995f0 100644
--- a/src/librustc_const_math/us.rs
+++ b/src/librustc_const_math/usize.rs
@@ -38,9 +38,9 @@
     pub fn new(i: u64, usize_ty: ast::UintTy) -> Result<Self, ConstMathErr> {
         match usize_ty {
             ast::UintTy::U16 if i as u16 as u64 == i => Ok(Us16(i as u16)),
-            ast::UintTy::U16 => Err(ULitOutOfRange(ast::UintTy::Us)),
+            ast::UintTy::U16 => Err(ULitOutOfRange(ast::UintTy::Usize)),
             ast::UintTy::U32 if i as u32 as u64 == i => Ok(Us32(i as u32)),
-            ast::UintTy::U32 => Err(ULitOutOfRange(ast::UintTy::Us)),
+            ast::UintTy::U32 => Err(ULitOutOfRange(ast::UintTy::Usize)),
             ast::UintTy::U64 => Ok(Us64(i)),
             _ => unreachable!(),
         }
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 82075ce..23e42f6 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -9,7 +9,7 @@
 crate-type = ["dylib"]
 
 [dependencies]
-log = "0.3"
+log = "0.4"
 serialize = { path = "../libserialize" }
 cfg-if = "0.1.2"
 stable_deref_trait = "1.0.0"
@@ -17,4 +17,4 @@
 
 [dependencies.parking_lot]
 version = "0.5"
-features = ["nightly"]
\ No newline at end of file
+features = ["nightly"]
diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs
index 1b39e02..511c407 100644
--- a/src/librustc_data_structures/array_vec.rs
+++ b/src/librustc_data_structures/array_vec.rs
@@ -12,7 +12,7 @@
 
 use std::marker::Unsize;
 use std::iter::Extend;
-use std::ptr::{self, drop_in_place, Shared};
+use std::ptr::{self, drop_in_place, NonNull};
 use std::ops::{Deref, DerefMut, Range};
 use std::hash::{Hash, Hasher};
 use std::slice;
@@ -138,7 +138,7 @@
             // Use the borrow in the IterMut to indicate borrowing behavior of the
             // whole Drain iterator (like &mut T).
             let range_slice = {
-                let arr = &mut self.values as &mut [ManuallyDrop<_>];
+                let arr = &mut self.values as &mut [ManuallyDrop<<A as Array>::Element>];
                 slice::from_raw_parts_mut(arr.as_mut_ptr().offset(start as isize),
                                           end - start)
             };
@@ -146,7 +146,7 @@
                 tail_start: end,
                 tail_len: len - end,
                 iter: range_slice.iter(),
-                array_vec: Shared::from(self),
+                array_vec: NonNull::from(self),
             }
         }
     }
@@ -232,7 +232,7 @@
     tail_start: usize,
     tail_len: usize,
     iter: slice::Iter<'a, ManuallyDrop<A::Element>>,
-    array_vec: Shared<ArrayVec<A>>,
+    array_vec: NonNull<ArrayVec<A>>,
 }
 
 impl<'a, A: Array> Iterator for Drain<'a, A> {
@@ -255,12 +255,13 @@
 
         if self.tail_len > 0 {
             unsafe {
-                let source_array_vec = self.array_vec.as_mut();
+                let source_array_vec: &mut ArrayVec<A> = self.array_vec.as_mut();
                 // memmove back untouched tail, update to new length
                 let start = source_array_vec.len();
                 let tail = self.tail_start;
                 {
-                    let arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>];
+                    let arr =
+                        &mut source_array_vec.values as &mut [ManuallyDrop<<A as Array>::Element>];
                     let src = arr.as_ptr().offset(tail as isize);
                     let dst = arr.as_mut_ptr().offset(start as isize);
                     ptr::copy(src, dst, self.tail_len);
diff --git a/src/librustc_data_structures/base_n.rs b/src/librustc_data_structures/base_n.rs
index cf54229..d333b63 100644
--- a/src/librustc_data_structures/base_n.rs
+++ b/src/librustc_data_structures/base_n.rs
@@ -13,18 +13,21 @@
 
 use std::str;
 
-pub const MAX_BASE: u64 = 64;
-pub const ALPHANUMERIC_ONLY: u64 = 62;
+pub const MAX_BASE: usize = 64;
+pub const ALPHANUMERIC_ONLY: usize = 62;
+pub const CASE_INSENSITIVE: usize = 36;
 
 const BASE_64: &'static [u8; MAX_BASE as usize] =
     b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
 
 #[inline]
-pub fn push_str(mut n: u64, base: u64, output: &mut String) {
+pub fn push_str(mut n: u128, base: usize, output: &mut String) {
     debug_assert!(base >= 2 && base <= MAX_BASE);
-    let mut s = [0u8; 64];
+    let mut s = [0u8; 128];
     let mut index = 0;
 
+    let base = base as u128;
+
     loop {
         s[index] = BASE_64[(n % base) as usize];
         index += 1;
@@ -39,16 +42,16 @@
 }
 
 #[inline]
-pub fn encode(n: u64, base: u64) -> String {
-    let mut s = String::with_capacity(13);
+pub fn encode(n: u128, base: usize) -> String {
+    let mut s = String::new();
     push_str(n, base, &mut s);
     s
 }
 
 #[test]
 fn test_encode() {
-    fn test(n: u64, base: u64) {
-        assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base), base as u32));
+    fn test(n: u128, base: usize) {
+        assert_eq!(Ok(n), u128::from_str_radix(&encode(n, base), base as u32));
     }
 
     for base in 2..37 {
@@ -57,7 +60,8 @@
         test(35, base);
         test(36, base);
         test(37, base);
-        test(u64::max_value(), base);
+        test(u64::max_value() as u128, base);
+        test(u128::max_value(), base);
 
         for i in 0 .. 1_000 {
             test(i * 983, base);
diff --git a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs
index 9067051..dc487f1 100644
--- a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs
+++ b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs
@@ -12,7 +12,7 @@
 //! A Simple, Fast Dominance Algorithm.
 //! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
 //! Rice Computer Science TS-06-33870
-//! https://www.cs.rice.edu/~keith/EMBED/dom.pdf
+//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>
 
 use super::ControlFlowGraph;
 use super::iterate::reverse_post_order;
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 24048e6..a35ef2f 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -21,7 +21,6 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(shared)]
 #![feature(collections_range)]
 #![feature(nonzero)]
 #![feature(unboxed_closures)]
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 04c0f9b..4f7bbd7 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -11,7 +11,7 @@
 [dependencies]
 arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
-log = { version = "0.3", features = ["release_max_level_info"] }
+log = { version = "0.4", features = ["release_max_level_info"] }
 env_logger = { version = "0.4", default-features = false }
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
diff --git a/src/librustc_driver/README.md b/src/librustc_driver/README.md
index 5331a05..839d183 100644
--- a/src/librustc_driver/README.md
+++ b/src/librustc_driver/README.md
@@ -3,7 +3,7 @@
 [the README.md file found in `librustc`](../librustc/README.md).
 
 The `driver` crate is effectively the "main" function for the rust
-compiler.  It orchstrates the compilation process and "knits together"
+compiler.  It orchestrates the compilation process and "knits together"
 the code from the other crates within rustc. This crate itself does
 not contain any of the "main logic" of the compiler (though it does
 have some code related to pretty printing or other minor compiler
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index c0bbab3..e97d83e 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -28,19 +28,17 @@
 use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
 use rustc_incremental;
-use rustc_resolve::{MakeGlobMap, Resolver};
+use rustc_resolve::{MakeGlobMap, Resolver, ResolverArenas};
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::{self, CStore};
-use rustc_trans as trans;
 use rustc_trans_utils::trans_crate::TransCrate;
 use rustc_typeck as typeck;
 use rustc_privacy;
 use rustc_plugin::registry::Registry;
 use rustc_plugin as plugin;
-use rustc_passes::{self, ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
+use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats};
 use rustc_const_eval::{self, check_match};
 use super::Compilation;
-use ::DefaultTransCrate;
 
 use serialize::json;
 
@@ -53,14 +51,12 @@
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
 use std::sync::mpsc;
-use syntax::{ast, diagnostics, visit};
-use syntax::attr;
+use syntax::{self, ast, attr, diagnostics, visit};
 use syntax::ext::base::ExtCtxt;
 use syntax::fold::Folder;
 use syntax::parse::{self, PResult};
 use syntax::util::node_count::NodeCounter;
 use syntax_pos::FileName;
-use syntax;
 use syntax_ext;
 
 use derive_registrar;
@@ -68,7 +64,8 @@
 
 use profile;
 
-pub fn compile_input(sess: &Session,
+pub fn compile_input(trans: Box<TransCrate>,
+                     sess: &Session,
                      cstore: &CStore,
                      input_path: &Option<PathBuf>,
                      input: &Input,
@@ -76,8 +73,6 @@
                      output: &Option<PathBuf>,
                      addl_plugins: Option<Vec<String>>,
                      control: &CompileController) -> CompileResult {
-    use rustc::session::config::CrateType;
-
     macro_rules! controller_entry_point {
         ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
             let state = &mut $make_state;
@@ -94,22 +89,6 @@
         }}
     }
 
-    if cfg!(not(feature="llvm")) {
-        for cty in sess.opts.crate_types.iter() {
-            match *cty {
-                CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
-                CrateType::CrateTypeExecutable => {},
-                _ => {
-                    sess.parse_sess.span_diagnostic.warn(
-                        &format!("LLVM unsupported, so output type {} is not supported", cty)
-                    );
-                },
-            }
-        }
-
-        sess.abort_if_errors();
-    }
-
     if sess.profile_queries() {
         profile::begin();
     }
@@ -117,7 +96,7 @@
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let (outputs, trans, dep_graph) = {
+    let (outputs, ongoing_trans, dep_graph) = {
         let krate = match phase_1_parse_input(control, sess, input) {
             Ok(krate) => krate,
             Err(mut parse_error) => {
@@ -158,6 +137,7 @@
 
         let crate_name =
             ::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
+
         let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
             phase_2_configure_and_expand(
                 sess,
@@ -191,7 +171,7 @@
                            || hir_map::map_crate(sess, cstore, &mut hir_forest, &defs));
 
         {
-            let _ignore = hir_map.dep_graph.in_ignore();
+            hir_map.dep_graph.assert_ignored();
             controller_entry_point!(after_hir_lowering,
                                     sess,
                                     CompileState::state_after_hir_lowering(input,
@@ -210,10 +190,6 @@
                                     Ok(()));
         }
 
-        time(sess.time_passes(), "attribute checking", || {
-            hir::check_attr::check_crate(sess, &expanded_crate);
-        });
-
         let opt_crate = if control.keep_ast {
             Some(&expanded_crate)
         } else {
@@ -221,7 +197,8 @@
             None
         };
 
-        phase_3_run_analysis_passes(control,
+        phase_3_run_analysis_passes(&*trans,
+                                    control,
                                     sess,
                                     cstore,
                                     hir_map,
@@ -233,18 +210,18 @@
                                     |tcx, analysis, rx, result| {
             {
                 // Eventually, we will want to track plugins.
-                let _ignore = tcx.dep_graph.in_ignore();
-
-                let mut state = CompileState::state_after_analysis(input,
-                                                                   sess,
-                                                                   outdir,
-                                                                   output,
-                                                                   opt_crate,
-                                                                   tcx.hir.krate(),
-                                                                   &analysis,
-                                                                   tcx,
-                                                                   &crate_name);
-                (control.after_analysis.callback)(&mut state);
+                tcx.dep_graph.with_ignore(|| {
+                    let mut state = CompileState::state_after_analysis(input,
+                                                                       sess,
+                                                                       outdir,
+                                                                       output,
+                                                                       opt_crate,
+                                                                       tcx.hir.krate(),
+                                                                       &analysis,
+                                                                       tcx,
+                                                                       &crate_name);
+                    (control.after_analysis.callback)(&mut state);
+                });
 
                 if control.after_analysis.stop == Compilation::Stop {
                     return result.and_then(|_| Err(CompileIncomplete::Stopped));
@@ -253,14 +230,14 @@
 
             result?;
 
-            if log_enabled!(::log::LogLevel::Info) {
+            if log_enabled!(::log::Level::Info) {
                 println!("Pre-trans");
                 tcx.print_debug_stats();
             }
 
-            let trans = phase_4_translate_to_llvm::<DefaultTransCrate>(tcx, rx);
+            let ongoing_trans = phase_4_translate_to_llvm(&*trans, tcx, rx);
 
-            if log_enabled!(::log::LogLevel::Info) {
+            if log_enabled!(::log::Level::Info) {
                 println!("Post-trans");
                 tcx.print_debug_stats();
             }
@@ -272,7 +249,7 @@
                 }
             }
 
-            Ok((outputs.clone(), trans, tcx.dep_graph.clone()))
+            Ok((outputs.clone(), ongoing_trans, tcx.dep_graph.clone()))
         })??
     };
 
@@ -280,25 +257,7 @@
         sess.code_stats.borrow().print_type_sizes();
     }
 
-    let (phase5_result, trans) =
-        phase_5_run_llvm_passes::<DefaultTransCrate>(sess, &dep_graph, trans);
-
-    controller_entry_point!(after_llvm,
-                            sess,
-                            CompileState::state_after_llvm(input, sess, outdir, output, &trans),
-                            phase5_result);
-    phase5_result?;
-
-    // Run the linker on any artifacts that resulted from the LLVM run.
-    // This should produce either a finished executable or library.
-    time(sess.time_passes(), "linking", || {
-        DefaultTransCrate::link_binary(sess, &trans, &outputs)
-    });
-
-    // Now that we won't touch anything in the incremental compilation directory
-    // any more, we can finalize it (which involves renaming it)
-    #[cfg(feature="llvm")]
-    rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
+    trans.join_trans_and_link(ongoing_trans, sess, &dep_graph, &outputs)?;
 
     if sess.opts.debugging_opts.perf_stats {
         sess.print_perf_stats();
@@ -314,10 +273,6 @@
     Ok(())
 }
 
-fn keep_hygiene_data(sess: &Session) -> bool {
-    sess.opts.debugging_opts.keep_hygiene_data
-}
-
 pub fn source_name(input: &Input) -> FileName {
     match *input {
         Input::File(ref ifile) => ifile.clone().into(),
@@ -344,7 +299,6 @@
     pub after_expand: PhaseController<'a>,
     pub after_hir_lowering: PhaseController<'a>,
     pub after_analysis: PhaseController<'a>,
-    pub after_llvm: PhaseController<'a>,
     pub compilation_done: PhaseController<'a>,
 
     // FIXME we probably want to group the below options together and offer a
@@ -370,7 +324,6 @@
             after_expand: PhaseController::basic(),
             after_hir_lowering: PhaseController::basic(),
             after_analysis: PhaseController::basic(),
-            after_llvm: PhaseController::basic(),
             compilation_done: PhaseController::basic(),
             make_glob_map: MakeGlobMap::No,
             keep_ast: false,
@@ -419,7 +372,6 @@
     pub resolutions: Option<&'a Resolutions>,
     pub analysis: Option<&'a ty::CrateAnalysis>,
     pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
-    pub trans: Option<&'a trans::CrateTranslation>,
 }
 
 impl<'a, 'tcx> CompileState<'a, 'tcx> {
@@ -444,7 +396,6 @@
             resolutions: None,
             analysis: None,
             tcx: None,
-            trans: None,
         }
     }
 
@@ -532,19 +483,6 @@
         }
     }
 
-    fn state_after_llvm(input: &'a Input,
-                        session: &'tcx Session,
-                        out_dir: &'a Option<PathBuf>,
-                        out_file: &'a Option<PathBuf>,
-                        trans: &'a trans::CrateTranslation)
-                        -> Self {
-        CompileState {
-            trans: Some(trans),
-            out_file: out_file.as_ref().map(|s| &**s),
-            ..CompileState::empty(input, session, out_dir)
-        }
-    }
-
     fn state_when_compilation_done(input: &'a Input,
                                    session: &'tcx Session,
                                    out_dir: &'a Option<PathBuf>,
@@ -619,6 +557,12 @@
     pub hir_forest: hir_map::Forest,
 }
 
+pub struct InnerExpansionResult<'a> {
+    pub expanded_crate: ast::Crate,
+    pub resolver: Resolver<'a>,
+    pub hir_forest: hir_map::Forest,
+}
+
 /// Run the "early phases" of the compiler: initial `cfg` processing,
 /// loading compiler plugins (including those from `addl_plugins`),
 /// syntax expansion, secondary `cfg` expansion, synthesis of a test
@@ -635,6 +579,55 @@
                                        make_glob_map: MakeGlobMap,
                                        after_expand: F)
                                        -> Result<ExpansionResult, CompileIncomplete>
+    where F: FnOnce(&ast::Crate) -> CompileResult {
+    // Currently, we ignore the name resolution data structures for the purposes of dependency
+    // tracking. Instead we will run name resolution and include its output in the hash of each
+    // item, much like we do for macro expansion. In other words, the hash reflects not just
+    // its contents but the results of name resolution on those contents. Hopefully we'll push
+    // this back at some point.
+    let mut crate_loader = CrateLoader::new(sess, &cstore, &crate_name);
+    let resolver_arenas = Resolver::arenas();
+    let result = phase_2_configure_and_expand_inner(sess, cstore, krate, registry, crate_name,
+                                                    addl_plugins, make_glob_map, &resolver_arenas,
+                                                    &mut crate_loader, after_expand);
+    match result {
+        Ok(InnerExpansionResult {expanded_crate, resolver, hir_forest}) => {
+            Ok(ExpansionResult {
+                expanded_crate,
+                defs: resolver.definitions,
+                hir_forest,
+                resolutions: Resolutions {
+                    freevars: resolver.freevars,
+                    export_map: resolver.export_map,
+                    trait_map: resolver.trait_map,
+                    maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
+                    maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
+                },
+
+                analysis: ty::CrateAnalysis {
+                    access_levels: Rc::new(AccessLevels::default()),
+                    name: crate_name.to_string(),
+                    glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
+                },
+            })
+        }
+        Err(x) => Err(x)
+    }
+}
+
+/// Same as phase_2_configure_and_expand, but doesn't let you keep the resolver
+/// around
+pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
+                                       cstore: &'a CStore,
+                                       krate: ast::Crate,
+                                       registry: Option<Registry>,
+                                       crate_name: &str,
+                                       addl_plugins: Option<Vec<String>>,
+                                       make_glob_map: MakeGlobMap,
+                                       resolver_arenas: &'a ResolverArenas<'a>,
+                                       crate_loader: &'a mut CrateLoader,
+                                       after_expand: F)
+                                       -> Result<InnerExpansionResult<'a>, CompileIncomplete>
     where F: FnOnce(&ast::Crate) -> CompileResult,
 {
     let time_passes = sess.time_passes();
@@ -723,19 +716,12 @@
         return Err(CompileIncomplete::Stopped);
     }
 
-    // Currently, we ignore the name resolution data structures for the purposes of dependency
-    // tracking. Instead we will run name resolution and include its output in the hash of each
-    // item, much like we do for macro expansion. In other words, the hash reflects not just
-    // its contents but the results of name resolution on those contents. Hopefully we'll push
-    // this back at some point.
-    let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name);
-    let resolver_arenas = Resolver::arenas();
     let mut resolver = Resolver::new(sess,
                                      cstore,
                                      &krate,
                                      crate_name,
                                      make_glob_map,
-                                     &mut crate_loader,
+                                     crate_loader,
                                      &resolver_arenas);
     resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives;
     syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote);
@@ -857,10 +843,6 @@
     }
 
     time(time_passes,
-         "checking for inline asm in case the target doesn't support it",
-         || no_asm::check_crate(sess, &krate));
-
-    time(time_passes,
          "AST validation",
          || ast_validation::check_crate(sess, &krate));
 
@@ -889,10 +871,11 @@
     let dep_graph = match future_dep_graph {
         None => DepGraph::new_disabled(),
         Some(future) => {
-            let prev_graph = future
-                .open()
-                .expect("Could not join with background dep_graph thread")
-                .open(sess);
+            let prev_graph = time(time_passes, "blocked while dep-graph loading finishes", || {
+                future.open()
+                      .expect("Could not join with background dep_graph thread")
+                      .open(sess)
+            });
             DepGraph::new(prev_graph)
         }
     };
@@ -911,25 +894,13 @@
          || lint::check_ast_crate(sess, &krate));
 
     // Discard hygiene data, which isn't required after lowering to HIR.
-    if !keep_hygiene_data(sess) {
+    if !sess.opts.debugging_opts.keep_hygiene_data {
         syntax::ext::hygiene::clear_markings();
     }
 
-    Ok(ExpansionResult {
+    Ok(InnerExpansionResult {
         expanded_crate: krate,
-        defs: resolver.definitions,
-        analysis: ty::CrateAnalysis {
-            access_levels: Rc::new(AccessLevels::default()),
-            name: crate_name.to_string(),
-            glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
-        },
-        resolutions: Resolutions {
-            freevars: resolver.freevars,
-            export_map: resolver.export_map,
-            trait_map: resolver.trait_map,
-            maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
-            maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
-        },
+        resolver,
         hir_forest,
     })
 }
@@ -940,7 +911,6 @@
     reachable::provide(providers);
     resolve_lifetime::provide(providers);
     rustc_privacy::provide(providers);
-    DefaultTransCrate::provide(providers);
     typeck::provide(providers);
     ty::provide(providers);
     traits::provide(providers);
@@ -954,13 +924,13 @@
 
 pub fn default_provide_extern(providers: &mut ty::maps::Providers) {
     cstore::provide_extern(providers);
-    DefaultTransCrate::provide_extern(providers);
 }
 
 /// Run the resolution, typechecking, region checking and other
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
-pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
+pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
+                                               control: &CompileController,
                                                sess: &'tcx Session,
                                                cstore: &'tcx CrateStore,
                                                hir_map: hir_map::Map<'tcx>,
@@ -976,18 +946,6 @@
                             mpsc::Receiver<Box<Any + Send>>,
                             CompileResult) -> R
 {
-    macro_rules! try_with_f {
-        ($e: expr, ($($t:tt)*)) => {
-            match $e {
-                Ok(x) => x,
-                Err(x) => {
-                    f($($t)*, Err(x));
-                    return Err(x);
-                }
-            }
-        }
-    }
-
     let time_passes = sess.time_passes();
 
     let query_result_on_disk_cache = time(time_passes,
@@ -1013,10 +971,12 @@
 
     let mut local_providers = ty::maps::Providers::default();
     default_provide(&mut local_providers);
+    trans.provide(&mut local_providers);
     (control.provide)(&mut local_providers);
 
     let mut extern_providers = local_providers;
     default_provide_extern(&mut extern_providers);
+    trans.provide_extern(&mut extern_providers);
     (control.provide_extern)(&mut extern_providers);
 
     let (tx, rx) = mpsc::channel();
@@ -1037,12 +997,22 @@
         // tcx available.
         rustc_incremental::dep_graph_tcx_init(tcx);
 
+        time(sess.time_passes(), "attribute checking", || {
+            hir::check_attr::check_crate(tcx)
+        });
+
         time(time_passes,
              "stability checking",
              || stability::check_unstable_api_usage(tcx));
 
         // passes are timed inside typeck
-        try_with_f!(typeck::check_crate(tcx), (tcx, analysis, rx));
+        match typeck::check_crate(tcx) {
+            Ok(x) => x,
+            Err(x) => {
+                f(tcx, analysis, rx, Err(x));
+                return Err(x);
+            }
+        }
 
         time(time_passes,
              "const checking",
@@ -1104,9 +1074,10 @@
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
-pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn phase_4_translate_to_llvm<'a, 'tcx>(trans: &TransCrate,
+                                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            rx: mpsc::Receiver<Box<Any + Send>>)
-                                           -> <Trans as TransCrate>::OngoingCrateTranslation {
+                                           -> Box<Any> {
     let time_passes = tcx.sess.time_passes();
 
     time(time_passes,
@@ -1115,7 +1086,7 @@
 
     let translation =
         time(time_passes, "translation", move || {
-            Trans::trans_crate(tcx, rx)
+            trans.trans_crate(tcx, rx)
         });
     if tcx.sess.profile_queries() {
         profile::dump("profile_queries".to_string())
@@ -1124,25 +1095,6 @@
     translation
 }
 
-/// Run LLVM itself, producing a bitcode file, assembly file or object file
-/// as a side effect.
-pub fn phase_5_run_llvm_passes<Trans: TransCrate>(sess: &Session,
-                               dep_graph: &DepGraph,
-                               trans: <Trans as TransCrate>::OngoingCrateTranslation)
-                               -> (CompileResult, <Trans as TransCrate>::TranslatedCrate) {
-    let trans = Trans::join_trans(trans, sess, dep_graph);
-
-    if sess.opts.debugging_opts.incremental_info {
-        Trans::dump_incremental_data(&trans);
-    }
-
-    time(sess.time_passes(),
-         "serialize work products",
-         move || rustc_incremental::save_work_products(sess, dep_graph));
-
-    (sess.compile_status(), trans)
-}
-
 fn escape_dep_filename(filename: &FileName) -> String {
     // Apparently clang and gcc *only* escape spaces:
     // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
@@ -1165,6 +1117,9 @@
                     out_filenames.push(p);
                 }
             }
+            OutputType::DepInfo if sess.opts.debugging_opts.dep_info_omit_d_target => {
+                // Don't add the dep-info output when omitting it from dep-info targets
+            }
             _ => {
                 out_filenames.push(file);
             }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 5fa8236..04e9497 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -48,7 +48,7 @@
 extern crate rustc_resolve;
 extern crate rustc_save_analysis;
 #[cfg(feature="llvm")]
-extern crate rustc_trans;
+pub extern crate rustc_trans;
 extern crate rustc_trans_utils;
 extern crate rustc_typeck;
 extern crate serialize;
@@ -66,7 +66,7 @@
 use rustc_save_analysis::DumpHandler;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::CompileIncomplete;
-use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
+use rustc::session::config::{Input, PrintRequest, ErrorOutputType};
 use rustc::session::config::nightly_options;
 use rustc::session::{early_error, early_warn};
 use rustc::lint::Lint;
@@ -106,9 +106,32 @@
 pub mod profile;
 pub mod driver;
 pub mod pretty;
-pub mod target_features;
 mod derive_registrar;
 
+pub mod target_features {
+    use syntax::ast;
+    use syntax::symbol::Symbol;
+    use rustc::session::Session;
+    use rustc_trans_utils::trans_crate::TransCrate;
+
+    /// Add `target_feature = "..."` cfgs for a variety of platform
+    /// specific features (SSE, NEON etc.).
+    ///
+    /// This is performed by checking whether a whitelisted set of
+    /// features is available on the target machine, by querying LLVM.
+    pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session, trans: &TransCrate) {
+        let tf = Symbol::intern("target_feature");
+
+        for feat in trans.target_features(sess) {
+            cfg.insert((tf, Some(feat)));
+        }
+
+        if sess.crt_static_feature() {
+            cfg.insert((tf, Some(Symbol::intern("crt-static"))));
+        }
+    }
+}
+
 const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
                                       md#bug-reports";
 
@@ -159,26 +182,51 @@
 pub use rustc_trans::LlvmTransCrate as DefaultTransCrate;
 
 #[cfg(not(feature="llvm"))]
-mod rustc_trans {
-    use syntax_pos::symbol::Symbol;
-    use rustc::session::Session;
-    use rustc::session::config::PrintRequest;
+pub mod rustc_trans {
     pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate;
-    pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation;
 
-    pub fn init(_sess: &Session) {}
-    pub fn enable_llvm_debug() {}
     pub fn print_version() {}
     pub fn print_passes() {}
-    pub fn print(_req: PrintRequest, _sess: &Session) {}
-    pub fn target_features(_sess: &Session) -> Vec<Symbol> { vec![] }
+}
 
-    pub mod back {
-        pub mod write {
-            pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
-            pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
-            pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = [];
+fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box<TransCrate> {
+    use std::path::Path;
+    use rustc_metadata::dynamic_lib::DynamicLibrary;
+
+    match DynamicLibrary::open(Some(Path::new(backend_name))) {
+        Ok(lib) => {
+            unsafe {
+                let trans = {
+                    let __rustc_codegen_backend: unsafe fn(&Session) -> Box<TransCrate>;
+                    __rustc_codegen_backend = match lib.symbol("__rustc_codegen_backend") {
+                        Ok(f) => ::std::mem::transmute::<*mut u8, _>(f),
+                        Err(e) => sess.fatal(&format!("Couldnt load codegen backend as it\
+                        doesn't export the __rustc_backend_new symbol: {:?}", e)),
+                    };
+                    __rustc_codegen_backend(sess)
+                };
+                ::std::mem::forget(lib);
+                trans
+            }
         }
+        Err(err) => {
+            sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", backend_name, err));
+        }
+    }
+}
+
+pub fn get_trans(sess: &Session) -> Box<TransCrate> {
+    let trans_name = sess.opts.debugging_opts.codegen_backend.clone();
+    match trans_name.as_ref().map(|s|&**s) {
+        None => DefaultTransCrate::new(&sess),
+        Some("llvm") => rustc_trans::LlvmTransCrate::new(&sess),
+        Some("metadata_only") => {
+            rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
+        }
+        Some(filename) if filename.contains(".") => {
+            load_backend_from_dylib(&sess, &filename)
+        }
+        Some(trans_name) => sess.fatal(&format!("Unknown codegen backend {}", trans_name)),
     }
 }
 
@@ -205,10 +253,6 @@
 
     let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
 
-    if sopts.debugging_opts.debug_llvm {
-        rustc_trans::enable_llvm_debug();
-    }
-
     let descriptions = diagnostics_registry();
 
     do_or_return!(callbacks.early_callback(&matches,
@@ -227,30 +271,36 @@
         },
     };
 
-    let cstore = CStore::new(DefaultTransCrate::metadata_loader());
-
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
     let mut sess = session::build_session_with_codemap(
         sopts, input_file_path.clone(), descriptions, codemap, emitter_dest,
     );
-    rustc_trans::init(&sess);
+
+    let trans = get_trans(&sess);
+
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess, cfg);
-    target_features::add_configuration(&mut cfg, &sess);
+    target_features::add_configuration(&mut cfg, &sess, &*trans);
     sess.parse_sess.config = cfg;
 
-    do_or_return!(callbacks.late_callback(&matches,
+    let plugins = sess.opts.debugging_opts.extra_plugins.clone();
+
+    let cstore = CStore::new(trans.metadata_loader());
+
+    do_or_return!(callbacks.late_callback(&*trans,
+                                          &matches,
                                           &sess,
                                           &cstore,
                                           &input,
                                           &odir,
                                           &ofile), Some(sess));
 
-    let plugins = sess.opts.debugging_opts.extra_plugins.clone();
     let control = callbacks.build_controller(&sess, &matches);
-    (driver::compile_input(&sess,
+
+    (driver::compile_input(trans,
+                           &sess,
                            &cstore,
                            &input_file_path,
                            &input,
@@ -297,8 +347,9 @@
     } else {
         None
     };
-    if pretty.is_none() && sess.unstable_options() {
-        matches.opt_str("unpretty").map(|a| {
+
+    if pretty.is_none() {
+        sess.opts.debugging_opts.unpretty.as_ref().map(|a| {
             // extended with unstable pretty-print variants
             pretty::parse_pretty(sess, &a, true)
         })
@@ -343,6 +394,7 @@
     // be called just before actual compilation starts (and before build_controller
     // is called), after all arguments etc. have been completely handled.
     fn late_callback(&mut self,
+                     _: &TransCrate,
                      _: &getopts::Matches,
                      _: &Session,
                      _: &CrateStore,
@@ -522,13 +574,18 @@
                 let mut sess = build_session(sopts.clone(),
                     None,
                     descriptions.clone());
-                rustc_trans::init(&sess);
                 rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
                 let mut cfg = config::build_configuration(&sess, cfg.clone());
-                target_features::add_configuration(&mut cfg, &sess);
+                let trans = get_trans(&sess);
+                target_features::add_configuration(&mut cfg, &sess, &*trans);
                 sess.parse_sess.config = cfg;
-                let should_stop =
-                    RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile);
+                let should_stop = RustcDefaultCalls::print_crate_info(
+                    &*trans,
+                    &sess,
+                    None,
+                    odir,
+                    ofile
+                );
 
                 if should_stop == Compilation::Stop {
                     return None;
@@ -541,6 +598,7 @@
     }
 
     fn late_callback(&mut self,
+                     trans: &TransCrate,
                      matches: &getopts::Matches,
                      sess: &Session,
                      cstore: &CrateStore,
@@ -548,7 +606,7 @@
                      odir: &Option<PathBuf>,
                      ofile: &Option<PathBuf>)
                      -> Compilation {
-        RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile)
+        RustcDefaultCalls::print_crate_info(trans, sess, Some(input), odir, ofile)
             .and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input))
     }
 
@@ -612,12 +670,7 @@
             control.after_hir_lowering.stop = Compilation::Stop;
         }
 
-        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
-                                                   i == OutputType::Metadata) {
-            control.after_llvm.stop = Compilation::Stop;
-        }
-
-        if save_analysis(sess) {
+        if sess.opts.debugging_opts.save_analysis {
             enable_save_analysis(&mut control);
         }
 
@@ -652,10 +705,6 @@
     control.make_glob_map = resolve::MakeGlobMap::Yes;
 }
 
-fn save_analysis(sess: &Session) -> bool {
-    sess.opts.debugging_opts.save_analysis
-}
-
 impl RustcDefaultCalls {
     pub fn list_metadata(sess: &Session,
                          cstore: &CrateStore,
@@ -686,11 +735,13 @@
     }
 
 
-    fn print_crate_info(sess: &Session,
+    fn print_crate_info(trans: &TransCrate,
+                        sess: &Session,
                         input: Option<&Input>,
                         odir: &Option<PathBuf>,
                         ofile: &Option<PathBuf>)
                         -> Compilation {
+        use rustc::session::config::PrintRequest::*;
         // PrintRequest::NativeStaticLibs is special - printed during linking
         // (empty iterator returns true)
         if sess.opts.prints.iter().all(|&p| p==PrintRequest::NativeStaticLibs) {
@@ -712,15 +763,14 @@
         };
         for req in &sess.opts.prints {
             match *req {
-                PrintRequest::TargetList => {
+                TargetList => {
                     let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
                     targets.sort();
                     println!("{}", targets.join("\n"));
                 },
-                PrintRequest::Sysroot => println!("{}", sess.sysroot().display()),
-                PrintRequest::TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
-                PrintRequest::FileNames |
-                PrintRequest::CrateName => {
+                Sysroot => println!("{}", sess.sysroot().display()),
+                TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
+                FileNames | CrateName => {
                     let input = match input {
                         Some(input) => input,
                         None => early_error(ErrorOutputType::default(), "no input file provided"),
@@ -746,7 +796,7 @@
                                       .to_string_lossy());
                     }
                 }
-                PrintRequest::Cfg => {
+                Cfg => {
                     let allow_unstable_cfg = UnstableFeatures::from_environment()
                         .is_nightly_build();
 
@@ -786,29 +836,8 @@
                         println!("{}", cfg);
                     }
                 }
-                PrintRequest::RelocationModels => {
-                    println!("Available relocation models:");
-                    for &(name, _) in rustc_trans::back::write::RELOC_MODEL_ARGS.iter() {
-                        println!("    {}", name);
-                    }
-                    println!("");
-                }
-                PrintRequest::CodeModels => {
-                    println!("Available code models:");
-                    for &(name, _) in rustc_trans::back::write::CODE_GEN_MODEL_ARGS.iter(){
-                        println!("    {}", name);
-                    }
-                    println!("");
-                }
-                PrintRequest::TlsModels => {
-                    println!("Available TLS models:");
-                    for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){
-                        println!("    {}", name);
-                    }
-                    println!("");
-                }
-                PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
-                    rustc_trans::print(*req, sess);
+                RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => {
+                    trans.print(*req, sess);
                 }
                 // Any output here interferes with Cargo's parsing of other printed output
                 PrintRequest::NativeStaticLibs => {}
@@ -1268,6 +1297,14 @@
     panic!();
 }
 
+#[cfg(stage0)]
+pub fn diagnostics_registry() -> errors::registry::Registry {
+    use errors::registry::Registry;
+
+    Registry::new(&[])
+}
+
+#[cfg(not(stage0))]
 pub fn diagnostics_registry() -> errors::registry::Registry {
     use errors::registry::Registry;
 
@@ -1278,6 +1315,7 @@
     all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
     #[cfg(feature="llvm")]
     all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_trans_utils::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
@@ -1288,20 +1326,19 @@
     Registry::new(&all_errors)
 }
 
-pub fn get_args() -> Vec<String> {
-    env::args_os().enumerate()
-        .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
-             early_error(ErrorOutputType::default(),
-                         &format!("Argument {} is not valid Unicode: {:?}", i, arg))
-         }))
-        .collect()
-}
-
 pub fn main() {
     env_logger::init().unwrap();
-    let result = run(|| run_compiler(&get_args(),
-                                     &mut RustcDefaultCalls,
-                                     None,
-                                     None));
+    let result = run(|| {
+        let args = env::args_os().enumerate()
+            .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
+                early_error(ErrorOutputType::default(),
+                            &format!("Argument {} is not valid Unicode: {:?}", i, arg))
+            }))
+            .collect::<Vec<_>>();
+        run_compiler(&args,
+                     &mut RustcDefaultCalls,
+                     None,
+                     None)
+    });
     process::exit(result as i32);
 }
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 76923be..68f4b17 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -66,7 +66,7 @@
 pub enum PpFlowGraphMode {
     Default,
     /// Drops the labels from the edges in the flowgraph output. This
-    /// is mostly for use in the --unpretty flowgraph run-make tests,
+    /// is mostly for use in the -Z unpretty flowgraph run-make tests,
     /// since the labels are largely uninteresting in those cases and
     /// have become a pain to maintain.
     UnlabelledEdges,
@@ -228,7 +228,8 @@
             }
             PpmTyped => {
                 let control = &driver::CompileController::basic();
-                abort_on_err(driver::phase_3_run_analysis_passes(control,
+                abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
+                                                                 control,
                                                                  sess,
                                                                  cstore,
                                                                  hir_map.clone(),
@@ -243,8 +244,9 @@
                         tcx,
                         tables: Cell::new(&empty_tables)
                     };
-                    let _ignore = tcx.dep_graph.in_ignore();
-                    f(&annotation, hir_map.forest.krate())
+                    tcx.dep_graph.with_ignore(|| {
+                        f(&annotation, hir_map.forest.krate())
+                    })
                 }),
                              sess)
             }
@@ -1005,7 +1007,7 @@
                                            move |annotation, _| {
                     debug!("pretty printing source code {:?}", s);
                     let sess = annotation.sess();
-                    let hir_map = annotation.hir_map().expect("--unpretty missing HIR map");
+                    let hir_map = annotation.hir_map().expect("-Z unpretty missing HIR map");
                     let mut pp_state = pprust_hir::State::new_from_input(sess.codemap(),
                                                                          &sess.parse_sess,
                                                                          src_name,
@@ -1018,7 +1020,7 @@
                         pp_state.print_node(node)?;
                         pp_state.s.space()?;
                         let path = annotation.node_path(node_id)
-                            .expect("--unpretty missing node paths");
+                            .expect("-Z unpretty missing node paths");
                         pp_state.synth_comment(path)?;
                         pp_state.s.hardbreak()?;
                     }
@@ -1070,7 +1072,7 @@
                                        ofile: Option<&Path>) {
     let nodeid = if let Some(uii) = uii {
         debug!("pretty printing for {:?}", uii);
-        Some(uii.to_one_node_id("--unpretty", sess, &hir_map))
+        Some(uii.to_one_node_id("-Z unpretty", sess, &hir_map))
     } else {
         debug!("pretty printing for whole crate");
         None
@@ -1079,7 +1081,8 @@
     let mut out = Vec::new();
 
     let control = &driver::CompileController::basic();
-    abort_on_err(driver::phase_3_run_analysis_passes(control,
+    abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
+                                                     control,
                                                      sess,
                                                      cstore,
                                                      hir_map.clone(),
diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs
deleted file mode 100644
index 9626447..0000000
--- a/src/librustc_driver/target_features.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use syntax::ast;
-use rustc::session::Session;
-use syntax::symbol::Symbol;
-use rustc_trans;
-
-/// Add `target_feature = "..."` cfgs for a variety of platform
-/// specific features (SSE, NEON etc.).
-///
-/// This is performed by checking whether a whitelisted set of
-/// features is available on the target machine, by querying LLVM.
-pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
-    let tf = Symbol::intern("target_feature");
-
-    for feat in rustc_trans::target_features(sess) {
-        cfg.insert((tf, Some(feat)));
-    }
-
-    if sess.crt_static_feature() {
-        cfg.insert((tf, Some(Symbol::intern("crt-static"))));
-    }
-}
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 6765ea5..306e7e9 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -16,7 +16,6 @@
 use driver;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
-use rustc_trans;
 use rustc::middle::region;
 use rustc::ty::subst::{Kind, Subst};
 use rustc::traits::{ObligationCause, Reveal};
@@ -29,7 +28,6 @@
 use rustc::hir::map as hir_map;
 use rustc::session::{self, config};
 use rustc::session::config::{OutputFilenames, OutputTypes};
-use rustc_trans_utils::trans_crate::TransCrate;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::abi::Abi;
@@ -104,12 +102,11 @@
     options.unstable_features = UnstableFeatures::Allow;
     let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
 
-    let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader()));
     let sess = session::build_session_(options,
                                        None,
                                        diagnostic_handler,
                                        Rc::new(CodeMap::new(FilePathMapping::empty())));
-    rustc_trans::init(&sess);
+    let cstore = Rc::new(CStore::new(::get_trans(&sess).metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     let input = config::Input::Str {
         name: FileName::Anon,
@@ -246,8 +243,7 @@
                 hir::ItemUnion(..) |
                 hir::ItemTrait(..) |
                 hir::ItemTraitAlias(..) |
-                hir::ItemImpl(..) |
-                hir::ItemAutoImpl(..) => None,
+                hir::ItemImpl(..) => None,
 
                 hir::ItemMod(ref m) => search_mod(this, m, idx, names),
             };
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 221c751..8da4321 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -100,9 +100,6 @@
 
     /// Cancel the diagnostic (a structured diagnostic must either be emitted or
     /// canceled or it will panic when dropped).
-    /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
-    /// bump the error count on the Handler and canceling it won't undo that.
-    /// If you want to decrement the error count you should use `Handler::cancel`.
     pub fn cancel(&mut self) {
         self.level = Level::Cancelled;
     }
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 27e8951..61674ad 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -83,7 +83,12 @@
             return;
         }
 
-        let is_error = match self.level {
+        self.handler.emit_db(&self);
+        self.cancel();
+    }
+
+    pub fn is_error(&self) -> bool {
+        match self.level {
             Level::Bug |
             Level::Fatal |
             Level::PhaseFatal |
@@ -97,18 +102,7 @@
             Level::Cancelled => {
                 false
             }
-        };
-
-        self.handler.emit_db(&self);
-        self.cancel();
-
-        if is_error {
-            self.handler.bump_err_count();
         }
-
-        // if self.is_fatal() {
-        //     panic!(FatalError);
-        // }
     }
 
     /// Convenience function for internal use, clients should use one of the
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index af556c5..58f851a 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -990,7 +990,7 @@
                     buffer.append(buffer_msg_line_offset,
                                   &format!("{}:{}:{}",
                                            loc.file.name,
-                                           loc.line,
+                                           cm.doctest_offset_line(loc.line),
                                            loc.col.0 + 1),
                                   Style::LineAndColumn);
                     for _ in 0..max_line_num_len {
@@ -1000,7 +1000,7 @@
                     buffer.prepend(0,
                                    &format!("{}:{}:{} - ",
                                             loc.file.name,
-                                            loc.line,
+                                            cm.doctest_offset_line(loc.line),
                                             loc.col.0 + 1),
                                    Style::LineAndColumn);
                 }
@@ -1187,8 +1187,8 @@
                     let sub_len = parts[0].snippet.trim().chars().fold(0, |acc, ch| {
                         acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
                     });
-                    let underline_start = span_start_pos.col.0 + start;
-                    let underline_end = span_start_pos.col.0 + start + sub_len;
+                    let underline_start = span_start_pos.col_display + start;
+                    let underline_end = span_start_pos.col_display + start + sub_len;
                     for p in underline_start..underline_end {
                         buffer.putc(row_num,
                                     max_line_num_len + 3 + p,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 2ac4995..1fb6738 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -103,6 +103,7 @@
     fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>;
     fn call_span_if_macro(&self, sp: Span) -> Span;
     fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool;
+    fn doctest_offset_line(&self, line: usize) -> usize;
 }
 
 impl CodeSuggestion {
@@ -310,9 +311,13 @@
         self.continue_after_error.set(continue_after_error);
     }
 
-    // NOTE: DO NOT call this function from rustc, as it relies on `err_count` being non-zero
-    // if an error happened to avoid ICEs. This function should only be called from tools.
+    /// Resets the diagnostic error count as well as the cached emitted diagnostics.
+    ///
+    /// NOTE: DO NOT call this function from rustc. It is only meant to be called from external
+    /// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
+    /// the overall count of emitted error diagnostics.
     pub fn reset_err_count(&self) {
+        self.emitted_diagnostics.replace(FxHashSet());
         self.err_count.store(0, SeqCst);
     }
 
@@ -588,6 +593,9 @@
         // one:
         if self.emitted_diagnostics.borrow_mut().insert(diagnostic_hash) {
             self.emitter.borrow_mut().emit(db);
+            if db.is_error() {
+                self.bump_err_count();
+            }
         }
     }
 }
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index b40a1b7..eabc3ab 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -10,7 +10,7 @@
 
 [dependencies]
 graphviz = { path = "../libgraphviz" }
-log = "0.3"
+log = "0.4"
 rand = "0.3"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index acbd3e0..5976b80 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -55,44 +55,44 @@
 use rustc::ich::{ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
 use graphviz::IntoCow;
 use std::env;
-use std::fs::File;
+use std::fs::{self, File};
 use std::io::Write;
 use syntax::ast;
 use syntax_pos::Span;
 
 pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let _ignore = tcx.dep_graph.in_ignore();
+    tcx.dep_graph.with_ignore(|| {
+        if tcx.sess.opts.debugging_opts.dump_dep_graph {
+            dump_graph(tcx);
+        }
 
-    if tcx.sess.opts.debugging_opts.dump_dep_graph {
-        dump_graph(tcx);
-    }
+        // if the `rustc_attrs` feature is not enabled, then the
+        // attributes we are interested in cannot be present anyway, so
+        // skip the walk.
+        if !tcx.sess.features.borrow().rustc_attrs {
+            return;
+        }
 
-    // if the `rustc_attrs` feature is not enabled, then the
-    // attributes we are interested in cannot be present anyway, so
-    // skip the walk.
-    if !tcx.sess.features.borrow().rustc_attrs {
-        return;
-    }
+        // Find annotations supplied by user (if any).
+        let (if_this_changed, then_this_would_need) = {
+            let mut visitor = IfThisChanged { tcx,
+                                            if_this_changed: vec![],
+                                            then_this_would_need: vec![] };
+            visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs);
+            tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+            (visitor.if_this_changed, visitor.then_this_would_need)
+        };
 
-    // Find annotations supplied by user (if any).
-    let (if_this_changed, then_this_would_need) = {
-        let mut visitor = IfThisChanged { tcx,
-                                          if_this_changed: vec![],
-                                          then_this_would_need: vec![] };
-        visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs);
-        tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
-        (visitor.if_this_changed, visitor.then_this_would_need)
-    };
+        if !if_this_changed.is_empty() || !then_this_would_need.is_empty() {
+            assert!(tcx.sess.opts.debugging_opts.query_dep_graph,
+                    "cannot use the `#[{}]` or `#[{}]` annotations \
+                    without supplying `-Z query-dep-graph`",
+                    ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED);
+        }
 
-    if !if_this_changed.is_empty() || !then_this_would_need.is_empty() {
-        assert!(tcx.sess.opts.debugging_opts.query_dep_graph,
-                "cannot use the `#[{}]` or `#[{}]` annotations \
-                 without supplying `-Z query-dep-graph`",
-                ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED);
-    }
-
-    // Check paths.
-    check_paths(tcx, &if_this_changed, &then_this_would_need);
+        // Check paths.
+        check_paths(tcx, &if_this_changed, &then_this_would_need);
+    })
 }
 
 type Sources = Vec<(Span, DefId, DepNode)>;
@@ -260,7 +260,7 @@
         let dot_path = format!("{}.dot", path);
         let mut v = Vec::new();
         dot::render(&GraphvizDepGraph(nodes, edges), &mut v).unwrap();
-        File::create(&dot_path).and_then(|mut f| f.write_all(&v)).unwrap();
+        fs::write(dot_path, v).unwrap();
     }
 }
 
diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
similarity index 88%
rename from src/librustc_trans/assert_module_sources.rs
rename to src/librustc_incremental/assert_module_sources.rs
index c891bd8..46ba94f 100644
--- a/src/librustc_trans/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -28,8 +28,10 @@
 //! perturb the reuse results.
 
 use rustc::dep_graph::{DepNode, DepConstructor};
+use rustc::mir::mono::CodegenUnit;
 use rustc::ty::TyCtxt;
 use syntax::ast;
+use syntax_pos::symbol::Symbol;
 use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
 
 const MODULE: &'static str = "module";
@@ -38,17 +40,17 @@
 #[derive(Debug, PartialEq, Clone, Copy)]
 enum Disposition { Reused, Translated }
 
-pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let _ignore = tcx.dep_graph.in_ignore();
+pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    tcx.dep_graph.with_ignore(|| {
+        if tcx.sess.opts.incremental.is_none() {
+            return;
+        }
 
-    if tcx.sess.opts.incremental.is_none() {
-        return;
-    }
-
-    let ams = AssertModuleSource { tcx };
-    for attr in &tcx.hir.krate().attrs {
-        ams.check_attr(attr);
-    }
+        let ams = AssertModuleSource { tcx };
+        for attr in &tcx.hir.krate().attrs {
+            ams.check_attr(attr);
+        }
+    })
 }
 
 struct AssertModuleSource<'a, 'tcx: 'a> {
@@ -71,9 +73,11 @@
         }
 
         let mname = self.field(attr, MODULE);
+        let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
+        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
 
         let dep_node = DepNode::new(self.tcx,
-                                    DepConstructor::CompileCodegenUnit(mname.as_str()));
+                                    DepConstructor::CompileCodegenUnit(mangled_cgu_name));
 
         if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
             match (disposition, loaded_from_cache) {
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index 5eaf855..b53ee1d 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -16,6 +16,7 @@
 #![deny(warnings)]
 
 #![feature(conservative_impl_trait)]
+#![feature(fs_read_write)]
 #![feature(i128_type)]
 #![feature(inclusive_range_syntax)]
 #![feature(specialization)]
@@ -31,6 +32,7 @@
 extern crate syntax_pos;
 
 mod assert_dep_graph;
+pub mod assert_module_sources;
 mod persist;
 
 pub use assert_dep_graph::assert_dep_graph;
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 7c3f903..c3e2835 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -223,25 +223,26 @@
         return;
     }
 
-    let _ignore = tcx.dep_graph.in_ignore();
-    let krate = tcx.hir.krate();
-    let mut dirty_clean_visitor = DirtyCleanVisitor {
-        tcx,
-        checked_attrs: FxHashSet(),
-    };
-    krate.visit_all_item_likes(&mut dirty_clean_visitor);
+    tcx.dep_graph.with_ignore(|| {
+        let krate = tcx.hir.krate();
+        let mut dirty_clean_visitor = DirtyCleanVisitor {
+            tcx,
+            checked_attrs: FxHashSet(),
+        };
+        krate.visit_all_item_likes(&mut dirty_clean_visitor);
 
-    let mut all_attrs = FindAllAttrs {
-        tcx,
-        attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
-        found_attrs: vec![],
-    };
-    intravisit::walk_crate(&mut all_attrs, krate);
+        let mut all_attrs = FindAllAttrs {
+            tcx,
+            attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
+            found_attrs: vec![],
+        };
+        intravisit::walk_crate(&mut all_attrs, krate);
 
-    // Note that we cannot use the existing "unused attribute"-infrastructure
-    // here, since that is running before trans. This is also the reason why
-    // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
-    all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
+        // Note that we cannot use the existing "unused attribute"-infrastructure
+        // here, since that is running before trans. This is also the reason why
+        // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
+        all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
+    })
 }
 
 pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
@@ -392,9 +393,6 @@
                     //
                     //HirItem::ItemTrait(..) => ("ItemTrait", LABELS_TRAIT),
 
-                    // `impl Trait for .. {}`
-                    HirItem::ItemAutoImpl(..) => ("ItemAutoImpl", LABELS_IMPL),
-
                     // An implementation, eg `impl<A> Trait for Foo { .. }`
                     HirItem::ItemImpl(..) => ("ItemImpl", LABELS_IMPL),
 
@@ -480,7 +478,8 @@
     fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
         debug!("assert_dirty({:?})", dep_node);
 
-        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
+        let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
+        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
         let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
 
         if Some(current_fingerprint) == prev_fingerprint {
@@ -494,7 +493,8 @@
     fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
         debug!("assert_clean({:?})", dep_node);
 
-        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
+        let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
+        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
         let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
 
         if Some(current_fingerprint) != prev_fingerprint {
diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs
index 108eccf..d45994a 100644
--- a/src/librustc_incremental/persist/file_format.rs
+++ b/src/librustc_incremental/persist/file_format.rs
@@ -21,7 +21,7 @@
 
 use std::io::{self, Read};
 use std::path::Path;
-use std::fs::File;
+use std::fs;
 use std::env;
 
 use rustc::session::config::nightly_options;
@@ -66,11 +66,7 @@
         return Ok(None);
     }
 
-    let mut file = File::open(path)?;
-    let file_size = file.metadata()?.len() as usize;
-
-    let mut data = Vec::with_capacity(file_size);
-    file.read_to_end(&mut data)?;
+    let data = fs::read(path)?;
 
     let mut file = io::Cursor::new(data);
 
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index 42b1fcc..f4171f9 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -137,7 +137,7 @@
 // or hexadecimal numbers (we want short file and directory names). Since these
 // numbers will be used in file names, we choose an encoding that is not
 // case-sensitive (as opposed to base64, for example).
-const INT_ENCODE_BASE: u64 = 36;
+const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE;
 
 pub fn dep_graph_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
@@ -357,7 +357,7 @@
     let mut new_sub_dir_name = String::from(&old_sub_dir_name[.. dash_indices[2] + 1]);
 
     // Append the svh
-    base_n::push_str(svh.as_u64(), INT_ENCODE_BASE, &mut new_sub_dir_name);
+    base_n::push_str(svh.as_u64() as u128, INT_ENCODE_BASE, &mut new_sub_dir_name);
 
     // Create the full path
     let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name);
@@ -465,7 +465,7 @@
 
     let directory_name = format!("s-{}-{}-working",
                                   timestamp,
-                                  base_n::encode(random_number as u64,
+                                  base_n::encode(random_number as u128,
                                                  INT_ENCODE_BASE));
     debug!("generate_session_dir_path: directory_name = {}", directory_name);
     let directory_path = crate_dir.join(directory_name);
@@ -599,7 +599,7 @@
     let duration = timestamp.duration_since(UNIX_EPOCH).unwrap();
     let micros = duration.as_secs() * 1_000_000 +
                 (duration.subsec_nanos() as u64) / 1000;
-    base_n::encode(micros, INT_ENCODE_BASE)
+    base_n::encode(micros as u128, INT_ENCODE_BASE)
 }
 
 fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
@@ -626,7 +626,8 @@
     // The full crate disambiguator is really long. 64 bits of it should be
     // sufficient.
     let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash();
-    let crate_disambiguator = base_n::encode(crate_disambiguator, INT_ENCODE_BASE);
+    let crate_disambiguator = base_n::encode(crate_disambiguator as u128,
+                                             INT_ENCODE_BASE);
 
     let crate_name = format!("{}-{}", crate_name, crate_disambiguator);
     incr_dir.join(crate_name)
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 6eaa14a..d44d1d6 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -15,8 +15,8 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_serialize::opaque::Encoder;
-use std::io::{self, Cursor, Write};
-use std::fs::{self, File};
+use std::io::{self, Cursor};
+use std::fs;
 use std::path::PathBuf;
 
 use super::data::*;
@@ -27,27 +27,28 @@
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     debug!("save_dep_graph()");
-    let _ignore = tcx.dep_graph.in_ignore();
-    let sess = tcx.sess;
-    if sess.opts.incremental.is_none() {
-        return;
-    }
+    tcx.dep_graph.with_ignore(|| {
+        let sess = tcx.sess;
+        if sess.opts.incremental.is_none() {
+            return;
+        }
 
-    time(sess.time_passes(), "persist query result cache", || {
-        save_in(sess,
-                query_cache_path(sess),
-                |e| encode_query_cache(tcx, e));
-    });
-
-    if tcx.sess.opts.debugging_opts.incremental_queries {
-        time(sess.time_passes(), "persist dep-graph", || {
+        time(sess.time_passes(), "persist query result cache", || {
             save_in(sess,
-                    dep_graph_path(sess),
-                    |e| encode_dep_graph(tcx, e));
+                    query_cache_path(sess),
+                    |e| encode_query_cache(tcx, e));
         });
-    }
 
-    dirty_clean::check_dirty_clean_annotations(tcx);
+        if tcx.sess.opts.debugging_opts.incremental_queries {
+            time(sess.time_passes(), "persist dep-graph", || {
+                save_in(sess,
+                        dep_graph_path(sess),
+                        |e| encode_dep_graph(tcx, e));
+            });
+        }
+
+        dirty_clean::check_dirty_clean_annotations(tcx);
+    })
 }
 
 pub fn save_work_products(sess: &Session, dep_graph: &DepGraph) {
@@ -56,7 +57,7 @@
     }
 
     debug!("save_work_products()");
-    let _ignore = dep_graph.in_ignore();
+    dep_graph.assert_ignored();
     let path = work_products_path(sess);
     save_in(sess, path, |e| encode_work_products(dep_graph, e));
 
@@ -124,7 +125,7 @@
 
     // write the data out
     let data = wr.into_inner();
-    match File::create(&path_buf).and_then(|mut file| file.write_all(&data)) {
+    match fs::write(&path_buf, data) {
         Ok(_) => {
             debug!("save: data written to disk successfully");
         }
diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs
index f23b8dc..879132b 100644
--- a/src/librustc_incremental/persist/work_product.rs
+++ b/src/librustc_incremental/persist/work_product.rs
@@ -35,9 +35,9 @@
                  let extension = match kind {
                      WorkProductFileKind::Object => "o",
                      WorkProductFileKind::Bytecode => "bc",
-                     WorkProductFileKind::BytecodeCompressed => "bc-compressed",
+                     WorkProductFileKind::BytecodeCompressed => "bc.z",
                  };
-                 let file_name = format!("cgu-{}.{}", cgu_name, extension);
+                 let file_name = format!("{}.{}", cgu_name, extension);
                  let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
                  match link_or_copy(path, &path_in_incr_dir) {
                      Ok(_) => Some((kind, file_name)),
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index cebf52d..9fee2d5 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -10,7 +10,7 @@
 test = false
 
 [dependencies]
-log = "0.3"
+log = "0.4"
 rustc = { path = "../librustc" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index 49f14e8..ad3760e 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -53,6 +53,10 @@
 
 impl NonCamelCaseTypes {
     fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+        fn char_has_case(c: char) -> bool {
+            c.is_lowercase() || c.is_uppercase()
+        }
+
         fn is_camel_case(name: ast::Name) -> bool {
             let name = name.as_str();
             if name.is_empty() {
@@ -62,20 +66,38 @@
 
             // start with a non-lowercase letter rather than non-uppercase
             // ones (some scripts don't have a concept of upper/lowercase)
-            !name.is_empty() && !name.chars().next().unwrap().is_lowercase() && !name.contains('_')
+            !name.is_empty() && !name.chars().next().unwrap().is_lowercase() &&
+                !name.contains("__") && !name.chars().collect::<Vec<_>>().windows(2).any(|pair| {
+                    // contains a capitalisable character followed by, or preceded by, an underscore
+                    char_has_case(pair[0]) && pair[1] == '_' ||
+                    char_has_case(pair[1]) && pair[0] == '_'
+                })
         }
 
         fn to_camel_case(s: &str) -> String {
-            s.split('_')
-                .flat_map(|word| {
+            s.trim_matches('_')
+                .split('_')
+                .map(|word| {
                     word.chars().enumerate().map(|(i, c)| if i == 0 {
                         c.to_uppercase().collect::<String>()
                     } else {
                         c.to_lowercase().collect()
                     })
+                    .collect::<Vec<_>>()
+                    .concat()
                 })
+                .filter(|x| !x.is_empty())
                 .collect::<Vec<_>>()
-                .concat()
+                .iter().fold((String::new(), None), |(acc, prev): (String, Option<&String>), next| {
+                    // separate two components with an underscore if their boundary cannot
+                    // be distinguished using a uppercase/lowercase case distinction
+                    let join = if let Some(prev) = prev {
+                                    let l = prev.chars().last().unwrap();
+                                    let f = next.chars().next().unwrap();
+                                    !char_has_case(l) && !char_has_case(f)
+                                } else { false };
+                    (acc + if join { "_" } else { "" } + next, Some(next))
+                }).0
         }
 
         if !is_camel_case(name) {
@@ -98,17 +120,15 @@
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        let extern_repr_count = it.attrs
+        let has_repr_c = it.attrs
             .iter()
-            .filter(|attr| {
+            .any(|attr| {
                 attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
                     .iter()
-                    .any(|r| r == &attr::ReprExtern)
-            })
-            .count();
-        let has_extern_repr = extern_repr_count > 0;
+                    .any(|r| r == &attr::ReprC)
+            });
 
-        if has_extern_repr {
+        if has_repr_c {
             return;
         }
 
@@ -128,7 +148,9 @@
 
     fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
         if let hir::GenericParam::Type(ref gen) = *param {
-            self.check_case(cx, "type parameter", gen.name, gen.span);
+            if gen.synthetic.is_none() {
+                self.check_case(cx, "type parameter", gen.name, gen.span);
+            }
         }
     }
 }
@@ -221,9 +243,7 @@
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
     fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
-        let attr_crate_name = cr.attrs
-            .iter()
-            .find(|at| at.check_name("crate_name"))
+        let attr_crate_name = attr::find_by_name(&cr.attrs, "crate_name")
             .and_then(|at| at.value_str().map(|s| (at, s)));
         if let Some(ref name) = cx.tcx.sess.opts.crate_name {
             self.check_snake_case(cx, "crate", name, None);
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 501f6bb..de55710 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -56,31 +56,6 @@
 pub use lint::builtin::*;
 
 declare_lint! {
-    pub AUTO_IMPL,
-    Deny,
-    "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`"
-}
-
-#[derive(Copy, Clone)]
-pub struct AutoImpl;
-
-impl LintPass for AutoImpl {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(AUTO_IMPL)
-    }
-}
-
-impl EarlyLintPass for AutoImpl {
-    fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) {
-        let msg = "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`";
-        match item.node {
-            ast::ItemKind::AutoImpl(..) => cx.span_lint(AUTO_IMPL, item.span, msg),
-            _ => ()
-        }
-     }
-}
-
-declare_lint! {
     WHILE_TRUE,
     Warn,
     "suggest using `loop { }` instead of `while true { }`"
@@ -102,11 +77,9 @@
                 if let ast::LitKind::Bool(true) = lit.node {
                     if lit.span.ctxt() == SyntaxContext::empty() {
                         let msg = "denote infinite loops with `loop { ... }`";
-                        let mut err = cx.struct_span_lint(WHILE_TRUE, e.span, msg);
                         let condition_span = cx.tcx.sess.codemap().def_span(e.span);
-                        err.span_suggestion_short(condition_span,
-                                                  "use `loop`",
-                                                  "loop".to_owned());
+                        let mut err = cx.struct_span_lint(WHILE_TRUE, condition_span, msg);
+                        err.span_suggestion_short(condition_span, "use `loop`", "loop".to_owned());
                         err.emit();
                     }
                 }
@@ -1181,9 +1154,11 @@
                         let msg = "function is marked #[no_mangle], but not exported";
                         let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
                         let insertion_span = it.span.with_hi(it.span.lo());
-                        err.span_suggestion(insertion_span,
-                                            "try making it public",
-                                            "pub ".to_owned());
+                        if it.vis == hir::Visibility::Inherited {
+                            err.span_suggestion(insertion_span,
+                                                "try making it public",
+                                                "pub ".to_owned());
+                        }
                         err.emit();
                     }
                     if generics.is_type_parameterized() {
@@ -1204,9 +1179,11 @@
                        let msg = "static is marked #[no_mangle], but not exported";
                        let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
                        let insertion_span = it.span.with_hi(it.span.lo());
-                       err.span_suggestion(insertion_span,
-                                           "try making it public",
-                                           "pub ".to_owned());
+                       if it.vis == hir::Visibility::Inherited {
+                           err.span_suggestion(insertion_span,
+                                               "try making it public",
+                                               "pub ".to_owned());
+                       }
                        err.emit();
                 }
             }
@@ -1216,8 +1193,13 @@
                     // don't have anything to attach a symbol to
                     let msg = "const items should never be #[no_mangle]";
                     let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
+
+                    // account for "pub const" (#45562)
+                    let start = cx.tcx.sess.codemap().span_to_snippet(it.span)
+                        .map(|snippet| snippet.find("const").unwrap_or(0))
+                        .unwrap_or(0) as u32;
                     // `const` is 5 chars
-                    let const_span = it.span.with_hi(BytePos(it.span.lo().0 + 5));
+                    let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
                     err.span_suggestion(const_span,
                                         "try a static value",
                                         "pub static".to_owned());
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 8b41dd6..699765d 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -109,7 +109,6 @@
                        AnonymousParameters,
                        IllegalFloatLiteralPattern,
                        UnusedDocComment,
-                       AutoImpl,
                        );
 
     add_early_builtin_with_new!(sess,
@@ -184,10 +183,6 @@
     store.register_future_incompatible(sess,
                                        vec![
         FutureIncompatibleInfo {
-            id: LintId::of(AUTO_IMPL),
-            reference: "issue #13231 <https://github.com/rust-lang/rust/issues/13231>",
-        },
-        FutureIncompatibleInfo {
             id: LintId::of(PRIVATE_IN_PUBLIC),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
         },
@@ -255,6 +250,10 @@
             id: LintId::of(COERCE_NEVER),
             reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
+            reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
+        },
         ]);
 
     // Register renamed and removed lints
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index c109a47..e0999db 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -140,7 +140,7 @@
                         match lit.node {
                             ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
                             ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => {
-                                let int_type = if let ast::IntTy::Is = t {
+                                let int_type = if let ast::IntTy::Isize = t {
                                     cx.sess().target.isize_ty
                                 } else {
                                     t
@@ -163,7 +163,7 @@
                         };
                     }
                     ty::TyUint(t) => {
-                        let uint_type = if let ast::UintTy::Us = t {
+                        let uint_type = if let ast::UintTy::Usize = t {
                             cx.sess().target.usize_ty
                         } else {
                             t
@@ -230,7 +230,7 @@
         // warnings are consistent between 32- and 64-bit platforms
         fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
             match int_ty {
-                ast::IntTy::Is => (i64::min_value() as i128, i64::max_value() as i128),
+                ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128),
                 ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
                 ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
                 ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
@@ -241,7 +241,7 @@
 
         fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
             match uint_ty {
-                ast::UintTy::Us => (u64::min_value() as u128, u64::max_value() as u128),
+                ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128),
                 ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
                 ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
                 ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
@@ -252,7 +252,7 @@
 
         fn int_ty_bits(int_ty: ast::IntTy, isize_ty: ast::IntTy) -> u64 {
             match int_ty {
-                ast::IntTy::Is => int_ty_bits(isize_ty, isize_ty),
+                ast::IntTy::Isize => int_ty_bits(isize_ty, isize_ty),
                 ast::IntTy::I8 => 8,
                 ast::IntTy::I16 => 16 as u64,
                 ast::IntTy::I32 => 32,
@@ -263,7 +263,7 @@
 
         fn uint_ty_bits(uint_ty: ast::UintTy, usize_ty: ast::UintTy) -> u64 {
             match uint_ty {
-                ast::UintTy::Us => uint_ty_bits(usize_ty, usize_ty),
+                ast::UintTy::Usize => uint_ty_bits(usize_ty, usize_ty),
                 ast::UintTy::U8 => 8,
                 ast::UintTy::U16 => 16,
                 ast::UintTy::U32 => 32,
@@ -387,7 +387,7 @@
         attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) |
         attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) |
         attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => true,
-        attr::SignedInt(ast::IntTy::Is) | attr::UnsignedInt(ast::UintTy::Us) => false
+        attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => false
     }
 }
 
@@ -416,24 +416,35 @@
                 }
                 match def.adt_kind() {
                     AdtKind::Struct => {
-                        if !def.repr.c() {
+                        if !def.repr.c() && !def.repr.transparent() {
                             return FfiUnsafe("found struct without foreign-function-safe \
                                               representation annotation in foreign module, \
                                               consider adding a #[repr(C)] attribute to the type");
                         }
 
-                        if def.struct_variant().fields.is_empty() {
+                        if def.non_enum_variant().fields.is_empty() {
                             return FfiUnsafe("found zero-size struct in foreign module, consider \
                                               adding a member to this struct");
                         }
 
-                        // We can't completely trust repr(C) markings; make sure the
-                        // fields are actually safe.
+                        // We can't completely trust repr(C) and repr(transparent) markings;
+                        // make sure the fields are actually safe.
                         let mut all_phantom = true;
-                        for field in &def.struct_variant().fields {
+                        for field in &def.non_enum_variant().fields {
                             let field_ty = cx.fully_normalize_associated_types_in(
                                 &field.ty(cx, substs)
                             );
+                            // repr(transparent) types are allowed to have arbitrary ZSTs, not just
+                            // PhantomData -- skip checking all ZST fields
+                            if def.repr.transparent() {
+                                let is_zst = (cx, cx.param_env(field.did))
+                                    .layout_of(field_ty)
+                                    .map(|layout| layout.is_zst())
+                                    .unwrap_or(false);
+                                if is_zst {
+                                    continue;
+                                }
+                            }
                             let r = self.check_type_for_ffi(cache, field_ty);
                             match r {
                                 FfiSafe => {
@@ -458,13 +469,13 @@
                                               consider adding a #[repr(C)] attribute to the type");
                         }
 
-                        if def.struct_variant().fields.is_empty() {
+                        if def.non_enum_variant().fields.is_empty() {
                             return FfiUnsafe("found zero-size union in foreign module, consider \
                                               adding a member to this union");
                         }
 
                         let mut all_phantom = true;
-                        for field in &def.struct_variant().fields {
+                        for field in &def.non_enum_variant().fields {
                             let field_ty = cx.fully_normalize_associated_types_in(
                                 &field.ty(cx, substs)
                             );
@@ -628,6 +639,7 @@
             ty::TyError |
             ty::TyClosure(..) |
             ty::TyGenerator(..) |
+            ty::TyGeneratorWitness(..) |
             ty::TyProjection(..) |
             ty::TyAnon(..) |
             ty::TyFnDef(..) => bug!("Unexpected type in foreign function"),
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 4e066ec..ef6475f 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -302,6 +302,18 @@
             Assign(_, ref value) => (value, "assigned value", false),
             AssignOp(.., ref value) => (value, "assigned value", false),
             InPlace(_, ref value) => (value, "emplacement value", false),
+            Call(_, ref args) => {
+                for arg in args {
+                    self.check_unused_parens_core(cx, arg, "function argument", false)
+                }
+                return;
+            },
+            MethodCall(_, ref args) => {
+                for arg in &args[1..] { // first "argument" is self (which sometimes needs parens)
+                    self.check_unused_parens_core(cx, arg, "method argument", false)
+                }
+                return;
+            }
             _ => return,
         };
         self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens);
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 47ca30d..91dc321 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -234,6 +234,8 @@
     let stdcppname = if target.contains("openbsd") {
         // llvm-config on OpenBSD doesn't mention stdlib=libc++
         "c++"
+    } else if target.contains("freebsd") {
+        "c++"
     } else if target.contains("netbsd") && llvm_static_stdcpp.is_some() {
         // NetBSD uses a separate library when relocation is required
         "stdc++_pic"
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index cb38592..f51e51a 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -514,7 +514,7 @@
 #[link(name = "rustllvm", kind = "static")]
 extern "C" {
     // Create and destroy contexts.
-    pub fn LLVMContextCreate() -> ContextRef;
+    pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef;
     pub fn LLVMContextDispose(C: ContextRef);
     pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint;
 
@@ -538,9 +538,6 @@
     /// See llvm::LLVMTypeKind::getTypeID.
     pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
 
-    /// See llvm::Value::getContext
-    pub fn LLVMRustGetValueContext(V: ValueRef) -> ContextRef;
-
     // Operations on integer types
     pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
     pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
@@ -812,13 +809,12 @@
                                Bundle: OperandBundleDefRef,
                                Name: *const c_char)
                                -> ValueRef;
-    pub fn LLVMRustBuildLandingPad(B: BuilderRef,
-                                   Ty: TypeRef,
-                                   PersFn: ValueRef,
-                                   NumClauses: c_uint,
-                                   Name: *const c_char,
-                                   F: ValueRef)
-                                   -> ValueRef;
+    pub fn LLVMBuildLandingPad(B: BuilderRef,
+                               Ty: TypeRef,
+                               PersFn: ValueRef,
+                               NumClauses: c_uint,
+                               Name: *const c_char)
+                               -> ValueRef;
     pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
     pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
 
@@ -1319,9 +1315,6 @@
                              ElementCount: c_uint,
                              Packed: Bool);
 
-    /// Enables LLVM debug output.
-    pub fn LLVMRustSetDebug(Enabled: c_int);
-
     /// Prepares inline assembly.
     pub fn LLVMRustInlineAsm(Ty: TypeRef,
                              AsmString: *const c_char,
@@ -1553,7 +1546,7 @@
                                                 InlinedAt: MetadataRef)
                                                 -> ValueRef;
     pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
-    pub fn LLVMRustDIBuilderCreateOpPlus() -> i64;
+    pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;
 
     pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef);
     pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
@@ -1614,7 +1607,6 @@
     pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
     pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool);
     pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef, bc: *const c_char, len: size_t) -> bool;
-    pub fn LLVMRustLinkInParsedExternalBitcode(M: ModuleRef, M: ModuleRef) -> bool;
     pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t);
     pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
 
@@ -1650,8 +1642,6 @@
     pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
     pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
 
-    pub fn LLVMRustWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef);
-
     pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
                                                  H: InlineAsmDiagHandler,
                                                  CX: *mut c_void);
@@ -1671,7 +1661,6 @@
     pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
 
     pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef);
-    pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;
 
     pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
                                          Inputs: *const ValueRef,
@@ -1732,4 +1721,5 @@
                                            CU1: *mut *mut c_void,
                                            CU2: *mut *mut c_void);
     pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void);
+    pub fn LLVMRustThinLTORemoveAvailableExternally(M: ModuleRef);
 }
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 592bd62..c75a026 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -296,11 +296,6 @@
     build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
 }
 
-pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
-    build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
-        .expect("got a non-UTF8 DebugLoc from LLVM")
-}
-
 pub fn initialize_available_targets() {
     macro_rules! init_target(
         ($cfg:meta, $($method:ident),*) => { {
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index 3d61bc1..a2dcf7f 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -9,8 +9,8 @@
 crate-type = ["dylib"]
 
 [dependencies]
-flate2 = "0.2"
-log = "0.3"
+flate2 = "1.0"
+log = "0.4"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 5845306..246f5c9 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -15,7 +15,7 @@
 use native_libs::relevant_lib;
 use schema::CrateRoot;
 
-use rustc::hir::def_id::{CrateNum, DefIndex, CRATE_DEF_INDEX};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
 use rustc::hir::svh::Svh;
 use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::DepKind;
@@ -532,8 +532,7 @@
             Err(err) => self.sess.span_fatal(span, &err),
         };
 
-        let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator,
-                                                             root.macro_derive_registrar.unwrap());
+        let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator);
         let registrar = unsafe {
             let sym = match lib.symbol(&sym) {
                 Ok(f) => f,
@@ -588,7 +587,7 @@
     pub fn find_plugin_registrar(&mut self,
                                  span: Span,
                                  name: &str)
-                                 -> Option<(PathBuf, CrateDisambiguator, DefIndex)> {
+                                 -> Option<(PathBuf, CrateDisambiguator)> {
         let name = Symbol::intern(name);
         let ekrate = self.read_extension_crate(span, name, name);
 
@@ -603,11 +602,11 @@
         }
 
         let root = ekrate.metadata.get_root();
-        match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) {
-            (Some(dylib), Some(reg)) => {
-                Some((dylib.to_path_buf(), root.disambiguator, reg))
+        match ekrate.dylib.as_ref() {
+            Some(dylib) => {
+                Some((dylib.to_path_buf(), root.disambiguator))
             }
-            (None, Some(_)) => {
+            None => {
                 span_err!(self.sess, span, E0457,
                           "plugin `{}` only found in rlib format, but must be available \
                            in dylib format",
@@ -616,7 +615,6 @@
                 // empty dylib.
                 None
             }
-            _ => None,
         }
     }
 
@@ -1051,7 +1049,7 @@
         self.inject_allocator_crate(krate);
         self.inject_panic_runtime(krate);
 
-        if log_enabled!(log::LogLevel::Info) {
+        if log_enabled!(log::Level::Info) {
             dump_crates(&self.cstore);
         }
     }
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 87e41ca..f3d0b38 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -91,7 +91,7 @@
 }
 
 pub struct CStore {
-    metas: RefCell<FxHashMap<CrateNum, Rc<CrateMetadata>>>,
+    metas: RefCell<IndexVec<CrateNum, Option<Rc<CrateMetadata>>>>,
     /// Map from NodeId's of local extern crate statements to crate numbers
     extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
     pub metadata_loader: Box<MetadataLoader>,
@@ -100,7 +100,7 @@
 impl CStore {
     pub fn new(metadata_loader: Box<MetadataLoader>) -> CStore {
         CStore {
-            metas: RefCell::new(FxHashMap()),
+            metas: RefCell::new(IndexVec::new()),
             extern_mod_crate_map: RefCell::new(FxHashMap()),
             metadata_loader,
         }
@@ -111,18 +111,25 @@
     }
 
     pub fn get_crate_data(&self, cnum: CrateNum) -> Rc<CrateMetadata> {
-        self.metas.borrow().get(&cnum).unwrap().clone()
+        self.metas.borrow()[cnum].clone().unwrap()
     }
 
     pub fn set_crate_data(&self, cnum: CrateNum, data: Rc<CrateMetadata>) {
-        self.metas.borrow_mut().insert(cnum, data);
+        use rustc_data_structures::indexed_vec::Idx;
+        let mut met = self.metas.borrow_mut();
+        while met.len() <= cnum.index() {
+            met.push(None);
+        }
+        met[cnum] = Some(data);
     }
 
     pub fn iter_crate_data<I>(&self, mut i: I)
         where I: FnMut(CrateNum, &Rc<CrateMetadata>)
     {
-        for (&k, v) in self.metas.borrow().iter() {
-            i(k, v);
+        for (k, v) in self.metas.borrow().iter_enumerated() {
+            if let &Some(ref v) = v {
+                i(k, v);
+            }
         }
     }
 
@@ -150,8 +157,10 @@
 
     pub fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
         let mut ordering = Vec::new();
-        for (&num, _) in self.metas.borrow().iter() {
-            self.push_dependencies_in_postorder(&mut ordering, num);
+        for (num, v) in self.metas.borrow().iter_enumerated() {
+            if let &Some(_) = v {
+                self.push_dependencies_in_postorder(&mut ordering, num);
+            }
         }
         return ordering
     }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 9556482..d73e968 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -143,7 +143,6 @@
     inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_const_fn => { cdata.is_const_fn(def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
-    is_auto_impl => { cdata.is_auto_impl(def_id.index) }
     describe_def => { cdata.get_def(def_id.index) }
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
     lookup_stability => {
@@ -463,7 +462,7 @@
     fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
         let data = self.get_crate_data(id.krate);
         if let Some(ref proc_macros) = data.proc_macros {
-            return LoadedMacro::ProcMacro(proc_macros[id.index.as_usize() - 1].1.clone());
+            return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
         } else if data.name == "proc_macro" &&
                   self.get_crate_data(id.krate).item_name(id.index) == "quote" {
             let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter));
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 0e9f4a8..06728b2 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -18,7 +18,8 @@
 use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
                             ExternBodyNestedBodies};
 use rustc::hir::def::{self, Def, CtorKind};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
+                         CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::ich::Fingerprint;
 use rustc::middle::lang_items;
 use rustc::mir;
@@ -36,7 +37,6 @@
 use std::u32;
 
 use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
-use rustc_data_structures::indexed_vec::Idx;
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
@@ -264,25 +264,23 @@
 impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
-        Ok(DefIndex::from_u32(self.read_u32()?))
+        Ok(DefIndex::from_raw_u32(self.read_u32()?))
     }
 }
 
 impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
+        let tag = u8::decode(self)?;
+
+        if tag == TAG_INVALID_SPAN {
+            return Ok(DUMMY_SP)
+        }
+
+        debug_assert_eq!(tag, TAG_VALID_SPAN);
+
         let lo = BytePos::decode(self)?;
-        let hi = BytePos::decode(self)?;
-
-        if lo == BytePos(0) && hi == BytePos(0) {
-            // Don't try to rebase DUMMY_SP. Otherwise it will look like a valid
-            // Span again.
-            return Ok(DUMMY_SP)
-        }
-
-        if hi < lo {
-            // Consistently map invalid spans to DUMMY_SP.
-            return Ok(DUMMY_SP)
-        }
+        let len = BytePos::decode(self)?;
+        let hi = lo + len;
 
         let sess = if let Some(sess) = self.sess {
             sess
@@ -297,9 +295,7 @@
             let last_filemap = &imported_filemaps[self.last_filemap_index];
 
             if lo >= last_filemap.original_start_pos &&
-               lo <= last_filemap.original_end_pos &&
-               hi >= last_filemap.original_start_pos &&
-               hi <= last_filemap.original_end_pos {
+               lo <= last_filemap.original_end_pos {
                 last_filemap
             } else {
                 let mut a = 0;
@@ -323,11 +319,9 @@
         debug_assert!(lo >= filemap.original_start_pos &&
                       lo <= filemap.original_end_pos);
 
-        if hi < filemap.original_start_pos || hi > filemap.original_end_pos {
-            // `hi` points to a different FileMap than `lo` which is invalid.
-            // Again, map invalid Spans to DUMMY_SP.
-            return Ok(DUMMY_SP)
-        }
+        // Make sure we correctly filtered out invalid spans during encoding
+        debug_assert!(hi >= filemap.original_start_pos &&
+                      hi <= filemap.original_end_pos);
 
         let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
         let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
@@ -336,6 +330,12 @@
     }
 }
 
+impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
+    fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+        Fingerprint::decode_opaque(&mut self.opaque)
+    }
+}
+
 impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
 for DecodeContext<'a, 'tcx> {
     #[inline]
@@ -404,7 +404,6 @@
 
             EntryKind::ForeignMod |
             EntryKind::Impl(_) |
-            EntryKind::AutoImpl(_) |
             EntryKind::Field |
             EntryKind::Generator(_) |
             EntryKind::Closure(_) => return None,
@@ -453,7 +452,7 @@
         if !self.is_proc_macro(index) {
             self.entry(index).kind.to_def(self.local_def_id(index))
         } else {
-            let kind = self.proc_macros.as_ref().unwrap()[index.as_usize() - 1].1.kind();
+            let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind();
             Some(Def::Macro(self.local_def_id(index), kind))
         }
     }
@@ -634,7 +633,7 @@
                     let def = Def::Macro(
                         DefId {
                             krate: self.cnum,
-                            index: DefIndex::new(id + 1)
+                            index: DefIndex::from_proc_macro_index(id),
                         },
                         ext.kind()
                     );
@@ -690,8 +689,7 @@
                         }
                         continue;
                     }
-                    EntryKind::Impl(_) |
-                    EntryKind::AutoImpl(_) => continue,
+                    EntryKind::Impl(_) => continue,
 
                     _ => {}
                 }
@@ -704,8 +702,8 @@
                     let vis = self.get_visibility(child_index);
                     let is_import = false;
                     callback(def::Export { def, ident, vis, span, is_import });
-                    // For non-reexport structs and variants add their constructors to children.
-                    // Reexport lists automatically contain constructors when necessary.
+                    // For non-re-export structs and variants add their constructors to children.
+                    // Re-export lists automatically contain constructors when necessary.
                     match def {
                         Def::Struct(..) => {
                             if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
@@ -781,7 +779,7 @@
         } else {
             ExternBodyNestedBodies {
                 nested_bodies: Rc::new(BTreeMap::new()),
-                fingerprint: Fingerprint::zero(),
+                fingerprint: Fingerprint::ZERO,
             }
         }
     }
@@ -1045,13 +1043,6 @@
         self.dllimport_foreign_items.contains(&id)
     }
 
-    pub fn is_auto_impl(&self, impl_id: DefIndex) -> bool {
-        match self.entry(impl_id).kind {
-            EntryKind::AutoImpl(_) => true,
-            _ => false,
-        }
-    }
-
     pub fn fn_sig(&self,
                   id: DefIndex,
                   tcx: TyCtxt<'a, 'tcx, 'tcx>)
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 5ddbb18..78578ca 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -18,6 +18,7 @@
 use rustc::hir::def::CtorKind;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
 use rustc::hir::map::definitions::DefPathTable;
+use rustc::ich::Fingerprint;
 use rustc::middle::dependency_format::Linkage;
 use rustc::middle::lang_items;
 use rustc::mir;
@@ -41,7 +42,7 @@
 use syntax::codemap::Spanned;
 use syntax::attr;
 use syntax::symbol::Symbol;
-use syntax_pos::{self, FileName};
+use syntax_pos::{self, FileName, FileMap, Span, DUMMY_SP};
 
 use rustc::hir::{self, PatKind};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -57,6 +58,9 @@
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+
+    // This is used to speed up Span encoding.
+    filemap_cache: Rc<FileMap>,
 }
 
 macro_rules! encoder_methods {
@@ -136,7 +140,42 @@
 impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> {
     #[inline]
     fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
-        self.emit_u32(def_index.as_u32())
+        self.emit_u32(def_index.as_raw_u32())
+    }
+}
+
+impl<'a, 'tcx> SpecializedEncoder<Span> for EncodeContext<'a, 'tcx> {
+    fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
+        if *span == DUMMY_SP {
+            return TAG_INVALID_SPAN.encode(self)
+        }
+
+        let span = span.data();
+
+        // The Span infrastructure should make sure that this invariant holds:
+        debug_assert!(span.lo <= span.hi);
+
+        if !self.filemap_cache.contains(span.lo) {
+            let codemap = self.tcx.sess.codemap();
+            let filemap_index = codemap.lookup_filemap_idx(span.lo);
+            self.filemap_cache = codemap.files()[filemap_index].clone();
+        }
+
+        if !self.filemap_cache.contains(span.hi) {
+            // Unfortunately, macro expansion still sometimes generates Spans
+            // that malformed in this way.
+            return TAG_INVALID_SPAN.encode(self)
+        }
+
+        TAG_VALID_SPAN.encode(self)?;
+        span.lo.encode(self)?;
+
+        // Encode length which is usually less than span.hi and profits more
+        // from the variable-length integer encoding that we use.
+        let len = span.hi - span.lo;
+        len.encode(self)
+
+        // Don't encode the expansion context.
     }
 }
 
@@ -154,6 +193,12 @@
     }
 }
 
+impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'a, 'tcx> {
+    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+        f.encode_opaque(&mut self.opaque)
+    }
+}
+
 impl<'a, 'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>>
 for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self,
@@ -587,7 +632,7 @@
         debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
         let adt_def = tcx.adt_def(adt_def_id);
-        let variant = adt_def.struct_variant();
+        let variant = adt_def.non_enum_variant();
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -820,14 +865,15 @@
 
     fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
                                     -> LazySeq<ast::Name> {
-        let _ignore = self.tcx.dep_graph.in_ignore();
-        let body = self.tcx.hir.body(body_id);
-        self.lazy_seq(body.arguments.iter().map(|arg| {
-            match arg.pat.node {
-                PatKind::Binding(_, _, name, _) => name.node,
-                _ => Symbol::intern("")
-            }
-        }))
+        self.tcx.dep_graph.with_ignore(|| {
+            let body = self.tcx.hir.body(body_id);
+            self.lazy_seq(body.arguments.iter().map(|arg| {
+                match arg.pat.node {
+                    PatKind::Binding(_, _, name, _) => name.node,
+                    _ => Symbol::intern("")
+                }
+            }))
+        })
     }
 
     fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
@@ -897,7 +943,7 @@
             hir::ItemTy(..) => EntryKind::Type,
             hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
             hir::ItemStruct(ref struct_def, _) => {
-                let variant = tcx.adt_def(def_id).struct_variant();
+                let variant = tcx.adt_def(def_id).non_enum_variant();
 
                 // Encode def_ids for each field and method
                 // for methods, write all the stuff get_trait_method
@@ -918,7 +964,7 @@
                 }), repr_options)
             }
             hir::ItemUnion(..) => {
-                let variant = tcx.adt_def(def_id).struct_variant();
+                let variant = tcx.adt_def(def_id).non_enum_variant();
                 let repr_options = get_repr_options(&tcx, def_id);
 
                 EntryKind::Union(self.lazy(&VariantData {
@@ -928,17 +974,6 @@
                     ctor_sig: None,
                 }), repr_options)
             }
-            hir::ItemAutoImpl(..) => {
-                let data = ImplData {
-                    polarity: hir::ImplPolarity::Positive,
-                    defaultness: hir::Defaultness::Final,
-                    parent_impl: None,
-                    coerce_unsized_info: None,
-                    trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
-                };
-
-                EntryKind::AutoImpl(self.lazy(&data))
-            }
             hir::ItemImpl(_, polarity, defaultness, ..) => {
                 let trait_ref = tcx.impl_trait_ref(def_id);
                 let parent = if let Some(trait_ref) = trait_ref {
@@ -1011,7 +1046,7 @@
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) => {
                     let def = self.tcx.adt_def(def_id);
-                    self.lazy_seq(def.struct_variant().fields.iter().map(|f| {
+                    self.lazy_seq(def.non_enum_variant().fields.iter().map(|f| {
                         assert!(f.did.is_local());
                         f.did.index
                     }))
@@ -1533,7 +1568,6 @@
             hir::ItemGlobalAsm(..) |
             hir::ItemExternCrate(..) |
             hir::ItemUse(..) |
-            hir::ItemAutoImpl(..) |
             hir::ItemTy(..) |
             hir::ItemTraitAlias(..) => {
                 // no sub-item recording needed in these cases
@@ -1648,6 +1682,7 @@
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
+            filemap_cache: tcx.sess.codemap().files()[0].clone(),
         };
 
         // Encode the rustc version string in a predictable location.
diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs
index 69fbc93..157b838 100644
--- a/src/librustc_metadata/index.rs
+++ b/src/librustc_metadata/index.rs
@@ -74,10 +74,9 @@
     #[inline(never)]
     pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
         let words = &bytes_to_words(&bytes[self.position..])[..self.len];
-        let index = def_index.as_usize();
 
         debug!("Index::lookup: index={:?} words.len={:?}",
-               index,
+               def_index,
                words.len());
 
         let positions = match def_index.address_space() {
diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs
index f218268..fd2c223 100644
--- a/src/librustc_metadata/index_builder.rs
+++ b/src/librustc_metadata/index_builder.rs
@@ -119,19 +119,18 @@
         where DATA: DepGraphRead
     {
         assert!(id.is_local());
-        let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
 
         // We don't track this since we are explicitly computing the incr. comp.
         // hashes anyway. In theory we could do some tracking here and use it to
         // avoid rehashing things (and instead cache the hashes) but it's
         // unclear whether that would be a win since hashing is cheap enough.
-        let _task = tcx.dep_graph.in_ignore();
+        self.ecx.tcx.dep_graph.with_ignore(move || {
+            let mut entry_builder = IsolatedEncoder::new(self.ecx);
+            let entry = op(&mut entry_builder, data);
+            let entry = entry_builder.lazy(&entry);
 
-        let mut entry_builder = IsolatedEncoder::new(self.ecx);
-        let entry = op(&mut entry_builder, data);
-        let entry = entry_builder.lazy(&entry);
-
-        self.items.record(id, entry);
+            self.items.record(id, entry);
+        })
     }
 
     pub fn into_items(self) -> Index {
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index a65ddce..33075e4 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -15,6 +15,7 @@
 
 #![feature(box_patterns)]
 #![feature(conservative_impl_trait)]
+#![feature(fs_read_write)]
 #![feature(i128_type)]
 #![feature(libc)]
 #![feature(proc_macro_internals)]
@@ -58,4 +59,5 @@
 pub mod dynamic_lib;
 pub mod locator;
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_metadata, DIAGNOSTICS }
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 90c469e..e0fb924 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -237,7 +237,7 @@
 
 use std::cmp;
 use std::fmt;
-use std::fs::{self, File};
+use std::fs;
 use std::io::{self, Read};
 use std::path::{Path, PathBuf};
 use std::time::Instant;
@@ -870,10 +870,7 @@
             }
         }
         CrateFlavor::Rmeta => {
-            let mut file = File::open(filename).map_err(|_|
-                format!("could not open file: '{}'", filename.display()))?;
-            let mut buf = vec![];
-            file.read_to_end(&mut buf).map_err(|_|
+            let buf = fs::read(filename).map_err(|_|
                 format!("failed to read rmeta metadata: '{}'", filename.display()))?;
             OwningRef::new(buf).map_owner_box().erase_owner()
         }
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index cc332ac..c0ce32c 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -92,9 +92,19 @@
             let cfg = items.iter().find(|k| {
                 k.check_name("cfg")
             }).and_then(|a| a.meta_item_list());
-            let cfg = cfg.map(|list| {
-                list[0].meta_item().unwrap().clone()
-            });
+            let cfg = if let Some(list) = cfg {
+                if list.is_empty() {
+                    self.tcx.sess.span_err(m.span(), "`cfg()` must have an argument");
+                    return;
+                } else if let cfg @ Some(..) = list[0].meta_item() {
+                    cfg.cloned()
+                } else {
+                    self.tcx.sess.span_err(list[0].span(), "invalid argument for `cfg(..)`");
+                    return;
+                }
+            } else {
+                None
+            };
             let foreign_items = fm.items.iter()
                 .map(|it| self.tcx.hir.local_def_id(it.id))
                 .collect();
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 8ff3274..c542f65 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -303,7 +303,6 @@
     Generator(Lazy<GeneratorData<'tcx>>),
     Trait(Lazy<TraitData<'tcx>>),
     Impl(Lazy<ImplData<'tcx>>),
-    AutoImpl(Lazy<ImplData<'tcx>>),
     Method(Lazy<MethodData<'tcx>>),
     AssociatedType(AssociatedContainer),
     AssociatedConst(AssociatedContainer, u8),
@@ -359,7 +358,6 @@
             EntryKind::Trait(ref trait_data) => {
                 trait_data.hash_stable(hcx, hasher);
             }
-            EntryKind::AutoImpl(ref impl_data) |
             EntryKind::Impl(ref impl_data) => {
                 impl_data.hash_stable(hcx, hasher);
             }
@@ -521,3 +519,7 @@
     pub layout: mir::GeneratorLayout<'tcx>,
 }
 impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
+
+// Tags used for encoding Spans:
+pub const TAG_VALID_SPAN: u8 = 0;
+pub const TAG_INVALID_SPAN: u8 = 1;
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index a54f155..ea05a51 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -11,9 +11,10 @@
 [dependencies]
 bitflags = "1.0"
 graphviz = { path = "../libgraphviz" }
-log = "0.3"
+log = "0.4"
 log_settings = "0.1.1"
 rustc = { path = "../librustc" }
+rustc_back = { path = "../librustc_back" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
@@ -23,4 +24,3 @@
 syntax_pos = { path = "../libsyntax_pos" }
 byteorder = { version = "1.1", features = ["i128"] }
 rustc_apfloat = { path = "../librustc_apfloat" }
-rustc_trans_utils = { path = "../librustc_trans_utils" }
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index bc1b3ed..7bd3b6e 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -10,7 +10,7 @@
 
 use syntax_pos::Span;
 use rustc::middle::region::ScopeTree;
-use rustc::mir::{BorrowKind, Field, Local, Location, Operand};
+use rustc::mir::{BorrowKind, Field, Local, LocalKind, Location, Operand};
 use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::ty::{self, RegionKind};
 use rustc_data_structures::indexed_vec::Idx;
@@ -62,13 +62,7 @@
                 Origin::Mir,
             );
 
-            err.span_label(
-                span,
-                format!(
-                    "value {} here after move",
-                    desired_action.as_verb_in_past_tense()
-                ),
-            );
+            let mut is_loop_move = false;
             for moi in mois {
                 let move_msg = ""; //FIXME: add " (into closure)"
                 let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span;
@@ -77,11 +71,48 @@
                         span,
                         format!("value moved{} here in previous iteration of loop", move_msg),
                     );
+                    is_loop_move = true;
                 } else {
                     err.span_label(move_span, format!("value moved{} here", move_msg));
                 };
             }
-            //FIXME: add note for closure
+            if !is_loop_move {
+                err.span_label(
+                    span,
+                    format!(
+                        "value {} here after move",
+                        desired_action.as_verb_in_past_tense()
+                    ),
+                );
+            }
+
+            if let Some(ty) = self.retrieve_type_for_place(place) {
+                let needs_note = match ty.sty {
+                    ty::TypeVariants::TyClosure(id, _) => {
+                        let tables = self.tcx.typeck_tables_of(id);
+                        let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
+                        let hir_id = self.tcx.hir.node_to_hir_id(node_id);
+                        if let Some(_) = tables.closure_kind_origins().get(hir_id) {
+                            false
+                        } else {
+                            true
+                        }
+                    },
+                    _ => true,
+                };
+
+                if needs_note {
+                    let note_msg = match self.describe_place(place) {
+                        Some(name) => format!("`{}`", name),
+                        None => "value".to_owned(),
+                    };
+
+                    err.note(&format!("move occurs because {} has type `{}`, \
+                                       which does not implement the `Copy` trait",
+                                       note_msg, ty));
+                }
+            }
+
             err.emit();
         }
     }
@@ -537,19 +568,39 @@
         (place, span): (&Place<'tcx>, Span),
         assigned_span: Span,
     ) {
+        let is_arg = if let Place::Local(local) = place {
+            if let LocalKind::Arg = self.mir.local_kind(*local) {
+                true
+            } else {
+                false
+            }
+        } else {
+            false
+        };
+
         let mut err = self.tcx.cannot_reassign_immutable(
             span,
             &self.describe_place(place).unwrap_or("_".to_owned()),
+            is_arg,
             Origin::Mir,
         );
-        err.span_label(span, "cannot assign twice to immutable variable");
+        let msg = if is_arg {
+            "cannot assign to immutable argument"
+        } else {
+            "cannot assign twice to immutable variable"
+        };
         if span != assigned_span {
-            let value_msg = match self.describe_place(place) {
-                Some(name) => format!("`{}`", name),
-                None => "value".to_owned(),
-            };
-            err.span_label(assigned_span, format!("first assignment to {}", value_msg));
+            if is_arg {
+                err.span_label(assigned_span, "argument not declared as `mut`");
+            } else {
+                let value_msg = match self.describe_place(place) {
+                    Some(name) => format!("`{}`", name),
+                    None => "value".to_owned(),
+                };
+                err.span_label(assigned_span, format!("first assignment to {}", value_msg));
+            }
         }
+        err.span_label(span, msg);
         err.emit();
     }
 }
@@ -688,7 +739,7 @@
                 ty::TyAdt(def, _) => if def.is_enum() {
                     format!("{}", field.index())
                 } else {
-                    format!("{}", def.struct_variant().fields[field.index()].name)
+                    format!("{}", def.non_enum_variant().fields[field.index()].name)
                 },
                 ty::TyTuple(_, _) => format!("{}", field.index()),
                 ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => {
@@ -718,7 +769,24 @@
     }
 
     // Retrieve span of given borrow from the current MIR representation
-    fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
+    pub fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
         self.mir.source_info(borrow.location).span
     }
+
+    // Retrieve type of a place for the current MIR representation
+    fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option<ty::Ty> {
+        match place {
+            Place::Local(local) => {
+                let local = &self.mir.local_decls[*local];
+                Some(local.ty)
+            },
+            Place::Static(ref st) => Some(st.ty),
+            Place::Projection(ref proj) => {
+                match proj.elem {
+                    ProjectionElem::Field(_, ty) => Some(ty),
+                    _ => None,
+                }
+            },
+        }
+    }
 }
diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs
index 69a08c7..61d6c14 100644
--- a/src/librustc_mir/borrow_check/flows.rs
+++ b/src/librustc_mir/borrow_check/flows.rs
@@ -88,7 +88,8 @@
             };
             saw_one = true;
             let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
-            s.push_str(&format!("{}", borrow_data));
+            s.push_str(&format!("{}{}", borrow_data,
+                                if borrow.is_activation() { "@active" } else { "" }));
         });
         s.push_str("] ");
 
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 1e8a679..d6937c4 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -209,12 +209,21 @@
     };
     let flow_inits = flow_inits; // remove mut
 
+    let movable_generator = !match tcx.hir.get(id) {
+        hir::map::Node::NodeExpr(&hir::Expr {
+            node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)),
+            ..
+        }) => true,
+        _ => false,
+    };
+
     let mut mbcx = MirBorrowckCtxt {
         tcx: tcx,
         mir: mir,
         node_id: id,
         move_data: &mdpe.move_data,
         param_env: param_env,
+        movable_generator,
         locals_are_invalidated_at_exit: match tcx.hir.body_owner_kind(id) {
             hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false,
             hir::BodyOwnerKind::Fn => true,
@@ -277,6 +286,7 @@
     node_id: ast::NodeId,
     move_data: &'cx MoveData<'tcx>,
     param_env: ParamEnv<'gcx>,
+    movable_generator: bool,
     /// This keeps track of whether local variables are free-ed when the function
     /// exits even without a `StorageDead`, which appears to be the case for
     /// constants.
@@ -392,7 +402,7 @@
                         self.mutate_place(
                             context,
                             (output, span),
-                            Deep,
+                            if o.is_rw { Deep } else { Shallow(None) },
                             if o.is_rw { WriteAndRead } else { JustWrite },
                             flow_state,
                         );
@@ -534,6 +544,18 @@
                 drop: _,
             } => {
                 self.consume_operand(ContextKind::Yield.new(loc), (value, span), flow_state);
+
+                if self.movable_generator {
+                    // Look for any active borrows to locals
+                    let domain = flow_state.borrows.operator();
+                    let data = domain.borrows();
+                    flow_state.borrows.with_elems_outgoing(|borrows| {
+                        for i in borrows {
+                            let borrow = &data[i.borrow_index()];
+                            self.check_for_local_borrow(borrow, span);
+                        }
+                    });
+                }
             }
 
             TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
@@ -552,6 +574,7 @@
                 });
             }
             TerminatorKind::Goto { target: _ }
+            | TerminatorKind::Abort
             | TerminatorKind::Unreachable
             | TerminatorKind::FalseEdges { .. } => {
                 // no data used, thus irrelevant to borrowck
@@ -1098,6 +1121,45 @@
         }
     }
 
+    /// Reports an error if this is a borrow of local data.
+    /// This is called for all Yield statements on movable generators
+    fn check_for_local_borrow(
+        &mut self,
+        borrow: &BorrowData<'tcx>,
+        yield_span: Span)
+    {
+        fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
+            match place {
+                Place::Static(..) => false,
+                Place::Local(..) => true,
+                Place::Projection(box proj) => {
+                    match proj.elem {
+                        // Reborrow of already borrowed data is ignored
+                        // Any errors will be caught on the initial borrow
+                        ProjectionElem::Deref => false,
+
+                        // For interior references and downcasts, find out if the base is local
+                        ProjectionElem::Field(..) |
+                        ProjectionElem::Index(..) |
+                        ProjectionElem::ConstantIndex { .. } |
+                        ProjectionElem::Subslice { .. } |
+                        ProjectionElem::Downcast(..) => {
+                            borrow_of_local_data(&proj.base)
+                        }
+                    }
+                }
+            }
+        }
+
+        debug!("check_for_local_borrow({:?})", borrow);
+
+        if borrow_of_local_data(&borrow.borrowed_place) {
+            self.tcx.cannot_borrow_across_generator_yield(self.retrieve_borrow_span(borrow),
+                                                          yield_span,
+                                                          Origin::Mir).emit();
+        }
+    }
+
     fn check_activations(
         &mut self,
         location: Location,
@@ -2011,6 +2073,8 @@
             let borrowed = &data[i.borrow_index()];
 
             if self.places_conflict(&borrowed.borrowed_place, place, access) {
+                debug!("each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}",
+                       i, borrowed, place, access);
                 let ctrl = op(self, i, borrowed);
                 if ctrl == Control::Break {
                     return;
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index bdacd83..3a39eb5 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -69,6 +69,7 @@
     fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
         match ty_context {
             TyContext::ReturnTy(source_info) |
+            TyContext::YieldTy(source_info) |
             TyContext::LocalDecl { source_info, .. } => {
                 span_bug!(source_info.span,
                           "should not be visiting outside of the CFG: {:?}",
@@ -130,38 +131,91 @@
             });
     }
 
+    // Add the reborrow constraint at `location` so that `borrowed_place`
+    // is valid for `borrow_region`.
     fn add_reborrow_constraint(
         &mut self,
         location: Location,
         borrow_region: ty::Region<'tcx>,
         borrowed_place: &Place<'tcx>,
     ) {
-        if let Projection(ref proj) = *borrowed_place {
-            let PlaceProjection { ref base, ref elem } = **proj;
+        let mut borrowed_place = borrowed_place;
 
-            if let ProjectionElem::Deref = *elem {
-                let tcx = self.infcx.tcx;
-                let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
-                let base_sty = &base_ty.sty;
+        debug!("add_reborrow_constraint({:?}, {:?}, {:?})",
+               location, borrow_region, borrowed_place);
+        while let Projection(box PlaceProjection { base, elem }) = borrowed_place {
+            debug!("add_reborrow_constraint - iteration {:?}", borrowed_place);
 
-                if let ty::TyRef(base_region, ty::TypeAndMut { ty: _, mutbl }) = *base_sty {
-                    match mutbl {
-                        hir::Mutability::MutImmutable => {}
+            match *elem {
+                ProjectionElem::Deref => {
+                    let tcx = self.infcx.tcx;
+                    let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
 
-                        hir::Mutability::MutMutable => {
-                            self.add_reborrow_constraint(location, borrow_region, base);
+                    debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
+                    match base_ty.sty {
+                        ty::TyRef(ref_region, ty::TypeAndMut { ty: _, mutbl }) => {
+                            let span = self.mir.source_info(location).span;
+                            self.regioncx.add_outlives(
+                                span,
+                                ref_region.to_region_vid(),
+                                borrow_region.to_region_vid(),
+                                location.successor_within_block(),
+                            );
+
+                            match mutbl {
+                                hir::Mutability::MutImmutable => {
+                                    // Immutable reference. We don't need the base
+                                    // to be valid for the entire lifetime of
+                                    // the borrow.
+                                    break
+                                }
+                                hir::Mutability::MutMutable => {
+                                    // Mutable reference. We *do* need the base
+                                    // to be valid, because after the base becomes
+                                    // invalid, someone else can use our mutable deref.
+
+                                    // This is in order to make the following function
+                                    // illegal:
+                                    // ```
+                                    // fn unsafe_deref<'a, 'b>(x: &'a &'b mut T) -> &'b mut T {
+                                    //     &mut *x
+                                    // }
+                                    // ```
+                                    //
+                                    // As otherwise you could clone `&mut T` using the
+                                    // following function:
+                                    // ```
+                                    // fn bad(x: &mut T) -> (&mut T, &mut T) {
+                                    //     let my_clone = unsafe_deref(&'a x);
+                                    //     ENDREGION 'a;
+                                    //     (my_clone, x)
+                                    // }
+                                    // ```
+                                }
+                            }
                         }
+                        ty::TyRawPtr(..) => {
+                            // deref of raw pointer, guaranteed to be valid
+                            break
+                        }
+                        ty::TyAdt(def, _) if def.is_box() => {
+                            // deref of `Box`, need the base to be valid - propagate
+                        }
+                        _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place)
                     }
-
-                    let span = self.mir.source_info(location).span;
-                    self.regioncx.add_outlives(
-                        span,
-                        base_region.to_region_vid(),
-                        borrow_region.to_region_vid(),
-                        location.successor_within_block(),
-                    );
+                }
+                ProjectionElem::Field(..) |
+                ProjectionElem::Downcast(..) |
+                ProjectionElem::Index(..) |
+                ProjectionElem::ConstantIndex { .. } |
+                ProjectionElem::Subslice { .. } => {
+                    // other field access
                 }
             }
+
+            // The "propagate" case. We need to check that our base is valid
+            // for the borrow's lifetime.
+            borrowed_place = base;
         }
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index da136a3..9a2f98d 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -989,7 +989,7 @@
 
         if let (Some(f), Some(o)) = (fr_name, outlived_fr_name) {
             let tables = infcx.tcx.typeck_tables_of(mir_def_id);
-            let nice = NiceRegionError::new(infcx.tcx, blame_span, o, f, Some(tables));
+            let nice = NiceRegionError::new_from_span(infcx.tcx, blame_span, o, f, Some(tables));
             if let Some(ErrorReported) = nice.try_report() {
                 return;
             }
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 4aee48b..c54acda 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, ClosureSubsts, Ty, TypeFoldable};
+use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
 use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -90,6 +90,21 @@
         *constant = self.renumber_regions(ty_context, &*constant);
     }
 
+    fn visit_generator_interior(&mut self,
+                                interior: &mut GeneratorInterior<'tcx>,
+                                location: Location) {
+        debug!(
+            "visit_generator_interior(interior={:?}, location={:?})",
+            interior,
+            location,
+        );
+
+        let ty_context = TyContext::Location(location);
+        *interior = self.renumber_regions(ty_context, interior);
+
+        debug!("visit_generator_interior: interior={:?}", interior);
+    }
+
     fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
         debug!(
             "visit_closure_substs(substs={:?}, location={:?})",
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index 9e88a63..b1aeae0 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -60,6 +60,15 @@
             self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty);
         }
 
+        assert!(
+            mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() ||
+            mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
+            );
+        if let Some(mir_yield_ty) = mir.yield_ty {
+            let ur_yield_ty = universal_regions.yield_ty.unwrap();
+            self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty);
+        }
+
         // Return types are a bit more complex. They may contain existential `impl Trait`
         // types.
         debug!(
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
index 50b38f9..8a0578a 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
@@ -214,6 +214,7 @@
             // associated types here and possibly recursively process.
             for ty in dtorck_types {
                 let ty = self.cx.normalize(&ty, location);
+                let ty = self.cx.infcx.resolve_type_and_region_vars_if_possible(&ty);
                 match ty.sty {
                     ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
                         let cause = Cause::DropVar(dropped_local, location);
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 4c8a171..901b73c 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -780,6 +780,7 @@
         match term.kind {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
+            | TerminatorKind::Abort
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
@@ -1082,6 +1083,9 @@
             TerminatorKind::Resume => if !is_cleanup {
                 span_mirbug!(self, block_data, "resume on non-cleanup block!")
             },
+            TerminatorKind::Abort => if !is_cleanup {
+                span_mirbug!(self, block_data, "abort on non-cleanup block!")
+            },
             TerminatorKind::Return => if is_cleanup {
                 span_mirbug!(self, block_data, "return on cleanup block")
             },
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 45604d5..e47e3c7 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -96,6 +96,8 @@
     /// our special inference variable there, we would mess that up.
     pub region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
 
+    pub yield_ty: Option<Ty<'tcx>>,
+
     relations: UniversalRegionRelations,
 }
 
@@ -505,6 +507,13 @@
             num_universals
         );
 
+        let yield_ty = match defining_ty {
+            DefiningTy::Generator(def_id, substs, _) => {
+                Some(substs.generator_yield_ty(def_id, self.infcx.tcx))
+            }
+            _ => None,
+        };
+
         UniversalRegions {
             indices,
             fr_static,
@@ -516,6 +525,7 @@
             unnormalized_output_ty,
             unnormalized_input_tys,
             region_bound_pairs: self.region_bound_pairs,
+            yield_ty: yield_ty,
             relations: self.relations,
         }
     }
@@ -584,13 +594,9 @@
 
             DefiningTy::FnDef(_, substs) => substs,
 
-            // When we encounter other sorts of constant
-            // expressions, such as the `22` in `[foo; 22]`, we can
-            // get the type `usize` here. For now, just return an
-            // empty vector of substs in this case, since there are no
-            // generics in scope in such expressions right now.
+            // When we encounter a constant body, just return whatever
+            // substitutions are in scope for that constant.
             DefiningTy::Const(_) => {
-                assert!(identity_substs.is_empty());
                 identity_substs
             }
         };
@@ -654,9 +660,8 @@
                 sig.inputs_and_output()
             }
 
-            // This happens on things like `[foo; 22]`. Hence, no
-            // inputs, one output, but it seems like we need a more
-            // general way to handle this category of MIR.
+            // For a constant body, there are no inputs, and one
+            // "output" (the type of the constant).
             DefiningTy::Const(ty) => ty::Binder::dummy(tcx.mk_type_list(iter::once(ty))),
         }
     }
@@ -799,10 +804,12 @@
     /// during initialization. Relies on the `indices` map having been
     /// fully initialized.
     pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
-        match r {
-            ty::ReEarlyBound(..) | ty::ReStatic => *self.indices.get(&r).unwrap(),
-            ty::ReVar(..) => r.to_region_vid(),
-            _ => bug!("cannot convert `{:?}` to a region vid", r),
+        if let ty::ReVar(..) = r {
+            r.to_region_vid()
+        } else {
+            *self.indices.get(&r).unwrap_or_else(|| {
+                bug!("cannot convert `{:?}` to a region vid", r)
+            })
         }
     }
 
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index ee0b7bb..d3cc952 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -392,7 +392,7 @@
                     ast::IntTy::I32 => ConstInt::I32(-1),
                     ast::IntTy::I64 => ConstInt::I64(-1),
                     ast::IntTy::I128 => ConstInt::I128(-1),
-                    ast::IntTy::Is => {
+                    ast::IntTy::Isize => {
                         let int_ty = self.hir.tcx().sess.target.isize_ty;
                         let val = ConstIsize::new(-1, int_ty).unwrap();
                         ConstInt::Isize(val)
@@ -424,7 +424,7 @@
                     ast::IntTy::I32 => ConstInt::I32(i32::min_value()),
                     ast::IntTy::I64 => ConstInt::I64(i64::min_value()),
                     ast::IntTy::I128 => ConstInt::I128(i128::min_value()),
-                    ast::IntTy::Is => {
+                    ast::IntTy::Isize => {
                         let int_ty = self.hir.tcx().sess.target.isize_ty;
                         let min = match int_ty {
                             ast::IntTy::I16 => std::i16::MIN as i64,
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index ed33911..3e0ccc7 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -237,7 +237,7 @@
                         ty: ptr_ty,
                         name: None,
                         source_info,
-                        lexical_scope: source_info.scope,
+                        syntactic_scope: source_info.scope,
                         internal: true,
                         is_user_variable: false
                     });
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 23095bc..6cb9217 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -196,16 +196,18 @@
                             pattern: &Pattern<'tcx>)
                             -> Option<VisibilityScope> {
         assert!(!(var_scope.is_some() && lint_level.is_explicit()),
-               "can't have both a var and a lint scope at the same time");
+                "can't have both a var and a lint scope at the same time");
+        let mut syntactic_scope = self.visibility_scope;
         self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| {
             if var_scope.is_none() {
                 var_scope = Some(this.new_visibility_scope(scope_span,
                                                            LintLevel::Inherited,
                                                            None));
                 // If we have lints, create a new visibility scope
-                // that marks the lints for the locals.
+                // that marks the lints for the locals. See the comment
+                // on the `syntactic_scope` field for why this is needed.
                 if lint_level.is_explicit() {
-                    this.visibility_scope =
+                    syntactic_scope =
                         this.new_visibility_scope(scope_span, lint_level, None);
                 }
             }
@@ -213,12 +215,8 @@
                 span,
                 scope: var_scope.unwrap()
             };
-            this.declare_binding(source_info, mutability, name, var, ty);
+            this.declare_binding(source_info, syntactic_scope, mutability, name, var, ty);
         });
-        // Pop any scope we created for the locals.
-        if let Some(var_scope) = var_scope {
-            self.visibility_scope = var_scope;
-        }
         var_scope
     }
 
@@ -783,21 +781,23 @@
 
     fn declare_binding(&mut self,
                        source_info: SourceInfo,
+                       syntactic_scope: VisibilityScope,
                        mutability: Mutability,
                        name: Name,
                        var_id: NodeId,
                        var_ty: Ty<'tcx>)
                        -> Local
     {
-        debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, source_info={:?})",
-               var_id, name, var_ty, source_info);
+        debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, source_info={:?}, \
+                syntactic_scope={:?})",
+               var_id, name, var_ty, source_info, syntactic_scope);
 
         let var = self.local_decls.push(LocalDecl::<'tcx> {
             mutability,
             ty: var_ty.clone(),
             name: Some(name),
             source_info,
-            lexical_scope: self.visibility_scope,
+            syntactic_scope,
             internal: false,
             is_user_variable: true,
         });
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index b2357b7..bdcbfc0 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -174,12 +174,50 @@
         }
     }
 
+    /// Convert a byte array or byte slice to a byte slice.
+    fn to_slice_operand(&mut self,
+                        block: BasicBlock,
+                        source_info: SourceInfo,
+                        operand: Operand<'tcx>)
+                        -> Operand<'tcx>
+    {
+        let tcx = self.hir.tcx();
+        let ty = operand.ty(&self.local_decls, tcx);
+        debug!("to_slice_operand({:?}, {:?}: {:?})", block, operand, ty);
+        match ty.sty {
+            ty::TyRef(region, mt) => match mt.ty.sty {
+                ty::TyArray(ety, _) => {
+                    let ty = tcx.mk_imm_ref(region, tcx.mk_slice(ety));
+                    let temp = self.temp(ty, source_info.span);
+                    self.cfg.push_assign(block, source_info, &temp,
+                                         Rvalue::Cast(CastKind::Unsize, operand, ty));
+                    Operand::Move(temp)
+                }
+                ty::TySlice(_) => operand,
+                _ => {
+                    span_bug!(source_info.span,
+                              "bad operand {:?}: {:?} to `to_slice_operand`", operand, ty)
+                }
+            }
+            _ => {
+                span_bug!(source_info.span,
+                          "bad operand {:?}: {:?} to `to_slice_operand`", operand, ty)
+            }
+        }
+
+    }
+
     /// Generates the code to perform a test.
     pub fn perform_test(&mut self,
                         block: BasicBlock,
                         place: &Place<'tcx>,
                         test: &Test<'tcx>)
                         -> Vec<BasicBlock> {
+        debug!("perform_test({:?}, {:?}: {:?}, {:?})",
+               block,
+               place,
+               place.ty(&self.local_decls, self.hir.tcx()),
+               test);
         let source_info = self.source_info(test.span);
         match test.kind {
             TestKind::Switch { adt_def, ref variants } => {
@@ -258,45 +296,35 @@
                 ret
             }
 
-            TestKind::Eq { value, mut ty } => {
+            TestKind::Eq { value, ty } => {
+                let tcx = self.hir.tcx();
                 let mut val = Operand::Copy(place.clone());
 
                 // If we're using b"..." as a pattern, we need to insert an
                 // unsizing coercion, as the byte string has the type &[u8; N].
-                let expect = if let ConstVal::ByteStr(bytes) = value.val {
-                    let tcx = self.hir.tcx();
-
-                    // Unsize the place to &[u8], too, if necessary.
-                    if let ty::TyRef(region, mt) = ty.sty {
-                        if let ty::TyArray(_, _) = mt.ty.sty {
-                            ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
-                            let val_slice = self.temp(ty, test.span);
-                            self.cfg.push_assign(block, source_info, &val_slice,
-                                                 Rvalue::Cast(CastKind::Unsize, val, ty));
-                            val = Operand::Move(val_slice);
-                        }
-                    }
-
-                    assert!(ty.is_slice());
-
+                //
+                // We want to do this even when the scrutinee is a reference to an
+                // array, so we can call `<[u8]>::eq` rather than having to find an
+                // `<[u8; N]>::eq`.
+                let (expect, val) = if let ConstVal::ByteStr(bytes) = value.val {
                     let array_ty = tcx.mk_array(tcx.types.u8, bytes.data.len() as u64);
                     let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
                     let array = self.literal_operand(test.span, array_ref, Literal::Value {
                         value
                     });
 
-                    let slice = self.temp(ty, test.span);
-                    self.cfg.push_assign(block, source_info, &slice,
-                                         Rvalue::Cast(CastKind::Unsize, array, ty));
-                    Operand::Move(slice)
+                    let val = self.to_slice_operand(block, source_info, val);
+                    let slice = self.to_slice_operand(block, source_info, array);
+                    (slice, val)
                 } else {
-                    self.literal_operand(test.span, ty, Literal::Value {
+                    (self.literal_operand(test.span, ty, Literal::Value {
                         value
-                    })
+                    }), val)
                 };
 
                 // Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
                 let fail = self.cfg.start_new_block();
+                let ty = expect.ty(&self.local_decls, tcx);
                 if let ty::TyRef(_, mt) = ty.sty {
                     assert!(ty.is_slice());
                     let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 8486c63..a3350cb 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -74,7 +74,7 @@
                     ast::UintTy::U32 => ConstInt::U32(0),
                     ast::UintTy::U64 => ConstInt::U64(0),
                     ast::UintTy::U128 => ConstInt::U128(0),
-                    ast::UintTy::Us => {
+                    ast::UintTy::Usize => {
                         let uint_ty = self.hir.tcx().sess.target.usize_ty;
                         let val = ConstUsize::new(0, uint_ty).unwrap();
                         ConstInt::Usize(val)
@@ -95,7 +95,7 @@
                     ast::IntTy::I32 => ConstInt::I32(0),
                     ast::IntTy::I64 => ConstInt::I64(0),
                     ast::IntTy::I128 => ConstInt::I128(0),
-                    ast::IntTy::Is => {
+                    ast::IntTy::Isize => {
                         let int_ty = self.hir.tcx().sess.target.isize_ty;
                         let val = ConstIsize::new(0, int_ty).unwrap();
                         ConstInt::Isize(val)
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 51ebb78..57059cd 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -20,6 +20,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::NodeMap;
+use rustc_back::PanicStrategy;
 use rustc_const_eval::pattern::{BindingMode, PatternKind};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use shim;
@@ -353,6 +354,27 @@
     };
 }
 
+fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                         fn_id: ast::NodeId,
+                                         abi: Abi)
+                                         -> bool {
+
+    // Not callable from C, so we can safely unwind through these
+    if abi == Abi::Rust || abi == Abi::RustCall { return false; }
+
+    // We never unwind, so it's not relevant to stop an unwind
+    if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; }
+
+    // We cannot add landing pads, so don't add one
+    if tcx.sess.no_landing_pads() { return false; }
+
+    // This is a special case: some functions have a C abi but are meant to
+    // unwind anyway. Don't stop them.
+    if tcx.has_attr(tcx.hir.local_def_id(fn_id), "unwind") { return false; }
+
+    return true;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 /// the main entry point for building MIR for a function
 
@@ -383,6 +405,10 @@
     let source_info = builder.source_info(span);
     let call_site_s = (call_site_scope, source_info);
     unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| {
+        if should_abort_on_panic(tcx, fn_id, abi) {
+            builder.schedule_abort();
+        }
+
         let arg_scope_s = (arg_scope, source_info);
         unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| {
             builder.args_and_body(block, &arguments, arg_scope, &body.value)
@@ -409,6 +435,9 @@
         // RustCall pseudo-ABI untuples the last argument.
         spread_arg = Some(Local::new(arguments.len()));
     }
+    let closure_expr_id = tcx.hir.local_def_id(fn_id);
+    info!("fn_id {:?} has attrs {:?}", closure_expr_id,
+          tcx.get_attrs(closure_expr_id));
 
     // Gather the upvars of a closure, if any.
     let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
@@ -578,7 +607,7 @@
                     scope: ARGUMENT_VISIBILITY_SCOPE,
                     span: pattern.map_or(self.fn_span, |pat| pat.span)
                 },
-                lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+                syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
                 name,
                 internal: false,
                 is_user_variable: false,
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 630d0bf..ddb4bf0 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -612,6 +612,16 @@
         }
     }
 
+    // Schedule an abort block - this is used for some ABIs that cannot unwind
+    pub fn schedule_abort(&mut self) -> BasicBlock {
+        self.scopes[0].needs_cleanup = true;
+        let abortblk = self.cfg.start_new_cleanup_block();
+        let source_info = self.scopes[0].source_info(self.fn_span);
+        self.cfg.terminate(abortblk, source_info, TerminatorKind::Abort);
+        self.cached_resume_block = Some(abortblk);
+        abortblk
+    }
+
     // Scheduling drops
     // ================
     /// Indicates that `place` should be dropped on exit from
diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs
index 7f243ad..b1f73bf 100644
--- a/src/librustc_mir/dataflow/at_location.rs
+++ b/src/librustc_mir/dataflow/at_location.rs
@@ -149,6 +149,18 @@
     fn reconstruct_statement_effect(&mut self, loc: Location) {
         self.stmt_gen.reset_to_empty();
         self.stmt_kill.reset_to_empty();
+        {
+            let mut sets = BlockSets {
+                on_entry: &mut self.curr_state,
+                gen_set: &mut self.stmt_gen,
+                kill_set: &mut self.stmt_kill,
+            };
+            self.base_results
+                .operator()
+                .before_statement_effect(&mut sets, loc);
+        }
+        self.apply_local_effect(loc);
+
         let mut sets = BlockSets {
             on_entry: &mut self.curr_state,
             gen_set: &mut self.stmt_gen,
@@ -162,6 +174,18 @@
     fn reconstruct_terminator_effect(&mut self, loc: Location) {
         self.stmt_gen.reset_to_empty();
         self.stmt_kill.reset_to_empty();
+        {
+            let mut sets = BlockSets {
+                on_entry: &mut self.curr_state,
+                gen_set: &mut self.stmt_gen,
+                kill_set: &mut self.stmt_kill,
+            };
+            self.base_results
+                .operator()
+                .before_terminator_effect(&mut sets, loc);
+        }
+        self.apply_local_effect(loc);
+
         let mut sets = BlockSets {
             on_entry: &mut self.curr_state,
             gen_set: &mut self.stmt_gen,
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index b79e044..fb3cb15 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -18,7 +18,7 @@
 use dot;
 use dot::IntoCow;
 
-use std::fs::File;
+use std::fs;
 use std::io;
 use std::io::prelude::*;
 use std::marker::PhantomData;
@@ -67,7 +67,7 @@
     dot::render(&g, &mut v)?;
     debug!("print_borrowck_graph_to path: {} node_id: {}",
            path.display(), mbcx.node_id);
-    File::create(path).and_then(|mut f| f.write_all(&v))
+    fs::write(path, v)
 }
 
 pub type Node = BasicBlock;
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index c39ae10..f543a33 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -131,7 +131,7 @@
 }
 
 impl ReserveOrActivateIndex {
-    fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2)) }
+    fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new(i.index() * 2) }
     fn active(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2) + 1) }
 
     pub(crate) fn is_reservation(self) -> bool { self.index() % 2 == 0 }
@@ -416,7 +416,20 @@
                 self.kill_borrows_on_local(sets, &local, is_activations)
             }
 
-            mir::StatementKind::InlineAsm { .. } |
+            mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
+                for (output, kind) in outputs.iter().zip(&asm.outputs) {
+                    if !kind.is_indirect && !kind.is_rw {
+                        // Make sure there are no remaining borrows for direct
+                        // output variables.
+                        if let Place::Local(ref local) = *output {
+                            // FIXME: Handle the case in which we're assigning over
+                            // a projection (`foo.bar`).
+                            self.kill_borrows_on_local(sets, local, is_activations);
+                        }
+                    }
+                }
+            }
+
             mir::StatementKind::SetDiscriminant { .. } |
             mir::StatementKind::StorageLive(..) |
             mir::StatementKind::Validate(..) |
@@ -496,6 +509,7 @@
                     }
                 }
             }
+            mir::TerminatorKind::Abort |
             mir::TerminatorKind::SwitchInt {..} |
             mir::TerminatorKind::Drop {..} |
             mir::TerminatorKind::DropAndReplace {..} |
@@ -635,6 +649,13 @@
         // `_sets`.
     }
 
+    fn before_statement_effect(&self,
+                               sets: &mut BlockSets<ReserveOrActivateIndex>,
+                               location: Location) {
+        debug!("Reservations::before_statement_effect sets: {:?} location: {:?}", sets, location);
+        self.0.kill_loans_out_of_scope_at_location(sets, location, false);
+    }
+
     fn statement_effect(&self,
                         sets: &mut BlockSets<ReserveOrActivateIndex>,
                         location: Location) {
@@ -642,6 +663,13 @@
         self.0.statement_effect_on_borrows(sets, location, false);
     }
 
+    fn before_terminator_effect(&self,
+                                sets: &mut BlockSets<ReserveOrActivateIndex>,
+                                location: Location) {
+        debug!("Reservations::before_terminator_effect sets: {:?} location: {:?}", sets, location);
+        self.0.kill_loans_out_of_scope_at_location(sets, location, false);
+    }
+
     fn terminator_effect(&self,
                          sets: &mut BlockSets<ReserveOrActivateIndex>,
                          location: Location) {
@@ -682,6 +710,13 @@
         // `_sets`.
     }
 
+    fn before_statement_effect(&self,
+                               sets: &mut BlockSets<ReserveOrActivateIndex>,
+                               location: Location) {
+        debug!("ActiveBorrows::before_statement_effect sets: {:?} location: {:?}", sets, location);
+        self.0.kill_loans_out_of_scope_at_location(sets, location, true);
+    }
+
     fn statement_effect(&self,
                         sets: &mut BlockSets<ReserveOrActivateIndex>,
                         location: Location) {
@@ -689,6 +724,13 @@
         self.0.statement_effect_on_borrows(sets, location, true);
     }
 
+    fn before_terminator_effect(&self,
+                                sets: &mut BlockSets<ReserveOrActivateIndex>,
+                                location: Location) {
+        debug!("ActiveBorrows::before_terminator_effect sets: {:?} location: {:?}", sets, location);
+        self.0.kill_loans_out_of_scope_at_location(sets, location, true);
+    }
+
     fn terminator_effect(&self,
                          sets: &mut BlockSets<ReserveOrActivateIndex>,
                          location: Location) {
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 83c46e0..b18fb7c 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -214,6 +214,7 @@
             }
             for j_stmt in 0..statements.len() {
                 let location = Location { block: bb, statement_index: j_stmt };
+                self.flow_state.operator.before_statement_effect(sets, location);
                 self.flow_state.operator.statement_effect(sets, location);
                 if track_intrablock {
                     sets.apply_local_effect();
@@ -222,6 +223,7 @@
 
             if terminator.is_some() {
                 let location = Location { block: bb, statement_index: statements.len() };
+                self.flow_state.operator.before_terminator_effect(sets, location);
                 self.flow_state.operator.terminator_effect(sets, location);
                 if track_intrablock {
                     sets.apply_local_effect();
@@ -365,9 +367,10 @@
     fn mir(&self) -> &'a Mir<'tcx>;
 }
 
-pub fn state_for_location<T: BitDenotation>(loc: Location,
-                                            analysis: &T,
-                                            result: &DataflowResults<T>)
+pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
+                                                  analysis: &T,
+                                                  result: &DataflowResults<T>,
+                                                  mir: &Mir<'tcx>)
     -> IdxSetBuf<T::Idx> {
     let mut entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
 
@@ -381,8 +384,16 @@
         for stmt in 0..loc.statement_index {
             let mut stmt_loc = loc;
             stmt_loc.statement_index = stmt;
+            analysis.before_statement_effect(&mut sets, stmt_loc);
             analysis.statement_effect(&mut sets, stmt_loc);
         }
+
+        // Apply the pre-statement effect of the statement we're evaluating.
+        if loc.statement_index == mir[loc.block].statements.len() {
+            analysis.before_terminator_effect(&mut sets, loc);
+        } else {
+            analysis.before_statement_effect(&mut sets, loc);
+        }
     }
 
     entry
@@ -637,6 +648,21 @@
     /// (For example, establishing the call arguments.)
     fn start_block_effect(&self, entry_set: &mut IdxSet<Self::Idx>);
 
+    /// Similar to `statement_effect`, except it applies
+    /// *just before* the statement rather than *just after* it.
+    ///
+    /// This matters for "dataflow at location" APIs, because the
+    /// before-statement effect is visible while visiting the
+    /// statement, while the after-statement effect only becomes
+    /// visible at the next statement.
+    ///
+    /// Both the before-statement and after-statement effects are
+    /// applied, in that order, before moving for the next
+    /// statement.
+    fn before_statement_effect(&self,
+                               _sets: &mut BlockSets<Self::Idx>,
+                               _location: Location) {}
+
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects of evaluating statement.
     ///
@@ -651,6 +677,21 @@
                         sets: &mut BlockSets<Self::Idx>,
                         location: Location);
 
+    /// Similar to `terminator_effect`, except it applies
+    /// *just before* the terminator rather than *just after* it.
+    ///
+    /// This matters for "dataflow at location" APIs, because the
+    /// before-terminator effect is visible while visiting the
+    /// terminator, while the after-terminator effect only becomes
+    /// visible at the terminator's successors.
+    ///
+    /// Both the before-terminator and after-terminator effects are
+    /// applied, in that order, before moving for the next
+    /// terminator.
+    fn before_terminator_effect(&self,
+                                _sets: &mut BlockSets<Self::Idx>,
+                                _location: Location) {}
+
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects of evaluating
     /// the terminator.
@@ -771,6 +812,7 @@
         match bb_data.terminator().kind {
             mir::TerminatorKind::Return |
             mir::TerminatorKind::Resume |
+            mir::TerminatorKind::Abort |
             mir::TerminatorKind::GeneratorDrop |
             mir::TerminatorKind::Unreachable => {}
             mir::TerminatorKind::Goto { ref target } |
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index c20beb7..cd36282 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -278,6 +278,16 @@
                 }
                 self.gather_rvalue(rval);
             }
+            StatementKind::InlineAsm { ref outputs, ref inputs, ref asm } => {
+                for (output, kind) in outputs.iter().zip(&asm.outputs) {
+                    if !kind.is_indirect {
+                        self.gather_init(output, InitKind::Deep);
+                    }
+                }
+                for input in inputs {
+                    self.gather_operand(input);
+                }
+            }
             StatementKind::StorageLive(_) => {}
             StatementKind::StorageDead(local) => {
                 self.gather_move(&Place::Local(local));
@@ -286,7 +296,6 @@
                 span_bug!(stmt.source_info.span,
                           "SetDiscriminant should not exist during borrowck");
             }
-            StatementKind::InlineAsm { .. } |
             StatementKind::EndRegion(_) |
             StatementKind::Validate(..) |
             StatementKind::Nop => {}
@@ -334,6 +343,7 @@
         match term.kind {
             TerminatorKind::Goto { target: _ } |
             TerminatorKind::Resume |
+            TerminatorKind::Abort |
             TerminatorKind::GeneratorDrop |
             TerminatorKind::FalseEdges { .. } |
             TerminatorKind::Unreachable => { }
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 306b417..725a1b8 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -27,6 +27,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use syntax::ast;
+use syntax::attr;
 use syntax::symbol::Symbol;
 use rustc::hir;
 use rustc_const_math::{ConstInt, ConstUsize};
@@ -78,8 +79,7 @@
         // Some functions always have overflow checks enabled,
         // however, they may not get codegen'd, depending on
         // the settings for the crate they are translated in.
-        let mut check_overflow = attrs.iter()
-            .any(|item| item.check_name("rustc_inherit_overflow_checks"));
+        let mut check_overflow = attr::contains_name(attrs, "rustc_inherit_overflow_checks");
 
         // Respect -C overflow-checks.
         check_overflow |= tcx.sess.overflow_checks();
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 6f4a28f..b476ea5 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -49,7 +49,7 @@
             IntTy::I32 => v as i32 as u128,
             IntTy::I64 => v as i64 as u128,
             IntTy::I128 => v as u128,
-            IntTy::Is => {
+            IntTy::Isize => {
                 let ty = self.tcx.sess.target.isize_ty;
                 self.int_to_int(v, ty)
             }
@@ -62,7 +62,7 @@
             UintTy::U32 => v as u32 as u128,
             UintTy::U64 => v as u64 as u128,
             UintTy::U128 => v,
-            UintTy::Us => {
+            UintTy::Usize => {
                 let ty = self.tcx.sess.target.usize_ty;
                 self.int_to_uint(v, ty)
             }
@@ -124,8 +124,8 @@
         match ty.sty {
             // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
             TyRawPtr(_) |
-            TyInt(IntTy::Is) |
-            TyUint(UintTy::Us) => Ok(PrimVal::Ptr(ptr)),
+            TyInt(IntTy::Isize) |
+            TyUint(UintTy::Usize) => Ok(PrimVal::Ptr(ptr)),
             TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes),
             _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
         }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index a37cf41..2913f72 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -12,7 +12,7 @@
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
 
-use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, Pointer, PrimVal};
+use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, MemoryPointer, Pointer, PrimVal};
 use super::{Place, EvalContext, StackPopCleanup, ValTy};
 
 use rustc_const_math::ConstInt;
@@ -67,7 +67,7 @@
             layout.align,
             None,
         )?;
-        tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
+        tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
         let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
         let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
         trace!("const_eval: pushing stack frame for global: {}", name);
@@ -81,8 +81,8 @@
 
         while ecx.step()? {}
     }
-    let value = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
-    Ok((value, instance_ty))
+    let alloc = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
+    Ok((MemoryPointer::new(alloc, 0).into(), instance_ty))
 }
 
 pub fn eval_body_as_integer<'a, 'tcx>(
@@ -106,7 +106,7 @@
         TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
         TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
         TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
-        TyInt(IntTy::Is) => ConstInt::Isize(
+        TyInt(IntTy::Isize) => ConstInt::Isize(
             ConstIsize::new(prim as i128 as i64, tcx.sess.target.isize_ty)
                 .expect("miri should already have errored"),
         ),
@@ -115,7 +115,7 @@
         TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
         TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
         TyUint(UintTy::U128) => ConstInt::U128(prim),
-        TyUint(UintTy::Us) => ConstInt::Usize(
+        TyUint(UintTy::Usize) => ConstInt::Usize(
             ConstUsize::new(prim as u64, tcx.sess.target.usize_ty)
                 .expect("miri should already have errored"),
         ),
@@ -488,7 +488,7 @@
                 miri_place = ecx.place_downcast(miri_place, variant).unwrap();
                 &def.variants[variant]
             } else {
-                def.struct_variant()
+                def.non_enum_variant()
             };
             let vec = match ctfe {
                 ConstVal::Aggregate(Struct(v)) => v,
@@ -514,6 +514,7 @@
         TyDynamic(..) => bug!("miri produced a trait object"),
         TyClosure(..) => bug!("miri produced a closure"),
         TyGenerator(..) => bug!("miri produced a generator"),
+        TyGeneratorWitness(..) => bug!("miri produced a generator witness"),
         TyNever => bug!("miri produced a value of the never type"),
         TyProjection(_) => bug!("miri produced a projection"),
         TyAnon(..) => bug!("miri produced an impl Trait type"),
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 89d0e91..baec0fe 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -781,7 +781,7 @@
             }
         }
 
-        if log_enabled!(::log::LogLevel::Trace) {
+        if log_enabled!(::log::Level::Trace) {
             self.dump_local(dest);
         }
 
@@ -950,8 +950,8 @@
     }
 
     pub fn read_global_as_value(&self, gid: GlobalId, layout: TyLayout) -> Value {
-        Value::ByRef(self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"),
-                     layout.align)
+        let alloc = self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached");
+        Value::ByRef(MemoryPointer::new(alloc, 0).into(), layout.align)
     }
 
     pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
@@ -1165,7 +1165,7 @@
                     I32 => 4,
                     I64 => 8,
                     I128 => 16,
-                    Is => self.memory.pointer_size(),
+                    Isize => self.memory.pointer_size(),
                 };
                 PrimValKind::from_int_size(size)
             }
@@ -1178,7 +1178,7 @@
                     U32 => 4,
                     U64 => 8,
                     U128 => 16,
-                    Us => self.memory.pointer_size(),
+                    Usize => self.memory.pointer_size(),
                 };
                 PrimValKind::from_uint_size(size)
             }
@@ -1292,7 +1292,7 @@
                     I32 => 4,
                     I64 => 8,
                     I128 => 16,
-                    Is => self.memory.pointer_size(),
+                    Isize => self.memory.pointer_size(),
                 };
                 self.memory.read_primval(ptr, ptr_align, size, true)?
             }
@@ -1305,7 +1305,7 @@
                     U32 => 4,
                     U64 => 8,
                     U128 => 16,
-                    Us => self.memory.pointer_size(),
+                    Usize => self.memory.pointer_size(),
                 };
                 self.memory.read_primval(ptr, ptr_align, size, false)?
             }
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 47a6bfe..c2989db 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -2,7 +2,7 @@
 //! This separation exists to ensure that no fancy miri features like
 //! interpreting common C functions leak into CTFE.
 
-use rustc::mir::interpret::{EvalResult, PrimVal, MemoryPointer, AccessKind};
+use rustc::mir::interpret::{AllocId, EvalResult, PrimVal, MemoryPointer, AccessKind};
 use super::{EvalContext, Place, ValTy, Memory};
 
 use rustc::mir;
@@ -89,12 +89,12 @@
 
     fn add_lock<'a>(
         _mem: &mut Memory<'a, 'tcx, Self>,
-        _id: u64,
+        _id: AllocId,
     ) {}
 
     fn free_lock<'a>(
         _mem: &mut Memory<'a, 'tcx, Self>,
-        _id: u64,
+        _id: AllocId,
         _len: u64,
     ) -> EvalResult<'tcx> {
         Ok(())
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 671fe29..3a28eae 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -34,15 +34,15 @@
     pub data: M::MemoryData,
 
     /// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate`
-    alloc_kind: HashMap<u64, MemoryKind<M::MemoryKinds>>,
+    alloc_kind: HashMap<AllocId, MemoryKind<M::MemoryKinds>>,
 
     /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations).
-    alloc_map: HashMap<u64, Allocation>,
+    alloc_map: HashMap<AllocId, Allocation>,
 
     /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations).
     ///
     /// Stores statics while they are being processed, before they are interned and thus frozen
-    uninitialized_statics: HashMap<u64, Allocation>,
+    uninitialized_statics: HashMap<AllocId, Allocation>,
 
     /// Number of virtual bytes allocated.
     memory_usage: u64,
@@ -73,17 +73,17 @@
     pub fn allocations<'x>(
         &'x self,
     ) -> impl Iterator<Item = (AllocId, &'x Allocation)> {
-        self.alloc_map.iter().map(|(&id, alloc)| (AllocId(id), alloc))
+        self.alloc_map.iter().map(|(&id, alloc)| (id, alloc))
     }
 
     pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> MemoryPointer {
         let id = self.tcx.interpret_interner.borrow_mut().create_fn_alloc(instance);
-        MemoryPointer::new(AllocId(id), 0)
+        MemoryPointer::new(id, 0)
     }
 
     pub fn allocate_cached(&mut self, bytes: &[u8]) -> MemoryPointer {
         let id = self.tcx.allocate_cached(bytes);
-        MemoryPointer::new(AllocId(id), 0)
+        MemoryPointer::new(id, 0)
     }
 
     /// kind is `None` for statics
@@ -121,7 +121,7 @@
             },
             Some(MemoryKind::MutableStatic) => bug!("don't allocate mutable statics directly")
         }
-        Ok(MemoryPointer::new(AllocId(id), 0))
+        Ok(MemoryPointer::new(id, 0))
     }
 
     pub fn reallocate(
@@ -136,8 +136,8 @@
         if ptr.offset != 0 {
             return err!(ReallocateNonBasePtr);
         }
-        if self.alloc_map.contains_key(&ptr.alloc_id.0) {
-            let alloc_kind = self.alloc_kind[&ptr.alloc_id.0];
+        if self.alloc_map.contains_key(&ptr.alloc_id) {
+            let alloc_kind = self.alloc_kind[&ptr.alloc_id];
             if alloc_kind != kind {
                 return err!(ReallocatedWrongMemoryKind(
                     format!("{:?}", alloc_kind),
@@ -163,7 +163,7 @@
     }
 
     pub fn deallocate_local(&mut self, ptr: MemoryPointer) -> EvalResult<'tcx> {
-        match self.alloc_kind.get(&ptr.alloc_id.0).cloned() {
+        match self.alloc_kind.get(&ptr.alloc_id).cloned() {
             // for a constant like `const FOO: &i32 = &1;` the local containing
             // the `1` is referred to by the global. We transitively marked everything
             // the global refers to as static itself, so we don't free it here
@@ -185,19 +185,19 @@
             return err!(DeallocateNonBasePtr);
         }
 
-        let alloc = match self.alloc_map.remove(&ptr.alloc_id.0) {
+        let alloc = match self.alloc_map.remove(&ptr.alloc_id) {
             Some(alloc) => alloc,
-            None => if self.uninitialized_statics.contains_key(&ptr.alloc_id.0) {
+            None => if self.uninitialized_statics.contains_key(&ptr.alloc_id) {
                 return err!(DeallocatedWrongMemoryKind(
                     "uninitializedstatic".to_string(),
                     format!("{:?}", kind),
                 ))
-            } else if self.tcx.interpret_interner.borrow().get_fn(ptr.alloc_id.0).is_some() {
+            } else if self.tcx.interpret_interner.borrow().get_fn(ptr.alloc_id).is_some() {
                 return err!(DeallocatedWrongMemoryKind(
                     "function".to_string(),
                     format!("{:?}", kind),
                 ))
-            } else if self.tcx.interpret_interner.borrow().get_alloc(ptr.alloc_id.0).is_some() {
+            } else if self.tcx.interpret_interner.borrow().get_alloc(ptr.alloc_id).is_some() {
                 return err!(DeallocatedWrongMemoryKind(
                     "static".to_string(),
                     format!("{:?}", kind),
@@ -207,14 +207,14 @@
             },
         };
 
-        let alloc_kind = self.alloc_kind.remove(&ptr.alloc_id.0).expect("alloc_map out of sync with alloc_kind");
+        let alloc_kind = self.alloc_kind.remove(&ptr.alloc_id).expect("alloc_map out of sync with alloc_kind");
 
         // It is okay for us to still holds locks on deallocation -- for example, we could store data we own
         // in a local, and the local could be deallocated (from StorageDead) before the function returns.
         // However, we should check *something*.  For now, we make sure that there is no conflicting write
         // lock by another frame.  We *have* to permit deallocation if we hold a read lock.
         // TODO: Figure out the exact rules here.
-        M::free_lock(self, ptr.alloc_id.0, alloc.bytes.len() as u64)?;
+        M::free_lock(self, ptr.alloc_id, alloc.bytes.len() as u64)?;
 
         if alloc_kind != kind {
             return err!(DeallocatedWrongMemoryKind(
@@ -295,17 +295,17 @@
 impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
     pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
         // normal alloc?
-        match self.alloc_map.get(&id.0) {
+        match self.alloc_map.get(&id) {
                     Some(alloc) => Ok(alloc),
             // uninitialized static alloc?
-            None => match self.uninitialized_statics.get(&id.0) {
+            None => match self.uninitialized_statics.get(&id) {
                 Some(alloc) => Ok(alloc),
                 None => {
                     let int = self.tcx.interpret_interner.borrow();
                     // static alloc?
-                    int.get_alloc(id.0)
+                    int.get_alloc(id)
                         // no alloc? produce an error
-                        .ok_or_else(|| if int.get_fn(id.0).is_some() {
+                        .ok_or_else(|| if int.get_fn(id).is_some() {
                             EvalErrorKind::DerefFunctionPointer.into()
                         } else {
                             EvalErrorKind::DanglingPointerDeref.into()
@@ -320,17 +320,17 @@
         id: AllocId,
     ) -> EvalResult<'tcx, &mut Allocation> {
         // normal alloc?
-        match self.alloc_map.get_mut(&id.0) {
+        match self.alloc_map.get_mut(&id) {
             Some(alloc) => Ok(alloc),
             // uninitialized static alloc?
-            None => match self.uninitialized_statics.get_mut(&id.0) {
+            None => match self.uninitialized_statics.get_mut(&id) {
                 Some(alloc) => Ok(alloc),
                 None => {
                     let int = self.tcx.interpret_interner.borrow();
                     // no alloc or immutable alloc? produce an error
-                    if int.get_alloc(id.0).is_some() {
+                    if int.get_alloc(id).is_some() {
                         err!(ModifiedConstantMemory)
-                    } else if int.get_fn(id.0).is_some() {
+                    } else if int.get_fn(id).is_some() {
                         err!(DerefFunctionPointer)
                     } else {
                         err!(DanglingPointerDeref)
@@ -348,7 +348,7 @@
         self.tcx
             .interpret_interner
             .borrow()
-            .get_fn(ptr.alloc_id.0)
+            .get_fn(ptr.alloc_id)
             .ok_or(EvalErrorKind::ExecuteMemory.into())
     }
 
@@ -372,21 +372,21 @@
 
             let (alloc, immutable) =
                 // normal alloc?
-                match self.alloc_map.get(&id.0) {
-                    Some(a) => (a, match self.alloc_kind[&id.0] {
+                match self.alloc_map.get(&id) {
+                    Some(a) => (a, match self.alloc_kind[&id] {
                         MemoryKind::Stack => " (stack)".to_owned(),
                         MemoryKind::Machine(m) => format!(" ({:?})", m),
                         MemoryKind::MutableStatic => " (static mut)".to_owned(),
                     }),
                     // uninitialized static alloc?
-                    None => match self.uninitialized_statics.get(&id.0) {
+                    None => match self.uninitialized_statics.get(&id) {
                         Some(a) => (a, " (static in the process of initialization)".to_owned()),
                         None => {
                             let int = self.tcx.interpret_interner.borrow();
                             // static alloc?
-                            match int.get_alloc(id.0) {
+                            match int.get_alloc(id) {
                                 Some(a) => (a, "(immutable)".to_owned()),
-                                None => if let Some(func) = int.get_fn(id.0) {
+                                None => if let Some(func) = int.get_fn(id) {
                                     trace!("{} {}", msg, func);
                     continue;
                                 } else {
@@ -445,7 +445,7 @@
         let leaks: Vec<_> = self.alloc_map
             .keys()
             .filter_map(|key| if kinds[key] != MemoryKind::MutableStatic {
-                Some(AllocId(*key))
+                Some(*key)
             } else {
                 None
             })
@@ -528,7 +528,7 @@
         alloc: AllocId,
         mutability: Mutability,
     ) -> EvalResult<'tcx> {
-        match self.alloc_kind.get(&alloc.0) {
+        match self.alloc_kind.get(&alloc) {
             // do not go into immutable statics
             None |
             // or mutable statics
@@ -550,13 +550,13 @@
             mutability
         );
         if mutability == Mutability::Immutable {
-            let alloc = self.alloc_map.remove(&alloc_id.0);
-            let kind = self.alloc_kind.remove(&alloc_id.0);
+            let alloc = self.alloc_map.remove(&alloc_id);
+            let kind = self.alloc_kind.remove(&alloc_id);
             assert_ne!(kind, Some(MemoryKind::MutableStatic));
-            let uninit = self.uninitialized_statics.remove(&alloc_id.0);
+            let uninit = self.uninitialized_statics.remove(&alloc_id);
             if let Some(alloc) = alloc.or(uninit) {
                 let alloc = self.tcx.intern_const_alloc(alloc);
-                self.tcx.interpret_interner.borrow_mut().intern_at_reserved(alloc_id.0, alloc);
+                self.tcx.interpret_interner.borrow_mut().intern_at_reserved(alloc_id, alloc);
                 // recurse into inner allocations
                 for &alloc in alloc.relocations.values() {
                     self.mark_inner_allocation_initialized(alloc, mutability)?;
@@ -565,17 +565,17 @@
             return Ok(());
         }
         // We are marking the static as initialized, so move it out of the uninit map
-        if let Some(uninit) = self.uninitialized_statics.remove(&alloc_id.0) {
-            self.alloc_map.insert(alloc_id.0, uninit);
+        if let Some(uninit) = self.uninitialized_statics.remove(&alloc_id) {
+            self.alloc_map.insert(alloc_id, uninit);
         }
         // do not use `self.get_mut(alloc_id)` here, because we might have already marked a
         // sub-element or have circular pointers (e.g. `Rc`-cycles)
-        let relocations = match self.alloc_map.get_mut(&alloc_id.0) {
+        let relocations = match self.alloc_map.get_mut(&alloc_id) {
             Some(&mut Allocation {
                      ref mut relocations,
                      ..
                  }) => {
-                match self.alloc_kind.get(&alloc_id.0) {
+                match self.alloc_kind.get(&alloc_id) {
                     // const eval results can refer to "locals".
                     // E.g. `const Foo: &u32 = &1;` refers to the temp local that stores the `1`
                     None |
@@ -587,7 +587,7 @@
                     },
                 }
                 // overwrite or insert
-                self.alloc_kind.insert(alloc_id.0, MemoryKind::MutableStatic);
+                self.alloc_kind.insert(alloc_id, MemoryKind::MutableStatic);
                 // take out the relocations vector to free the borrow on self, so we can call
                 // mark recursively
                 mem::replace(relocations, Default::default())
@@ -600,7 +600,7 @@
         }
         // put back the relocations
         self.alloc_map
-            .get_mut(&alloc_id.0)
+            .get_mut(&alloc_id)
             .expect("checked above")
             .relocations = relocations;
         Ok(())
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 097f769..c2c6b23 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -194,8 +194,9 @@
                     promoted: None,
                 };
                 let layout = self.layout_of(self.place_ty(mir_place))?;
+                let alloc = self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global");
                 Place::Ptr {
-                    ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global"),
+                    ptr: MemoryPointer::new(alloc, 0).into(),
                     align: layout.align,
                     extra: PlaceExtra::None,
                 }
@@ -208,7 +209,7 @@
             }
         };
 
-        if log_enabled!(::log::LogLevel::Trace) {
+        if log_enabled!(::log::Level::Trace) {
             self.dump_local(place);
         }
 
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 140da7e..2b0f904 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -180,7 +180,7 @@
             layout.align,
             None,
         )?;
-        self.tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
+        self.tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
         let internally_mutable = !layout.ty.is_freeze(self.tcx, self.param_env, span);
         let mutability = if mutability == Mutability::Mutable || internally_mutable {
             Mutability::Mutable
@@ -265,7 +265,7 @@
                         layout.align,
                         None,
                     )?;
-                    this.ecx.tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
+                    this.ecx.tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
                     trace!("pushing stack frame for {:?}", index);
                     this.ecx.push_stack_frame(
                         this.instance,
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index 3eef057..c8a0dbd 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -163,6 +163,7 @@
             GeneratorDrop => unimplemented!(),
             DropAndReplace { .. } => unimplemented!(),
             Resume => unimplemented!(),
+            Abort => unimplemented!(),
             FalseEdges { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"),
             Unreachable => return err!(Unreachable),
         }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index a7efdaf..1699ad0 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -24,6 +24,7 @@
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
 #![feature(dyn_trait)]
+#![feature(fs_read_write)]
 #![feature(i128_type)]
 #![feature(inclusive_range_syntax)]
 #![feature(inclusive_range)]
@@ -49,13 +50,13 @@
 #[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
+extern crate rustc_back;
 extern crate rustc_const_math;
 extern crate rustc_const_eval;
 extern crate core; // for NonZero
 extern crate log_settings;
 extern crate rustc_apfloat;
 extern crate byteorder;
-extern crate rustc_trans_utils;
 
 mod diagnostics;
 
@@ -78,4 +79,5 @@
     providers.const_eval = interpret::const_eval_provider;
 }
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_mir, DIAGNOSTICS }
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 0d9976a..f161877 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -149,7 +149,7 @@
 //! The binary of a crate will not only contain machine code for the items
 //! defined in the source code of that crate. It will also contain monomorphic
 //! instantiations of any extern generic functions and of functions marked with
-//! #[inline].
+//! `#[inline]`.
 //! The collection algorithm handles this more or less mono. If it is
 //! about to create a mono item for something with an external `DefId`,
 //! it will take a look if the MIR for that item is available, and if so just
@@ -194,11 +194,12 @@
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::middle::const_val::ConstVal;
-use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
+use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::traits;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
+use rustc::session::config;
 use rustc::mir::{self, Location};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::MonoItem;
@@ -212,6 +213,8 @@
 
 use syntax::attr;
 
+use std::iter;
+
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum MonoItemCollectionMode {
     Eager,
@@ -329,6 +332,8 @@
             tcx.hir.local_def_id(node_id)
         });
 
+        debug!("collect_roots: entry_fn = {:?}", entry_fn);
+
         let mut visitor = RootCollector {
             tcx,
             mode,
@@ -625,6 +630,7 @@
             mir::TerminatorKind::Goto { .. } |
             mir::TerminatorKind::SwitchInt { .. } |
             mir::TerminatorKind::Resume |
+            mir::TerminatorKind::Abort |
             mir::TerminatorKind::Return |
             mir::TerminatorKind::Unreachable |
             mir::TerminatorKind::Assert { .. } => {}
@@ -832,8 +838,8 @@
                 CustomCoerceUnsized::Struct(i) => i
             };
 
-            let source_fields = &source_adt_def.struct_variant().fields;
-            let target_fields = &target_adt_def.struct_variant().fields;
+            let source_fields = &source_adt_def.non_enum_variant().fields;
+            let target_fields = &target_adt_def.non_enum_variant().fields;
 
             assert!(coerce_index < source_fields.len() &&
                     source_fields.len() == target_fields.len());
@@ -904,7 +910,6 @@
             hir::ItemUse(..)         |
             hir::ItemForeignMod(..)  |
             hir::ItemTy(..)          |
-            hir::ItemAutoImpl(..) |
             hir::ItemTrait(..)       |
             hir::ItemTraitAlias(..)  |
             hir::ItemMod(..)         => {
@@ -950,16 +955,8 @@
                 // actually used somewhere. Just declaring them is insufficient.
             }
             hir::ItemFn(..) => {
-                let tcx = self.tcx;
-                let def_id = tcx.hir.local_def_id(item.id);
-
-                if self.is_root(def_id) {
-                    debug!("RootCollector: ItemFn({})",
-                           def_id_to_string(tcx, def_id));
-
-                    let instance = Instance::mono(tcx, def_id);
-                    self.output.push(MonoItem::Fn(instance));
-                }
+                let def_id = self.tcx.hir.local_def_id(item.id);
+                self.push_if_root(def_id);
             }
         }
     }
@@ -972,16 +969,8 @@
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
         match ii.node {
             hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => {
-                let tcx = self.tcx;
-                let def_id = tcx.hir.local_def_id(ii.id);
-
-                if self.is_root(def_id) {
-                    debug!("RootCollector: MethodImplItem({})",
-                           def_id_to_string(tcx, def_id));
-
-                    let instance = Instance::mono(tcx, def_id);
-                    self.output.push(MonoItem::Fn(instance));
-                }
+                let def_id = self.tcx.hir.local_def_id(ii.id);
+                self.push_if_root(def_id);
             }
             _ => { /* Nothing to do here */ }
         }
@@ -1002,6 +991,56 @@
             }
         }
     }
+
+    /// If `def_id` represents a root, then push it onto the list of
+    /// outputs. (Note that all roots must be monomorphic.)
+    fn push_if_root(&mut self, def_id: DefId) {
+        if self.is_root(def_id) {
+            debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
+
+            let instance = Instance::mono(self.tcx, def_id);
+            self.output.push(create_fn_mono_item(instance));
+
+            self.push_extra_entry_roots(def_id);
+        }
+    }
+
+    /// As a special case, when/if we encounter the
+    /// `main()` function, we also have to generate a
+    /// monomorphized copy of the start lang item based on
+    /// the return type of `main`. This is not needed when
+    /// the user writes their own `start` manually.
+    fn push_extra_entry_roots(&mut self, def_id: DefId) {
+        if self.entry_fn != Some(def_id) {
+            return;
+        }
+
+        if self.tcx.sess.entry_type.get() != Some(config::EntryMain) {
+            return;
+        }
+
+        let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) {
+            Ok(s) => s,
+            Err(err) => self.tcx.sess.fatal(&err),
+        };
+        let main_ret_ty = self.tcx.fn_sig(def_id).output();
+
+        // Given that `main()` has no arguments,
+        // then its return type cannot have
+        // late-bound regions, since late-bound
+        // regions must appear in the argument
+        // listing.
+        let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
+
+        let start_instance = Instance::resolve(
+            self.tcx,
+            ty::ParamEnv::empty(traits::Reveal::All),
+            start_def_id,
+            self.tcx.mk_substs(iter::once(Kind::from(main_ret_ty)))
+        ).unwrap();
+
+        self.output.push(create_fn_mono_item(start_instance));
+    }
 }
 
 fn item_has_type_parameters<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index c3fb126..86a4dd4 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -18,15 +18,15 @@
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::session::config::OptLevel;
-use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::Substs;
 use syntax::ast;
 use syntax::attr::{self, InlineAttr};
 use std::fmt::{self, Write};
 use std::iter;
 use rustc::mir::mono::Linkage;
 use syntax_pos::symbol::Symbol;
+use syntax::codemap::Span;
 pub use rustc::mir::mono::MonoItem;
 
 pub fn linkage_by_name(name: &str) -> Option<Linkage> {
@@ -115,7 +115,7 @@
         let inline_in_all_cgus =
             tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| {
                 tcx.sess.opts.optimize != OptLevel::No
-            });
+            }) && !tcx.sess.opts.cg.link_dead_code;
 
         match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => {
@@ -214,8 +214,7 @@
             MonoItem::GlobalAsm(..) => return true
         };
 
-        let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs);
-        traits::normalize_and_test_predicates(tcx, predicates)
+        tcx.substitute_normalize_and_test_predicates((def_id, &substs))
     }
 
     fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
@@ -246,6 +245,18 @@
             result
         }
     }
+
+    fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
+        match *self.as_mono_item() {
+            MonoItem::Fn(Instance { def, .. }) => {
+                tcx.hir.as_local_node_id(def.def_id())
+            }
+            MonoItem::Static(node_id) |
+            MonoItem::GlobalAsm(node_id) => {
+                Some(node_id)
+            }
+        }.map(|node_id| tcx.hir.span(node_id))
+    }
 }
 
 impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
@@ -292,13 +303,13 @@
             ty::TyChar              => output.push_str("char"),
             ty::TyStr               => output.push_str("str"),
             ty::TyNever             => output.push_str("!"),
-            ty::TyInt(ast::IntTy::Is)    => output.push_str("isize"),
+            ty::TyInt(ast::IntTy::Isize)    => output.push_str("isize"),
             ty::TyInt(ast::IntTy::I8)    => output.push_str("i8"),
             ty::TyInt(ast::IntTy::I16)   => output.push_str("i16"),
             ty::TyInt(ast::IntTy::I32)   => output.push_str("i32"),
             ty::TyInt(ast::IntTy::I64)   => output.push_str("i64"),
             ty::TyInt(ast::IntTy::I128)   => output.push_str("i128"),
-            ty::TyUint(ast::UintTy::Us)   => output.push_str("usize"),
+            ty::TyUint(ast::UintTy::Usize)   => output.push_str("usize"),
             ty::TyUint(ast::UintTy::U8)   => output.push_str("u8"),
             ty::TyUint(ast::UintTy::U16)  => output.push_str("u16"),
             ty::TyUint(ast::UintTy::U32)  => output.push_str("u32"),
@@ -413,6 +424,7 @@
             ty::TyInfer(_) |
             ty::TyProjection(..) |
             ty::TyParam(_) |
+            ty::TyGeneratorWitness(_) |
             ty::TyAnon(..) => {
                 bug!("DefPathBasedNames: Trying to create type name for \
                                          unexpected type: {:?}", t);
diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs
index fcf0d71..95ebb6c 100644
--- a/src/librustc_mir/monomorphize/mod.rs
+++ b/src/librustc_mir/monomorphize/mod.rs
@@ -22,6 +22,54 @@
 pub mod item;
 pub mod partitioning;
 
+#[inline(never)] // give this a place in the profiler
+pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)
+    where I: Iterator<Item=&'a MonoItem<'tcx>>
+{
+    let mut symbols: Vec<_> = trans_items.map(|trans_item| {
+        (trans_item, trans_item.symbol_name(tcx))
+    }).collect();
+
+    (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
+        sym1.cmp(sym2)
+    });
+
+    for pair in (&symbols[..]).windows(2) {
+        let sym1 = &pair[0].1;
+        let sym2 = &pair[1].1;
+
+        if *sym1 == *sym2 {
+            let trans_item1 = pair[0].0;
+            let trans_item2 = pair[1].0;
+
+            let span1 = trans_item1.local_span(tcx);
+            let span2 = trans_item2.local_span(tcx);
+
+            // Deterministically select one of the spans for error reporting
+            let span = match (span1, span2) {
+                (Some(span1), Some(span2)) => {
+                    Some(if span1.lo().0 > span2.lo().0 {
+                        span1
+                    } else {
+                        span2
+                    })
+                }
+                (Some(span), None) |
+                (None, Some(span)) => Some(span),
+                _ => None
+            };
+
+            let error_message = format!("symbol `{}` is already defined", sym1);
+
+            if let Some(span) = span {
+                tcx.sess.span_fatal(span, &error_message)
+            } else {
+                tcx.sess.fatal(&error_message)
+            }
+        }
+    }
+}
+
 fn fn_once_adapter_instance<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     closure_did: DefId,
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index b1fef27..e899cc0 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -94,7 +94,7 @@
 //!   inlined, so it can distribute function instantiations accordingly. Since
 //!   there is no way of knowing for sure which functions LLVM will decide to
 //!   inline in the end, we apply a heuristic here: Only functions marked with
-//!   #[inline] are considered for inlining by the partitioner. The current
+//!   `#[inline]` are considered for inlining by the partitioner. The current
 //!   implementation will not try to determine if a function is likely to be
 //!   inlined by looking at the functions definition.
 //!
@@ -200,7 +200,16 @@
 }
 
 // Anything we can't find a proper codegen unit for goes into this.
-const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
+fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
+    const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
+
+    if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str()
+    } else {
+        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_str()
+    }
+}
+
 
 pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               trans_items: I,
@@ -236,7 +245,9 @@
 
     // Next we try to make as many symbols "internal" as possible, so LLVM has
     // more freedom to optimize.
-    internalize_symbols(tcx, &mut post_inlining, inlining_map);
+    if !tcx.sess.opts.cg.link_dead_code {
+        internalize_symbols(tcx, &mut post_inlining, inlining_map);
+    }
 
     // Finally, sort by codegen unit name, so that we get deterministic results
     let PostInliningPartitioning {
@@ -295,7 +306,7 @@
 
         let codegen_unit_name = match characteristic_def_id {
             Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile),
-            None => Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(),
+            None => fallback_cgu_name(tcx),
         };
 
         let make_codegen_unit = || {
@@ -305,6 +316,7 @@
         let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
                                             .or_insert_with(make_codegen_unit);
 
+        let mut can_be_internalized = true;
         let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
             Some(explicit_linkage) => (explicit_linkage, Visibility::Default),
             None => {
@@ -312,7 +324,28 @@
                     MonoItem::Fn(ref instance) => {
                         let visibility = match instance.def {
                             InstanceDef::Item(def_id) => {
-                                if def_id.is_local() {
+                                // The `start_fn` lang item is actually a
+                                // monomorphized instance of a function in the
+                                // standard library, used for the `main`
+                                // function. We don't want to export it so we
+                                // tag it with `Hidden` visibility but this
+                                // symbol is only referenced from the actual
+                                // `main` symbol which we unfortunately don't
+                                // know anything about during
+                                // partitioning/collection. As a result we
+                                // forcibly keep this symbol out of the
+                                // `internalization_candidates` set.
+                                //
+                                // FIXME: eventually we don't want to always
+                                // force this symbol to have hidden
+                                // visibility, it should indeed be a candidate
+                                // for internalization, but we have to
+                                // understand that it's referenced from the
+                                // `main` symbol we'll generate later.
+                                if tcx.lang_items().start_fn() == Some(def_id) {
+                                    can_be_internalized = false;
+                                    Visibility::Hidden
+                                } else if def_id.is_local() {
                                     if tcx.is_exported_symbol(def_id) {
                                         Visibility::Default
                                     } else {
@@ -346,7 +379,7 @@
                 }
             }
         };
-        if visibility == Visibility::Hidden {
+        if visibility == Visibility::Hidden && can_be_internalized {
             internalization_candidates.insert(trans_item);
         }
 
@@ -357,7 +390,7 @@
     // always ensure we have at least one CGU; otherwise, if we have a
     // crate with just types (for example), we could wind up with no CGU
     if codegen_units.is_empty() {
-        let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str();
+        let codegen_unit_name = fallback_cgu_name(tcx);
         codegen_units.insert(codegen_unit_name.clone(),
                              CodegenUnit::new(codegen_unit_name.clone()));
     }
@@ -606,10 +639,10 @@
     // Unfortunately we cannot just use the `ty::item_path` infrastructure here
     // because we need paths to modules and the DefIds of those are not
     // available anymore for external items.
-    let mut mod_path = String::with_capacity(64);
+    let mut cgu_name = String::with_capacity(64);
 
     let def_path = tcx.def_path(def_id);
-    mod_path.push_str(&tcx.crate_name(def_path.krate).as_str());
+    cgu_name.push_str(&tcx.crate_name(def_path.krate).as_str());
 
     for part in tcx.def_path(def_id)
                    .data
@@ -620,15 +653,21 @@
                             _ => false,
                         }
                     }) {
-        mod_path.push_str("-");
-        mod_path.push_str(&part.data.as_interned_str());
+        cgu_name.push_str("-");
+        cgu_name.push_str(&part.data.as_interned_str());
     }
 
     if volatile {
-        mod_path.push_str(".volatile");
+        cgu_name.push_str(".volatile");
     }
 
-    return Symbol::intern(&mod_path[..]).as_str();
+    let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+        cgu_name
+    } else {
+        CodegenUnit::mangle_name(&cgu_name)
+    };
+
+    Symbol::intern(&cgu_name[..]).as_str()
 }
 
 fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 46193de..c206d0e 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -28,7 +28,7 @@
 use std::iter;
 
 use transform::{add_moves_for_packed_drops, add_call_guards};
-use transform::{no_landing_pads, simplify};
+use transform::{remove_noop_landing_pads, no_landing_pads, simplify};
 use util::elaborate_drops::{self, DropElaborator, DropStyle, DropFlagMode};
 use util::patch::MirPatch;
 
@@ -118,6 +118,7 @@
     add_moves_for_packed_drops::add_moves_for_packed_drops(
         tcx, &mut result, instance.def_id());
     no_landing_pads::no_landing_pads(tcx, &mut result);
+    remove_noop_landing_pads::remove_noop_landing_pads(tcx, &mut result);
     simplify::simplify_cfg(&mut result);
     add_call_guards::CriticalCallEdges.add_call_guards(&mut result);
     debug!("make_shim({:?}) = {:?}", instance, result);
@@ -142,7 +143,7 @@
     LocalDecl {
         mutability, ty, name: None,
         source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span },
-        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+        syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false
     }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index e7ce528..ae27f54 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -73,6 +73,7 @@
             TerminatorKind::DropAndReplace { .. } |
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Resume |
+            TerminatorKind::Abort |
             TerminatorKind::Return |
             TerminatorKind::Unreachable |
             TerminatorKind::FalseEdges { .. } => {
@@ -123,13 +124,21 @@
                 &AggregateKind::Array(..) |
                 &AggregateKind::Tuple |
                 &AggregateKind::Adt(..) => {}
-                &AggregateKind::Closure(def_id, _) |
-                &AggregateKind::Generator(def_id, _, _) => {
+                &AggregateKind::Closure(def_id, _) => {
                     let UnsafetyCheckResult {
                         violations, unsafe_blocks
                     } = self.tcx.unsafety_check_result(def_id);
                     self.register_violations(&violations, &unsafe_blocks);
                 }
+                &AggregateKind::Generator(def_id, _, interior) => {
+                    let UnsafetyCheckResult {
+                        violations, unsafe_blocks
+                    } = self.tcx.unsafety_check_result(def_id);
+                    self.register_violations(&violations, &unsafe_blocks);
+                    if !interior.movable {
+                        self.require_unsafe("construction of immovable generator")
+                    }
+                }
             }
         }
         self.super_rvalue(rvalue, location);
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 455a07c..ebd34f8 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -301,7 +301,7 @@
         ty: ret_ty,
         name: None,
         source_info: source_info(mir),
-        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+        syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false,
     };
@@ -332,9 +332,39 @@
     }
 }
 
+struct BorrowedLocals(liveness::LocalSet);
+
+fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) {
+    match *place {
+        Place::Local(l) => { locals.0.add(&l); },
+        Place::Static(..) => (),
+        Place::Projection(ref proj) => {
+            match proj.elem {
+                // For derefs we don't look any further.
+                // If it pointed to a Local, it would already be borrowed elsewhere
+                ProjectionElem::Deref => (),
+                _ => mark_as_borrowed(&proj.base, locals)
+            }
+        }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for BorrowedLocals {
+    fn visit_rvalue(&mut self,
+                    rvalue: &Rvalue<'tcx>,
+                    location: Location) {
+        if let Rvalue::Ref(_, _, ref place) = *rvalue {
+            mark_as_borrowed(place, self);
+        }
+
+        self.super_rvalue(rvalue, location)
+    }
+}
+
 fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                mir: &Mir<'tcx>,
-                                               source: MirSource) ->
+                                               source: MirSource,
+                                               movable: bool) ->
                                                (liveness::LocalSet,
                                                 HashMap<BasicBlock, liveness::LocalSet>) {
     let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
@@ -347,8 +377,11 @@
     let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len()));
     ignored.visit_mir(mir);
 
+    let mut borrowed_locals = BorrowedLocals(IdxSetBuf::new_empty(mir.local_decls.len()));
+    borrowed_locals.visit_mir(mir);
+
     let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
-    let liveness = liveness::liveness_of_locals(mir, LivenessMode {
+    let mut liveness = liveness::liveness_of_locals(mir, LivenessMode {
         include_regular_use: true,
         include_drops: true,
     });
@@ -363,7 +396,7 @@
                 statement_index: data.statements.len(),
             };
 
-            let storage_liveness = state_for_location(loc, &analysis, &storage_live);
+            let storage_liveness = state_for_location(loc, &analysis, &storage_live, mir);
 
             storage_liveness_map.insert(block, storage_liveness.clone());
 
@@ -372,6 +405,12 @@
             // Mark locals without storage statements as always having live storage
             live_locals.union(&ignored.0);
 
+            if !movable {
+                // For immovable generators we consider borrowed locals to always be live.
+                // This effectively makes those locals use just the storage liveness.
+                liveness.outs[block].union(&borrowed_locals.0);
+            }
+
             // Locals live are live at this point only if they are used across suspension points
             // and their storage is live
             live_locals.intersect(&liveness.outs[block]);
@@ -390,6 +429,7 @@
 
 fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             source: MirSource,
+                            upvars: Vec<Ty<'tcx>>,
                             interior: GeneratorInterior<'tcx>,
                             mir: &mut Mir<'tcx>)
     -> (HashMap<Local, (Ty<'tcx>, usize)>,
@@ -397,11 +437,17 @@
         HashMap<BasicBlock, liveness::LocalSet>)
 {
     // Use a liveness analysis to compute locals which are live across a suspension point
-    let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx, mir, source);
-
+    let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx,
+                                                                            mir,
+                                                                            source,
+                                                                            interior.movable);
     // Erase regions from the types passed in from typeck so we can compare them with
     // MIR types
-    let allowed = tcx.erase_regions(&interior.as_slice());
+    let allowed_upvars = tcx.erase_regions(&upvars);
+    let allowed = match interior.witness.sty {
+        ty::TyGeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
+        _ => bug!(),
+    };
 
     for (local, decl) in mir.local_decls.iter_enumerated() {
         // Ignore locals which are internal or not live
@@ -411,7 +457,7 @@
 
         // Sanity check that typeck knows about the type of locals which are
         // live across a suspension point
-        if !allowed.contains(&decl.ty) {
+        if !allowed.contains(&decl.ty) && !allowed_upvars.contains(&decl.ty) {
             span_bug!(mir.span,
                       "Broken MIR: generator contains type {} in MIR, \
                        but typeck only knows about {}",
@@ -562,7 +608,7 @@
         ty: tcx.mk_nil(),
         name: None,
         source_info,
-        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+        syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false,
     };
@@ -578,7 +624,7 @@
         }),
         name: None,
         source_info,
-        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
+        syntactic_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false,
     };
@@ -763,19 +809,18 @@
         assert!(mir.generator_drop.is_none());
 
         let def_id = source.def_id;
-        let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-        let hir_id = tcx.hir.node_to_hir_id(node_id);
-
-        // Get the interior types which typeck computed
-        let tables = tcx.typeck_tables_of(def_id);
-        let interior = match tables.node_id_to_type(hir_id).sty {
-            ty::TyGenerator(_, _, interior) => interior,
-            ref t => bug!("type of generator not a generator: {:?}", t),
-        };
 
         // The first argument is the generator type passed by value
         let gen_ty = mir.local_decls.raw[1].ty;
 
+        // Get the interior types and substs which typeck computed
+        let (upvars, interior) = match gen_ty.sty {
+            ty::TyGenerator(_, substs, interior) => {
+                (substs.upvar_tys(def_id, tcx).collect(), interior)
+            }
+            _ => bug!(),
+        };
+
         // Compute GeneratorState<yield_ty, return_ty>
         let state_did = tcx.lang_items().gen_state().unwrap();
         let state_adt_ref = tcx.adt_def(state_did);
@@ -790,7 +835,7 @@
         // Extract locals which are live across suspension point into `layout`
         // `remap` gives a mapping from local indices onto generator struct indices
         // `storage_liveness` tells us which locals have live storage at suspension points
-        let (remap, layout, storage_liveness) = compute_layout(tcx, source, interior, mir);
+        let (remap, layout, storage_liveness) = compute_layout(tcx, source, upvars, interior, mir);
 
         let state_field = mir.upvar_decls.len();
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 7216384..43ee75d 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -806,6 +806,7 @@
                     *kind = TerminatorKind::Goto { target: tgt }
                 }
             }
+            TerminatorKind::Abort => { }
             TerminatorKind::Unreachable => { }
             TerminatorKind::FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
                 *real_target = self.update_target(*real_target);
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 2b23239..b896e6c 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -122,7 +122,6 @@
     return_qualif: Option<Qualif>,
     qualif: Qualif,
     const_fn_arg_vars: BitVector,
-    local_needs_drop: IndexVec<Local, Option<Span>>,
     temp_promotion_state: IndexVec<Local, TempState>,
     promotion_candidates: Vec<Candidate>
 }
@@ -136,6 +135,16 @@
         let mut rpo = traversal::reverse_postorder(mir);
         let temps = promote_consts::collect_temps(mir, &mut rpo);
         rpo.reset();
+
+        let param_env = tcx.param_env(def_id);
+
+        let mut temp_qualif = IndexVec::from_elem(None, &mir.local_decls);
+        for arg in mir.args_iter() {
+            let mut qualif = Qualif::NEEDS_DROP;
+            qualif.restrict(mir.local_decls[arg].ty, tcx, param_env);
+            temp_qualif[arg] = Some(qualif);
+        }
+
         Qualifier {
             mode,
             span: mir.span,
@@ -143,12 +152,11 @@
             mir,
             rpo,
             tcx,
-            param_env: tcx.param_env(def_id),
-            temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
+            param_env,
+            temp_qualif,
             return_qualif: None,
             qualif: Qualif::empty(),
             const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
-            local_needs_drop: IndexVec::from_elem(None, &mir.local_decls),
             temp_promotion_state: temps,
             promotion_candidates: vec![]
         }
@@ -255,15 +263,6 @@
             return;
         }
 
-        // When initializing a local, record whether the *value* being
-        // stored in it needs dropping, which it may not, even if its
-        // type does, e.g. `None::<String>`.
-        if let Place::Local(local) = *dest {
-            if qualif.intersects(Qualif::NEEDS_DROP) {
-                self.local_needs_drop[local] = Some(self.span);
-            }
-        }
-
         match *dest {
             Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
                 debug!("store to temp {:?}", index);
@@ -324,6 +323,7 @@
                 TerminatorKind::SwitchInt {..} |
                 TerminatorKind::DropAndReplace { .. } |
                 TerminatorKind::Resume |
+                TerminatorKind::Abort |
                 TerminatorKind::GeneratorDrop |
                 TerminatorKind::Yield { .. } |
                 TerminatorKind::Unreachable |
@@ -423,17 +423,20 @@
                    &local: &Local,
                    _: PlaceContext<'tcx>,
                    _: Location) {
-        match self.mir.local_kind(local) {
+        let kind = self.mir.local_kind(local);
+        match kind {
             LocalKind::ReturnPointer => {
                 self.not_const();
             }
-            LocalKind::Arg => {
-                self.add(Qualif::FN_ARGUMENT);
-            }
             LocalKind::Var => {
                 self.add(Qualif::NOT_CONST);
             }
+            LocalKind::Arg |
             LocalKind::Temp => {
+                if let LocalKind::Arg = kind {
+                    self.add(Qualif::FN_ARGUMENT);
+                }
+
                 if !self.temp_promotion_state[local].is_promotable() {
                     self.add(Qualif::NOT_PROMOTABLE);
                 }
@@ -528,16 +531,18 @@
 
     fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
         match *operand {
-            Operand::Copy(ref place) |
-            Operand::Move(ref place) => {
+            Operand::Copy(_) |
+            Operand::Move(_) => {
                 self.nest(|this| {
                     this.super_operand(operand, location);
                     this.try_consume();
                 });
 
                 // Mark the consumed locals to indicate later drops are noops.
-                if let Place::Local(local) = *place {
-                    self.local_needs_drop[local] = None;
+                if let Operand::Move(Place::Local(local)) = *operand {
+                    self.temp_qualif[local] = self.temp_qualif[local].map(|q|
+                        q - Qualif::NEEDS_DROP
+                    );
                 }
             }
             Operand::Constant(ref constant) => {
@@ -846,9 +851,13 @@
                 // HACK(eddyb) Emulate a bit of dataflow analysis,
                 // conservatively, that drop elaboration will do.
                 let needs_drop = if let Place::Local(local) = *place {
-                    self.local_needs_drop[local]
+                    if self.temp_qualif[local].map_or(true, |q| q.intersects(Qualif::NEEDS_DROP)) {
+                        Some(self.mir.local_decls[local].source_info.span)
+                    } else {
+                        None
+                    }
                 } else {
-                    None
+                    Some(self.span)
                 };
 
                 if let Some(span) = needs_drop {
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index d29174d5..e7cab46 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -20,17 +20,24 @@
 /// code for these.
 pub struct RemoveNoopLandingPads;
 
+pub fn remove_noop_landing_pads<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &mut Mir<'tcx>)
+{
+    if tcx.sess.no_landing_pads() {
+        return
+    }
+    debug!("remove_noop_landing_pads({:?})", mir);
+
+    RemoveNoopLandingPads.remove_nop_landing_pads(mir)
+}
+
 impl MirPass for RemoveNoopLandingPads {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource,
                           mir: &mut Mir<'tcx>) {
-        if tcx.sess.no_landing_pads() {
-            return
-        }
-
-        debug!("remove_noop_landing_pads({:?})", mir);
-        self.remove_nop_landing_pads(mir);
+        remove_noop_landing_pads(tcx, mir);
     }
 }
 
@@ -76,6 +83,7 @@
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Yield { .. } |
             TerminatorKind::Return |
+            TerminatorKind::Abort |
             TerminatorKind::Unreachable |
             TerminatorKind::Call { .. } |
             TerminatorKind::Assert { .. } |
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 6b8e2b0..b6153ea 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -203,11 +203,18 @@
         // reset GEN and KILL sets before emulating their effect.
         for e in sets.gen_set.words_mut() { *e = 0; }
         for e in sets.kill_set.words_mut() { *e = 0; }
-        results.0.operator.statement_effect(&mut sets, Location { block: bb, statement_index: j });
+        results.0.operator.before_statement_effect(
+            &mut sets, Location { block: bb, statement_index: j });
+        results.0.operator.statement_effect(
+            &mut sets, Location { block: bb, statement_index: j });
         sets.on_entry.union(sets.gen_set);
         sets.on_entry.subtract(sets.kill_set);
     }
 
+    results.0.operator.before_terminator_effect(
+        &mut sets,
+        Location { block: bb, statement_index: statements.len() });
+
     tcx.sess.span_err(span, &format!("rustc_peek: MIR did not match \
                                       anticipated pattern; note that \
                                       rustc_peek expects input of \
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 38227bd..4a7ee39 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -269,12 +269,17 @@
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_reassign_immutable(&self, span: Span, desc: &str, o: Origin)
+    fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin)
                                  -> DiagnosticBuilder
     {
+        let msg = if is_arg {
+            "to immutable argument"
+        } else {
+            "twice to immutable variable"
+        };
         let err = struct_span_err!(self, span, E0384,
-                                   "cannot assign twice to immutable variable `{}`{OGN}",
-                                   desc, OGN=o);
+                                   "cannot assign {} `{}`{OGN}",
+                                   msg, desc, OGN=o);
 
         self.cancel_if_wrong_origin(err, o)
     }
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 765d50b..6251b64 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -407,10 +407,7 @@
     result: &LivenessResult,
 ) {
     let mut file_path = PathBuf::new();
-    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
-        let p = Path::new(file_dir);
-        file_path.push(p);
-    };
+    file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir));
     let item_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
     let file_name = format!("rustc.node{}{}-liveness.mir", item_id, pass_name);
     file_path.push(&file_name);
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 37f5977..f326b6e 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -189,11 +189,7 @@
     };
 
     let mut file_path = PathBuf::new();
-
-    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
-        let p = Path::new(file_dir);
-        file_path.push(p);
-    };
+    file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir));
 
     let item_name = tcx.hir
         .def_path(source.def_id)
@@ -401,17 +397,17 @@
         self.super_constant(constant, location);
         let Constant { span, ty, literal } = constant;
         self.push(&format!("mir::Constant"));
-        self.push(&format!("└ span: {:?}", span));
-        self.push(&format!("└ ty: {:?}", ty));
-        self.push(&format!("└ literal: {:?}", literal));
+        self.push(&format!("+ span: {:?}", span));
+        self.push(&format!("+ ty: {:?}", ty));
+        self.push(&format!("+ literal: {:?}", literal));
     }
 
     fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
         self.super_const(constant);
         let ty::Const { ty, val } = constant;
         self.push(&format!("ty::Const"));
-        self.push(&format!("└ ty: {:?}", ty));
-        self.push(&format!("└ val: {:?}", val));
+        self.push(&format!("+ ty: {:?}", ty));
+        self.push(&format!("+ val: {:?}", val));
     }
 
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
@@ -420,15 +416,15 @@
             Rvalue::Aggregate(kind, _) => match **kind {
                 AggregateKind::Closure(def_id, substs) => {
                     self.push(&format!("closure"));
-                    self.push(&format!("└ def_id: {:?}", def_id));
-                    self.push(&format!("└ substs: {:#?}", substs));
+                    self.push(&format!("+ def_id: {:?}", def_id));
+                    self.push(&format!("+ substs: {:#?}", substs));
                 }
 
                 AggregateKind::Generator(def_id, substs, interior) => {
                     self.push(&format!("generator"));
-                    self.push(&format!("└ def_id: {:?}", def_id));
-                    self.push(&format!("└ substs: {:#?}", substs));
-                    self.push(&format!("└ interior: {:?}", interior));
+                    self.push(&format!("+ def_id: {:?}", def_id));
+                    self.push(&format!("+ substs: {:#?}", substs));
+                    self.push(&format!("+ interior: {:?}", interior));
                 }
 
                 _ => {}
@@ -522,7 +518,7 @@
     w: &mut Write,
 ) -> io::Result<()> {
     write_mir_sig(tcx, src, mir, w)?;
-    writeln!(w, " {{")?;
+    writeln!(w, "{{")?;
 
     // construct a scope tree and write it out
     let mut scope_tree: FxHashMap<VisibilityScope, Vec<VisibilityScope>> = FxHashMap();
@@ -585,13 +581,20 @@
                 write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
             }
 
-            write!(w, ") -> {}", mir.return_ty())
+            write!(w, ") -> {}", mir.return_ty())?;
         }
         (hir::BodyOwnerKind::Const, _) | (hir::BodyOwnerKind::Static(_), _) | (_, Some(_)) => {
             assert_eq!(mir.arg_count, 0);
-            write!(w, ": {} =", mir.return_ty())
+            write!(w, ": {} =", mir.return_ty())?;
         }
     }
+
+    if let Some(yield_ty) = mir.yield_ty {
+        writeln!(w)?;
+        writeln!(w, "yields {}", yield_ty)?;
+    }
+
+    Ok(())
 }
 
 fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index d2560c2..776f330 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -9,7 +9,7 @@
 crate-type = ["dylib"]
 
 [dependencies]
-log = "0.3"
+log = "0.4"
 rustc = { path = "../librustc" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index d74a8af..3f49128 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -51,8 +51,7 @@
     }
 
     fn invalid_non_exhaustive_attribute(&self, variant: &Variant) {
-        let has_non_exhaustive = variant.node.attrs.iter()
-            .any(|attr| attr.check_name("non_exhaustive"));
+        let has_non_exhaustive = attr::contains_name(&variant.node.attrs, "non_exhaustive");
         if has_non_exhaustive {
             self.err_handler().span_err(variant.span,
                                         "#[non_exhaustive] is not yet supported on variants");
@@ -150,6 +149,9 @@
             ExprKind::Continue(Some(ident)) => {
                 self.check_label(ident.node, ident.span);
             }
+            ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
+                span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
+            }
             _ => {}
         }
 
@@ -216,8 +218,16 @@
 
     fn visit_item(&mut self, item: &'a Item) {
         match item.node {
-            ItemKind::Impl(.., Some(..), _, ref impl_items) => {
+            ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
                 self.invalid_visibility(&item.vis, item.span, None);
+                if ty.node == TyKind::Err {
+                    self.err_handler()
+                        .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
+                        .help("use `auto trait Trait {}` instead").emit();
+                }
+                if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
+                    span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
+                }
                 for impl_item in impl_items {
                     self.invalid_visibility(&impl_item.vis, impl_item.span, None);
                     if let ImplItemKind::Method(ref sig, _) = impl_item.node {
@@ -225,13 +235,19 @@
                     }
                 }
             }
-            ItemKind::Impl(.., None, _, _) => {
+            ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => {
                 self.invalid_visibility(&item.vis,
                                         item.span,
                                         Some("place qualifiers on individual impl items instead"));
-            }
-            ItemKind::AutoImpl(..) => {
-                self.invalid_visibility(&item.vis, item.span, None);
+                if unsafety == Unsafety::Unsafe {
+                    span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
+                }
+                if polarity == ImplPolarity::Negative {
+                    self.err_handler().span_err(item.span, "inherent impls cannot be negative");
+                }
+                if defaultness == Defaultness::Default {
+                    self.err_handler().span_err(item.span, "inherent impls cannot be default");
+                }
             }
             ItemKind::ForeignMod(..) => {
                 self.invalid_visibility(&item.vis,
@@ -251,16 +267,16 @@
                 if is_auto == IsAuto::Yes {
                     // Auto traits cannot have generics, super traits nor contain items.
                     if generics.is_parameterized() {
-                        self.err_handler().span_err(item.span,
-                                                    "auto traits cannot have generics");
+                        struct_span_err!(self.session, item.span, E0567,
+                                        "auto traits cannot have generic parameters").emit();
                     }
                     if !bounds.is_empty() {
-                        self.err_handler().span_err(item.span,
-                                                    "auto traits cannot have super traits");
+                        struct_span_err!(self.session, item.span, E0568,
+                                        "auto traits cannot have super traits").emit();
                     }
                     if !trait_items.is_empty() {
-                        self.err_handler().span_err(item.span,
-                                                    "auto traits cannot contain items");
+                        struct_span_err!(self.session, item.span, E0380,
+                                "auto traits cannot have methods or associated items").emit();
                     }
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
@@ -308,7 +324,7 @@
             ItemKind::Mod(_) => {
                 // Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
                 attr::first_attr_value_str_by_name(&item.attrs, "path");
-                if item.attrs.iter().any(|attr| attr.check_name("warn_directory_ownership")) {
+                if attr::contains_name(&item.attrs, "warn_directory_ownership") {
                     let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP;
                     let msg = "cannot declare a new module at this location";
                     self.session.buffer_lint(lint, item.id, item.span, msg);
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 3597a6f..743f7b7 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -82,6 +82,52 @@
 ```
 "##,
 
+E0197: r##"
+Inherent implementations (one that do not implement a trait but provide
+methods associated with a type) are always safe because they are not
+implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
+implementation will resolve this error.
+
+```compile_fail,E0197
+struct Foo;
+
+// this will cause this error
+unsafe impl Foo { }
+// converting it to this will fix it
+impl Foo { }
+```
+"##,
+
+E0198: r##"
+A negative implementation is one that excludes a type from implementing a
+particular trait. Not being able to use a trait is always a safe operation,
+so negative implementations are always safe and never need to be marked as
+unsafe.
+
+```compile_fail
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+// unsafe is unnecessary
+unsafe impl !Clone for Foo { }
+```
+
+This will compile:
+
+```ignore (ignore auto_trait future compatibility warning)
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+auto trait Enterprise {}
+
+impl !Enterprise for Foo { }
+```
+
+Please note that negative impls are only allowed for auto traits.
+"##,
+
 E0265: r##"
 This error indicates that a static or constant references itself.
 All statics and constants need to resolve to a value in an acyclic manner.
@@ -150,6 +196,13 @@
 [RFC 911]: https://github.com/rust-lang/rfcs/pull/911
 "##,
 
+E0380: r##"
+Auto traits cannot have methods or associated items.
+For more information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
+"##,
+
 E0449: r##"
 A visibility qualifier was used when it was unnecessary. Erroneous code
 examples:
@@ -264,5 +317,7 @@
     E0226, // only a single explicit lifetime bound is permitted
     E0472, // asm! is unsupported on this target
     E0561, // patterns aren't allowed in function pointer types
+    E0567, // auto traits can not have generic parameters
+    E0568, // auto traits can not have super traits
     E0642, // patterns aren't allowed in methods without bodies
 }
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 9a150ab..73c71ec 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -42,9 +42,9 @@
 pub mod hir_stats;
 pub mod loops;
 mod mir_stats;
-pub mod no_asm;
 pub mod static_recursion;
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index 8a9936e..b379a17 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -113,6 +113,7 @@
             TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
             TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
             TerminatorKind::Resume => "TerminatorKind::Resume",
+            TerminatorKind::Abort => "TerminatorKind::Abort",
             TerminatorKind::Return => "TerminatorKind::Return",
             TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
             TerminatorKind::Drop { .. } => "TerminatorKind::Drop",
diff --git a/src/librustc_passes/no_asm.rs b/src/librustc_passes/no_asm.rs
deleted file mode 100644
index 4dbf57a..0000000
--- a/src/librustc_passes/no_asm.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// Run over the whole crate and check for ExprInlineAsm.
-/// Inline asm isn't allowed on virtual ISA based targets, so we reject it
-/// here.
-
-use rustc::session::Session;
-
-use syntax::ast;
-use syntax::visit::Visitor;
-use syntax::visit;
-
-pub fn check_crate(sess: &Session, krate: &ast::Crate) {
-    if sess.target.target.options.allow_asm {
-        return;
-    }
-
-    visit::walk_crate(&mut CheckNoAsm { sess: sess }, krate);
-}
-
-#[derive(Copy, Clone)]
-struct CheckNoAsm<'a> {
-    sess: &'a Session,
-}
-
-impl<'a> Visitor<'a> for CheckNoAsm<'a> {
-    fn visit_expr(&mut self, e: &'a ast::Expr) {
-        match e.node {
-            ast::ExprKind::InlineAsm(_) => {
-                span_err!(self.sess,
-                          e.span,
-                          E0472,
-                          "asm! is unsupported on this target")
-            }
-            _ => {}
-        }
-        visit::walk_expr(self, e)
-    }
-}
diff --git a/src/librustc_platform_intrinsics/x86.rs b/src/librustc_platform_intrinsics/x86.rs
index acb6942..e23222a 100644
--- a/src/librustc_platform_intrinsics/x86.rs
+++ b/src/librustc_platform_intrinsics/x86.rs
@@ -354,7 +354,7 @@
         },
         "_mm256_sad_epu8" => Intrinsic {
             inputs: { static INPUTS: [&'static Type; 2] = [&::U8x32, &::U8x32]; &INPUTS },
-            output: &::U8x32,
+            output: &::U64x4,
             definition: Named("llvm.x86.avx2.psad.bw")
         },
         "_mm256_shuffle_epi8" => Intrinsic {
diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs
index 3df56c4..38df598 100644
--- a/src/librustc_plugin/lib.rs
+++ b/src/librustc_plugin/lib.rs
@@ -57,7 +57,7 @@
 //! #![plugin(myplugin)]
 //! ```
 //!
-//! See the [`plugin` feature](../../unstable-book/language-features/plugin.html) of
+//! See the [`plugin` feature](../unstable-book/language-features/plugin.html) of
 //! the Unstable Book for more examples.
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -82,4 +82,5 @@
 pub mod load;
 pub mod build;
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_plugin, DIAGNOSTICS }
diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs
index 8a4ec03..a46b85d 100644
--- a/src/librustc_plugin/load.rs
+++ b/src/librustc_plugin/load.rs
@@ -100,8 +100,8 @@
     fn load_plugin(&mut self, span: Span, name: &str, args: Vec<ast::NestedMetaItem>) {
         let registrar = self.reader.find_plugin_registrar(span, name);
 
-        if let Some((lib, disambiguator, index)) = registrar {
-            let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator, index);
+        if let Some((lib, disambiguator)) = registrar {
+            let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator);
             let fun = self.dylink_registrar(span, lib, symbol);
             self.plugins.push(PluginRegistrar {
                 fun,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index bb0a4be..b46882f 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -147,10 +147,6 @@
                 let def_id = self.tcx.hir.local_def_id(item.id);
                 cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id))
             }
-            hir::ItemAutoImpl(..) => {
-                let def_id = self.tcx.hir.local_def_id(item.id);
-                self.impl_trait_level(def_id)
-            }
             // Foreign mods inherit level from parents
             hir::ItemForeignMod(..) => {
                 self.prev_level
@@ -214,7 +210,7 @@
             }
             hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
             hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) |
-            hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {}
+            hir::ItemFn(..) | hir::ItemExternCrate(..) => {}
         }
 
         // Mark all items in interfaces of reachable items as reachable
@@ -223,11 +219,9 @@
             hir::ItemExternCrate(..) => {}
             // All nested items are checked by visit_item
             hir::ItemMod(..) => {}
-            // Reexports are handled in visit_mod
+            // Re-exports are handled in visit_mod
             hir::ItemUse(..) => {}
             // The interface is empty
-            hir::ItemAutoImpl(..) => {}
-            // The interface is empty
             hir::ItemGlobalAsm(..) => {}
             // Visit everything
             hir::ItemConst(..) | hir::ItemStatic(..) |
@@ -1055,7 +1049,7 @@
 
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
-            // contents of a private mod can be reexported, so we need
+            // contents of a private mod can be re-exported, so we need
             // to check internals.
             hir::ItemMod(_) => {}
 
@@ -1571,8 +1565,6 @@
                     self.check(field.id, min(item_visibility, field_visibility)).ty();
                 }
             }
-            // The interface is empty
-            hir::ItemAutoImpl(..) => {}
             // An inherent impl is public when its type is public
             // Subitems of inherent impls have their own publicity
             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
@@ -1725,4 +1717,5 @@
     Rc::new(visitor.access_levels)
 }
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index ab2d152..4c8d42c 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -10,7 +10,7 @@
 test = false
 
 [dependencies]
-log = "0.3"
+log = "0.4"
 syntax = { path = "../libsyntax" }
 rustc = { path = "../librustc" }
 arena = { path = "../libarena" }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 3b20c1e..c55bf39 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -156,7 +156,7 @@
 
                     // Disallow `use $crate;`
                     if source.name == keywords::DollarCrate.name() && path.segments.len() == 1 {
-                        let crate_root = self.resolve_crate_root(source.ctxt);
+                        let crate_root = self.resolve_crate_root(source.ctxt, true);
                         let crate_name = match crate_root.kind {
                             ModuleKind::Def(_, name) => name,
                             ModuleKind::Block(..) => unreachable!(),
@@ -220,7 +220,7 @@
                         ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
 
                     for other_span in self_spans.iter().skip(1) {
-                        e.span_note(*other_span, "another `self` import appears here");
+                        e.span_label(*other_span, "another `self` import appears here");
                     }
 
                     e.emit();
@@ -358,8 +358,7 @@
 
                 let mut ctor_vis = vis;
 
-                let has_non_exhaustive = item.attrs.iter()
-                    .any(|item| item.check_name("non_exhaustive"));
+                let has_non_exhaustive = attr::contains_name(&item.attrs, "non_exhaustive");
 
                 // If the structure is marked as non_exhaustive then lower the visibility
                 // to within the crate.
@@ -401,7 +400,7 @@
                 self.insert_field_names(item_def_id, field_names);
             }
 
-            ItemKind::AutoImpl(..) | ItemKind::Impl(..) => {}
+            ItemKind::Impl(..) => {}
 
             ItemKind::Trait(..) => {
                 let def_id = self.definitions.local_def_id(item.id);
@@ -684,7 +683,7 @@
                 let (def, vis) = (binding.def(), binding.vis);
                 self.macro_exports.push(Export { ident, def, vis, span, is_import: true });
             } else {
-                span_err!(self.session, span, E0470, "reexported macro not found");
+                span_err!(self.session, span, E0470, "re-exported macro not found");
             }
         }
         used
@@ -730,7 +729,7 @@
                 }
             } else if attr.check_name("macro_reexport") {
                 let bad_macro_reexport = |this: &mut Self, span| {
-                    span_err!(this.session, span, E0467, "bad macro reexport");
+                    span_err!(this.session, span, E0467, "bad macro re-export");
                 };
                 if let Some(names) = attr.meta_item_list() {
                     for attr in names {
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 564626a..8a29155 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1374,7 +1374,7 @@
 "##,
 
 E0467: r##"
-Macro reexport declarations were empty or malformed.
+Macro re-export declarations were empty or malformed.
 
 Erroneous code examples:
 
@@ -1389,12 +1389,12 @@
 This is a syntax error at the level of attribute declarations.
 
 Currently, `macro_reexport` requires at least one macro name to be listed.
-Unlike `macro_use`, listing no names does not reexport all macros from the
+Unlike `macro_use`, listing no names does not re-export all macros from the
 given crate.
 
 Decide which macros you would like to export and list them properly.
 
-These are proper reexport declarations:
+These are proper re-export declarations:
 
 ```ignore (cannot-doctest-multicrate-project)
 #[macro_reexport(some_macro, another_macro)]
@@ -1475,7 +1475,7 @@
 "##,
 
 E0470: r##"
-A macro listed for reexport was not found.
+A macro listed for re-export was not found.
 
 Erroneous code example:
 
@@ -1493,7 +1493,7 @@
 
 This could be caused by a typo. Did you misspell the macro's name?
 
-Double-check the names of the macros listed for reexport, and that the crate
+Double-check the names of the macros listed for re-export, and that the crate
 in question exports them.
 
 A working version:
@@ -1621,6 +1621,59 @@
 ```
 "##,
 
+E0659: r##"
+An item usage is ambiguous.
+
+Erroneous code example:
+
+```compile_fail,E0659
+pub mod moon {
+    pub fn foo() {}
+}
+
+pub mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon::*;
+    pub use earth::*;
+}
+
+fn main() {
+    collider::foo(); // ERROR: `foo` is ambiguous
+}
+```
+
+This error generally appears when two items with the same name are imported into
+a module. Here, the `foo` functions are imported and reexported from the
+`collider` module and therefore, when we're using `collider::foo()`, both
+functions collide.
+
+To solve this error, the best solution is generally to keep the path before the
+item when using it. Example:
+
+```
+pub mod moon {
+    pub fn foo() {}
+}
+
+pub mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon;
+    pub use earth;
+}
+
+fn main() {
+    collider::moon::foo(); // ok!
+    collider::earth::foo(); // ok!
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b57a8bc..55c7e5f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -42,7 +42,7 @@
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 
 use syntax::codemap::{dummy_spanned, respan};
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
@@ -67,6 +67,7 @@
 use std::cmp;
 use std::collections::BTreeSet;
 use std::fmt;
+use std::iter;
 use std::mem::replace;
 use std::rc::Rc;
 
@@ -290,17 +291,17 @@
                              "`self` imports are only allowed within a { } list")
         }
         ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0430,
-                             "`self` import can only appear once in the list")
+            let mut err = struct_span_err!(resolver.session, span, E0430,
+                                           "`self` import can only appear once in an import list");
+            err.span_label(span, "can only appear once in an import list");
+            err
         }
         ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0431,
-                             "`self` import can only appear in an import list with a \
-                              non-empty prefix")
+            let mut err = struct_span_err!(resolver.session, span, E0431,
+                                           "`self` import can only appear in an import list with \
+                                            a non-empty prefix");
+            err.span_label(span, "can only appear in an import list with a non-empty prefix");
+            err
         }
         ResolutionError::UnresolvedImport(name) => {
             let (span, msg) = match name {
@@ -320,18 +321,17 @@
             err
         }
         ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0434,
-                             "{}",
-                             "can't capture dynamic environment in a fn item; use the || { ... } \
-                              closure form instead")
+            let mut err = struct_span_err!(resolver.session,
+                                           span,
+                                           E0434,
+                                           "{}",
+                                           "can't capture dynamic environment in a fn item");
+            err.help("use the `|| { ... }` closure form instead");
+            err
         }
         ResolutionError::AttemptToUseNonConstantValueInConstant => {
-            let mut err = struct_span_err!(resolver.session,
-                             span,
-                             E0435,
-                             "attempt to use a non-constant value in a constant");
+            let mut err = struct_span_err!(resolver.session, span, E0435,
+                                           "attempt to use a non-constant value in a constant");
             err.span_label(span, "non-constant value");
             err
         }
@@ -351,8 +351,7 @@
             let mut err = struct_span_err!(resolver.session, span, E0128,
                                            "type parameters with a default cannot use \
                                             forward declared identifiers");
-            err.span_label(span, format!("defaulted type parameters \
-                                           cannot be forward declared"));
+            err.span_label(span, format!("defaulted type parameters cannot be forward declared"));
             err
         }
     }
@@ -900,7 +899,7 @@
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 enum PathResult<'a> {
     Module(Module<'a>),
     NonModule(PathResolution),
@@ -965,7 +964,7 @@
             unresolved_invocations: RefCell::new(FxHashSet()),
             no_implicit_prelude: false,
             glob_importers: RefCell::new(Vec::new()),
-            globs: RefCell::new((Vec::new())),
+            globs: RefCell::new(Vec::new()),
             traits: RefCell::new(None),
             populated: Cell::new(normal_ancestor_id.is_local()),
             span,
@@ -1206,14 +1205,14 @@
         table.intern("char", TyChar);
         table.intern("f32", TyFloat(FloatTy::F32));
         table.intern("f64", TyFloat(FloatTy::F64));
-        table.intern("isize", TyInt(IntTy::Is));
+        table.intern("isize", TyInt(IntTy::Isize));
         table.intern("i8", TyInt(IntTy::I8));
         table.intern("i16", TyInt(IntTy::I16));
         table.intern("i32", TyInt(IntTy::I32));
         table.intern("i64", TyInt(IntTy::I64));
         table.intern("i128", TyInt(IntTy::I128));
         table.intern("str", TyStr);
-        table.intern("usize", TyUint(UintTy::Us));
+        table.intern("usize", TyUint(UintTy::Usize));
         table.intern("u8", TyUint(UintTy::U8));
         table.intern("u16", TyUint(UintTy::U16));
         table.intern("u32", TyUint(UintTy::U32));
@@ -1322,6 +1321,7 @@
     crate_loader: &'a mut CrateLoader,
     macro_names: FxHashSet<Ident>,
     global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
+    pub all_macros: FxHashMap<Name, Def>,
     lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
     macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
     macro_defs: FxHashMap<Mark, DefId>,
@@ -1409,6 +1409,71 @@
 
 impl<'a> hir::lowering::Resolver for Resolver<'a> {
     fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
+        self.resolve_hir_path_cb(path, is_value,
+                                 |resolver, span, error| resolve_error(resolver, span, error))
+    }
+
+    fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
+                        components: &[&str], is_value: bool) -> hir::Path {
+        let mut path = hir::Path {
+            span,
+            def: Def::Err,
+            segments: iter::once(keywords::CrateRoot.name()).chain({
+                crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
+            }).map(hir::PathSegment::from_name).collect(),
+        };
+
+        self.resolve_hir_path(&mut path, is_value);
+        path
+    }
+
+    fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
+        self.def_map.get(&id).cloned()
+    }
+
+    fn definitions(&mut self) -> &mut Definitions {
+        &mut self.definitions
+    }
+}
+
+impl<'a> Resolver<'a> {
+    /// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a>
+    /// isn't something that can be returned because it can't be made to live that long,
+    /// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
+    /// just that an error occured.
+    pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool)
+        -> Result<hir::Path, ()> {
+        use std::iter;
+        let mut errored = false;
+
+        let mut path = if path_str.starts_with("::") {
+            hir::Path {
+                span,
+                def: Def::Err,
+                segments: iter::once(keywords::CrateRoot.name()).chain({
+                    path_str.split("::").skip(1).map(Symbol::intern)
+                }).map(hir::PathSegment::from_name).collect(),
+            }
+        } else {
+            hir::Path {
+                span,
+                def: Def::Err,
+                segments: path_str.split("::").map(Symbol::intern)
+                                  .map(hir::PathSegment::from_name).collect(),
+            }
+        };
+        self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true);
+        if errored || path.def == Def::Err {
+            Err(())
+        } else {
+            Ok(path)
+        }
+    }
+
+    /// resolve_hir_path, but takes a callback in case there was an error
+    fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F)
+            where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
+        {
         let namespace = if is_value { ValueNS } else { TypeNS };
         let hir::Path { ref segments, span, ref mut def } = *path;
         let path: Vec<SpannedIdent> = segments.iter()
@@ -1420,24 +1485,16 @@
                 *def = path_res.base_def(),
             PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
                 PathResult::Failed(span, msg, _) => {
-                    resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
+                    error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 }
                 _ => {}
             },
             PathResult::Indeterminate => unreachable!(),
             PathResult::Failed(span, msg, _) => {
-                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
+                error_callback(self, span, ResolutionError::FailedToResolve(&msg));
             }
         }
     }
-
-    fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
-        self.def_map.get(&id).cloned()
-    }
-
-    fn definitions(&mut self) -> &mut Definitions {
-        &mut self.definitions
-    }
 }
 
 impl<'a> Resolver<'a> {
@@ -1540,6 +1597,7 @@
             crate_loader,
             macro_names: FxHashSet(),
             global_macros: FxHashMap(),
+            all_macros: FxHashMap(),
             lexical_macro_resolutions: Vec::new(),
             macro_map: FxHashMap(),
             macro_exports: Vec::new(),
@@ -1791,8 +1849,17 @@
         result
     }
 
-    fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext) -> Module<'a> {
-        let module = match ctxt.adjust(Mark::root()) {
+    fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext, legacy: bool) -> Module<'a> {
+        let mark = if legacy {
+            // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
+            // we don't want to pretend that the `macro_rules!` definition is in the `macro`
+            // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
+            ctxt.marks().into_iter().find(|&mark| mark.kind() != MarkKind::Modern)
+        } else {
+            ctxt = ctxt.modern();
+            ctxt.adjust(Mark::root())
+        };
+        let module = match mark {
             Some(def) => self.macro_def_scope(def),
             None => return self.graph_root,
         };
@@ -1826,8 +1893,8 @@
     // generate a fake "implementation scope" containing all the
     // implementations thus found, for compatibility with old resolve pass.
 
-    fn with_scope<F>(&mut self, id: NodeId, f: F)
-        where F: FnOnce(&mut Resolver)
+    pub fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
+        where F: FnOnce(&mut Resolver) -> T
     {
         let id = self.definitions.local_def_id(id);
         let module = self.module_map.get(&id).cloned(); // clones a reference
@@ -1838,13 +1905,14 @@
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
 
             self.finalize_current_module_macro_resolutions();
-            f(self);
+            let ret = f(self);
 
             self.current_module = orig_module;
             self.ribs[ValueNS].pop();
             self.ribs[TypeNS].pop();
+            ret
         } else {
-            f(self);
+            f(self)
         }
     }
 
@@ -1895,12 +1963,6 @@
                                              |this| visit::walk_item(this, item));
             }
 
-            ItemKind::AutoImpl(_, ref trait_ref) => {
-                self.with_optional_trait_ref(Some(trait_ref), |this, _| {
-                    // Resolve type arguments in trait path
-                    visit::walk_trait_ref(this, trait_ref);
-                });
-            }
             ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
                 self.resolve_implementation(generics,
                                             opt_trait_ref,
@@ -2567,7 +2629,8 @@
             let code = source.error_code(def.is_some());
             let (base_msg, fallback_label, base_span) = if let Some(def) = def {
                 (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
-                 format!("not a {}", expected), span)
+                 format!("not a {}", expected),
+                 span)
             } else {
                 let item_str = path[path.len() - 1].node;
                 let item_span = path[path.len() - 1].span;
@@ -2584,7 +2647,8 @@
                     (mod_prefix, format!("`{}`", names_to_string(mod_path)))
                 };
                 (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
-                 format!("not found in {}", mod_str), item_span)
+                 format!("not found in {}", mod_str),
+                 item_span)
             };
             let code = DiagnosticId::Error(code.into());
             let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
@@ -2699,20 +2763,37 @@
                         }
                         return (err, candidates);
                     },
-                    _ if ns == ValueNS && is_struct_like(def) => {
-                        if let Def::Struct(def_id) = def {
-                            if let Some((ctor_def, ctor_vis))
-                                    = this.struct_constructors.get(&def_id).cloned() {
-                                if is_expected(ctor_def) && !this.is_accessible(ctor_vis) {
-                                    err.span_label(span, format!("constructor is not visible \
-                                                                   here due to private fields"));
-                                }
+                    (Def::Struct(def_id), _) if ns == ValueNS => {
+                        if let Some((ctor_def, ctor_vis))
+                                = this.struct_constructors.get(&def_id).cloned() {
+                            let accessible_ctor = this.is_accessible(ctor_vis);
+                            if is_expected(ctor_def) && !accessible_ctor {
+                                err.span_label(span, format!("constructor is not visible \
+                                                              here due to private fields"));
                             }
+                        } else {
+                            err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
+                                                         path_str));
                         }
+                        return (err, candidates);
+                    }
+                    (Def::Union(..), _) |
+                    (Def::Variant(..), _) |
+                    (Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => {
                         err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
                                                      path_str));
                         return (err, candidates);
                     }
+                    (Def::SelfTy(..), _) if ns == ValueNS => {
+                        err.span_label(span, fallback_label);
+                        err.note("can't use `Self` as a constructor, you must use the \
+                                  implemented struct");
+                        return (err, candidates);
+                    }
+                    (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
+                        err.note("can't use a type alias as a constructor");
+                        return (err, candidates);
+                    }
                     _ => {}
                 }
             }
@@ -2750,7 +2831,7 @@
                                 let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
                                 self.session.buffer_lint(lint, id, span,
                                     "private struct constructors are not usable through \
-                                     reexports in outer modules",
+                                     re-exports in outer modules",
                                 );
                                 res = Some(PathResolution::new(ctor_def));
                             }
@@ -2984,6 +3065,8 @@
                     let msg = "There are too many initial `super`s.".to_string();
                     return PathResult::Failed(ident.span, msg, false);
                 }
+            } else if i == 0 && ns == TypeNS && name == keywords::Extern.name() {
+                continue;
             }
             allow_super = false;
 
@@ -2992,22 +3075,25 @@
                    (i == 1 && name == keywords::Crate.name() &&
                               path[0].node.name == keywords::CrateRoot.name()) {
                     // `::a::b` or `::crate::a::b`
-                    module = Some(self.resolve_crate_root(ident.node.ctxt.modern()));
+                    module = Some(self.resolve_crate_root(ident.node.ctxt, false));
                     continue
                 } else if i == 0 && name == keywords::DollarCrate.name() {
                     // `$crate::a::b`
-                    module = Some(self.resolve_crate_root(ident.node.ctxt));
+                    module = Some(self.resolve_crate_root(ident.node.ctxt, true));
                     continue
-                } else if i == 1 && self.session.features.borrow().extern_absolute_paths &&
-                                    path[0].node.name == keywords::CrateRoot.name() &&
-                                    !token::Ident(ident.node).is_path_segment_keyword() {
-                    // `::extern_crate::a::b`
-                    let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
-                    let crate_root =
-                        self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
-                    self.populate_module_if_necessary(crate_root);
-                    module = Some(crate_root);
-                    continue
+                } else if i == 1 && !token::Ident(ident.node).is_path_segment_keyword() {
+                    let prev_name = path[0].node.name;
+                    if prev_name == keywords::Extern.name() ||
+                       prev_name == keywords::CrateRoot.name() &&
+                       self.session.features.borrow().extern_absolute_paths {
+                        // `::extern_crate::a::b`
+                        let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
+                        let crate_root =
+                            self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+                        self.populate_module_if_necessary(crate_root);
+                        module = Some(crate_root);
+                        continue
+                    }
                 }
             }
 
@@ -3017,6 +3103,7 @@
                name == keywords::SelfValue.name() && i != 0 ||
                name == keywords::SelfType.name() && i != 0 ||
                name == keywords::Super.name() && i != 0 ||
+               name == keywords::Extern.name() && i != 0 ||
                name == keywords::Crate.name() && i != 1 &&
                     path[0].node.name != keywords::CrateRoot.name() {
                 let name_str = if name == keywords::CrateRoot.name() {
@@ -3776,7 +3863,7 @@
                 self.session.buffer_lint(lint::builtin::LEGACY_IMPORTS, id, span, &msg);
             } else {
                 let mut err =
-                    self.session.struct_span_err(span, &format!("`{}` is ambiguous", name));
+                    struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
                 err.span_note(b1.span, &msg1);
                 match b2.def() {
                     Def::Macro(..) if b2.span == DUMMY_SP =>
@@ -3950,7 +4037,7 @@
 
                     feature_err(&self.session.parse_sess, feature,
                                 attr.span, GateIssue::Language, msg)
-                        .span_note(binding.span(), "procedural macro imported here")
+                        .span_label(binding.span(), "procedural macro imported here")
                         .emit();
                 }
             }
@@ -3958,13 +4045,6 @@
     }
 }
 
-fn is_struct_like(def: Def) -> bool {
-    match def {
-        Def::VariantCtor(_, CtorKind::Fictive) => true,
-        _ => PathSource::Struct.is_expected(def),
-    }
-}
-
 fn is_self_type(path: &[SpannedIdent], namespace: Namespace) -> bool {
     namespace == TypeNS && path.len() == 1 && path[0].node.name == keywords::SelfType.name()
 }
@@ -4055,7 +4135,7 @@
 }
 
 /// A somewhat inefficient routine to obtain the name of a module.
-fn module_to_string(module: Module) -> String {
+fn module_to_string(module: Module) -> Option<String> {
     let mut names = Vec::new();
 
     fn collect_mod(names: &mut Vec<Ident>, module: Module) {
@@ -4073,12 +4153,12 @@
     collect_mod(&mut names, module);
 
     if names.is_empty() {
-        return "???".to_string();
+        return None;
     }
-    names_to_string(&names.into_iter()
+    Some(names_to_string(&names.into_iter()
                         .rev()
                         .map(|n| dummy_spanned(n))
-                        .collect::<Vec<_>>())
+                        .collect::<Vec<_>>()))
 }
 
 fn err_path_resolution() -> PathResolution {
@@ -4091,4 +4171,5 @@
     No,
 }
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 260a0cd..080ef32 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -13,8 +13,8 @@
 use Namespace::{self, MacroNS};
 use build_reduced_graph::BuildReducedGraphVisitor;
 use resolve_imports::ImportResolver;
-use rustc_data_structures::indexed_vec::Idx;
-use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
+use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
+                         DefIndexAddressSpace};
 use rustc::hir::def::{Def, Export};
 use rustc::hir::map::{self, DefCollector};
 use rustc::{ty, lint};
@@ -140,7 +140,7 @@
                 let ident = path.segments[0].identifier;
                 if ident.name == keywords::DollarCrate.name() {
                     path.segments[0].identifier.name = keywords::CrateRoot.name();
-                    let module = self.0.resolve_crate_root(ident.ctxt);
+                    let module = self.0.resolve_crate_root(ident.ctxt, true);
                     if !module.is_local() {
                         let span = path.segments[0].span;
                         path.segments.insert(1, match module.kind {
@@ -188,7 +188,8 @@
     fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         let def_id = DefId {
             krate: BUILTIN_MACROS_CRATE,
-            index: DefIndex::new(self.macro_map.len()),
+            index: DefIndex::from_array_index(self.macro_map.len(),
+                                              DefIndexAddressSpace::Low),
         };
         let kind = ext.kind();
         self.macro_map.insert(def_id, ext);
@@ -408,7 +409,7 @@
         def
     }
 
-    fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
+    pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
                                   kind: MacroKind, force: bool)
                                   -> Result<Def, Determinacy> {
         let ast::Path { ref segments, span } = *path;
@@ -429,7 +430,15 @@
             let def = match self.resolve_path(&path, Some(MacroNS), false, span) {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
-                    def @ _ => Ok(def),
+                    def @ _ => {
+                        if path_res.unresolved_segments() > 0 {
+                            self.found_unresolved_macro = true;
+                            self.session.span_err(span, "fail to resolve non-ident macro path");
+                            Err(Determinacy::Determined)
+                        } else {
+                            Ok(def)
+                        }
+                    }
                 },
                 PathResult::Module(..) => unreachable!(),
                 PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
@@ -682,8 +691,7 @@
         if let Some(suggestion) = suggestion {
             if suggestion != name {
                 if let MacroKind::Bang = kind {
-                    err.span_suggestion(span, "you could try the macro",
-                                        format!("{}!", suggestion));
+                    err.span_suggestion(span, "you could try the macro", suggestion.to_string());
                 } else {
                     err.span_suggestion(span, "try", suggestion.to_string());
                 }
@@ -747,8 +755,9 @@
             *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
                 parent: Cell::new(*legacy_scope), ident: ident, def_id: def_id, span: item.span,
             }));
+            let def = Def::Macro(def_id, MacroKind::Bang);
+            self.all_macros.insert(ident.name, def);
             if attr::contains_name(&item.attrs, "macro_export") {
-                let def = Def::Macro(def_id, MacroKind::Bang);
                 self.macro_exports.push(Export {
                     ident: ident.modern(),
                     def: def,
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index e249ecf..07b08e2 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -46,8 +46,8 @@
     },
     GlobImport {
         is_prelude: bool,
-        max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
-        // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
+        max_vis: Cell<ty::Visibility>, // The visibility of the greatest re-export.
+        // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
     },
     ExternCrate(Option<Name>),
     MacroUse,
@@ -524,7 +524,7 @@
     fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
         debug!("(resolving import for module) resolving import `{}::...` in `{}`",
                names_to_string(&directive.module_path[..]),
-               module_to_string(self.current_module));
+               module_to_string(self.current_module).unwrap_or("???".to_string()));
 
         self.current_module = directive.parent;
 
@@ -604,26 +604,28 @@
         self.current_module = directive.parent;
         let ImportDirective { ref module_path, span, .. } = *directive;
 
-        // Extern crate mode for absolute paths needs some
-        // special support for single-segment imports.
-        let extern_absolute_paths = self.session.features.borrow().extern_absolute_paths;
-        if module_path.len() == 1 && module_path[0].node.name == keywords::CrateRoot.name() {
+        // FIXME: Last path segment is treated specially in import resolution, so extern crate
+        // mode for absolute paths needs some special support for single-segment imports.
+        if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() ||
+                                      module_path[0].node.name == keywords::Extern.name()) {
+            let is_extern = module_path[0].node.name == keywords::Extern.name() ||
+                            self.session.features.borrow().extern_absolute_paths;
             match directive.subclass {
-                GlobImport { .. } if extern_absolute_paths => {
+                GlobImport { .. } if is_extern => {
                     return Some((directive.span,
                                  "cannot glob-import all possible crates".to_string()));
                 }
                 SingleImport { source, target, .. } => {
-                    let crate_root = if source.name == keywords::Crate.name() {
+                    let crate_root = if source.name == keywords::Crate.name() &&
+                                        module_path[0].node.name != keywords::Extern.name() {
                         if target.name == keywords::Crate.name() {
                             return Some((directive.span,
                                          "crate root imports need to be explicitly named: \
                                           `use crate as name;`".to_string()));
                         } else {
-                            Some(self.resolve_crate_root(source.ctxt.modern()))
+                            Some(self.resolve_crate_root(source.ctxt.modern(), false))
                         }
-                    } else if extern_absolute_paths &&
-                              !token::Ident(source).is_path_segment_keyword() {
+                    } else if is_extern && !token::Ident(source).is_path_segment_keyword() {
                         let crate_id =
                             self.crate_loader.resolve_crate_from_path(source.name, directive.span);
                         let crate_root =
@@ -771,10 +773,10 @@
                         None => "".to_owned(),
                     };
                 let module_str = module_to_string(module);
-                let msg = if &module_str == "???" {
-                    format!("no `{}` in the root{}", ident, lev_suggestion)
-                } else {
+                let msg = if let Some(module_str) = module_str {
                     format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
+                } else {
+                    format!("no `{}` in the root{}", ident, lev_suggestion)
                 };
                 Some((span, msg))
             } else {
@@ -801,8 +803,9 @@
         if !any_successful_reexport {
             let (ns, binding) = reexport_error.unwrap();
             if ns == TypeNS && binding.is_extern_crate() {
-                let msg = format!("extern crate `{}` is private, and cannot be reexported \
-                                   (error E0365), consider declaring with `pub`",
+                let msg = format!("extern crate `{}` is private, and cannot be \
+                                   re-exported (error E0365), consider declaring with \
+                                   `pub`",
                                    ident);
                 self.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE,
                                          directive.id,
@@ -810,12 +813,12 @@
                                          &msg);
             } else if ns == TypeNS {
                 struct_span_err!(self.session, directive.span, E0365,
-                                 "`{}` is private, and cannot be reexported", ident)
-                    .span_label(directive.span, format!("reexport of private `{}`", ident))
+                                 "`{}` is private, and cannot be re-exported", ident)
+                    .span_label(directive.span, format!("re-export of private `{}`", ident))
                     .note(&format!("consider declaring type or module `{}` with `pub`", ident))
                     .emit();
             } else {
-                let msg = format!("`{}` is private, and cannot be reexported", ident);
+                let msg = format!("`{}` is private, and cannot be re-exported", ident);
                 let note_msg =
                     format!("consider marking `{}` as `pub` in the imported module", ident);
                 struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
@@ -874,7 +877,7 @@
         self.record_def(directive.id, PathResolution::new(module.def().unwrap()));
     }
 
-    // Miscellaneous post-processing, including recording reexports,
+    // Miscellaneous post-processing, including recording re-exports,
     // reporting conflicts, and reporting unresolved imports.
     fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         // Since import resolution is finished, globs will not define any more names.
@@ -930,12 +933,12 @@
                         !orig_binding.vis.is_at_least(binding.vis, &*self) {
                             let msg = match directive.subclass {
                                 ImportDirectiveSubclass::SingleImport { .. } => {
-                                    format!("variant `{}` is private and cannot be reexported",
+                                    format!("variant `{}` is private and cannot be re-exported",
                                             ident)
                                 },
                                 ImportDirectiveSubclass::GlobImport { .. } => {
                                     let msg = "enum is private and its variants \
-                                               cannot be reexported".to_owned();
+                                               cannot be re-exported".to_owned();
                                     let error_id = (DiagnosticMessageId::ErrorId(0), // no code?!
                                                     Some(binding.span),
                                                     msg.clone());
diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml
index d8581f5..8b2658b 100644
--- a/src/librustc_save_analysis/Cargo.toml
+++ b/src/librustc_save_analysis/Cargo.toml
@@ -9,7 +9,7 @@
 crate-type = ["dylib"]
 
 [dependencies]
-log = "0.3"
+log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_typeck = { path = "../librustc_typeck" }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index ed3b8ea..69cef20 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1252,7 +1252,13 @@
                          root_item: &'l ast::Item,
                          prefix: &ast::Path) {
         let path = &use_tree.prefix;
-        let access = access_from!(self.save_ctxt, root_item);
+
+        // The access is calculated using the current tree ID, but with the root tree's visibility
+        // (since nested trees don't have their own visibility).
+        let access = Access {
+            public: root_item.vis == ast::Visibility::Public,
+            reachable: self.save_ctxt.analysis.access_levels.is_reachable(id),
+        };
 
         // The parent def id of a given use tree is always the enclosing item.
         let parent = self.save_ctxt.tcx.hir.opt_local_def_id(id)
@@ -1583,10 +1589,12 @@
                         if !self.span.filter_generated(sub_span, ex.span) {
                             let span =
                                 self.span_from_span(sub_span.expect("No span found for var ref"));
+                            let ref_id =
+                                ::id_from_def_id(def.non_enum_variant().fields[idx.node].did);
                             self.dumper.dump_ref(Ref {
                                 kind: RefKind::Variable,
                                 span,
-                                ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did),
+                                ref_id,
                             });
                         }
                     }
@@ -1594,7 +1602,7 @@
                     _ => span_bug!(ex.span, "Expected struct or tuple type, found {:?}", ty),
                 }
             }
-            ast::ExprKind::Closure(_, ref decl, ref body, _fn_decl_span) => {
+            ast::ExprKind::Closure(_, _, ref decl, ref body, _fn_decl_span) => {
                 let mut id = String::from("$");
                 id.push_str(&ex.id.to_string());
 
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 93fb22a..2e494fd 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -528,7 +528,7 @@
                 };
                 match self.tables.expr_ty_adjusted(&hir_node).sty {
                     ty::TyAdt(def, _) if !def.is_enum() => {
-                        let f = def.struct_variant().field_named(ident.node.name);
+                        let f = def.non_enum_variant().field_named(ident.node.name);
                         let sub_span = self.span_utils.span_for_last_ident(expr.span);
                         filter!(self.span_utils, sub_span, expr.span, None);
                         let span = self.span_from_span(sub_span.unwrap());
@@ -1077,21 +1077,21 @@
     config: Option<Config>,
     mut handler: H,
 ) {
-    let _ignore = tcx.dep_graph.in_ignore();
+    tcx.dep_graph.with_ignore(|| {
+        assert!(analysis.glob_map.is_some());
 
-    assert!(analysis.glob_map.is_some());
+        info!("Dumping crate {}", cratename);
 
-    info!("Dumping crate {}", cratename);
+        let save_ctxt = SaveContext {
+            tcx,
+            tables: &ty::TypeckTables::empty(None),
+            analysis,
+            span_utils: SpanUtils::new(&tcx.sess),
+            config: find_config(config),
+        };
 
-    let save_ctxt = SaveContext {
-        tcx,
-        tables: &ty::TypeckTables::empty(None),
-        analysis,
-        span_utils: SpanUtils::new(&tcx.sess),
-        config: find_config(config),
-    };
-
-    handler.save(save_ctxt, krate, cratename)
+        handler.save(save_ctxt, krate, cratename)
+    })
 }
 
 fn find_config(supplied: Option<Config>) -> Config {
@@ -1123,7 +1123,7 @@
 fn id_from_def_id(id: DefId) -> rls_data::Id {
     rls_data::Id {
         krate: id.krate.as_u32(),
-        index: id.index.as_u32(),
+        index: id.index.as_raw_u32(),
     }
 }
 
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 9211ddf..0c890ce 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -511,17 +511,6 @@
 
                 Ok(sig)
             }
-            ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
-                let mut text = String::new();
-                if unsafety == ast::Unsafety::Unsafe {
-                    text.push_str("unsafe ");
-                }
-                text.push_str("impl ");
-                let trait_sig = trait_ref.path.make(offset + text.len(), id, scx)?;
-                text.push_str(&trait_sig.text);
-                text.push_str(" for .. {}");
-                Ok(replace_text(trait_sig, text))
-            }
             ast::ItemKind::Impl(
                 unsafety,
                 polarity,
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index f1549d9..79dd57b 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -11,9 +11,9 @@
 
 [dependencies]
 bitflags = "1.0"
-flate2 = "0.2"
+flate2 = "1.0"
 jobserver = "0.1.5"
-log = "0.3"
+log = "0.4"
 num_cpus = "1.0"
 rustc = { path = "../librustc" }
 rustc-demangle = "0.1.4"
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 32dc106..5079ce7 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -12,7 +12,7 @@
 use base;
 use builder::Builder;
 use common::{ty_fn_sig, C_usize};
-use context::CrateContext;
+use context::CodegenCx;
 use cabi_x86;
 use cabi_x86_64;
 use cabi_x86_win64;
@@ -209,8 +209,8 @@
 }
 
 impl Reg {
-    pub fn align(&self, ccx: &CrateContext) -> Align {
-        let dl = ccx.data_layout();
+    pub fn align(&self, cx: &CodegenCx) -> Align {
+        let dl = cx.data_layout();
         match self.kind {
             RegKind::Integer => {
                 match self.size.bits() {
@@ -234,18 +234,18 @@
         }
     }
 
-    pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
+    pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
         match self.kind {
-            RegKind::Integer => Type::ix(ccx, self.size.bits()),
+            RegKind::Integer => Type::ix(cx, self.size.bits()),
             RegKind::Float => {
                 match self.size.bits() {
-                    32 => Type::f32(ccx),
-                    64 => Type::f64(ccx),
+                    32 => Type::f32(cx),
+                    64 => Type::f64(cx),
                     _ => bug!("unsupported float: {:?}", self)
                 }
             }
             RegKind::Vector => {
-                Type::vector(&Type::i8(ccx), self.size.bytes())
+                Type::vector(&Type::i8(cx), self.size.bytes())
             }
         }
     }
@@ -276,12 +276,12 @@
 }
 
 impl Uniform {
-    pub fn align(&self, ccx: &CrateContext) -> Align {
-        self.unit.align(ccx)
+    pub fn align(&self, cx: &CodegenCx) -> Align {
+        self.unit.align(cx)
     }
 
-    pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
-        let llunit = self.unit.llvm_type(ccx);
+    pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
+        let llunit = self.unit.llvm_type(cx);
 
         if self.total <= self.unit.size {
             return llunit;
@@ -298,16 +298,16 @@
         assert_eq!(self.unit.kind, RegKind::Integer);
 
         let args: Vec<_> = (0..count).map(|_| llunit)
-            .chain(iter::once(Type::ix(ccx, rem_bytes * 8)))
+            .chain(iter::once(Type::ix(cx, rem_bytes * 8)))
             .collect();
 
-        Type::struct_(ccx, &args, false)
+        Type::struct_(cx, &args, false)
     }
 }
 
 pub trait LayoutExt<'tcx> {
     fn is_aggregate(&self) -> bool;
-    fn homogeneous_aggregate<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Option<Reg>;
+    fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg>;
 }
 
 impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
@@ -321,7 +321,7 @@
         }
     }
 
-    fn homogeneous_aggregate<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Option<Reg> {
+    fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg> {
         match self.abi {
             layout::Abi::Uninhabited => None,
 
@@ -354,7 +354,7 @@
                 let is_union = match self.fields {
                     layout::FieldPlacement::Array { count, .. } => {
                         if count > 0 {
-                            return self.field(ccx, 0).homogeneous_aggregate(ccx);
+                            return self.field(cx, 0).homogeneous_aggregate(cx);
                         } else {
                             return None;
                         }
@@ -368,8 +368,8 @@
                         return None;
                     }
 
-                    let field = self.field(ccx, i);
-                    match (result, field.homogeneous_aggregate(ccx)) {
+                    let field = self.field(cx, i);
+                    match (result, field.homogeneous_aggregate(cx)) {
                         // The field itself must be a homogeneous aggregate.
                         (_, None) => return None,
                         // If this is the first field, record the unit.
@@ -423,34 +423,34 @@
 }
 
 impl CastTarget {
-    pub fn size(&self, ccx: &CrateContext) -> Size {
+    pub fn size(&self, cx: &CodegenCx) -> Size {
         match *self {
             CastTarget::Uniform(u) => u.total,
             CastTarget::Pair(a, b) => {
-                (a.size.abi_align(a.align(ccx)) + b.size)
-                    .abi_align(self.align(ccx))
+                (a.size.abi_align(a.align(cx)) + b.size)
+                    .abi_align(self.align(cx))
             }
         }
     }
 
-    pub fn align(&self, ccx: &CrateContext) -> Align {
+    pub fn align(&self, cx: &CodegenCx) -> Align {
         match *self {
-            CastTarget::Uniform(u) => u.align(ccx),
+            CastTarget::Uniform(u) => u.align(cx),
             CastTarget::Pair(a, b) => {
-                ccx.data_layout().aggregate_align
-                    .max(a.align(ccx))
-                    .max(b.align(ccx))
+                cx.data_layout().aggregate_align
+                    .max(a.align(cx))
+                    .max(b.align(cx))
             }
         }
     }
 
-    pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
+    pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
         match *self {
-            CastTarget::Uniform(u) => u.llvm_type(ccx),
+            CastTarget::Uniform(u) => u.llvm_type(cx),
             CastTarget::Pair(a, b) => {
-                Type::struct_(ccx, &[
-                    a.llvm_type(ccx),
-                    b.llvm_type(ccx)
+                Type::struct_(cx, &[
+                    a.llvm_type(cx),
+                    b.llvm_type(cx)
                 ], false)
             }
         }
@@ -547,28 +547,28 @@
 
     /// Get the LLVM type for an place of the original Rust type of
     /// this argument/return, i.e. the result of `type_of::type_of`.
-    pub fn memory_ty(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
-        self.layout.llvm_type(ccx)
+    pub fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+        self.layout.llvm_type(cx)
     }
 
     /// Store a direct/indirect value described by this ArgType into a
     /// place for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
     /// or results of call/invoke instructions into their destinations.
-    pub fn store(&self, bcx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
+    pub fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
         if self.is_ignore() {
             return;
         }
-        let ccx = bcx.ccx;
+        let cx = bx.cx;
         if self.is_indirect() {
-            OperandValue::Ref(val, self.layout.align).store(bcx, dst)
+            OperandValue::Ref(val, self.layout.align).store(bx, dst)
         } else if let PassMode::Cast(cast) = self.mode {
             // FIXME(eddyb): Figure out when the simpler Store is safe, clang
             // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
             let can_store_through_cast_ptr = false;
             if can_store_through_cast_ptr {
-                let cast_dst = bcx.pointercast(dst.llval, cast.llvm_type(ccx).ptr_to());
-                bcx.store(val, cast_dst, self.layout.align);
+                let cast_dst = bx.pointercast(dst.llval, cast.llvm_type(cx).ptr_to());
+                bx.store(val, cast_dst, self.layout.align);
             } else {
                 // The actual return type is a struct, but the ABI
                 // adaptation code has cast it into some scalar type.  The
@@ -585,44 +585,41 @@
                 //   bitcasting to the struct type yields invalid cast errors.
 
                 // We instead thus allocate some scratch space...
-                let scratch_size = cast.size(ccx);
-                let scratch_align = cast.align(ccx);
-                let llscratch = bcx.alloca(cast.llvm_type(ccx), "abi_cast", scratch_align);
-                bcx.lifetime_start(llscratch, scratch_size);
+                let scratch_size = cast.size(cx);
+                let scratch_align = cast.align(cx);
+                let llscratch = bx.alloca(cast.llvm_type(cx), "abi_cast", scratch_align);
+                bx.lifetime_start(llscratch, scratch_size);
 
                 // ...where we first store the value...
-                bcx.store(val, llscratch, scratch_align);
+                bx.store(val, llscratch, scratch_align);
 
                 // ...and then memcpy it to the intended destination.
-                base::call_memcpy(bcx,
-                                  bcx.pointercast(dst.llval, Type::i8p(ccx)),
-                                  bcx.pointercast(llscratch, Type::i8p(ccx)),
-                                  C_usize(ccx, self.layout.size.bytes()),
+                base::call_memcpy(bx,
+                                  bx.pointercast(dst.llval, Type::i8p(cx)),
+                                  bx.pointercast(llscratch, Type::i8p(cx)),
+                                  C_usize(cx, self.layout.size.bytes()),
                                   self.layout.align.min(scratch_align));
 
-                bcx.lifetime_end(llscratch, scratch_size);
+                bx.lifetime_end(llscratch, scratch_size);
             }
         } else {
-            OperandValue::Immediate(val).store(bcx, dst);
+            OperandValue::Immediate(val).store(bx, dst);
         }
     }
 
-    pub fn store_fn_arg(&self, bcx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
-        if self.pad.is_some() {
-            *idx += 1;
-        }
+    pub fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
         let mut next = || {
-            let val = llvm::get_param(bcx.llfn(), *idx as c_uint);
+            let val = llvm::get_param(bx.llfn(), *idx as c_uint);
             *idx += 1;
             val
         };
         match self.mode {
             PassMode::Ignore => {},
             PassMode::Pair(..) => {
-                OperandValue::Pair(next(), next()).store(bcx, dst);
+                OperandValue::Pair(next(), next()).store(bx, dst);
             }
             PassMode::Direct(_) | PassMode::Indirect(_) | PassMode::Cast(_) => {
-                self.store(bcx, next(), dst);
+                self.store(bx, next(), dst);
             }
         }
     }
@@ -647,26 +644,26 @@
 }
 
 impl<'a, 'tcx> FnType<'tcx> {
-    pub fn of_instance(ccx: &CrateContext<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+    pub fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
                        -> Self {
-        let fn_ty = instance.ty(ccx.tcx());
-        let sig = ty_fn_sig(ccx, fn_ty);
-        let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
-        FnType::new(ccx, sig, &[])
+        let fn_ty = instance.ty(cx.tcx);
+        let sig = ty_fn_sig(cx, fn_ty);
+        let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
+        FnType::new(cx, sig, &[])
     }
 
-    pub fn new(ccx: &CrateContext<'a, 'tcx>,
+    pub fn new(cx: &CodegenCx<'a, 'tcx>,
                sig: ty::FnSig<'tcx>,
                extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
-        let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
-        fn_ty.adjust_for_abi(ccx, sig.abi);
+        let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
+        fn_ty.adjust_for_abi(cx, sig.abi);
         fn_ty
     }
 
-    pub fn new_vtable(ccx: &CrateContext<'a, 'tcx>,
+    pub fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
                       sig: ty::FnSig<'tcx>,
                       extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
-        let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
+        let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
         // Don't pass the vtable, it's not an argument of the virtual fn.
         {
             let self_arg = &mut fn_ty.args[0];
@@ -681,20 +678,20 @@
                 .unwrap_or_else(|| {
                     bug!("FnType::new_vtable: non-pointer self {:?}", self_arg)
                 }).ty;
-            let fat_ptr_ty = ccx.tcx().mk_mut_ptr(pointee);
-            self_arg.layout = ccx.layout_of(fat_ptr_ty).field(ccx, 0);
+            let fat_ptr_ty = cx.tcx.mk_mut_ptr(pointee);
+            self_arg.layout = cx.layout_of(fat_ptr_ty).field(cx, 0);
         }
-        fn_ty.adjust_for_abi(ccx, sig.abi);
+        fn_ty.adjust_for_abi(cx, sig.abi);
         fn_ty
     }
 
-    pub fn unadjusted(ccx: &CrateContext<'a, 'tcx>,
+    pub fn unadjusted(cx: &CodegenCx<'a, 'tcx>,
                       sig: ty::FnSig<'tcx>,
                       extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
         debug!("FnType::unadjusted({:?}, {:?})", sig, extra_args);
 
         use self::Abi::*;
-        let cconv = match ccx.sess().target.target.adjust_abi(sig.abi) {
+        let cconv = match cx.sess().target.target.adjust_abi(sig.abi) {
             RustIntrinsic | PlatformIntrinsic |
             Rust | RustCall => llvm::CCallConv,
 
@@ -737,7 +734,7 @@
             extra_args
         };
 
-        let target = &ccx.sess().target.target;
+        let target = &cx.sess().target.target;
         let win_x64_gnu = target.target_os == "windows"
                        && target.arch == "x86_64"
                        && target.target_env == "gnu";
@@ -772,7 +769,7 @@
                 }
             }
 
-            if let Some(pointee) = layout.pointee_info_at(ccx, offset) {
+            if let Some(pointee) = layout.pointee_info_at(cx, offset) {
                 if let Some(kind) = pointee.safe {
                     attrs.pointee_size = pointee.size;
                     attrs.pointee_align = Some(pointee.align);
@@ -809,7 +806,7 @@
         };
 
         let arg_of = |ty: Ty<'tcx>, is_return: bool| {
-            let mut arg = ArgType::new(ccx.layout_of(ty));
+            let mut arg = ArgType::new(cx.layout_of(ty));
             if arg.layout.is_zst() {
                 // For some forsaken reason, x86_64-pc-windows-gnu
                 // doesn't ignore zero-sized struct arguments.
@@ -832,7 +829,7 @@
                     adjust_for_rust_scalar(&mut b_attrs,
                                            b,
                                            arg.layout,
-                                           a.value.size(ccx).abi_align(b.value.align(ccx)),
+                                           a.value.size(cx).abi_align(b.value.align(cx)),
                                            false);
                     arg.mode = PassMode::Pair(a_attrs, b_attrs);
                     return arg;
@@ -863,7 +860,7 @@
     }
 
     fn adjust_for_abi(&mut self,
-                      ccx: &CrateContext<'a, 'tcx>,
+                      cx: &CodegenCx<'a, 'tcx>,
                       abi: Abi) {
         if abi == Abi::Unadjusted { return }
 
@@ -878,7 +875,7 @@
                 }
 
                 let size = arg.layout.size;
-                if size > layout::Pointer.size(ccx) {
+                if size > layout::Pointer.size(cx) {
                     arg.make_indirect();
                 } else {
                     // We want to pass small aggregates as immediates, but using
@@ -900,38 +897,38 @@
             return;
         }
 
-        match &ccx.sess().target.target.arch[..] {
+        match &cx.sess().target.target.arch[..] {
             "x86" => {
                 let flavor = if abi == Abi::Fastcall {
                     cabi_x86::Flavor::Fastcall
                 } else {
                     cabi_x86::Flavor::General
                 };
-                cabi_x86::compute_abi_info(ccx, self, flavor);
+                cabi_x86::compute_abi_info(cx, self, flavor);
             },
             "x86_64" => if abi == Abi::SysV64 {
-                cabi_x86_64::compute_abi_info(ccx, self);
-            } else if abi == Abi::Win64 || ccx.sess().target.target.options.is_like_windows {
+                cabi_x86_64::compute_abi_info(cx, self);
+            } else if abi == Abi::Win64 || cx.sess().target.target.options.is_like_windows {
                 cabi_x86_win64::compute_abi_info(self);
             } else {
-                cabi_x86_64::compute_abi_info(ccx, self);
+                cabi_x86_64::compute_abi_info(cx, self);
             },
-            "aarch64" => cabi_aarch64::compute_abi_info(ccx, self),
-            "arm" => cabi_arm::compute_abi_info(ccx, self),
-            "mips" => cabi_mips::compute_abi_info(ccx, self),
-            "mips64" => cabi_mips64::compute_abi_info(ccx, self),
-            "powerpc" => cabi_powerpc::compute_abi_info(ccx, self),
-            "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self),
-            "s390x" => cabi_s390x::compute_abi_info(ccx, self),
-            "asmjs" => cabi_asmjs::compute_abi_info(ccx, self),
-            "wasm32" => cabi_asmjs::compute_abi_info(ccx, self),
+            "aarch64" => cabi_aarch64::compute_abi_info(cx, self),
+            "arm" => cabi_arm::compute_abi_info(cx, self),
+            "mips" => cabi_mips::compute_abi_info(cx, self),
+            "mips64" => cabi_mips64::compute_abi_info(cx, self),
+            "powerpc" => cabi_powerpc::compute_abi_info(cx, self),
+            "powerpc64" => cabi_powerpc64::compute_abi_info(cx, self),
+            "s390x" => cabi_s390x::compute_abi_info(cx, self),
+            "asmjs" => cabi_asmjs::compute_abi_info(cx, self),
+            "wasm32" => cabi_asmjs::compute_abi_info(cx, self),
             "msp430" => cabi_msp430::compute_abi_info(self),
-            "sparc" => cabi_sparc::compute_abi_info(ccx, self),
-            "sparc64" => cabi_sparc64::compute_abi_info(ccx, self),
+            "sparc" => cabi_sparc::compute_abi_info(cx, self),
+            "sparc64" => cabi_sparc64::compute_abi_info(cx, self),
             "nvptx" => cabi_nvptx::compute_abi_info(self),
             "nvptx64" => cabi_nvptx64::compute_abi_info(self),
             "hexagon" => cabi_hexagon::compute_abi_info(self),
-            a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
+            a => cx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
         }
 
         if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
@@ -939,37 +936,37 @@
         }
     }
 
-    pub fn llvm_type(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
+    pub fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         let mut llargument_tys = Vec::new();
 
         let llreturn_ty = match self.ret.mode {
-            PassMode::Ignore => Type::void(ccx),
+            PassMode::Ignore => Type::void(cx),
             PassMode::Direct(_) | PassMode::Pair(..) => {
-                self.ret.layout.immediate_llvm_type(ccx)
+                self.ret.layout.immediate_llvm_type(cx)
             }
-            PassMode::Cast(cast) => cast.llvm_type(ccx),
+            PassMode::Cast(cast) => cast.llvm_type(cx),
             PassMode::Indirect(_) => {
-                llargument_tys.push(self.ret.memory_ty(ccx).ptr_to());
-                Type::void(ccx)
+                llargument_tys.push(self.ret.memory_ty(cx).ptr_to());
+                Type::void(cx)
             }
         };
 
         for arg in &self.args {
             // add padding
             if let Some(ty) = arg.pad {
-                llargument_tys.push(ty.llvm_type(ccx));
+                llargument_tys.push(ty.llvm_type(cx));
             }
 
             let llarg_ty = match arg.mode {
                 PassMode::Ignore => continue,
-                PassMode::Direct(_) => arg.layout.immediate_llvm_type(ccx),
+                PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx),
                 PassMode::Pair(..) => {
-                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(ccx, 0));
-                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(ccx, 1));
+                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0));
+                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1));
                     continue;
                 }
-                PassMode::Cast(cast) => cast.llvm_type(ccx),
-                PassMode::Indirect(_) => arg.memory_ty(ccx).ptr_to(),
+                PassMode::Cast(cast) => cast.llvm_type(cx),
+                PassMode::Indirect(_) => arg.memory_ty(cx).ptr_to(),
             };
             llargument_tys.push(llarg_ty);
         }
diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs
index 9abb6d6..fd5aa13 100644
--- a/src/librustc_trans/allocator.rs
+++ b/src/librustc_trans/allocator.rs
@@ -19,7 +19,7 @@
 use ModuleLlvm;
 use llvm::{self, False, True};
 
-pub unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
+pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
     let llcx = mods.llcx;
     let llmod = mods.llmod;
     let usize = match &tcx.sess.target.target.target_pointer_width[..] {
diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs
index ef76fec..c7be0c4 100644
--- a/src/librustc_trans/asm.rs
+++ b/src/librustc_trans/asm.rs
@@ -27,7 +27,7 @@
 
 // Take an inline assembly expression and splat it out via LLVM
 pub fn trans_inline_asm<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     ia: &hir::InlineAsm,
     outputs: Vec<PlaceRef<'tcx>>,
     mut inputs: Vec<ValueRef>
@@ -39,13 +39,13 @@
     let mut indirect_outputs = vec![];
     for (i, (out, place)) in ia.outputs.iter().zip(&outputs).enumerate() {
         if out.is_rw {
-            inputs.push(place.load(bcx).immediate());
+            inputs.push(place.load(bx).immediate());
             ext_constraints.push(i.to_string());
         }
         if out.is_indirect {
-            indirect_outputs.push(place.load(bcx).immediate());
+            indirect_outputs.push(place.load(bx).immediate());
         } else {
-            output_types.push(place.layout.llvm_type(bcx.ccx));
+            output_types.push(place.layout.llvm_type(bx.cx));
         }
     }
     if !indirect_outputs.is_empty() {
@@ -58,7 +58,7 @@
 
     // Default per-arch clobbers
     // Basically what clang does
-    let arch_clobbers = match &bcx.sess().target.target.arch[..] {
+    let arch_clobbers = match &bx.sess().target.target.arch[..] {
         "x86" | "x86_64" => vec!["~{dirflag}", "~{fpsr}", "~{flags}"],
         _                => Vec::new()
     };
@@ -76,9 +76,9 @@
     // Depending on how many outputs we have, the return type is different
     let num_outputs = output_types.len();
     let output_type = match num_outputs {
-        0 => Type::void(bcx.ccx),
+        0 => Type::void(bx.cx),
         1 => output_types[0],
-        _ => Type::struct_(bcx.ccx, &output_types, false)
+        _ => Type::struct_(bx.cx, &output_types, false)
     };
 
     let dialect = match ia.dialect {
@@ -88,7 +88,7 @@
 
     let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
     let constraint_cstr = CString::new(all_constraints).unwrap();
-    let r = bcx.inline_asm_call(
+    let r = bx.inline_asm_call(
         asm.as_ptr(),
         constraint_cstr.as_ptr(),
         &inputs,
@@ -101,28 +101,28 @@
     // Again, based on how many outputs we have
     let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
     for (i, (_, &place)) in outputs.enumerate() {
-        let v = if num_outputs == 1 { r } else { bcx.extract_value(r, i as u64) };
-        OperandValue::Immediate(v).store(bcx, place);
+        let v = if num_outputs == 1 { r } else { bx.extract_value(r, i as u64) };
+        OperandValue::Immediate(v).store(bx, place);
     }
 
     // Store mark in a metadata node so we can map LLVM errors
     // back to source locations.  See #17552.
     unsafe {
         let key = "srcloc";
-        let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx.llcx(),
+        let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx,
             key.as_ptr() as *const c_char, key.len() as c_uint);
 
-        let val: llvm::ValueRef = C_i32(bcx.ccx, ia.ctxt.outer().as_u32() as i32);
+        let val: llvm::ValueRef = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
 
         llvm::LLVMSetMetadata(r, kind,
-            llvm::LLVMMDNodeInContext(bcx.ccx.llcx(), &val, 1));
+            llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
     }
 }
 
-pub fn trans_global_asm<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn trans_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                   ga: &hir::GlobalAsm) {
     let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
     unsafe {
-        llvm::LLVMRustAppendModuleInlineAsm(ccx.llmod(), asm.as_ptr());
+        llvm::LLVMRustAppendModuleInlineAsm(cx.llmod, asm.as_ptr());
     }
 }
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index 745aa0d..6c80883 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -10,14 +10,21 @@
 //! Set and unset common attributes on LLVM values.
 
 use std::ffi::{CStr, CString};
+use std::rc::Rc;
 
+use rustc::hir::Unsafety;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::session::config::Sanitizer;
+use rustc::ty::TyCtxt;
+use rustc::ty::maps::Providers;
+use rustc_data_structures::fx::FxHashSet;
 
 use llvm::{self, Attribute, ValueRef};
 use llvm::AttributePlace::Function;
+use llvm_util;
 pub use syntax::attr::{self, InlineAttr};
 use syntax::ast;
-use context::CrateContext;
+use context::CodegenCx;
 
 /// Mark LLVM function to use provided inline heuristic.
 #[inline]
@@ -60,27 +67,27 @@
     Attribute::Naked.toggle_llfn(Function, val, is_naked);
 }
 
-pub fn set_frame_pointer_elimination(ccx: &CrateContext, llfn: ValueRef) {
+pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) {
     // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
     // parameter.
-    if ccx.sess().must_not_eliminate_frame_pointers() {
+    if cx.sess().must_not_eliminate_frame_pointers() {
         llvm::AddFunctionAttrStringValue(
             llfn, llvm::AttributePlace::Function,
             cstr("no-frame-pointer-elim\0"), cstr("true\0"));
     }
 }
 
-pub fn set_probestack(ccx: &CrateContext, llfn: ValueRef) {
+pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
     // Only use stack probes if the target specification indicates that we
     // should be using stack probes
-    if !ccx.sess().target.target.options.stack_probes {
+    if !cx.sess().target.target.options.stack_probes {
         return
     }
 
     // Currently stack probes seem somewhat incompatible with the address
     // sanitizer. With asan we're already protected from stack overflow anyway
     // so we don't really need stack probes regardless.
-    match ccx.sess().opts.debugging_opts.sanitizer {
+    match cx.sess().opts.debugging_opts.sanitizer {
         Some(Sanitizer::Address) => return,
         _ => {}
     }
@@ -94,23 +101,16 @@
 
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
-pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
+pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
     use syntax::attr::*;
-    inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
+    let attrs = cx.tcx.get_attrs(id);
+    inline(llfn, find_inline_attr(Some(cx.sess().diagnostic()), &attrs));
 
-    set_frame_pointer_elimination(ccx, llfn);
-    set_probestack(ccx, llfn);
-    let mut target_features = vec![];
-    for attr in attrs {
-        if attr.check_name("target_feature") {
-            if let Some(val) = attr.value_str() {
-                for feat in val.as_str().split(",").map(|f| f.trim()) {
-                    if !feat.is_empty() && !feat.contains('\0') {
-                        target_features.push(feat.to_string());
-                    }
-                }
-            }
-        } else if attr.check_name("cold") {
+    set_frame_pointer_elimination(cx, llfn);
+    set_probestack(cx, llfn);
+
+    for attr in attrs.iter() {
+        if attr.check_name("cold") {
             Attribute::Cold.apply_llfn(Function, llfn);
         } else if attr.check_name("naked") {
             naked(llfn, true);
@@ -123,6 +123,8 @@
             unwind(llfn, false);
         }
     }
+
+    let target_features = cx.tcx.target_features_enabled(id);
     if !target_features.is_empty() {
         let val = CString::new(target_features.join(",")).unwrap();
         llvm::AddFunctionAttrStringValue(
@@ -134,3 +136,97 @@
 fn cstr(s: &'static str) -> &CStr {
     CStr::from_bytes_with_nul(s.as_bytes()).expect("null-terminated string")
 }
+
+pub fn provide(providers: &mut Providers) {
+    providers.target_features_whitelist = |tcx, cnum| {
+        assert_eq!(cnum, LOCAL_CRATE);
+        Rc::new(llvm_util::target_feature_whitelist(tcx.sess)
+            .iter()
+            .map(|c| c.to_str().unwrap().to_string())
+            .collect())
+    };
+
+    providers.target_features_enabled = |tcx, id| {
+        let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
+        let mut target_features = Vec::new();
+        for attr in tcx.get_attrs(id).iter() {
+            if !attr.check_name("target_feature") {
+                continue
+            }
+            if let Some(val) = attr.value_str() {
+                for feat in val.as_str().split(",").map(|f| f.trim()) {
+                    if !feat.is_empty() && !feat.contains('\0') {
+                        target_features.push(feat.to_string());
+                    }
+                }
+                let msg = "#[target_feature = \"..\"] is deprecated and will \
+                           eventually be removed, use \
+                           #[target_feature(enable = \"..\")] instead";
+                tcx.sess.span_warn(attr.span, &msg);
+                continue
+            }
+
+            if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
+                let msg = "#[target_feature(..)] can only be applied to \
+                           `unsafe` function";
+                tcx.sess.span_err(attr.span, msg);
+            }
+            from_target_feature(tcx, attr, &whitelist, &mut target_features);
+        }
+        Rc::new(target_features)
+    };
+}
+
+fn from_target_feature(
+    tcx: TyCtxt,
+    attr: &ast::Attribute,
+    whitelist: &FxHashSet<String>,
+    target_features: &mut Vec<String>,
+) {
+    let list = match attr.meta_item_list() {
+        Some(list) => list,
+        None => {
+            let msg = "#[target_feature] attribute must be of the form \
+                       #[target_feature(..)]";
+            tcx.sess.span_err(attr.span, &msg);
+            return
+        }
+    };
+
+    for item in list {
+        if !item.check_name("enable") {
+            let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
+                       currently";
+            tcx.sess.span_err(item.span, &msg);
+            continue
+        }
+        let value = match item.value_str() {
+            Some(list) => list,
+            None => {
+                let msg = "#[target_feature] attribute must be of the form \
+                           #[target_feature(enable = \"..\")]";
+                tcx.sess.span_err(item.span, &msg);
+                continue
+            }
+        };
+        let value = value.as_str();
+        for feature in value.split(',') {
+            if whitelist.contains(feature) {
+                target_features.push(format!("+{}", feature));
+                continue
+            }
+
+            let msg = format!("the feature named `{}` is not valid for \
+                               this target", feature);
+            let mut err = tcx.sess.struct_span_err(item.span, &msg);
+
+            if feature.starts_with("+") {
+                let valid = whitelist.contains(&feature[1..]);
+                if valid {
+                    err.help("consider removing the leading `+` in the feature name");
+                }
+            }
+            err.emit();
+        }
+    }
+}
diff --git a/src/librustc_trans/back/bytecode.rs b/src/librustc_trans/back/bytecode.rs
index 55c9632..212d1aa 100644
--- a/src/librustc_trans/back/bytecode.rs
+++ b/src/librustc_trans/back/bytecode.rs
@@ -47,7 +47,7 @@
 // The version number this compiler will write to bytecode objects in rlibs
 pub const RLIB_BYTECODE_OBJECT_VERSION: u8 = 2;
 
-pub const RLIB_BYTECODE_EXTENSION: &str = "bytecode.encoded";
+pub const RLIB_BYTECODE_EXTENSION: &str = "bc.z";
 
 pub fn encode(identifier: &str, bytecode: &[u8]) -> Vec<u8> {
     let mut encoded = Vec::new();
@@ -74,7 +74,7 @@
     encoded.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
 
     let before = encoded.len();
-    DeflateEncoder::new(&mut encoded, Compression::Fast)
+    DeflateEncoder::new(&mut encoded, Compression::fast())
         .write_all(bytecode)
         .unwrap();
     let after = encoded.len();
diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs
index ea68e3b..3b765a4 100644
--- a/src/librustc_trans/back/command.rs
+++ b/src/librustc_trans/back/command.rs
@@ -14,22 +14,34 @@
 use std::ffi::{OsStr, OsString};
 use std::fmt;
 use std::io;
-use std::process::{self, Output, Child};
+use std::mem;
+use std::process::{self, Output};
 
+#[derive(Clone)]
 pub struct Command {
-    program: OsString,
+    program: Program,
     args: Vec<OsString>,
     env: Vec<(OsString, OsString)>,
 }
 
+#[derive(Clone)]
+enum Program {
+    Normal(OsString),
+    CmdBatScript(OsString),
+}
+
 impl Command {
     pub fn new<P: AsRef<OsStr>>(program: P) -> Command {
-        Command::_new(program.as_ref())
+        Command::_new(Program::Normal(program.as_ref().to_owned()))
     }
 
-    fn _new(program: &OsStr) -> Command {
+    pub fn bat_script<P: AsRef<OsStr>>(program: P) -> Command {
+        Command::_new(Program::CmdBatScript(program.as_ref().to_owned()))
+    }
+
+    fn _new(program: Program) -> Command {
         Command {
-            program: program.to_owned(),
+            program,
             args: Vec::new(),
             env: Vec::new(),
         }
@@ -81,12 +93,15 @@
         self.command().output()
     }
 
-    pub fn spawn(&mut self) -> io::Result<Child> {
-        self.command().spawn()
-    }
-
     pub fn command(&self) -> process::Command {
-        let mut ret = process::Command::new(&self.program);
+        let mut ret = match self.program {
+            Program::Normal(ref p) => process::Command::new(p),
+            Program::CmdBatScript(ref p) => {
+                let mut c = process::Command::new("cmd");
+                c.arg("/c").arg(p);
+                c
+            }
+        };
         ret.args(&self.args);
         ret.envs(self.env.clone());
         return ret
@@ -94,16 +109,45 @@
 
     // extensions
 
-    pub fn get_program(&self) -> &OsStr {
-        &self.program
+    pub fn take_args(&mut self) -> Vec<OsString> {
+        mem::replace(&mut self.args, Vec::new())
     }
 
-    pub fn get_args(&self) -> &[OsString] {
-        &self.args
-    }
+    /// Returns a `true` if we're pretty sure that this'll blow OS spawn limits,
+    /// or `false` if we should attempt to spawn and see what the OS says.
+    pub fn very_likely_to_exceed_some_spawn_limit(&self) -> bool {
+        // We mostly only care about Windows in this method, on Unix the limits
+        // can be gargantuan anyway so we're pretty unlikely to hit them
+        if cfg!(unix) {
+            return false
+        }
 
-    pub fn get_env(&self) -> &[(OsString, OsString)] {
-        &self.env
+        // Ok so on Windows to spawn a process is 32,768 characters in its
+        // command line [1]. Unfortunately we don't actually have access to that
+        // as it's calculated just before spawning. Instead we perform a
+        // poor-man's guess as to how long our command line will be. We're
+        // assuming here that we don't have to escape every character...
+        //
+        // Turns out though that `cmd.exe` has even smaller limits, 8192
+        // characters [2]. Linkers can often be batch scripts (for example
+        // Emscripten, Gecko's current build system) which means that we're
+        // running through batch scripts. These linkers often just forward
+        // arguments elsewhere (and maybe tack on more), so if we blow 8192
+        // bytes we'll typically cause them to blow as well.
+        //
+        // Basically as a result just perform an inflated estimate of what our
+        // command line will look like and test if it's > 8192 (we actually
+        // test against 6k to artificially inflate our estimate). If all else
+        // fails we'll fall back to the normal unix logic of testing the OS
+        // error code if we fail to spawn and automatically re-spawning the
+        // linker with smaller arguments.
+        //
+        // [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
+        // [2]: https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553
+
+        let estimated_command_line_len =
+            self.args.iter().map(|a| a.len()).sum::<usize>();
+        estimated_command_line_len > 1024 * 6
     }
 }
 
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index ec1c7e1..923e554 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -36,8 +36,8 @@
 use std::env;
 use std::ffi::OsString;
 use std::fmt;
-use std::fs::{self, File};
-use std::io::{self, Write, BufWriter};
+use std::fs;
+use std::io;
 use std::path::{Path, PathBuf};
 use std::process::{Output, Stdio};
 use std::str;
@@ -69,13 +69,12 @@
     // was tagged as #42791) and some more info can be found on #44443 for
     // emscripten itself.
     let cmd = |linker: &Path| {
-        if cfg!(windows) && linker.ends_with(".bat") {
-            let mut cmd = Command::new("cmd");
-            cmd.arg("/c").arg(linker);
-            cmd
-        } else {
-            Command::new(linker)
+        if let Some(linker) = linker.to_str() {
+            if cfg!(windows) && linker.ends_with(".bat") {
+                return Command::bat_script(linker)
+            }
         }
+        Command::new(linker)
     };
 
     if let Some(ref linker) = sess.opts.cg.linker {
@@ -140,10 +139,10 @@
 
 /// Perform the linkage portion of the compilation phase. This will generate all
 /// of the requested outputs for this compilation session.
-pub fn link_binary(sess: &Session,
-                   trans: &CrateTranslation,
-                   outputs: &OutputFilenames,
-                   crate_name: &str) -> Vec<PathBuf> {
+pub(crate) fn link_binary(sess: &Session,
+                          trans: &CrateTranslation,
+                          outputs: &OutputFilenames,
+                          crate_name: &str) -> Vec<PathBuf> {
     let mut out_filenames = Vec::new();
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-trans, as they will error.
@@ -200,9 +199,9 @@
     out_filename
 }
 
-pub fn each_linked_rlib(sess: &Session,
-                        info: &CrateInfo,
-                        f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
+pub(crate) fn each_linked_rlib(sess: &Session,
+                               info: &CrateInfo,
+                               f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
     let crates = info.used_crates_static.iter();
     let fmts = sess.dependency_formats.borrow();
     let fmts = fmts.get(&config::CrateTypeExecutable)
@@ -246,7 +245,7 @@
 /// It's unusual for a crate to not participate in LTO. Typically only
 /// compiler-specific and unstable crates have a reason to not participate in
 /// LTO.
-pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
+pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
     // If our target enables builtin function lowering in LLVM then the
     // crates providing these functions don't participate in LTO (e.g.
     // no_builtins or compiler builtins crates).
@@ -342,9 +341,7 @@
 fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, tmpdir: &TempDir)
                      -> PathBuf {
     let out_filename = tmpdir.path().join(METADATA_FILENAME);
-    let result = fs::File::create(&out_filename).and_then(|mut f| {
-        f.write_all(&trans.metadata.raw_data)
-    });
+    let result = fs::write(&out_filename, &trans.metadata.raw_data);
 
     if let Err(e) = result {
         sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
@@ -708,10 +705,25 @@
             info!("linker stdout:\n{}", escape_string(&prog.stdout));
         },
         Err(e) => {
-            sess.struct_err(&format!("could not exec the linker `{}`: {}", pname.display(), e))
-                .note(&format!("{:?}", &cmd))
-                .emit();
-            if sess.target.target.options.is_like_msvc && e.kind() == io::ErrorKind::NotFound {
+            let linker_not_found = e.kind() == io::ErrorKind::NotFound;
+
+            let mut linker_error = {
+                if linker_not_found {
+                    sess.struct_err(&format!("linker `{}` not found", pname.display()))
+                } else {
+                    sess.struct_err(&format!("could not exec the linker `{}`", pname.display()))
+                }
+            };
+
+            linker_error.note(&format!("{}", e));
+
+            if !linker_not_found {
+                linker_error.note(&format!("{:?}", &cmd));
+            }
+
+            linker_error.emit();
+
+            if sess.target.target.options.is_like_msvc && linker_not_found {
                 sess.note_without_error("the msvc targets depend on the msvc linker \
                     but `link.exe` was not found");
                 sess.note_without_error("please ensure that VS 2013 or VS 2015 was installed \
@@ -744,26 +756,26 @@
     // that contains all the arguments. The theory is that this is then
     // accepted on all linkers and the linker will read all its options out of
     // there instead of looking at the command line.
-    match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
-        Ok(child) => return child.wait_with_output(),
-        Err(ref e) if command_line_too_big(e) => {}
-        Err(e) => return Err(e)
+    if !cmd.very_likely_to_exceed_some_spawn_limit() {
+        match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
+            Ok(child) => return child.wait_with_output(),
+            Err(ref e) if command_line_too_big(e) => {}
+            Err(e) => return Err(e)
+        }
     }
 
-    let file = tmpdir.join("linker-arguments");
-    let mut cmd2 = Command::new(cmd.get_program());
-    cmd2.arg(format!("@{}", file.display()));
-    for &(ref k, ref v) in cmd.get_env() {
-        cmd2.env(k, v);
-    }
-    let mut f = BufWriter::new(File::create(&file)?);
-    for arg in cmd.get_args() {
-        writeln!(f, "{}", Escape {
+    let mut cmd2 = cmd.clone();
+    let mut args = String::new();
+    for arg in cmd2.take_args() {
+        args.push_str(&Escape {
             arg: arg.to_str().unwrap(),
             is_like_msvc: sess.target.target.options.is_like_msvc,
-        })?;
+        }.to_string());
+        args.push_str("\n");
     }
-    f.into_inner()?;
+    let file = tmpdir.join("linker-arguments");
+    fs::write(&file, args.as_bytes())?;
+    cmd2.arg(format!("@{}", file.display()));
     return cmd2.output();
 
     #[cfg(unix)]
diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs
index ba8c26b..b612247 100644
--- a/src/librustc_trans/back/lto.rs
+++ b/src/librustc_trans/back/lto.rs
@@ -42,7 +42,7 @@
     }
 }
 
-pub enum LtoModuleTranslation {
+pub(crate) enum LtoModuleTranslation {
     Fat {
         module: Option<ModuleTranslation>,
         _serialized_bitcode: Vec<SerializedModule>,
@@ -65,9 +65,9 @@
     /// points to LLVM data structures owned by this `LtoModuleTranslation`.
     /// It's intended that the module returned is immediately code generated and
     /// dropped, and then this LTO module is dropped.
-    pub unsafe fn optimize(&mut self,
-                           cgcx: &CodegenContext,
-                           timeline: &mut Timeline)
+    pub(crate) unsafe fn optimize(&mut self,
+                                  cgcx: &CodegenContext,
+                                  timeline: &mut Timeline)
         -> Result<ModuleTranslation, FatalError>
     {
         match *self {
@@ -100,7 +100,7 @@
     JustThisCrate,
 }
 
-pub fn run(cgcx: &CodegenContext,
+pub(crate) fn run(cgcx: &CodegenContext,
            modules: Vec<ModuleTranslation>,
            mode: LTOMode,
            timeline: &mut Timeline)
@@ -607,7 +607,7 @@
         // into that context. One day, however, we may do this for upstream
         // crates but for locally translated modules we may be able to reuse
         // that LLVM Context and Module.
-        let llcx = llvm::LLVMContextCreate();
+        let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
         let llmod = llvm::LLVMRustParseBitcodeForThinLTO(
             llcx,
             self.data().as_ptr(),
@@ -726,6 +726,21 @@
         run_pass_manager(cgcx, tm, llmod, config, true);
         cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-pm");
         timeline.record("thin-done");
+
+        // FIXME: this is a hack around a bug in LLVM right now. Discovered in
+        // #46910 it was found out that on 32-bit MSVC LLVM will hit a codegen
+        // error if there's an available_externally function in the LLVM module.
+        // Typically we don't actually use these functions but ThinLTO makes
+        // heavy use of them when inlining across modules.
+        //
+        // Tracked upstream at https://bugs.llvm.org/show_bug.cgi?id=35736 this
+        // function call (and its definition on the C++ side of things)
+        // shouldn't be necessary eventually and we can safetly delete these few
+        // lines.
+        llvm::LLVMRustThinLTORemoveAvailableExternally(llmod);
+        cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rm-ae");
+        timeline.record("no-ae");
+
         Ok(mtrans)
     }
 }
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index fa6fe2e..15ff59c 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -115,9 +115,8 @@
 
         if let Some(id) = tcx.sess.derive_registrar_fn.get() {
             let def_id = tcx.hir.local_def_id(id);
-            let idx = def_id.index;
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
+            let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator);
             local_crate.push((registrar, Some(def_id), SymbolExportLevel::C));
         }
 
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index d8e95cd..a013af7 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -46,9 +46,8 @@
 
 use std::any::Any;
 use std::ffi::{CString, CStr};
-use std::fs::{self, File};
-use std::io;
-use std::io::{Read, Write};
+use std::fs;
+use std::io::{self, Write};
 use std::mem;
 use std::path::{Path, PathBuf};
 use std::str;
@@ -323,6 +322,7 @@
     pub thinlto: bool,
     pub no_landing_pads: bool,
     pub save_temps: bool,
+    pub fewer_names: bool,
     pub exported_symbols: Arc<ExportedSymbols>,
     pub opts: Arc<config::Options>,
     pub crate_types: Vec<config::CrateType>,
@@ -363,7 +363,7 @@
         Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
     }
 
-    pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
+    pub(crate) fn config(&self, kind: ModuleKind) -> &ModuleConfig {
         match kind {
             ModuleKind::Regular => &self.regular_module_config,
             ModuleKind::Metadata => &self.metadata_module_config,
@@ -371,7 +371,7 @@
         }
     }
 
-    pub fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) {
+    pub(crate) fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) {
         if !self.save_temps {
             return
         }
@@ -665,7 +665,7 @@
         timeline.record("make-bc");
 
         if write_bc {
-            if let Err(e) = File::create(&bc_out).and_then(|mut f| f.write_all(data)) {
+            if let Err(e) = fs::write(&bc_out, data) {
                 diag_handler.err(&format!("failed to write bytecode: {}", e));
             }
             timeline.record("write-bc");
@@ -674,7 +674,7 @@
         if config.emit_bc_compressed {
             let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
             let data = bytecode::encode(&mtrans.llmod_id, data);
-            if let Err(e) = File::create(&dst).and_then(|mut f| f.write_all(&data)) {
+            if let Err(e) = fs::write(&dst, data) {
                 diag_handler.err(&format!("failed to write bytecode: {}", e));
             }
             timeline.record("compress-bc");
@@ -798,9 +798,7 @@
                      object: &Path) {
     use rustc_binaryen::{Module, ModuleOptions};
 
-    let input = File::open(&assembly).and_then(|mut f| {
-        let mut contents = Vec::new();
-        f.read_to_end(&mut contents)?;
+    let input = fs::read(&assembly).and_then(|contents| {
         Ok(CString::new(contents)?)
     });
     let mut options = ModuleOptions::new();
@@ -817,14 +815,14 @@
             .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
     });
     let err = assembled.and_then(|binary| {
-        File::create(&object).and_then(|mut f| f.write_all(binary.data()))
+        fs::write(&object, binary.data())
     });
     if let Err(e) = err {
         handler.err(&format!("failed to run binaryen assembler: {}", e));
     }
 }
 
-pub struct CompiledModules {
+pub(crate) struct CompiledModules {
     pub modules: Vec<CompiledModule>,
     pub metadata_module: CompiledModule,
     pub allocator_module: Option<CompiledModule>,
@@ -1164,7 +1162,7 @@
     // These are used in linking steps and will be cleaned up afterward.
 }
 
-pub fn dump_incremental_data(trans: &CrateTranslation) {
+pub(crate) fn dump_incremental_data(trans: &CrateTranslation) {
     println!("[incremental] Re-using {} out of {} modules",
               trans.modules.iter().filter(|m| m.pre_existing).count(),
               trans.modules.len());
@@ -1362,15 +1360,10 @@
     let sess = tcx.sess;
 
     // First up, convert our jobserver into a helper thread so we can use normal
-    // mpsc channels to manage our messages and such. Once we've got the helper
-    // thread then request `n-1` tokens because all of our work items are ready
-    // to go.
-    //
-    // Note that the `n-1` is here because we ourselves have a token (our
-    // process) and we'll use that token to execute at least one unit of work.
-    //
-    // After we've requested all these tokens then we'll, when we can, get
-    // tokens on `rx` above which will get managed in the main loop below.
+    // mpsc channels to manage our messages and such.
+    // After we've requested tokens then we'll, when we can,
+    // get tokens on `coordinator_receive` which will
+    // get managed in the main loop below.
     let coordinator_send2 = coordinator_send.clone();
     let helper = jobserver.into_helper_thread(move |token| {
         drop(coordinator_send2.send(Box::new(Message::Token(token))));
@@ -1407,6 +1400,7 @@
             unsafe { llvm::LLVMRustThinLTOAvailable() },
 
         no_landing_pads: sess.no_landing_pads(),
+        fewer_names: sess.fewer_names(),
         save_temps: sess.opts.cg.save_temps,
         opts: Arc::new(sess.opts.clone()),
         time_passes: sess.time_passes(),
@@ -2150,7 +2144,7 @@
 }
 
 impl OngoingCrateTranslation {
-    pub fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
+    pub(crate) fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
         self.shared_emitter_main.check(sess, true);
         let compiled_modules = match self.future.join() {
             Ok(Ok(compiled_modules)) => compiled_modules,
@@ -2218,9 +2212,9 @@
         trans
     }
 
-    pub fn submit_pre_translated_module_to_llvm(&self,
-                                                tcx: TyCtxt,
-                                                mtrans: ModuleTranslation) {
+    pub(crate) fn submit_pre_translated_module_to_llvm(&self,
+                                                       tcx: TyCtxt,
+                                                       mtrans: ModuleTranslation) {
         self.wait_for_signal_to_translate_item();
         self.check_for_errors(tcx.sess);
 
@@ -2253,9 +2247,9 @@
     }
 }
 
-pub fn submit_translated_module_to_llvm(tcx: TyCtxt,
-                                        mtrans: ModuleTranslation,
-                                        cost: u64) {
+pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt,
+                                               mtrans: ModuleTranslation,
+                                               cost: u64) {
     let llvm_work_item = WorkItem::Optimize(mtrans);
     drop(tcx.tx_to_llvm_workers.send(Box::new(Message::TranslationDone {
         llvm_work_item,
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index ea68925..734ad8f 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -29,7 +29,6 @@
 use super::ModuleKind;
 
 use abi;
-use assert_module_sources;
 use back::link;
 use back::symbol_export;
 use back::write::{self, OngoingCrateTranslation, create_target_machine};
@@ -43,7 +42,8 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
 use rustc::ty::maps::Providers;
-use rustc::dep_graph::{DepNode, DepKind, DepConstructor};
+use rustc::dep_graph::{DepNode, DepConstructor};
+use rustc::ty::subst::Kind;
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::session::config::{self, NoDebugInfo};
@@ -56,16 +56,16 @@
 use callee;
 use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
 use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
-use common::{self, C_struct_in_context, C_array, CrateContext, val_ty};
+use common::{self, C_struct_in_context, C_array, val_ty};
 use consts;
-use context::{self, LocalCrateContext, SharedCrateContext};
+use context::{self, CodegenCx};
 use debuginfo;
 use declare;
 use meth;
 use mir;
 use monomorphize::Instance;
 use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
-use symbol_names_test;
+use rustc_trans_utils::symbol_names_test;
 use time_graph;
 use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
 use type_::Type;
@@ -79,6 +79,7 @@
 use std::sync::Arc;
 use std::time::{Instant, Duration};
 use std::i32;
+use std::iter;
 use std::sync::mpsc;
 use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
@@ -92,16 +93,16 @@
 pub use rustc_mir::monomorphize::item::linkage_by_name;
 
 pub struct StatRecorder<'a, 'tcx: 'a> {
-    ccx: &'a CrateContext<'a, 'tcx>,
+    cx: &'a CodegenCx<'a, 'tcx>,
     name: Option<String>,
     istart: usize,
 }
 
 impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
-    pub fn new(ccx: &'a CrateContext<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> {
-        let istart = ccx.stats().borrow().n_llvm_insns;
+    pub fn new(cx: &'a CodegenCx<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> {
+        let istart = cx.stats.borrow().n_llvm_insns;
         StatRecorder {
-            ccx,
+            cx,
             name: Some(name),
             istart,
         }
@@ -110,8 +111,8 @@
 
 impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
     fn drop(&mut self) {
-        if self.ccx.sess().trans_stats() {
-            let mut stats = self.ccx.stats().borrow_mut();
+        if self.cx.sess().trans_stats() {
+            let mut stats = self.cx.stats.borrow_mut();
             let iend = stats.n_llvm_insns;
             stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
             stats.n_fns += 1;
@@ -156,7 +157,7 @@
 }
 
 pub fn compare_simd_types<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     lhs: ValueRef,
     rhs: ValueRef,
     t: Ty<'tcx>,
@@ -166,7 +167,7 @@
     let signed = match t.sty {
         ty::TyFloat(_) => {
             let cmp = bin_op_to_fcmp_predicate(op);
-            return bcx.sext(bcx.fcmp(cmp, lhs, rhs), ret_ty);
+            return bx.sext(bx.fcmp(cmp, lhs, rhs), ret_ty);
         },
         ty::TyUint(_) => false,
         ty::TyInt(_) => true,
@@ -178,7 +179,7 @@
     // to get the correctly sized type. This will compile to a single instruction
     // once the IR is converted to assembly if the SIMD instruction is supported
     // by the target architecture.
-    bcx.sext(bcx.icmp(cmp, lhs, rhs), ret_ty)
+    bx.sext(bx.icmp(cmp, lhs, rhs), ret_ty)
 }
 
 /// Retrieve the information we are losing (making dynamic) in an unsizing
@@ -187,15 +188,15 @@
 /// The `old_info` argument is a bit funny. It is intended for use
 /// in an upcast, where the new vtable for an object will be derived
 /// from the old one.
-pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
+pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
                                 source: Ty<'tcx>,
                                 target: Ty<'tcx>,
                                 old_info: Option<ValueRef>)
                                 -> ValueRef {
-    let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
+    let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::TyArray(_, len), &ty::TySlice(_)) => {
-            C_usize(ccx, len.val.to_const_int().unwrap().to_u64().unwrap())
+            C_usize(cx, len.val.to_const_int().unwrap().to_u64().unwrap())
         }
         (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
             // For now, upcasts are limited to changes in marker
@@ -204,10 +205,10 @@
             old_info.expect("unsized_info: missing old info for trait upcast")
         }
         (_, &ty::TyDynamic(ref data, ..)) => {
-            let vtable_ptr = ccx.layout_of(ccx.tcx().mk_mut_ptr(target))
-                .field(ccx, abi::FAT_PTR_EXTRA);
-            consts::ptrcast(meth::get_vtable(ccx, source, data.principal()),
-                            vtable_ptr.llvm_type(ccx))
+            let vtable_ptr = cx.layout_of(cx.tcx.mk_mut_ptr(target))
+                .field(cx, abi::FAT_PTR_EXTRA);
+            consts::ptrcast(meth::get_vtable(cx, source, data.principal()),
+                            vtable_ptr.llvm_type(cx))
         }
         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
                                      source,
@@ -217,7 +218,7 @@
 
 /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
 pub fn unsize_thin_ptr<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     src: ValueRef,
     src_ty: Ty<'tcx>,
     dst_ty: Ty<'tcx>
@@ -230,24 +231,24 @@
          &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
         (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
          &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
-            assert!(bcx.ccx.shared().type_is_sized(a));
-            let ptr_ty = bcx.ccx.layout_of(b).llvm_type(bcx.ccx).ptr_to();
-            (bcx.pointercast(src, ptr_ty), unsized_info(bcx.ccx, a, b, None))
+            assert!(bx.cx.type_is_sized(a));
+            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
+            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
         }
         (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
-            assert!(bcx.ccx.shared().type_is_sized(a));
-            let ptr_ty = bcx.ccx.layout_of(b).llvm_type(bcx.ccx).ptr_to();
-            (bcx.pointercast(src, ptr_ty), unsized_info(bcx.ccx, a, b, None))
+            assert!(bx.cx.type_is_sized(a));
+            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
+            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
         }
         (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            let src_layout = bcx.ccx.layout_of(src_ty);
-            let dst_layout = bcx.ccx.layout_of(dst_ty);
+            let src_layout = bx.cx.layout_of(src_ty);
+            let dst_layout = bx.cx.layout_of(dst_ty);
             let mut result = None;
             for i in 0..src_layout.fields.count() {
-                let src_f = src_layout.field(bcx.ccx, i);
+                let src_f = src_layout.field(bx.cx, i);
                 assert_eq!(src_layout.fields.offset(i).bytes(), 0);
                 assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
                 if src_f.is_zst() {
@@ -255,15 +256,15 @@
                 }
                 assert_eq!(src_layout.size, src_f.size);
 
-                let dst_f = dst_layout.field(bcx.ccx, i);
+                let dst_f = dst_layout.field(bx.cx, i);
                 assert_ne!(src_f.ty, dst_f.ty);
                 assert_eq!(result, None);
-                result = Some(unsize_thin_ptr(bcx, src, src_f.ty, dst_f.ty));
+                result = Some(unsize_thin_ptr(bx, src, src_f.ty, dst_f.ty));
             }
             let (lldata, llextra) = result.unwrap();
             // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
-            (bcx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bcx.ccx, 0)),
-             bcx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bcx.ccx, 1)))
+            (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx, 0)),
+             bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx, 1)))
         }
         _ => bug!("unsize_thin_ptr: called on bad types"),
     }
@@ -271,27 +272,27 @@
 
 /// Coerce `src`, which is a reference to a value of type `src_ty`,
 /// to a value of type `dst_ty` and store the result in `dst`
-pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                                      src: PlaceRef<'tcx>,
                                      dst: PlaceRef<'tcx>) {
     let src_ty = src.layout.ty;
     let dst_ty = dst.layout.ty;
     let coerce_ptr = || {
-        let (base, info) = match src.load(bcx).val {
+        let (base, info) = match src.load(bx).val {
             OperandValue::Pair(base, info) => {
                 // fat-ptr to fat-ptr unsize preserves the vtable
                 // i.e. &'a fmt::Debug+Send => &'a fmt::Debug
                 // So we need to pointercast the base to ensure
                 // the types match up.
-                let thin_ptr = dst.layout.field(bcx.ccx, abi::FAT_PTR_ADDR);
-                (bcx.pointercast(base, thin_ptr.llvm_type(bcx.ccx)), info)
+                let thin_ptr = dst.layout.field(bx.cx, abi::FAT_PTR_ADDR);
+                (bx.pointercast(base, thin_ptr.llvm_type(bx.cx)), info)
             }
             OperandValue::Immediate(base) => {
-                unsize_thin_ptr(bcx, base, src_ty, dst_ty)
+                unsize_thin_ptr(bx, base, src_ty, dst_ty)
             }
             OperandValue::Ref(..) => bug!()
         };
-        OperandValue::Pair(base, info).store(bcx, dst);
+        OperandValue::Pair(base, info).store(bx, dst);
     };
     match (&src_ty.sty, &dst_ty.sty) {
         (&ty::TyRef(..), &ty::TyRef(..)) |
@@ -307,18 +308,18 @@
             assert_eq!(def_a, def_b);
 
             for i in 0..def_a.variants[0].fields.len() {
-                let src_f = src.project_field(bcx, i);
-                let dst_f = dst.project_field(bcx, i);
+                let src_f = src.project_field(bx, i);
+                let dst_f = dst.project_field(bx, i);
 
                 if dst_f.layout.is_zst() {
                     continue;
                 }
 
                 if src_f.layout.ty == dst_f.layout.ty {
-                    memcpy_ty(bcx, dst_f.llval, src_f.llval, src_f.layout,
+                    memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout,
                         src_f.align.min(dst_f.align));
                 } else {
-                    coerce_unsized_into(bcx, src_f, dst_f);
+                    coerce_unsized_into(bx, src_f, dst_f);
                 }
             }
         }
@@ -386,47 +387,47 @@
     sess.target.target.options.is_like_msvc
 }
 
-pub fn call_assume<'a, 'tcx>(b: &Builder<'a, 'tcx>, val: ValueRef) {
-    let assume_intrinsic = b.ccx.get_intrinsic("llvm.assume");
-    b.call(assume_intrinsic, &[val], None);
+pub fn call_assume<'a, 'tcx>(bx: &Builder<'a, 'tcx>, val: ValueRef) {
+    let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
+    bx.call(assume_intrinsic, &[val], None);
 }
 
-pub fn from_immediate(bcx: &Builder, val: ValueRef) -> ValueRef {
-    if val_ty(val) == Type::i1(bcx.ccx) {
-        bcx.zext(val, Type::i8(bcx.ccx))
+pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
+    if val_ty(val) == Type::i1(bx.cx) {
+        bx.zext(val, Type::i8(bx.cx))
     } else {
         val
     }
 }
 
-pub fn to_immediate(bcx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
+pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
     if let layout::Abi::Scalar(ref scalar) = layout.abi {
         if scalar.is_bool() {
-            return bcx.trunc(val, Type::i1(bcx.ccx));
+            return bx.trunc(val, Type::i1(bx.cx));
         }
     }
     val
 }
 
-pub fn call_memcpy(b: &Builder,
+pub fn call_memcpy(bx: &Builder,
                    dst: ValueRef,
                    src: ValueRef,
                    n_bytes: ValueRef,
                    align: Align) {
-    let ccx = b.ccx;
-    let ptr_width = &ccx.sess().target.target.target_pointer_width;
+    let cx = bx.cx;
+    let ptr_width = &cx.sess().target.target.target_pointer_width;
     let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
-    let memcpy = ccx.get_intrinsic(&key);
-    let src_ptr = b.pointercast(src, Type::i8p(ccx));
-    let dst_ptr = b.pointercast(dst, Type::i8p(ccx));
-    let size = b.intcast(n_bytes, ccx.isize_ty(), false);
-    let align = C_i32(ccx, align.abi() as i32);
-    let volatile = C_bool(ccx, false);
-    b.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
+    let memcpy = cx.get_intrinsic(&key);
+    let src_ptr = bx.pointercast(src, Type::i8p(cx));
+    let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
+    let size = bx.intcast(n_bytes, cx.isize_ty, false);
+    let align = C_i32(cx, align.abi() as i32);
+    let volatile = C_bool(cx, false);
+    bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
 }
 
 pub fn memcpy_ty<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     dst: ValueRef,
     src: ValueRef,
     layout: TyLayout<'tcx>,
@@ -437,28 +438,28 @@
         return;
     }
 
-    call_memcpy(bcx, dst, src, C_usize(bcx.ccx, size), align);
+    call_memcpy(bx, dst, src, C_usize(bx.cx, size), align);
 }
 
-pub fn call_memset<'a, 'tcx>(b: &Builder<'a, 'tcx>,
+pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                              ptr: ValueRef,
                              fill_byte: ValueRef,
                              size: ValueRef,
                              align: ValueRef,
                              volatile: bool) -> ValueRef {
-    let ptr_width = &b.ccx.sess().target.target.target_pointer_width;
+    let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
     let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
-    let llintrinsicfn = b.ccx.get_intrinsic(&intrinsic_key);
-    let volatile = C_bool(b.ccx, volatile);
-    b.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
+    let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
+    let volatile = C_bool(bx.cx, volatile);
+    bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
 }
 
-pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
-    let _s = if ccx.sess().trans_stats() {
+pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
+    let _s = if cx.sess().trans_stats() {
         let mut instance_name = String::new();
-        DefPathBasedNames::new(ccx.tcx(), true, true)
+        DefPathBasedNames::new(cx.tcx, true, true)
             .push_def_path(instance.def_id(), &mut instance_name);
-        Some(StatRecorder::new(ccx, instance_name))
+        Some(StatRecorder::new(cx, instance_name))
     } else {
         None
     };
@@ -468,16 +469,16 @@
     // release builds.
     info!("trans_instance({})", instance);
 
-    let fn_ty = instance.ty(ccx.tcx());
-    let sig = common::ty_fn_sig(ccx, fn_ty);
-    let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
+    let fn_ty = instance.ty(cx.tcx);
+    let sig = common::ty_fn_sig(cx, fn_ty);
+    let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
 
-    let lldecl = match ccx.instances().borrow().get(&instance) {
+    let lldecl = match cx.instances.borrow().get(&instance) {
         Some(&val) => val,
         None => bug!("Instance `{:?}` not already declared", instance)
     };
 
-    ccx.stats().borrow_mut().n_closures += 1;
+    cx.stats.borrow_mut().n_closures += 1;
 
     // The `uwtable` attribute according to LLVM is:
     //
@@ -495,21 +496,21 @@
     //
     // You can also find more info on why Windows is whitelisted here in:
     //      https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
-    if !ccx.sess().no_landing_pads() ||
-       ccx.sess().target.target.options.is_like_windows {
+    if !cx.sess().no_landing_pads() ||
+       cx.sess().target.target.options.is_like_windows {
         attributes::emit_uwtable(lldecl, true);
     }
 
-    let mir = ccx.tcx().instance_mir(instance.def);
-    mir::trans_mir(ccx, lldecl, &mir, instance, sig);
+    let mir = cx.tcx.instance_mir(instance.def);
+    mir::trans_mir(cx, lldecl, &mir, instance, sig);
 }
 
-pub fn set_link_section(ccx: &CrateContext,
+pub fn set_link_section(cx: &CodegenCx,
                         llval: ValueRef,
                         attrs: &[ast::Attribute]) {
     if let Some(sect) = attr::first_attr_value_str_by_name(attrs, "link_section") {
         if contains_null(&sect.as_str()) {
-            ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", &sect));
+            cx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", &sect));
         }
         unsafe {
             let buf = CString::new(sect.as_str().as_bytes()).unwrap();
@@ -520,76 +521,82 @@
 
 /// Create the `main` function which will initialize the rust runtime and call
 /// users main function.
-fn maybe_create_entry_wrapper(ccx: &CrateContext) {
-    let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() {
+fn maybe_create_entry_wrapper(cx: &CodegenCx) {
+    let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
         Some((id, span)) => {
-            (ccx.tcx().hir.local_def_id(id), span)
+            (cx.tcx.hir.local_def_id(id), span)
         }
         None => return,
     };
 
-    let instance = Instance::mono(ccx.tcx(), main_def_id);
+    let instance = Instance::mono(cx.tcx, main_def_id);
 
-    if !ccx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
+    if !cx.codegen_unit.contains_item(&MonoItem::Fn(instance)) {
         // We want to create the wrapper in the same codegen unit as Rust's main
         // function.
         return;
     }
 
-    let main_llfn = callee::get_fn(ccx, instance);
+    let main_llfn = callee::get_fn(cx, instance);
 
-    let et = ccx.sess().entry_type.get().unwrap();
+    let et = cx.sess().entry_type.get().unwrap();
     match et {
-        config::EntryMain => create_entry_fn(ccx, span, main_llfn, true),
-        config::EntryStart => create_entry_fn(ccx, span, main_llfn, false),
+        config::EntryMain => create_entry_fn(cx, span, main_llfn, main_def_id, true),
+        config::EntryStart => create_entry_fn(cx, span, main_llfn, main_def_id, false),
         config::EntryNone => {}    // Do nothing.
     }
 
-    fn create_entry_fn(ccx: &CrateContext,
+    fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
                        sp: Span,
                        rust_main: ValueRef,
+                       rust_main_def_id: DefId,
                        use_start_lang_item: bool) {
-        // Signature of native main(), corresponding to C's `int main(int, char **)`
-        let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &Type::c_int(ccx));
+        let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], &Type::c_int(cx));
 
-        if declare::get_defined_value(ccx, "main").is_some() {
+        let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
+        // Given that `main()` has no arguments,
+        // then its return type cannot have
+        // late-bound regions, since late-bound
+        // regions must appear in the argument
+        // listing.
+        let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
+
+        if declare::get_defined_value(cx, "main").is_some() {
             // FIXME: We should be smart and show a better diagnostic here.
-            ccx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
+            cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
                       .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
                       .emit();
-            ccx.sess().abort_if_errors();
+            cx.sess().abort_if_errors();
             bug!();
         }
-        let llfn = declare::declare_cfn(ccx, "main", llfty);
+        let llfn = declare::declare_cfn(cx, "main", llfty);
 
         // `main` should respect same config for frame pointer elimination as rest of code
-        attributes::set_frame_pointer_elimination(ccx, llfn);
+        attributes::set_frame_pointer_elimination(cx, llfn);
 
-        let bld = Builder::new_block(ccx, llfn, "top");
+        let bx = Builder::new_block(cx, llfn, "top");
 
-        debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(ccx, &bld);
+        debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(&bx);
 
         // Params from native main() used as args for rust start function
         let param_argc = get_param(llfn, 0);
         let param_argv = get_param(llfn, 1);
-        let arg_argc = bld.intcast(param_argc, ccx.isize_ty(), true);
+        let arg_argc = bx.intcast(param_argc, cx.isize_ty, true);
         let arg_argv = param_argv;
 
         let (start_fn, args) = if use_start_lang_item {
-            let start_def_id = ccx.tcx().require_lang_item(StartFnLangItem);
-            let start_instance = Instance::mono(ccx.tcx(), start_def_id);
-            let start_fn = callee::get_fn(ccx, start_instance);
-            (start_fn, vec![bld.pointercast(rust_main, Type::i8p(ccx).ptr_to()),
+            let start_def_id = cx.tcx.require_lang_item(StartFnLangItem);
+            let start_fn = callee::resolve_and_get_fn(cx, start_def_id, cx.tcx.mk_substs(
+                iter::once(Kind::from(main_ret_ty))));
+            (start_fn, vec![bx.pointercast(rust_main, Type::i8p(cx).ptr_to()),
                             arg_argc, arg_argv])
         } else {
             debug!("using user-defined start fn");
             (rust_main, vec![arg_argc, arg_argv])
         };
 
-        let result = bld.call(start_fn, &args, None);
-
-        // Return rust start function's result from native main()
-        bld.ret(bld.intcast(result, Type::c_int(ccx), true));
+        let result = bx.call(start_fn, &args, None);
+        bx.ret(bx.intcast(result, Type::c_int(cx), true));
     }
 }
 
@@ -643,7 +650,7 @@
 
     assert!(kind == MetadataKind::Compressed);
     let mut compressed = tcx.metadata_encoding_version();
-    DeflateEncoder::new(&mut compressed, Compression::Fast)
+    DeflateEncoder::new(&mut compressed, Compression::fast())
         .write_all(&metadata.raw_data).unwrap();
 
     let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
@@ -709,12 +716,10 @@
         }
     }
 
-    let crate_hash = tcx.dep_graph
-                        .fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
+    let crate_hash = tcx.crate_hash(LOCAL_CRATE);
     let link_meta = link::build_link_meta(crate_hash);
     let exported_symbol_node_ids = find_exported_symbols(tcx);
 
-    let shared_ccx = SharedCrateContext::new(tcx);
     // Translate the metadata.
     let llmod_id = "metadata";
     let (metadata_llcx, metadata_llmod, metadata) =
@@ -763,7 +768,7 @@
     // Run the translation item collector and partition the collected items into
     // codegen units.
     let codegen_units =
-        shared_ccx.tcx().collect_and_partition_translation_items(LOCAL_CRATE).1;
+        tcx.collect_and_partition_translation_items(LOCAL_CRATE).1;
     let codegen_units = (*codegen_units).clone();
 
     // Force all codegen_unit queries so they are already either red or green
@@ -898,12 +903,12 @@
                             total_trans_time);
 
     if tcx.sess.opts.incremental.is_some() {
-        assert_module_sources::assert_module_sources(tcx);
+        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
     }
 
     symbol_names_test::report_symbol_names(tcx);
 
-    if shared_ccx.sess().trans_stats() {
+    if tcx.sess.trans_stats() {
         println!("--- trans stats ---");
         println!("n_glues_created: {}", all_stats.n_glues_created);
         println!("n_null_glues: {}", all_stats.n_null_glues);
@@ -919,7 +924,7 @@
         }
     }
 
-    if shared_ccx.sess().count_llvm_insns() {
+    if tcx.sess.count_llvm_insns() {
         for (k, v) in all_stats.llvm_insns.iter() {
             println!("{:7} {}", *v, *k);
         }
@@ -941,54 +946,6 @@
          || rustc_incremental::save_dep_graph(tcx));
 }
 
-#[inline(never)] // give this a place in the profiler
-fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)
-    where I: Iterator<Item=&'a MonoItem<'tcx>>
-{
-    let mut symbols: Vec<_> = trans_items.map(|trans_item| {
-        (trans_item, trans_item.symbol_name(tcx))
-    }).collect();
-
-    (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
-        sym1.cmp(sym2)
-    });
-
-    for pair in (&symbols[..]).windows(2) {
-        let sym1 = &pair[0].1;
-        let sym2 = &pair[1].1;
-
-        if *sym1 == *sym2 {
-            let trans_item1 = pair[0].0;
-            let trans_item2 = pair[1].0;
-
-            let span1 = trans_item1.local_span(tcx);
-            let span2 = trans_item2.local_span(tcx);
-
-            // Deterministically select one of the spans for error reporting
-            let span = match (span1, span2) {
-                (Some(span1), Some(span2)) => {
-                    Some(if span1.lo().0 > span2.lo().0 {
-                        span1
-                    } else {
-                        span2
-                    })
-                }
-                (Some(span), None) |
-                (None, Some(span)) => Some(span),
-                _ => None
-            };
-
-            let error_message = format!("symbol `{}` is already defined", sym1);
-
-            if let Some(span) = span {
-                tcx.sess.span_fatal(span, &error_message)
-            } else {
-                tcx.sess.fatal(&error_message)
-            }
-        }
-    }
-}
-
 fn collect_and_partition_translation_items<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cnum: CrateNum,
@@ -1014,7 +971,13 @@
                 MonoItemCollectionMode::Lazy
             }
         }
-        None => MonoItemCollectionMode::Lazy
+        None => {
+            if tcx.sess.opts.cg.link_dead_code {
+                MonoItemCollectionMode::Eager
+            } else {
+                MonoItemCollectionMode::Lazy
+            }
+        }
     };
 
     let (items, inlining_map) =
@@ -1022,7 +985,7 @@
             collector::collect_crate_mono_items(tcx, collection_mode)
     });
 
-    assert_symbols_are_distinct(tcx, items.iter());
+    ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
 
     let strategy = if tcx.sess.opts.incremental.is_some() {
         PartitioningStrategy::PerModule
@@ -1191,27 +1154,25 @@
                                    .to_fingerprint().to_hex());
 
         // Instantiate translation items without filling out definitions yet...
-        let scx = SharedCrateContext::new(tcx);
-        let lcx = LocalCrateContext::new(&scx, cgu, &llmod_id);
+        let cx = CodegenCx::new(tcx, cgu, &llmod_id);
         let module = {
-            let ccx = CrateContext::new(&scx, &lcx);
-            let trans_items = ccx.codegen_unit()
-                                 .items_in_deterministic_order(ccx.tcx());
+            let trans_items = cx.codegen_unit
+                                 .items_in_deterministic_order(cx.tcx);
             for &(trans_item, (linkage, visibility)) in &trans_items {
-                trans_item.predefine(&ccx, linkage, visibility);
+                trans_item.predefine(&cx, linkage, visibility);
             }
 
             // ... and now that we have everything pre-defined, fill out those definitions.
             for &(trans_item, _) in &trans_items {
-                trans_item.define(&ccx);
+                trans_item.define(&cx);
             }
 
             // If this codegen unit contains the main function, also create the
             // wrapper here
-            maybe_create_entry_wrapper(&ccx);
+            maybe_create_entry_wrapper(&cx);
 
             // Run replace-all-uses-with for statics that need it
-            for &(old_g, new_g) in ccx.statics_to_rauw().borrow().iter() {
+            for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
                 unsafe {
                     let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
                     llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
@@ -1221,13 +1182,13 @@
 
             // Create the llvm.used variable
             // This variable has type [N x i8*] and is stored in the llvm.metadata section
-            if !ccx.used_statics().borrow().is_empty() {
+            if !cx.used_statics.borrow().is_empty() {
                 let name = CString::new("llvm.used").unwrap();
                 let section = CString::new("llvm.metadata").unwrap();
-                let array = C_array(Type::i8(&ccx).ptr_to(), &*ccx.used_statics().borrow());
+                let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
 
                 unsafe {
-                    let g = llvm::LLVMAddGlobal(ccx.llmod(),
+                    let g = llvm::LLVMAddGlobal(cx.llmod,
                                                 val_ty(array).to_ref(),
                                                 name.as_ptr());
                     llvm::LLVMSetInitializer(g, array);
@@ -1237,14 +1198,14 @@
             }
 
             // Finalize debuginfo
-            if ccx.sess().opts.debuginfo != NoDebugInfo {
-                debuginfo::finalize(&ccx);
+            if cx.sess().opts.debuginfo != NoDebugInfo {
+                debuginfo::finalize(&cx);
             }
 
             let llvm_module = ModuleLlvm {
-                llcx: ccx.llcx(),
-                llmod: ccx.llmod(),
-                tm: create_target_machine(ccx.sess()),
+                llcx: cx.llcx,
+                llmod: cx.llmod,
+                tm: create_target_machine(cx.sess()),
             };
 
             ModuleTranslation {
@@ -1255,7 +1216,7 @@
             }
         };
 
-        (lcx.into_stats(), module)
+        (cx.into_stats(), module)
     }
 }
 
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index 5b697d6..5ab8d03 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -32,7 +32,7 @@
 #[must_use]
 pub struct Builder<'a, 'tcx: 'a> {
     pub llbuilder: BuilderRef,
-    pub ccx: &'a CrateContext<'a, 'tcx>,
+    pub cx: &'a CodegenCx<'a, 'tcx>,
 }
 
 impl<'a, 'tcx> Drop for Builder<'a, 'tcx> {
@@ -51,41 +51,41 @@
 }
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn new_block<'b>(ccx: &'a CrateContext<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self {
-        let builder = Builder::with_ccx(ccx);
+    pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self {
+        let bx = Builder::with_cx(cx);
         let llbb = unsafe {
             let name = CString::new(name).unwrap();
             llvm::LLVMAppendBasicBlockInContext(
-                ccx.llcx(),
+                cx.llcx,
                 llfn,
                 name.as_ptr()
             )
         };
-        builder.position_at_end(llbb);
-        builder
+        bx.position_at_end(llbb);
+        bx
     }
 
-    pub fn with_ccx(ccx: &'a CrateContext<'a, 'tcx>) -> Self {
+    pub fn with_cx(cx: &'a CodegenCx<'a, 'tcx>) -> Self {
         // Create a fresh builder from the crate context.
         let llbuilder = unsafe {
-            llvm::LLVMCreateBuilderInContext(ccx.llcx())
+            llvm::LLVMCreateBuilderInContext(cx.llcx)
         };
         Builder {
             llbuilder,
-            ccx,
+            cx,
         }
     }
 
     pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'tcx> {
-        Builder::new_block(self.ccx, self.llfn(), name)
+        Builder::new_block(self.cx, self.llfn(), name)
     }
 
     pub fn sess(&self) -> &Session {
-        self.ccx.sess()
+        self.cx.sess()
     }
 
     pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
-        self.ccx.tcx()
+        self.cx.tcx
     }
 
     pub fn llfn(&self) -> ValueRef {
@@ -101,11 +101,11 @@
     }
 
     fn count_insn(&self, category: &str) {
-        if self.ccx.sess().trans_stats() {
-            self.ccx.stats().borrow_mut().n_llvm_insns += 1;
+        if self.cx.sess().trans_stats() {
+            self.cx.stats.borrow_mut().n_llvm_insns += 1;
         }
-        if self.ccx.sess().count_llvm_insns() {
-            *self.ccx.stats()
+        if self.cx.sess().count_llvm_insns() {
+            *self.cx.stats
                 .borrow_mut()
                 .llvm_insns
                 .entry(category.to_string())
@@ -489,11 +489,11 @@
     }
 
     pub fn alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
-        let builder = Builder::with_ccx(self.ccx);
-        builder.position_at_start(unsafe {
+        let bx = Builder::with_cx(self.cx);
+        bx.position_at_start(unsafe {
             llvm::LLVMGetFirstBasicBlock(self.llfn())
         });
-        builder.dynamic_alloca(ty, name, align)
+        bx.dynamic_alloca(ty, name, align)
     }
 
     pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
@@ -558,7 +558,7 @@
             ];
 
             llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
-                                  llvm::LLVMMDNodeInContext(self.ccx.llcx(),
+                                  llvm::LLVMMDNodeInContext(self.cx.llcx,
                                                             v.as_ptr(),
                                                             v.len() as c_uint));
         }
@@ -567,7 +567,7 @@
     pub fn nonnull_metadata(&self, load: ValueRef) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
-                                  llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
+                                  llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
         }
     }
 
@@ -620,8 +620,8 @@
             // point to a metadata value of the integer 1. Who knew?
             //
             // [1]: http://llvm.org/docs/LangRef.html#store-instruction
-            let one = C_i32(self.ccx, 1);
-            let node = llvm::LLVMMDNodeInContext(self.ccx.llcx(),
+            let one = C_i32(self.cx, 1);
+            let node = llvm::LLVMMDNodeInContext(self.cx.llcx,
                                                  &one,
                                                  1);
             llvm::LLVMSetMetadata(insn,
@@ -840,24 +840,24 @@
     }
 
     pub fn add_span_comment(&self, sp: Span, text: &str) {
-        if self.ccx.sess().asm_comments() {
+        if self.cx.sess().asm_comments() {
             let s = format!("{} ({})",
                             text,
-                            self.ccx.sess().codemap().span_to_string(sp));
+                            self.cx.sess().codemap().span_to_string(sp));
             debug!("{}", s);
             self.add_comment(&s);
         }
     }
 
     pub fn add_comment(&self, text: &str) {
-        if self.ccx.sess().asm_comments() {
+        if self.cx.sess().asm_comments() {
             let sanitized = text.replace("$", "");
             let comment_text = format!("{} {}", "#",
                                        sanitized.replace("\n", "\n\t# "));
             self.count_insn("inlineasm");
             let comment_text = CString::new(comment_text).unwrap();
             let asm = unsafe {
-                llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
+                llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.cx)).to_ref(),
                                          comment_text.as_ptr(), noname(), False,
                                          False)
             };
@@ -949,8 +949,8 @@
         unsafe {
             let elt_ty = val_ty(elt);
             let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
-            let vec = self.insert_element(undef, elt, C_i32(self.ccx, 0));
-            let vec_i32_ty = Type::vector(&Type::i32(self.ccx), num_elts as u64);
+            let vec = self.insert_element(undef, elt, C_i32(self.cx, 0));
+            let vec_i32_ty = Type::vector(&Type::i32(self.cx), num_elts as u64);
             self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
         }
     }
@@ -1012,12 +1012,11 @@
     }
 
     pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef,
-                       num_clauses: usize,
-                       llfn: ValueRef) -> ValueRef {
+                       num_clauses: usize) -> ValueRef {
         self.count_insn("landingpad");
         unsafe {
-            llvm::LLVMRustBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
-                                          num_clauses as c_uint, noname(), llfn)
+            llvm::LLVMBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
+                                      num_clauses as c_uint, noname())
         }
     }
 
@@ -1161,7 +1160,7 @@
     pub fn set_invariant_load(&self, load: ValueRef) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
-                                  llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
+                                  llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
         }
     }
 
@@ -1246,7 +1245,7 @@
     /// If LLVM lifetime intrinsic support is disabled (i.e.  optimizations
     /// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
     fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: ValueRef, size: Size) {
-        if self.ccx.sess().opts.optimize == config::OptLevel::No {
+        if self.cx.sess().opts.optimize == config::OptLevel::No {
             return;
         }
 
@@ -1255,9 +1254,9 @@
             return;
         }
 
-        let lifetime_intrinsic = self.ccx.get_intrinsic(intrinsic);
+        let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
 
-        let ptr = self.pointercast(ptr, Type::i8p(self.ccx));
-        self.call(lifetime_intrinsic, &[C_u64(self.ccx, size), ptr], None);
+        let ptr = self.pointercast(ptr, Type::i8p(self.cx));
+        self.call(lifetime_intrinsic, &[C_u64(self.cx, size), ptr], None);
     }
 }
diff --git a/src/librustc_trans/cabi_aarch64.rs b/src/librustc_trans/cabi_aarch64.rs
index d5f341f..72ae144 100644
--- a/src/librustc_trans/cabi_aarch64.rs
+++ b/src/librustc_trans/cabi_aarch64.rs
@@ -9,15 +9,15 @@
 // except according to those terms.
 
 use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>)
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
                                      -> Option<Uniform> {
-    arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+    arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         let size = arg.layout.size;
 
         // Ensure we have at most four uniquely addressable members.
-        if size > unit.size.checked_mul(4, ccx).unwrap() {
+        if size > unit.size.checked_mul(4, cx).unwrap() {
             return None;
         }
 
@@ -38,12 +38,12 @@
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
         return;
     }
-    if let Some(uniform) = is_homogeneous_aggregate(ccx, ret) {
+    if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
         ret.cast_to(uniform);
         return;
     }
@@ -69,12 +69,12 @@
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
         return;
     }
-    if let Some(uniform) = is_homogeneous_aggregate(ccx, arg) {
+    if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
         arg.cast_to(uniform);
         return;
     }
@@ -100,13 +100,13 @@
     arg.make_indirect();
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret);
+        classify_ret_ty(cx, &mut fty.ret);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg);
+        classify_arg_ty(cx, arg);
     }
 }
diff --git a/src/librustc_trans/cabi_arm.rs b/src/librustc_trans/cabi_arm.rs
index 438053d..b6cf16c 100644
--- a/src/librustc_trans/cabi_arm.rs
+++ b/src/librustc_trans/cabi_arm.rs
@@ -9,16 +9,16 @@
 // except according to those terms.
 
 use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 use llvm::CallConv;
 
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>)
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
                                      -> Option<Uniform> {
-    arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+    arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         let size = arg.layout.size;
 
         // Ensure we have at most four uniquely addressable members.
-        if size > unit.size.checked_mul(4, ccx).unwrap() {
+        if size > unit.size.checked_mul(4, cx).unwrap() {
             return None;
         }
 
@@ -39,14 +39,14 @@
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
         return;
     }
 
     if vfp {
-        if let Some(uniform) = is_homogeneous_aggregate(ccx, ret) {
+        if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
             ret.cast_to(uniform);
             return;
         }
@@ -71,14 +71,14 @@
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
         return;
     }
 
     if vfp {
-        if let Some(uniform) = is_homogeneous_aggregate(ccx, arg) {
+        if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
             arg.cast_to(uniform);
             return;
         }
@@ -92,19 +92,19 @@
     });
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     // If this is a target with a hard-float ABI, and the function is not explicitly
     // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
-    let vfp = ccx.sess().target.target.llvm_target.ends_with("hf")
+    let vfp = cx.sess().target.target.llvm_target.ends_with("hf")
         && fty.cconv != CallConv::ArmAapcsCallConv
         && !fty.variadic;
 
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret, vfp);
+        classify_ret_ty(cx, &mut fty.ret, vfp);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg, vfp);
+        classify_arg_ty(cx, arg, vfp);
     }
 }
diff --git a/src/librustc_trans/cabi_asmjs.rs b/src/librustc_trans/cabi_asmjs.rs
index 1664251..b182f83 100644
--- a/src/librustc_trans/cabi_asmjs.rs
+++ b/src/librustc_trans/cabi_asmjs.rs
@@ -9,16 +9,16 @@
 // except according to those terms.
 
 use abi::{FnType, ArgType, LayoutExt, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 
 // Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
 
 // See the https://github.com/kripken/emscripten-fastcomp-clang repository.
 // The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
     if ret.layout.is_aggregate() {
-        if let Some(unit) = ret.layout.homogeneous_aggregate(ccx) {
+        if let Some(unit) = ret.layout.homogeneous_aggregate(cx) {
             let size = ret.layout.size;
             if unit.size == size {
                 ret.cast_to(Uniform {
@@ -39,9 +39,9 @@
     }
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret);
+        classify_ret_ty(cx, &mut fty.ret);
     }
 
     for arg in &mut fty.args {
diff --git a/src/librustc_trans/cabi_mips.rs b/src/librustc_trans/cabi_mips.rs
index fe61670..cd567f5 100644
--- a/src/librustc_trans/cabi_mips.rs
+++ b/src/librustc_trans/cabi_mips.rs
@@ -9,23 +9,23 @@
 // except according to those terms.
 
 use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 
 use rustc::ty::layout::Size;
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              ret: &mut ArgType<'tcx>,
                              offset: &mut Size) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
     } else {
         ret.make_indirect();
-        *offset += ccx.tcx().data_layout.pointer_size;
+        *offset += cx.tcx.data_layout.pointer_size;
     }
 }
 
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
-    let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+    let dl = &cx.tcx.data_layout;
     let size = arg.layout.size;
     let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
 
@@ -44,14 +44,14 @@
     *offset = offset.abi_align(align) + size.abi_align(align);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+        classify_ret_ty(cx, &mut fty.ret, &mut offset);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg, &mut offset);
+        classify_arg_ty(cx, arg, &mut offset);
     }
 }
diff --git a/src/librustc_trans/cabi_mips64.rs b/src/librustc_trans/cabi_mips64.rs
index 16d0cfe..e44063f 100644
--- a/src/librustc_trans/cabi_mips64.rs
+++ b/src/librustc_trans/cabi_mips64.rs
@@ -9,23 +9,23 @@
 // except according to those terms.
 
 use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 
 use rustc::ty::layout::Size;
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              ret: &mut ArgType<'tcx>,
                              offset: &mut Size) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
     } else {
         ret.make_indirect();
-        *offset += ccx.tcx().data_layout.pointer_size;
+        *offset += cx.tcx.data_layout.pointer_size;
     }
 }
 
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
-    let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+    let dl = &cx.tcx.data_layout;
     let size = arg.layout.size;
     let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
 
@@ -44,14 +44,14 @@
     *offset = offset.abi_align(align) + size.abi_align(align);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+        classify_ret_ty(cx, &mut fty.ret, &mut offset);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg, &mut offset);
+        classify_arg_ty(cx, arg, &mut offset);
     }
 }
diff --git a/src/librustc_trans/cabi_powerpc.rs b/src/librustc_trans/cabi_powerpc.rs
index c3c8c74..1ea6e9b 100644
--- a/src/librustc_trans/cabi_powerpc.rs
+++ b/src/librustc_trans/cabi_powerpc.rs
@@ -9,23 +9,23 @@
 // except according to those terms.
 
 use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 
 use rustc::ty::layout::Size;
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              ret: &mut ArgType<'tcx>,
                              offset: &mut Size) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
     } else {
         ret.make_indirect();
-        *offset += ccx.tcx().data_layout.pointer_size;
+        *offset += cx.tcx.data_layout.pointer_size;
     }
 }
 
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
-    let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+    let dl = &cx.tcx.data_layout;
     let size = arg.layout.size;
     let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
 
@@ -44,14 +44,14 @@
     *offset = offset.abi_align(align) + size.abi_align(align);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+        classify_ret_ty(cx, &mut fty.ret, &mut offset);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg, &mut offset);
+        classify_arg_ty(cx, arg, &mut offset);
     }
 }
diff --git a/src/librustc_trans/cabi_powerpc64.rs b/src/librustc_trans/cabi_powerpc64.rs
index 2206a4f..c614cf3 100644
--- a/src/librustc_trans/cabi_powerpc64.rs
+++ b/src/librustc_trans/cabi_powerpc64.rs
@@ -13,7 +13,7 @@
 // need to be fixed when PowerPC vector support is added.
 
 use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 use rustc::ty::layout;
 
 #[derive(Debug, Clone, Copy, PartialEq)]
@@ -23,15 +23,15 @@
 }
 use self::ABI::*;
 
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                       arg: &mut ArgType<'tcx>,
                                       abi: ABI)
                                      -> Option<Uniform> {
-    arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+    arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         // ELFv1 only passes one-member aggregates transparently.
         // ELFv2 passes up to eight uniquely addressable members.
         if (abi == ELFv1 && arg.layout.size > unit.size)
-                || arg.layout.size > unit.size.checked_mul(8, ccx).unwrap() {
+                || arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
             return None;
         }
 
@@ -52,7 +52,7 @@
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>, abi: ABI) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, abi: ABI) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
         return;
@@ -64,7 +64,7 @@
         return;
     }
 
-    if let Some(uniform) = is_homogeneous_aggregate(ccx, ret, abi) {
+    if let Some(uniform) = is_homogeneous_aggregate(cx, ret, abi) {
         ret.cast_to(uniform);
         return;
     }
@@ -92,13 +92,13 @@
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>, abi: ABI) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, abi: ABI) {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
         return;
     }
 
-    if let Some(uniform) = is_homogeneous_aggregate(ccx, arg, abi) {
+    if let Some(uniform) = is_homogeneous_aggregate(cx, arg, abi) {
         arg.cast_to(uniform);
         return;
     }
@@ -128,19 +128,19 @@
     });
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
-    let abi = match ccx.sess().target.target.target_endian.as_str() {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+    let abi = match cx.sess().target.target.target_endian.as_str() {
         "big" => ELFv1,
         "little" => ELFv2,
         _ => unimplemented!(),
     };
 
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret, abi);
+        classify_ret_ty(cx, &mut fty.ret, abi);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg, abi);
+        classify_arg_ty(cx, arg, abi);
     }
 }
diff --git a/src/librustc_trans/cabi_s390x.rs b/src/librustc_trans/cabi_s390x.rs
index 9fb4600..5e81768 100644
--- a/src/librustc_trans/cabi_s390x.rs
+++ b/src/librustc_trans/cabi_s390x.rs
@@ -12,7 +12,7 @@
 // for a pre-z13 machine or using -mno-vx.
 
 use abi::{FnType, ArgType, LayoutExt, Reg};
-use context::CrateContext;
+use context::CodegenCx;
 
 use rustc::ty::layout::{self, TyLayout};
 
@@ -24,7 +24,7 @@
     }
 }
 
-fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                   layout: TyLayout<'tcx>) -> bool {
     match layout.abi {
         layout::Abi::Scalar(ref scalar) => {
@@ -35,7 +35,7 @@
         }
         layout::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
-                is_single_fp_element(ccx, layout.field(ccx, 0))
+                is_single_fp_element(cx, layout.field(cx, 0))
             } else {
                 false
             }
@@ -44,13 +44,13 @@
     }
 }
 
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
     if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
         arg.extend_integer_width_to(64);
         return;
     }
 
-    if is_single_fp_element(ccx, arg.layout) {
+    if is_single_fp_element(cx, arg.layout) {
         match arg.layout.size.bytes() {
             4 => arg.cast_to(Reg::f32()),
             8 => arg.cast_to(Reg::f64()),
@@ -67,13 +67,13 @@
     }
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     if !fty.ret.is_ignore() {
         classify_ret_ty(&mut fty.ret);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg);
+        classify_arg_ty(cx, arg);
     }
 }
diff --git a/src/librustc_trans/cabi_sparc.rs b/src/librustc_trans/cabi_sparc.rs
index fe61670..cd567f5 100644
--- a/src/librustc_trans/cabi_sparc.rs
+++ b/src/librustc_trans/cabi_sparc.rs
@@ -9,23 +9,23 @@
 // except according to those terms.
 
 use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 
 use rustc::ty::layout::Size;
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              ret: &mut ArgType<'tcx>,
                              offset: &mut Size) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
     } else {
         ret.make_indirect();
-        *offset += ccx.tcx().data_layout.pointer_size;
+        *offset += cx.tcx.data_layout.pointer_size;
     }
 }
 
-fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut Size) {
-    let dl = &ccx.tcx().data_layout;
+fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+    let dl = &cx.tcx.data_layout;
     let size = arg.layout.size;
     let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
 
@@ -44,14 +44,14 @@
     *offset = offset.abi_align(align) + size.abi_align(align);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret, &mut offset);
+        classify_ret_ty(cx, &mut fty.ret, &mut offset);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg, &mut offset);
+        classify_arg_ty(cx, arg, &mut offset);
     }
 }
diff --git a/src/librustc_trans/cabi_sparc64.rs b/src/librustc_trans/cabi_sparc64.rs
index 7c52e27..b3fc6a6 100644
--- a/src/librustc_trans/cabi_sparc64.rs
+++ b/src/librustc_trans/cabi_sparc64.rs
@@ -11,13 +11,13 @@
 // FIXME: This needs an audit for correctness and completeness.
 
 use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CrateContext;
+use context::CodegenCx;
 
-fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>)
+fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
                                      -> Option<Uniform> {
-    arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
+    arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         // Ensure we have at most eight uniquely addressable members.
-        if arg.layout.size > unit.size.checked_mul(8, ccx).unwrap() {
+        if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
             return None;
         }
 
@@ -38,19 +38,19 @@
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
         return;
     }
 
-    if let Some(uniform) = is_homogeneous_aggregate(ccx, ret) {
+    if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
         ret.cast_to(uniform);
         return;
     }
     let size = ret.layout.size;
     let bits = size.bits();
-    if bits <= 128 {
+    if bits <= 256 {
         let unit = if bits <= 8 {
             Reg::i8()
         } else if bits <= 16 {
@@ -72,31 +72,36 @@
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
         return;
     }
 
-    if let Some(uniform) = is_homogeneous_aggregate(ccx, arg) {
+    if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
         arg.cast_to(uniform);
         return;
     }
 
     let total = arg.layout.size;
+    if total.bits() > 128 {
+        arg.make_indirect();
+        return;
+    }
+
     arg.cast_to(Uniform {
         unit: Reg::i64(),
         total
     });
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     if !fty.ret.is_ignore() {
-        classify_ret_ty(ccx, &mut fty.ret);
+        classify_ret_ty(cx, &mut fty.ret);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(ccx, arg);
+        classify_arg_ty(cx, arg);
     }
 }
diff --git a/src/librustc_trans/cabi_x86.rs b/src/librustc_trans/cabi_x86.rs
index 6fd0140..60347ba 100644
--- a/src/librustc_trans/cabi_x86.rs
+++ b/src/librustc_trans/cabi_x86.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use abi::{ArgAttribute, FnType, LayoutExt, PassMode, Reg, RegKind};
-use common::CrateContext;
+use common::CodegenCx;
 
 use rustc::ty::layout::{self, TyLayout};
 
@@ -19,7 +19,7 @@
     Fastcall
 }
 
-fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                   layout: TyLayout<'tcx>) -> bool {
     match layout.abi {
         layout::Abi::Scalar(ref scalar) => {
@@ -30,7 +30,7 @@
         }
         layout::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
-                is_single_fp_element(ccx, layout.field(ccx, 0))
+                is_single_fp_element(cx, layout.field(cx, 0))
             } else {
                 false
             }
@@ -39,7 +39,7 @@
     }
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                   fty: &mut FnType<'tcx>,
                                   flavor: Flavor) {
     if !fty.ret.is_ignore() {
@@ -51,12 +51,12 @@
             // Some links:
             // http://www.angelcode.com/dev/callconv/callconv.html
             // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
-            let t = &ccx.sess().target.target;
+            let t = &cx.sess().target.target;
             if t.options.is_like_osx || t.options.is_like_windows
                 || t.options.is_like_openbsd {
                 // According to Clang, everyone but MSVC returns single-element
                 // float aggregates directly in a floating-point register.
-                if !t.options.is_like_msvc && is_single_fp_element(ccx, fty.ret.layout) {
+                if !t.options.is_like_msvc && is_single_fp_element(cx, fty.ret.layout) {
                     match fty.ret.layout.size.bytes() {
                         4 => fty.ret.cast_to(Reg::f32()),
                         8 => fty.ret.cast_to(Reg::f64()),
@@ -112,7 +112,7 @@
             };
 
             // At this point we know this must be a primitive of sorts.
-            let unit = arg.layout.homogeneous_aggregate(ccx).unwrap();
+            let unit = arg.layout.homogeneous_aggregate(cx).unwrap();
             assert_eq!(unit.size, arg.layout.size);
             if unit.kind == RegKind::Float {
                 continue;
diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs
index 7c9f257..6db18bf 100644
--- a/src/librustc_trans/cabi_x86_64.rs
+++ b/src/librustc_trans/cabi_x86_64.rs
@@ -12,7 +12,7 @@
 // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
 
 use abi::{ArgType, CastTarget, FnType, LayoutExt, Reg, RegKind};
-use context::CrateContext;
+use context::CodegenCx;
 
 use rustc::ty::layout::{self, TyLayout, Size};
 
@@ -31,7 +31,7 @@
 const LARGEST_VECTOR_SIZE: usize = 512;
 const MAX_EIGHTBYTES: usize = LARGEST_VECTOR_SIZE / 64;
 
-fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>)
+fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
                           -> Result<[Class; MAX_EIGHTBYTES], Memory> {
     fn unify(cls: &mut [Class],
              off: Size,
@@ -52,7 +52,7 @@
         cls[i] = to_write;
     }
 
-    fn classify<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+    fn classify<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                           layout: TyLayout<'tcx>,
                           cls: &mut [Class],
                           off: Size)
@@ -82,7 +82,7 @@
 
                 // everything after the first one is the upper
                 // half of a register.
-                let stride = element.value.size(ccx);
+                let stride = element.value.size(cx);
                 for i in 1..count {
                     let field_off = off + stride * i;
                     unify(cls, field_off, Class::SseUp);
@@ -95,7 +95,7 @@
                     layout::Variants::Single { .. } => {
                         for i in 0..layout.fields.count() {
                             let field_off = off + layout.fields.offset(i);
-                            classify(ccx, layout.field(ccx, i), cls, field_off)?;
+                            classify(cx, layout.field(cx, i), cls, field_off)?;
                         }
                     }
                     layout::Variants::Tagged { .. } |
@@ -114,7 +114,7 @@
     }
 
     let mut cls = [Class::None; MAX_EIGHTBYTES];
-    classify(ccx, arg.layout, &mut cls, Size::from_bytes(0))?;
+    classify(cx, arg.layout, &mut cls, Size::from_bytes(0))?;
     if n > 2 {
         if cls[0] != Class::Sse {
             return Err(Memory);
@@ -189,12 +189,12 @@
     target
 }
 
-pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
     let mut sse_regs = 8; // XMM0-7
 
     let mut x86_64_ty = |arg: &mut ArgType<'tcx>, is_arg: bool| {
-        let cls = classify_arg(ccx, arg);
+        let cls = classify_arg(cx, arg);
 
         let mut needed_int = 0;
         let mut needed_sse = 0;
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 0a0f261..c3d5e08 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -15,7 +15,7 @@
 //! closure.
 
 use attributes;
-use common::{self, CrateContext};
+use common::{self, CodegenCx};
 use consts;
 use declare;
 use llvm::{self, ValueRef};
@@ -34,13 +34,13 @@
 ///
 /// # Parameters
 ///
-/// - `ccx`: the crate context
+/// - `cx`: the crate context
 /// - `instance`: the instance to be instantiated
-pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                         instance: Instance<'tcx>)
                         -> ValueRef
 {
-    let tcx = ccx.tcx();
+    let tcx = cx.tcx;
 
     debug!("get_fn(instance={:?})", instance);
 
@@ -48,8 +48,8 @@
     assert!(!instance.substs.has_escaping_regions());
     assert!(!instance.substs.has_param_types());
 
-    let fn_ty = instance.ty(ccx.tcx());
-    if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
+    let fn_ty = instance.ty(cx.tcx);
+    if let Some(&llfn) = cx.instances.borrow().get(&instance) {
         return llfn;
     }
 
@@ -57,10 +57,10 @@
     debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
 
     // Create a fn pointer with the substituted signature.
-    let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty));
-    let llptrty = ccx.layout_of(fn_ptr_ty).llvm_type(ccx);
+    let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(cx, fn_ty));
+    let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx);
 
-    let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
+    let llfn = if let Some(llfn) = declare::get_declared_value(cx, &sym) {
         // This is subtle and surprising, but sometimes we have to bitcast
         // the resulting fn pointer.  The reason has to do with external
         // functions.  If you have two crates that both bind the same C
@@ -92,15 +92,14 @@
             llfn
         }
     } else {
-        let llfn = declare::declare_fn(ccx, &sym, fn_ty);
+        let llfn = declare::declare_fn(cx, &sym, fn_ty);
         assert_eq!(common::val_ty(llfn), llptrty);
         debug!("get_fn: not casting pointer!");
 
         if instance.def.is_inline(tcx) {
             attributes::inline(llfn, attributes::InlineAttr::Hint);
         }
-        let attrs = instance.def.attrs(ccx.tcx());
-        attributes::from_fn_attrs(ccx, &attrs, llfn);
+        attributes::from_fn_attrs(cx, llfn, instance.def.def_id());
 
         let instance_def_id = instance.def_id();
 
@@ -150,9 +149,9 @@
         unsafe {
             llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
 
-            if ccx.tcx().is_translated_function(instance_def_id) {
+            if cx.tcx.is_translated_function(instance_def_id) {
                 if instance_def_id.is_local() {
-                    if !ccx.tcx().is_exported_symbol(instance_def_id) {
+                    if !cx.tcx.is_exported_symbol(instance_def_id) {
                         llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
                     }
                 } else {
@@ -161,7 +160,7 @@
             }
         }
 
-        if ccx.use_dll_storage_attrs() &&
+        if cx.use_dll_storage_attrs &&
             tcx.is_dllimport_foreign_item(instance_def_id)
         {
             unsafe {
@@ -172,20 +171,20 @@
         llfn
     };
 
-    ccx.instances().borrow_mut().insert(instance, llfn);
+    cx.instances.borrow_mut().insert(instance, llfn);
 
     llfn
 }
 
-pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn resolve_and_get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                     def_id: DefId,
                                     substs: &'tcx Substs<'tcx>)
                                     -> ValueRef
 {
     get_fn(
-        ccx,
+        cx,
         ty::Instance::resolve(
-            ccx.tcx(),
+            cx.tcx,
             ty::ParamEnv::empty(traits::Reveal::All),
             def_id,
             substs
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index b1bdee3..9e745c3 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -38,7 +38,7 @@
 use syntax::symbol::InternedString;
 use syntax_pos::{Span, DUMMY_SP};
 
-pub use context::{CrateContext, SharedCrateContext};
+pub use context::CodegenCx;
 
 pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
     ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All))
@@ -152,46 +152,46 @@
     }
 }
 
-pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
-    C_uint(Type::i1(ccx), val as u64)
+pub fn C_bool(cx: &CodegenCx, val: bool) -> ValueRef {
+    C_uint(Type::i1(cx), val as u64)
 }
 
-pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
-    C_int(Type::i32(ccx), i as i64)
+pub fn C_i32(cx: &CodegenCx, i: i32) -> ValueRef {
+    C_int(Type::i32(cx), i as i64)
 }
 
-pub fn C_u32(ccx: &CrateContext, i: u32) -> ValueRef {
-    C_uint(Type::i32(ccx), i as u64)
+pub fn C_u32(cx: &CodegenCx, i: u32) -> ValueRef {
+    C_uint(Type::i32(cx), i as u64)
 }
 
-pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
-    C_uint(Type::i64(ccx), i)
+pub fn C_u64(cx: &CodegenCx, i: u64) -> ValueRef {
+    C_uint(Type::i64(cx), i)
 }
 
-pub fn C_usize(ccx: &CrateContext, i: u64) -> ValueRef {
-    let bit_size = ccx.data_layout().pointer_size.bits();
+pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef {
+    let bit_size = cx.data_layout().pointer_size.bits();
     if bit_size < 64 {
         // make sure it doesn't overflow
         assert!(i < (1<<bit_size));
     }
 
-    C_uint(ccx.isize_ty(), i)
+    C_uint(cx.isize_ty, i)
 }
 
-pub fn C_u8(ccx: &CrateContext, i: u8) -> ValueRef {
-    C_uint(Type::i8(ccx), i as u64)
+pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef {
+    C_uint(Type::i8(cx), i as u64)
 }
 
 
 // This is a 'c-like' raw string, which differs from
 // our boxed-and-length-annotated strings.
-pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> ValueRef {
+pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> ValueRef {
     unsafe {
-        if let Some(&llval) = cx.const_cstr_cache().borrow().get(&s) {
+        if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
             return llval;
         }
 
-        let sc = llvm::LLVMConstStringInContext(cx.llcx(),
+        let sc = llvm::LLVMConstStringInContext(cx.llcx,
                                                 s.as_ptr() as *const c_char,
                                                 s.len() as c_uint,
                                                 !null_terminated as Bool);
@@ -203,28 +203,28 @@
         llvm::LLVMSetGlobalConstant(g, True);
         llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
 
-        cx.const_cstr_cache().borrow_mut().insert(s, g);
+        cx.const_cstr_cache.borrow_mut().insert(s, g);
         g
     }
 }
 
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
+pub fn C_str_slice(cx: &CodegenCx, s: InternedString) -> ValueRef {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
-        cx.layout_of(cx.tcx().mk_str()).llvm_type(cx).ptr_to());
+        cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
     C_fat_ptr(cx, cs, C_usize(cx, len as u64))
 }
 
-pub fn C_fat_ptr(cx: &CrateContext, ptr: ValueRef, meta: ValueRef) -> ValueRef {
+pub fn C_fat_ptr(cx: &CodegenCx, ptr: ValueRef, meta: ValueRef) -> ValueRef {
     assert_eq!(abi::FAT_PTR_ADDR, 0);
     assert_eq!(abi::FAT_PTR_EXTRA, 1);
     C_struct(cx, &[ptr, meta], false)
 }
 
-pub fn C_struct(cx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
-    C_struct_in_context(cx.llcx(), elts, packed)
+pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef {
+    C_struct_in_context(cx.llcx, elts, packed)
 }
 
 pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
@@ -247,8 +247,8 @@
     }
 }
 
-pub fn C_bytes(cx: &CrateContext, bytes: &[u8]) -> ValueRef {
-    C_bytes_in_context(cx.llcx(), bytes)
+pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef {
+    C_bytes_in_context(cx.llcx, bytes)
 }
 
 pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
@@ -328,37 +328,37 @@
 // of Java. (See related discussion on #1877 and #10183.)
 
 pub fn build_unchecked_lshift<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     lhs: ValueRef,
     rhs: ValueRef
 ) -> ValueRef {
-    let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShl, lhs, rhs);
+    let rhs = base::cast_shift_expr_rhs(bx, hir::BinOp_::BiShl, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
-    let rhs = shift_mask_rhs(bcx, rhs);
-    bcx.shl(lhs, rhs)
+    let rhs = shift_mask_rhs(bx, rhs);
+    bx.shl(lhs, rhs)
 }
 
 pub fn build_unchecked_rshift<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef
+    bx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef
 ) -> ValueRef {
-    let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShr, lhs, rhs);
+    let rhs = base::cast_shift_expr_rhs(bx, hir::BinOp_::BiShr, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
-    let rhs = shift_mask_rhs(bcx, rhs);
+    let rhs = shift_mask_rhs(bx, rhs);
     let is_signed = lhs_t.is_signed();
     if is_signed {
-        bcx.ashr(lhs, rhs)
+        bx.ashr(lhs, rhs)
     } else {
-        bcx.lshr(lhs, rhs)
+        bx.lshr(lhs, rhs)
     }
 }
 
-fn shift_mask_rhs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef {
+fn shift_mask_rhs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef {
     let rhs_llty = val_ty(rhs);
-    bcx.and(rhs, shift_mask_val(bcx, rhs_llty, rhs_llty, false))
+    bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
 }
 
 pub fn shift_mask_val<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     llty: Type,
     mask_llty: Type,
     invert: bool
@@ -375,23 +375,23 @@
             }
         },
         TypeKind::Vector => {
-            let mask = shift_mask_val(bcx, llty.element_type(), mask_llty.element_type(), invert);
-            bcx.vector_splat(mask_llty.vector_length(), mask)
+            let mask = shift_mask_val(bx, llty.element_type(), mask_llty.element_type(), invert);
+            bx.vector_splat(mask_llty.vector_length(), mask)
         },
         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
     }
 }
 
-pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                            ty: Ty<'tcx>)
                            -> ty::PolyFnSig<'tcx>
 {
     match ty.sty {
         ty::TyFnDef(..) |
         // Shims currently have type TyFnPtr. Not sure this should remain.
-        ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
+        ty::TyFnPtr(_) => ty.fn_sig(cx.tcx),
         ty::TyClosure(def_id, substs) => {
-            let tcx = ccx.tcx();
+            let tcx = cx.tcx;
             let sig = substs.closure_sig(def_id, tcx);
 
             let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
@@ -404,8 +404,8 @@
             ))
         }
         ty::TyGenerator(def_id, substs, _) => {
-            let tcx = ccx.tcx();
-            let sig = substs.generator_poly_sig(def_id, ccx.tcx());
+            let tcx = cx.tcx;
+            let sig = substs.generator_poly_sig(def_id, cx.tcx);
 
             let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
             let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index f9fbceb..d5b33d8 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -17,7 +17,7 @@
 use debuginfo;
 use base;
 use monomorphize::{MonoItem, MonoItemExt};
-use common::{CrateContext, val_ty};
+use common::{CodegenCx, val_ty};
 use declare;
 use monomorphize::Instance;
 use type_::Type;
@@ -43,17 +43,17 @@
     }
 }
 
-fn set_global_alignment(ccx: &CrateContext,
+fn set_global_alignment(cx: &CodegenCx,
                         gv: ValueRef,
                         mut align: Align) {
     // The target may require greater alignment for globals than the type does.
     // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
     // which can force it to be smaller.  Rust doesn't support this yet.
-    if let Some(min) = ccx.sess().target.target.options.min_global_align {
+    if let Some(min) = cx.sess().target.target.options.min_global_align {
         match ty::layout::Align::from_bits(min, min) {
             Ok(min) => align = align.max(min),
             Err(err) => {
-                ccx.sess().err(&format!("invalid minimum global alignment: {}", err));
+                cx.sess().err(&format!("invalid minimum global alignment: {}", err));
             }
         }
     }
@@ -62,30 +62,30 @@
     }
 }
 
-pub fn addr_of_mut(ccx: &CrateContext,
+pub fn addr_of_mut(cx: &CodegenCx,
                    cv: ValueRef,
                    align: Align,
                    kind: &str)
                     -> ValueRef {
     unsafe {
-        let name = ccx.generate_local_symbol_name(kind);
-        let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
+        let name = cx.generate_local_symbol_name(kind);
+        let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{
             bug!("symbol `{}` is already defined", name);
         });
         llvm::LLVMSetInitializer(gv, cv);
-        set_global_alignment(ccx, gv, align);
+        set_global_alignment(cx, gv, align);
         llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
         SetUnnamedAddr(gv, true);
         gv
     }
 }
 
-pub fn addr_of(ccx: &CrateContext,
+pub fn addr_of(cx: &CodegenCx,
                cv: ValueRef,
                align: Align,
                kind: &str)
                -> ValueRef {
-    if let Some(&gv) = ccx.const_globals().borrow().get(&cv) {
+    if let Some(&gv) = cx.const_globals.borrow().get(&cv) {
         unsafe {
             // Upgrade the alignment in cases where the same constant is used with different
             // alignment requirements
@@ -96,42 +96,42 @@
         }
         return gv;
     }
-    let gv = addr_of_mut(ccx, cv, align, kind);
+    let gv = addr_of_mut(cx, cv, align, kind);
     unsafe {
         llvm::LLVMSetGlobalConstant(gv, True);
     }
-    ccx.const_globals().borrow_mut().insert(cv, gv);
+    cx.const_globals.borrow_mut().insert(cv, gv);
     gv
 }
 
-pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
-    let instance = Instance::mono(ccx.tcx(), def_id);
-    if let Some(&g) = ccx.instances().borrow().get(&instance) {
+pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
+    let instance = Instance::mono(cx.tcx, def_id);
+    if let Some(&g) = cx.instances.borrow().get(&instance) {
         return g;
     }
 
-    let ty = instance.ty(ccx.tcx());
-    let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) {
+    let ty = instance.ty(cx.tcx);
+    let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) {
 
-        let llty = ccx.layout_of(ty).llvm_type(ccx);
-        let (g, attrs) = match ccx.tcx().hir.get(id) {
+        let llty = cx.layout_of(ty).llvm_type(cx);
+        let (g, attrs) = match cx.tcx.hir.get(id) {
             hir_map::NodeItem(&hir::Item {
                 ref attrs, span, node: hir::ItemStatic(..), ..
             }) => {
-                let sym = MonoItem::Static(id).symbol_name(ccx.tcx());
+                let sym = MonoItem::Static(id).symbol_name(cx.tcx);
 
-                let defined_in_current_codegen_unit = ccx.codegen_unit()
+                let defined_in_current_codegen_unit = cx.codegen_unit
                                                          .items()
                                                          .contains_key(&MonoItem::Static(id));
                 assert!(!defined_in_current_codegen_unit);
 
-                if declare::get_declared_value(ccx, &sym[..]).is_some() {
+                if declare::get_declared_value(cx, &sym[..]).is_some() {
                     span_bug!(span, "trans: Conflicting symbol names for static?");
                 }
 
-                let g = declare::define_global(ccx, &sym[..], llty).unwrap();
+                let g = declare::define_global(cx, &sym[..], llty).unwrap();
 
-                if !ccx.tcx().is_exported_symbol(def_id) {
+                if !cx.tcx.is_exported_symbol(def_id) {
                     unsafe {
                         llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
                     }
@@ -143,7 +143,7 @@
             hir_map::NodeForeignItem(&hir::ForeignItem {
                 ref attrs, span, node: hir::ForeignItemStatic(..), ..
             }) => {
-                let sym = ccx.tcx().symbol_name(instance);
+                let sym = cx.tcx.symbol_name(instance);
                 let g = if let Some(name) =
                         attr::first_attr_value_str_by_name(&attrs, "linkage") {
                     // If this is a static with a linkage specified, then we need to handle
@@ -154,18 +154,18 @@
                     let linkage = match base::linkage_by_name(&name.as_str()) {
                         Some(linkage) => linkage,
                         None => {
-                            ccx.sess().span_fatal(span, "invalid linkage specified");
+                            cx.sess().span_fatal(span, "invalid linkage specified");
                         }
                     };
                     let llty2 = match ty.sty {
-                        ty::TyRawPtr(ref mt) => ccx.layout_of(mt.ty).llvm_type(ccx),
+                        ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
                         _ => {
-                            ccx.sess().span_fatal(span, "must have type `*const T` or `*mut T`");
+                            cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`");
                         }
                     };
                     unsafe {
                         // Declare a symbol `foo` with the desired linkage.
-                        let g1 = declare::declare_global(ccx, &sym, llty2);
+                        let g1 = declare::declare_global(cx, &sym, llty2);
                         llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
 
                         // Declare an internal global `extern_with_linkage_foo` which
@@ -176,8 +176,8 @@
                         // zero.
                         let mut real_name = "_rust_extern_with_linkage_".to_string();
                         real_name.push_str(&sym);
-                        let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
-                            ccx.sess().span_fatal(span,
+                        let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{
+                            cx.sess().span_fatal(span,
                                 &format!("symbol `{}` is already defined", &sym))
                         });
                         llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
@@ -186,7 +186,7 @@
                     }
                 } else {
                     // Generate an external declaration.
-                    declare::declare_global(ccx, &sym, llty)
+                    declare::declare_global(cx, &sym, llty)
                 };
 
                 (g, attrs)
@@ -197,29 +197,29 @@
 
         for attr in attrs {
             if attr.check_name("thread_local") {
-                llvm::set_thread_local_mode(g, ccx.tls_model());
+                llvm::set_thread_local_mode(g, cx.tls_model);
             }
         }
 
         g
     } else {
-        let sym = ccx.tcx().symbol_name(instance);
+        let sym = cx.tcx.symbol_name(instance);
 
         // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
         // FIXME(nagisa): investigate whether it can be changed into define_global
-        let g = declare::declare_global(ccx, &sym, ccx.layout_of(ty).llvm_type(ccx));
+        let g = declare::declare_global(cx, &sym, cx.layout_of(ty).llvm_type(cx));
         // Thread-local statics in some other crate need to *always* be linked
         // against in a thread-local fashion, so we need to be sure to apply the
         // thread-local attribute locally if it was present remotely. If we
         // don't do this then linker errors can be generated where the linker
         // complains that one object files has a thread local version of the
         // symbol and another one doesn't.
-        for attr in ccx.tcx().get_attrs(def_id).iter() {
+        for attr in cx.tcx.get_attrs(def_id).iter() {
             if attr.check_name("thread_local") {
-                llvm::set_thread_local_mode(g, ccx.tls_model());
+                llvm::set_thread_local_mode(g, cx.tls_model);
             }
         }
-        if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
+        if cx.use_dll_storage_attrs && !cx.tcx.is_foreign_item(def_id) {
             // This item is external but not foreign, i.e. it originates from an external Rust
             // crate. Since we don't know whether this crate will be linked dynamically or
             // statically in the final application, we always mark such symbols as 'dllimport'.
@@ -232,42 +232,42 @@
         g
     };
 
-    if ccx.use_dll_storage_attrs() && ccx.tcx().is_dllimport_foreign_item(def_id) {
+    if cx.use_dll_storage_attrs && cx.tcx.is_dllimport_foreign_item(def_id) {
         // For foreign (native) libs we know the exact storage type to use.
         unsafe {
             llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
         }
     }
 
-    ccx.instances().borrow_mut().insert(instance, g);
-    ccx.statics().borrow_mut().insert(g, def_id);
+    cx.instances.borrow_mut().insert(instance, g);
+    cx.statics.borrow_mut().insert(g, def_id);
     g
 }
 
-pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                               m: hir::Mutability,
                               id: ast::NodeId,
                               attrs: &[ast::Attribute])
                               -> Result<ValueRef, ConstEvalErr<'tcx>> {
     unsafe {
-        let def_id = ccx.tcx().hir.local_def_id(id);
-        let g = get_static(ccx, def_id);
+        let def_id = cx.tcx.hir.local_def_id(id);
+        let g = get_static(cx, def_id);
 
-        let v = ::mir::trans_static_initializer(ccx, def_id)?;
+        let v = ::mir::trans_static_initializer(cx, def_id)?;
 
         // boolean SSA values are i1, but they have to be stored in i8 slots,
         // otherwise some LLVM optimization passes don't work as expected
         let mut val_llty = val_ty(v);
-        let v = if val_llty == Type::i1(ccx) {
-            val_llty = Type::i8(ccx);
+        let v = if val_llty == Type::i1(cx) {
+            val_llty = Type::i8(cx);
             llvm::LLVMConstZExt(v, val_llty.to_ref())
         } else {
             v
         };
 
-        let instance = Instance::mono(ccx.tcx(), def_id);
-        let ty = instance.ty(ccx.tcx());
-        let llty = ccx.layout_of(ty).llvm_type(ccx);
+        let instance = Instance::mono(cx.tcx, def_id);
+        let ty = instance.ty(cx.tcx);
+        let llty = cx.layout_of(ty).llvm_type(cx);
         let g = if val_llty == llty {
             g
         } else {
@@ -282,7 +282,7 @@
             let visibility = llvm::LLVMRustGetVisibility(g);
 
             let new_g = llvm::LLVMRustGetOrInsertGlobal(
-                ccx.llmod(), name_string.as_ptr(), val_llty.to_ref());
+                cx.llmod, name_string.as_ptr(), val_llty.to_ref());
 
             llvm::LLVMRustSetLinkage(new_g, linkage);
             llvm::LLVMRustSetVisibility(new_g, visibility);
@@ -290,32 +290,32 @@
             // To avoid breaking any invariants, we leave around the old
             // global for the moment; we'll replace all references to it
             // with the new global later. (See base::trans_crate.)
-            ccx.statics_to_rauw().borrow_mut().push((g, new_g));
+            cx.statics_to_rauw.borrow_mut().push((g, new_g));
             new_g
         };
-        set_global_alignment(ccx, g, ccx.align_of(ty));
+        set_global_alignment(cx, g, cx.align_of(ty));
         llvm::LLVMSetInitializer(g, v);
 
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
         if m != hir::MutMutable {
-            if ccx.shared().type_is_freeze(ty) {
+            if cx.type_is_freeze(ty) {
                 llvm::LLVMSetGlobalConstant(g, llvm::True);
             }
         }
 
-        debuginfo::create_global_var_metadata(ccx, id, g);
+        debuginfo::create_global_var_metadata(cx, id, g);
 
         if attr::contains_name(attrs, "thread_local") {
-            llvm::set_thread_local_mode(g, ccx.tls_model());
+            llvm::set_thread_local_mode(g, cx.tls_model);
         }
 
-        base::set_link_section(ccx, g, attrs);
+        base::set_link_section(cx, g, attrs);
 
         if attr::contains_name(attrs, "used") {
             // This static will be stored in the llvm.used variable which is an array of i8*
-            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(ccx).to_ref());
-            ccx.used_statics().borrow_mut().push(cast);
+            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+            cx.used_statics.borrow_mut().push(cast);
         }
 
         Ok(g)
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index d5e7106..06b8d9f 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -11,10 +11,9 @@
 use common;
 use llvm;
 use llvm::{ContextRef, ModuleRef, ValueRef};
-use rustc::dep_graph::{DepGraph, DepGraphSafe};
+use rustc::dep_graph::DepGraphSafe;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::ich::StableHashingContext;
 use rustc::traits;
 use debuginfo;
 use callee;
@@ -28,7 +27,6 @@
 
 use rustc_data_structures::base_n;
 use rustc::mir::mono::Stats;
-use rustc_data_structures::stable_hasher::StableHashingContextProvider;
 use rustc::session::config::{self, NoDebugInfo};
 use rustc::session::Session;
 use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout};
@@ -41,38 +39,30 @@
 use std::iter;
 use std::str;
 use std::sync::Arc;
-use std::marker::PhantomData;
 use syntax::symbol::InternedString;
 use abi::Abi;
 
-/// The shared portion of a `CrateContext`.  There is one `SharedCrateContext`
-/// per crate.  The data here is shared between all compilation units of the
-/// crate, so it must not contain references to any LLVM data structures
-/// (aside from metadata-related ones).
-pub struct SharedCrateContext<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    check_overflow: bool,
-    use_dll_storage_attrs: bool,
-    tls_model: llvm::ThreadLocalMode,
-}
+/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
+/// `ContextRef` so that several compilation units may be optimized in parallel.
+/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`.
+pub struct CodegenCx<'a, 'tcx: 'a> {
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    pub check_overflow: bool,
+    pub use_dll_storage_attrs: bool,
+    pub tls_model: llvm::ThreadLocalMode,
 
-/// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
-/// per compilation unit.  Each one has its own LLVM `ContextRef` so that
-/// several compilation units may be optimized in parallel.  All other LLVM
-/// data structures in the `LocalCrateContext` are tied to that `ContextRef`.
-pub struct LocalCrateContext<'a, 'tcx: 'a> {
-    llmod: ModuleRef,
-    llcx: ContextRef,
-    stats: RefCell<Stats>,
-    codegen_unit: Arc<CodegenUnit<'tcx>>,
+    pub llmod: ModuleRef,
+    pub llcx: ContextRef,
+    pub stats: RefCell<Stats>,
+    pub codegen_unit: Arc<CodegenUnit<'tcx>>,
 
     /// Cache instances of monomorphic and polymorphic items
-    instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
+    pub instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
     /// Cache generated vtables
-    vtables: RefCell<FxHashMap<(Ty<'tcx>,
+    pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
                                 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
     /// Cache of constant strings,
-    const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
+    pub const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
 
     /// Reverse-direction for const ptrs cast from globals.
     /// Key is a ValueRef holding a *T,
@@ -82,72 +72,42 @@
     /// when we ptrcast, and we have to ptrcast during translation
     /// of a [T] const because we form a slice, a (*T,usize) pair, not
     /// a pointer to an LLVM array type. Similar for trait objects.
-    const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
+    pub const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
 
     /// Cache of emitted const globals (value -> global)
-    const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
+    pub const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
 
     /// Mapping from static definitions to their DefId's.
-    statics: RefCell<FxHashMap<ValueRef, DefId>>,
+    pub statics: RefCell<FxHashMap<ValueRef, DefId>>,
 
     /// List of globals for static variables which need to be passed to the
     /// LLVM function ReplaceAllUsesWith (RAUW) when translation is complete.
     /// (We have to make sure we don't invalidate any ValueRefs referring
     /// to constants.)
-    statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
+    pub statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
 
     /// Statics that will be placed in the llvm.used variable
     /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
-    used_statics: RefCell<Vec<ValueRef>>,
+    pub used_statics: RefCell<Vec<ValueRef>>,
 
-    lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>>,
-    scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
-    pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
-    isize_ty: Type,
+    pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>>,
+    pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
+    pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
+    pub isize_ty: Type,
 
-    dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
+    pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
 
     eh_personality: Cell<Option<ValueRef>>,
     eh_unwind_resume: Cell<Option<ValueRef>>,
-    rust_try_fn: Cell<Option<ValueRef>>,
+    pub rust_try_fn: Cell<Option<ValueRef>>,
 
     intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>,
 
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
-
-    /// A placeholder so we can add lifetimes
-    placeholder: PhantomData<&'a ()>,
 }
 
-/// A CrateContext value binds together one LocalCrateContext with the
-/// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
-/// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
-pub struct CrateContext<'a, 'tcx: 'a> {
-    shared: &'a SharedCrateContext<'a, 'tcx>,
-    local_ccx: &'a LocalCrateContext<'a, 'tcx>,
-}
-
-impl<'a, 'tcx> CrateContext<'a, 'tcx> {
-    pub fn new(shared: &'a SharedCrateContext<'a, 'tcx>,
-               local_ccx: &'a LocalCrateContext<'a, 'tcx>)
-               -> Self {
-        CrateContext { shared, local_ccx }
-    }
-}
-
-impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
-}
-
-impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> {
-}
-
-impl<'a, 'tcx> StableHashingContextProvider for SharedCrateContext<'a, 'tcx> {
-    type ContextType = StableHashingContext<'tcx>;
-
-    fn create_stable_hashing_context(&self) -> Self::ContextType {
-        self.tcx.create_stable_hashing_context()
-    }
+impl<'a, 'tcx> DepGraphSafe for CodegenCx<'a, 'tcx> {
 }
 
 pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
@@ -197,7 +157,7 @@
 }
 
 pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
-    let llcx = llvm::LLVMContextCreate();
+    let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
     let mod_name = CString::new(mod_name).unwrap();
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
@@ -252,8 +212,11 @@
     (llcx, llmod)
 }
 
-impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
-    pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> SharedCrateContext<'b, 'tcx> {
+impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               codegen_unit: Arc<CodegenUnit<'tcx>>,
+               llmod_id: &str)
+               -> CodegenCx<'a, 'tcx> {
         // An interesting part of Windows which MSVC forces our hand on (and
         // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
         // attributes in LLVM IR as well as native dependencies (in C these
@@ -303,14 +266,161 @@
 
         let tls_model = get_tls_model(&tcx.sess);
 
-        SharedCrateContext {
-            tcx,
-            check_overflow,
-            use_dll_storage_attrs,
-            tls_model,
+        unsafe {
+            let (llcx, llmod) = create_context_and_module(&tcx.sess,
+                                                          &llmod_id[..]);
+
+            let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
+                let dctx = debuginfo::CrateDebugContext::new(llmod);
+                debuginfo::metadata::compile_unit_metadata(tcx,
+                                                           codegen_unit.name(),
+                                                           &dctx);
+                Some(dctx)
+            } else {
+                None
+            };
+
+            let mut cx = CodegenCx {
+                tcx,
+                check_overflow,
+                use_dll_storage_attrs,
+                tls_model,
+                llmod,
+                llcx,
+                stats: RefCell::new(Stats::default()),
+                codegen_unit,
+                instances: RefCell::new(FxHashMap()),
+                vtables: RefCell::new(FxHashMap()),
+                const_cstr_cache: RefCell::new(FxHashMap()),
+                const_unsized: RefCell::new(FxHashMap()),
+                const_globals: RefCell::new(FxHashMap()),
+                statics: RefCell::new(FxHashMap()),
+                statics_to_rauw: RefCell::new(Vec::new()),
+                used_statics: RefCell::new(Vec::new()),
+                lltypes: RefCell::new(FxHashMap()),
+                scalar_lltypes: RefCell::new(FxHashMap()),
+                pointee_infos: RefCell::new(FxHashMap()),
+                isize_ty: Type::from_ref(ptr::null_mut()),
+                dbg_cx,
+                eh_personality: Cell::new(None),
+                eh_unwind_resume: Cell::new(None),
+                rust_try_fn: Cell::new(None),
+                intrinsics: RefCell::new(FxHashMap()),
+                local_gen_sym_counter: Cell::new(0),
+            };
+            cx.isize_ty = Type::isize(&cx);
+            cx
         }
     }
 
+    pub fn into_stats(self) -> Stats {
+        self.stats.into_inner()
+    }
+}
+
+impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
+    pub fn sess<'a>(&'a self) -> &'a Session {
+        &self.tcx.sess
+    }
+
+    pub fn get_intrinsic(&self, key: &str) -> ValueRef {
+        if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
+            return v;
+        }
+        match declare_intrinsic(self, key) {
+            Some(v) => return v,
+            None => bug!("unknown intrinsic '{}'", key)
+        }
+    }
+
+    /// Generate a new symbol name with the given prefix. This symbol name must
+    /// only be used for definitions with `internal` or `private` linkage.
+    pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
+        let idx = self.local_gen_sym_counter.get();
+        self.local_gen_sym_counter.set(idx + 1);
+        // Include a '.' character, so there can be no accidental conflicts with
+        // user defined names
+        let mut name = String::with_capacity(prefix.len() + 6);
+        name.push_str(prefix);
+        name.push_str(".");
+        base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name);
+        name
+    }
+
+    pub fn eh_personality(&self) -> ValueRef {
+        // The exception handling personality function.
+        //
+        // If our compilation unit has the `eh_personality` lang item somewhere
+        // within it, then we just need to translate that. Otherwise, we're
+        // building an rlib which will depend on some upstream implementation of
+        // this function, so we just codegen a generic reference to it. We don't
+        // specify any of the types for the function, we just make it a symbol
+        // that LLVM can later use.
+        //
+        // Note that MSVC is a little special here in that we don't use the
+        // `eh_personality` lang item at all. Currently LLVM has support for
+        // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
+        // *name of the personality function* to decide what kind of unwind side
+        // tables/landing pads to emit. It looks like Dwarf is used by default,
+        // injecting a dependency on the `_Unwind_Resume` symbol for resuming
+        // an "exception", but for MSVC we want to force SEH. This means that we
+        // can't actually have the personality function be our standard
+        // `rust_eh_personality` function, but rather we wired it up to the
+        // CRT's custom personality function, which forces LLVM to consider
+        // landing pads as "landing pads for SEH".
+        if let Some(llpersonality) = self.eh_personality.get() {
+            return llpersonality
+        }
+        let tcx = self.tcx;
+        let llfn = match tcx.lang_items().eh_personality() {
+            Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
+                callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
+            }
+            _ => {
+                let name = if base::wants_msvc_seh(self.sess()) {
+                    "__CxxFrameHandler3"
+                } else {
+                    "rust_eh_personality"
+                };
+                let fty = Type::variadic_func(&[], &Type::i32(self));
+                declare::declare_cfn(self, name, fty)
+            }
+        };
+        self.eh_personality.set(Some(llfn));
+        llfn
+    }
+
+    // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
+    // otherwise declares it as an external function.
+    pub fn eh_unwind_resume(&self) -> ValueRef {
+        use attributes;
+        let unwresume = &self.eh_unwind_resume;
+        if let Some(llfn) = unwresume.get() {
+            return llfn;
+        }
+
+        let tcx = self.tcx;
+        assert!(self.sess().target.target.options.custom_unwind_resume);
+        if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
+            let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
+            unwresume.set(Some(llfn));
+            return llfn;
+        }
+
+        let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+            iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
+            tcx.types.never,
+            false,
+            hir::Unsafety::Unsafe,
+            Abi::C
+        )));
+
+        let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty);
+        attributes::unwind(llfn, true);
+        unwresume.set(Some(llfn));
+        llfn
+    }
+
     pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
         common::type_needs_drop(self.tcx, ty)
     }
@@ -336,346 +446,21 @@
             _ => bug!("unexpected unsized tail: {:?}", tail.sty),
         }
     }
-
-    pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
-        self.tcx
-    }
-
-    pub fn sess<'a>(&'a self) -> &'a Session {
-        &self.tcx.sess
-    }
-
-    pub fn dep_graph<'a>(&'a self) -> &'a DepGraph {
-        &self.tcx.dep_graph
-    }
-
-    pub fn use_dll_storage_attrs(&self) -> bool {
-        self.use_dll_storage_attrs
-    }
 }
 
-impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
-    pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
-               codegen_unit: Arc<CodegenUnit<'tcx>>,
-               llmod_id: &str)
-               -> LocalCrateContext<'a, 'tcx> {
-        unsafe {
-            let (llcx, llmod) = create_context_and_module(&shared.tcx.sess,
-                                                          &llmod_id[..]);
-
-            let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
-                let dctx = debuginfo::CrateDebugContext::new(llmod);
-                debuginfo::metadata::compile_unit_metadata(shared,
-                                                           codegen_unit.name(),
-                                                           &dctx,
-                                                           shared.tcx.sess);
-                Some(dctx)
-            } else {
-                None
-            };
-
-            let local_ccx = LocalCrateContext {
-                llmod,
-                llcx,
-                stats: RefCell::new(Stats::default()),
-                codegen_unit,
-                instances: RefCell::new(FxHashMap()),
-                vtables: RefCell::new(FxHashMap()),
-                const_cstr_cache: RefCell::new(FxHashMap()),
-                const_unsized: RefCell::new(FxHashMap()),
-                const_globals: RefCell::new(FxHashMap()),
-                statics: RefCell::new(FxHashMap()),
-                statics_to_rauw: RefCell::new(Vec::new()),
-                used_statics: RefCell::new(Vec::new()),
-                lltypes: RefCell::new(FxHashMap()),
-                scalar_lltypes: RefCell::new(FxHashMap()),
-                pointee_infos: RefCell::new(FxHashMap()),
-                isize_ty: Type::from_ref(ptr::null_mut()),
-                dbg_cx,
-                eh_personality: Cell::new(None),
-                eh_unwind_resume: Cell::new(None),
-                rust_try_fn: Cell::new(None),
-                intrinsics: RefCell::new(FxHashMap()),
-                local_gen_sym_counter: Cell::new(0),
-                placeholder: PhantomData,
-            };
-
-            let (isize_ty, mut local_ccx) = {
-                // Do a little dance to create a dummy CrateContext, so we can
-                // create some things in the LLVM module of this codegen unit
-                let mut local_ccxs = vec![local_ccx];
-                let isize_ty = {
-                    let dummy_ccx = LocalCrateContext::dummy_ccx(shared,
-                                                                 local_ccxs.as_mut_slice());
-                    Type::isize(&dummy_ccx)
-                };
-                (isize_ty, local_ccxs.pop().unwrap())
-            };
-
-            local_ccx.isize_ty = isize_ty;
-
-            local_ccx
-        }
-    }
-
-    /// Create a dummy `CrateContext` from `self` and  the provided
-    /// `SharedCrateContext`.  This is somewhat dangerous because `self` may
-    /// not be fully initialized.
-    ///
-    /// This is used in the `LocalCrateContext` constructor to allow calling
-    /// functions that expect a complete `CrateContext`, even before the local
-    /// portion is fully initialized and attached to the `SharedCrateContext`.
-    fn dummy_ccx(shared: &'a SharedCrateContext<'a, 'tcx>,
-                 local_ccxs: &'a [LocalCrateContext<'a, 'tcx>])
-                 -> CrateContext<'a, 'tcx> {
-        assert!(local_ccxs.len() == 1);
-        CrateContext {
-            shared,
-            local_ccx: &local_ccxs[0]
-        }
-    }
-
-    pub fn into_stats(self) -> Stats {
-        self.stats.into_inner()
-    }
-}
-
-impl<'b, 'tcx> CrateContext<'b, 'tcx> {
-    pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> {
-        self.shared
-    }
-
-    fn local(&self) -> &'b LocalCrateContext<'b, 'tcx> {
-        self.local_ccx
-    }
-
-    pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
-        self.shared.tcx
-    }
-
-    pub fn sess<'a>(&'a self) -> &'a Session {
-        &self.shared.tcx.sess
-    }
-
-    pub fn get_intrinsic(&self, key: &str) -> ValueRef {
-        if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
-            return v;
-        }
-        match declare_intrinsic(self, key) {
-            Some(v) => return v,
-            None => bug!("unknown intrinsic '{}'", key)
-        }
-    }
-
-    pub fn llmod(&self) -> ModuleRef {
-        self.local().llmod
-    }
-
-    pub fn llcx(&self) -> ContextRef {
-        self.local().llcx
-    }
-
-    pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
-        &self.local().codegen_unit
-    }
-
-    pub fn td(&self) -> llvm::TargetDataRef {
-        unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
-    }
-
-    pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
-        &self.local().instances
-    }
-
-    pub fn vtables<'a>(&'a self)
-        -> &'a RefCell<FxHashMap<(Ty<'tcx>,
-                                  Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> {
-        &self.local().vtables
-    }
-
-    pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<FxHashMap<InternedString, ValueRef>> {
-        &self.local().const_cstr_cache
-    }
-
-    pub fn const_unsized<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
-        &self.local().const_unsized
-    }
-
-    pub fn const_globals<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
-        &self.local().const_globals
-    }
-
-    pub fn statics<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, DefId>> {
-        &self.local().statics
-    }
-
-    pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell<Vec<(ValueRef, ValueRef)>> {
-        &self.local().statics_to_rauw
-    }
-
-    pub fn used_statics<'a>(&'a self) -> &'a RefCell<Vec<ValueRef>> {
-        &self.local().used_statics
-    }
-
-    pub fn lltypes<'a>(&'a self) -> &'a RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>> {
-        &self.local().lltypes
-    }
-
-    pub fn scalar_lltypes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, Type>> {
-        &self.local().scalar_lltypes
-    }
-
-    pub fn pointee_infos<'a>(&'a self)
-                             -> &'a RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>> {
-        &self.local().pointee_infos
-    }
-
-    pub fn stats<'a>(&'a self) -> &'a RefCell<Stats> {
-        &self.local().stats
-    }
-
-    pub fn isize_ty(&self) -> Type {
-        self.local().isize_ty
-    }
-
-    pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> {
-        &self.local().dbg_cx
-    }
-
-    pub fn rust_try_fn<'a>(&'a self) -> &'a Cell<Option<ValueRef>> {
-        &self.local().rust_try_fn
-    }
-
-    fn intrinsics<'a>(&'a self) -> &'a RefCell<FxHashMap<&'static str, ValueRef>> {
-        &self.local().intrinsics
-    }
-
-    pub fn check_overflow(&self) -> bool {
-        self.shared.check_overflow
-    }
-
-    pub fn use_dll_storage_attrs(&self) -> bool {
-        self.shared.use_dll_storage_attrs()
-    }
-
-    pub fn tls_model(&self) -> llvm::ThreadLocalMode {
-        self.shared.tls_model
-    }
-
-    /// Generate a new symbol name with the given prefix. This symbol name must
-    /// only be used for definitions with `internal` or `private` linkage.
-    pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
-        let idx = self.local().local_gen_sym_counter.get();
-        self.local().local_gen_sym_counter.set(idx + 1);
-        // Include a '.' character, so there can be no accidental conflicts with
-        // user defined names
-        let mut name = String::with_capacity(prefix.len() + 6);
-        name.push_str(prefix);
-        name.push_str(".");
-        base_n::push_str(idx as u64, base_n::ALPHANUMERIC_ONLY, &mut name);
-        name
-    }
-
-    pub fn eh_personality(&self) -> ValueRef {
-        // The exception handling personality function.
-        //
-        // If our compilation unit has the `eh_personality` lang item somewhere
-        // within it, then we just need to translate that. Otherwise, we're
-        // building an rlib which will depend on some upstream implementation of
-        // this function, so we just codegen a generic reference to it. We don't
-        // specify any of the types for the function, we just make it a symbol
-        // that LLVM can later use.
-        //
-        // Note that MSVC is a little special here in that we don't use the
-        // `eh_personality` lang item at all. Currently LLVM has support for
-        // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
-        // *name of the personality function* to decide what kind of unwind side
-        // tables/landing pads to emit. It looks like Dwarf is used by default,
-        // injecting a dependency on the `_Unwind_Resume` symbol for resuming
-        // an "exception", but for MSVC we want to force SEH. This means that we
-        // can't actually have the personality function be our standard
-        // `rust_eh_personality` function, but rather we wired it up to the
-        // CRT's custom personality function, which forces LLVM to consider
-        // landing pads as "landing pads for SEH".
-        if let Some(llpersonality) = self.local().eh_personality.get() {
-            return llpersonality
-        }
-        let tcx = self.tcx();
-        let llfn = match tcx.lang_items().eh_personality() {
-            Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
-                callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
-            }
-            _ => {
-                let name = if base::wants_msvc_seh(self.sess()) {
-                    "__CxxFrameHandler3"
-                } else {
-                    "rust_eh_personality"
-                };
-                let fty = Type::variadic_func(&[], &Type::i32(self));
-                declare::declare_cfn(self, name, fty)
-            }
-        };
-        self.local().eh_personality.set(Some(llfn));
-        llfn
-    }
-
-    // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
-    // otherwise declares it as an external function.
-    pub fn eh_unwind_resume(&self) -> ValueRef {
-        use attributes;
-        let unwresume = &self.local().eh_unwind_resume;
-        if let Some(llfn) = unwresume.get() {
-            return llfn;
-        }
-
-        let tcx = self.tcx();
-        assert!(self.sess().target.target.options.custom_unwind_resume);
-        if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
-            let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
-            unwresume.set(Some(llfn));
-            return llfn;
-        }
-
-        let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
-            iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
-            tcx.types.never,
-            false,
-            hir::Unsafety::Unsafe,
-            Abi::C
-        )));
-
-        let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty);
-        attributes::unwind(llfn, true);
-        unwresume.set(Some(llfn));
-        llfn
-    }
-}
-
-impl<'a, 'tcx> ty::layout::HasDataLayout for &'a SharedCrateContext<'a, 'tcx> {
+impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CodegenCx<'a, 'tcx> {
     fn data_layout(&self) -> &ty::layout::TargetDataLayout {
         &self.tcx.data_layout
     }
 }
 
-impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
+impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'a, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.tcx
     }
 }
 
-impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CrateContext<'a, 'tcx> {
-    fn data_layout(&self) -> &ty::layout::TargetDataLayout {
-        &self.shared.tcx.data_layout
-    }
-}
-
-impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CrateContext<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
-        self.shared.tcx
-    }
-}
-
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a SharedCrateContext<'a, 'tcx> {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a CodegenCx<'a, 'tcx> {
     type TyLayout = TyLayout<'tcx>;
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
@@ -688,57 +473,48 @@
     }
 }
 
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a CrateContext<'a, 'tcx> {
-    type TyLayout = TyLayout<'tcx>;
-
-
-    fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
-        self.shared.layout_of(ty)
-    }
-}
-
 /// Declare any llvm intrinsics that you might need
-fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
+fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
     macro_rules! ifn {
         ($name:expr, fn() -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::func(&[], &$ret));
                 llvm::SetUnnamedAddr(f, false);
-                ccx.intrinsics().borrow_mut().insert($name, f.clone());
+                cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
         );
         ($name:expr, fn(...) -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(ccx, $name, Type::variadic_func(&[], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], &$ret));
                 llvm::SetUnnamedAddr(f, false);
-                ccx.intrinsics().borrow_mut().insert($name, f.clone());
+                cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
         );
         ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], &$ret));
                 llvm::SetUnnamedAddr(f, false);
-                ccx.intrinsics().borrow_mut().insert($name, f.clone());
+                cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
         );
     }
     macro_rules! mk_struct {
-        ($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false))
+        ($($field_ty:expr),*) => (Type::struct_(cx, &[$($field_ty),*], false))
     }
 
-    let i8p = Type::i8p(ccx);
-    let void = Type::void(ccx);
-    let i1 = Type::i1(ccx);
-    let t_i8 = Type::i8(ccx);
-    let t_i16 = Type::i16(ccx);
-    let t_i32 = Type::i32(ccx);
-    let t_i64 = Type::i64(ccx);
-    let t_i128 = Type::i128(ccx);
-    let t_f32 = Type::f32(ccx);
-    let t_f64 = Type::f64(ccx);
+    let i8p = Type::i8p(cx);
+    let void = Type::void(cx);
+    let i1 = Type::i1(cx);
+    let t_i8 = Type::i8(cx);
+    let t_i16 = Type::i16(cx);
+    let t_i32 = Type::i32(cx);
+    let t_i64 = Type::i64(cx);
+    let t_i128 = Type::i128(cx);
+    let t_f32 = Type::f32(cx);
+    let t_f64 = Type::f64(cx);
 
     ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
     ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
@@ -870,9 +646,9 @@
     ifn!("llvm.assume", fn(i1) -> void);
     ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
 
-    if ccx.sess().opts.debuginfo != NoDebugInfo {
-        ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
-        ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void);
+    if cx.sess().opts.debuginfo != NoDebugInfo {
+        ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void);
+        ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void);
     }
     return None;
 }
diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs
index 95f13ea..bddb3d9 100644
--- a/src/librustc_trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/debuginfo/create_scope_map.rs
@@ -14,7 +14,7 @@
 
 use llvm;
 use llvm::debuginfo::DIScope;
-use common::CrateContext;
+use common::CodegenCx;
 use rustc::mir::{Mir, VisibilityScope};
 
 use libc::c_uint;
@@ -44,7 +44,7 @@
 
 /// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
 /// If debuginfo is disabled, the returned vector is empty.
-pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &FunctionDebugContext)
+pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebugContext)
     -> IndexVec<VisibilityScope, MirDebugScope> {
     let null_scope = MirDebugScope {
         scope_metadata: ptr::null_mut(),
@@ -71,13 +71,13 @@
     // Instantiate all scopes.
     for idx in 0..mir.visibility_scopes.len() {
         let scope = VisibilityScope::new(idx);
-        make_mir_scope(ccx, &mir, &has_variables, debug_context, scope, &mut scopes);
+        make_mir_scope(cx, &mir, &has_variables, debug_context, scope, &mut scopes);
     }
 
     scopes
 }
 
-fn make_mir_scope(ccx: &CrateContext,
+fn make_mir_scope(cx: &CodegenCx,
                   mir: &Mir,
                   has_variables: &BitVector,
                   debug_context: &FunctionDebugContextData,
@@ -89,11 +89,11 @@
 
     let scope_data = &mir.visibility_scopes[scope];
     let parent_scope = if let Some(parent) = scope_data.parent_scope {
-        make_mir_scope(ccx, mir, has_variables, debug_context, parent, scopes);
+        make_mir_scope(cx, mir, has_variables, debug_context, parent, scopes);
         scopes[parent]
     } else {
         // The root is the function itself.
-        let loc = span_start(ccx, mir.span);
+        let loc = span_start(cx, mir.span);
         scopes[scope] = MirDebugScope {
             scope_metadata: debug_context.fn_metadata,
             file_start_pos: loc.file.start_pos,
@@ -115,14 +115,14 @@
         }
     }
 
-    let loc = span_start(ccx, scope_data.span);
-    let file_metadata = file_metadata(ccx,
+    let loc = span_start(cx, scope_data.span);
+    let file_metadata = file_metadata(cx,
                                       &loc.file.name,
                                       debug_context.defining_crate);
 
     let scope_metadata = unsafe {
         llvm::LLVMRustDIBuilderCreateLexicalBlock(
-            DIB(ccx),
+            DIB(cx),
             parent_scope.scope_metadata,
             file_metadata,
             loc.line as c_uint,
diff --git a/src/librustc_trans/debuginfo/doc.rs b/src/librustc_trans/debuginfo/doc.rs
index 93dca03..cbecc0e 100644
--- a/src/librustc_trans/debuginfo/doc.rs
+++ b/src/librustc_trans/debuginfo/doc.rs
@@ -32,7 +32,7 @@
 //! The public API of the module is a set of functions that will insert the
 //! correct metadata into the LLVM IR when called with the right parameters.
 //! The module is thus driven from an outside client with functions like
-//! `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
+//! `debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`.
 //!
 //! Internally the module will try to reuse already created metadata by
 //! utilizing a cache. The way to get a shared metadata node when needed is
@@ -44,8 +44,8 @@
 //! that exact file path.
 //!
 //! All private state used by the module is stored within either the
-//! CrateDebugContext struct (owned by the CrateContext) or the
-//! FunctionDebugContext (owned by the MirContext).
+//! CrateDebugContext struct (owned by the CodegenCx) or the
+//! FunctionDebugContext (owned by the FunctionCx).
 //!
 //! This file consists of three conceptual sections:
 //! 1. The public interface of the module
diff --git a/src/librustc_trans/debuginfo/gdb.rs b/src/librustc_trans/debuginfo/gdb.rs
index 14d3fa4..03e7c63 100644
--- a/src/librustc_trans/debuginfo/gdb.rs
+++ b/src/librustc_trans/debuginfo/gdb.rs
@@ -12,7 +12,7 @@
 
 use llvm;
 
-use common::{C_bytes, CrateContext, C_i32};
+use common::{C_bytes, CodegenCx, C_i32};
 use builder::Builder;
 use declare;
 use type_::Type;
@@ -24,14 +24,14 @@
 
 /// Inserts a side-effect free instruction sequence that makes sure that the
 /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
-pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext, builder: &Builder) {
-    if needs_gdb_debug_scripts_section(ccx) {
-        let gdb_debug_scripts_section_global = get_or_insert_gdb_debug_scripts_section_global(ccx);
+pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &Builder) {
+    if needs_gdb_debug_scripts_section(bx.cx) {
+        let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx.cx);
         // Load just the first byte as that's all that's necessary to force
         // LLVM to keep around the reference to the global.
-        let indices = [C_i32(ccx, 0), C_i32(ccx, 0)];
-        let element = builder.inbounds_gep(gdb_debug_scripts_section_global, &indices);
-        let volative_load_instruction = builder.volatile_load(element);
+        let indices = [C_i32(bx.cx, 0), C_i32(bx.cx, 0)];
+        let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
+        let volative_load_instruction = bx.volatile_load(element);
         unsafe {
             llvm::LLVMSetAlignment(volative_load_instruction, 1);
         }
@@ -40,13 +40,13 @@
 
 /// Allocates the global variable responsible for the .debug_gdb_scripts binary
 /// section.
-pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
+pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
                                                   -> llvm::ValueRef {
     let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0";
     let section_var_name = &c_section_var_name[..c_section_var_name.len()-1];
 
     let section_var = unsafe {
-        llvm::LLVMGetNamedGlobal(ccx.llmod(),
+        llvm::LLVMGetNamedGlobal(cx.llmod,
                                  c_section_var_name.as_ptr() as *const _)
     };
 
@@ -55,15 +55,15 @@
         let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
 
         unsafe {
-            let llvm_type = Type::array(&Type::i8(ccx),
+            let llvm_type = Type::array(&Type::i8(cx),
                                         section_contents.len() as u64);
 
-            let section_var = declare::define_global(ccx, section_var_name,
+            let section_var = declare::define_global(cx, section_var_name,
                                                      llvm_type).unwrap_or_else(||{
                 bug!("symbol `{}` is already defined", section_var_name)
             });
             llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
-            llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
+            llvm::LLVMSetInitializer(section_var, C_bytes(cx, section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
             llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
@@ -77,13 +77,13 @@
     }
 }
 
-pub fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool {
+pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool {
     let omit_gdb_pretty_printer_section =
-        attr::contains_name(&ccx.tcx().hir.krate_attrs(),
+        attr::contains_name(&cx.tcx.hir.krate_attrs(),
                             "omit_gdb_pretty_printer_section");
 
     !omit_gdb_pretty_printer_section &&
-    !ccx.sess().target.target.options.is_like_osx &&
-    !ccx.sess().target.target.options.is_like_windows &&
-    ccx.sess().opts.debuginfo != NoDebugInfo
+    !cx.sess().target.target.options.is_like_osx &&
+    !cx.sess().target.target.options.is_like_windows &&
+    cx.sess().opts.debuginfo != NoDebugInfo
 }
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 8e924e3..62ba918 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -18,7 +18,6 @@
 use super::type_names::compute_debuginfo_type_name;
 use super::{CrateDebugContext};
 use abi;
-use context::SharedCrateContext;
 
 use llvm::{self, ValueRef};
 use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
@@ -30,10 +29,10 @@
 use rustc::ty::util::TypeIdHasher;
 use rustc::ich::Fingerprint;
 use rustc::ty::Instance;
-use common::CrateContext;
-use rustc::ty::{self, AdtKind, Ty};
+use common::CodegenCx;
+use rustc::ty::{self, AdtKind, Ty, TyCtxt};
 use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
-use rustc::session::{Session, config};
+use rustc::session::config;
 use rustc::util::nodemap::FxHashMap;
 use rustc::util::common::path2cstr;
 
@@ -134,7 +133,7 @@
     // Get the UniqueTypeId for the given type. If the UniqueTypeId for the given
     // type has been requested before, this is just a table lookup. Otherwise an
     // ID will be generated and stored for later lookup.
-    fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
+    fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>,
                                       type_: Ty<'tcx>) -> UniqueTypeId {
         // Let's see if we already have something in the cache
         match self.type_to_unique_id.get(&type_).cloned() {
@@ -144,7 +143,7 @@
 
         // The hasher we are using to generate the UniqueTypeId. We want
         // something that provides more than the 64 bits of the DefaultHasher.
-        let mut type_id_hasher = TypeIdHasher::<Fingerprint>::new(cx.tcx());
+        let mut type_id_hasher = TypeIdHasher::<Fingerprint>::new(cx.tcx);
         type_id_hasher.visit_ty(type_);
         let unique_type_id = type_id_hasher.finish().to_hex();
 
@@ -158,7 +157,7 @@
     // types of their own, so they need special handling. We still need a
     // UniqueTypeId for them, since to debuginfo they *are* real types.
     fn get_unique_type_id_of_enum_variant<'a>(&mut self,
-                                              cx: &CrateContext<'a, 'tcx>,
+                                              cx: &CodegenCx<'a, 'tcx>,
                                               enum_type: Ty<'tcx>,
                                               variant_name: &str)
                                               -> UniqueTypeId {
@@ -187,7 +186,7 @@
 }
 
 fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
-    cx: &CrateContext<'a, 'tcx>,
+    cx: &CodegenCx<'a, 'tcx>,
     unfinished_type: Ty<'tcx>,
     unique_type_id: UniqueTypeId,
     metadata_stub: DICompositeType,
@@ -211,7 +210,7 @@
     // Finishes up the description of the type in question (mostly by providing
     // descriptions of the fields of the given type) and returns the final type
     // metadata.
-    fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult {
+    fn finalize<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> MetadataCreationResult {
         match *self {
             FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
             UnfinishedMetadata {
@@ -263,7 +262,7 @@
     )
 }
 
-fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 unique_type_id: UniqueTypeId,
                                 array_or_slice_type: Ty<'tcx>,
                                 element_type: Ty<'tcx>,
@@ -299,13 +298,13 @@
     return MetadataCreationResult::new(metadata, false);
 }
 
-fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 slice_ptr_type: Ty<'tcx>,
                                 element_type: Ty<'tcx>,
                                 unique_type_id: UniqueTypeId,
                                 span: Span)
                                 -> MetadataCreationResult {
-    let data_ptr_type = cx.tcx().mk_imm_ptr(element_type);
+    let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
 
     let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
 
@@ -314,7 +313,7 @@
     let slice_type_name = compute_debuginfo_type_name(cx, slice_ptr_type, true);
 
     let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type);
-    let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx().types.usize);
+    let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize);
 
     let member_descriptions = [
         MemberDescription {
@@ -327,7 +326,7 @@
         },
         MemberDescription {
             name: "length".to_string(),
-            type_metadata: type_metadata(cx, cx.tcx().types.usize, span),
+            type_metadata: type_metadata(cx, cx.tcx.types.usize, span),
             offset: pointer_size,
             size: usize_size,
             align: usize_align,
@@ -348,13 +347,13 @@
     MetadataCreationResult::new(metadata, false)
 }
 
-fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                       unique_type_id: UniqueTypeId,
                                       signature: ty::PolyFnSig<'tcx>,
                                       span: Span)
                                       -> MetadataCreationResult
 {
-    let signature = cx.tcx().erase_late_bound_regions_and_normalize(&signature);
+    let signature = cx.tcx.erase_late_bound_regions_and_normalize(&signature);
 
     let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs().len() + 1);
 
@@ -387,7 +386,7 @@
 // trait_type should be the actual trait (e.g., Trait). Where the trait is part
 // of a DST struct, there is no trait_object_type and the results of this
 // function will be a little bit weird.
-fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                     trait_type: Ty<'tcx>,
                                     trait_object_type: Option<Ty<'tcx>>,
                                     unique_type_id: UniqueTypeId)
@@ -416,7 +415,7 @@
 
     let file_metadata = unknown_file_metadata(cx);
 
-    let layout = cx.layout_of(cx.tcx().mk_mut_ptr(trait_type));
+    let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type));
 
     assert_eq!(abi::FAT_PTR_ADDR, 0);
     assert_eq!(abi::FAT_PTR_EXTRA, 1);
@@ -427,7 +426,7 @@
         MemberDescription {
             name: "pointer".to_string(),
             type_metadata: type_metadata(cx,
-                cx.tcx().mk_mut_ptr(cx.tcx().types.u8),
+                cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
                 syntax_pos::DUMMY_SP),
             offset: layout.fields.offset(0),
             size: data_ptr_field.size,
@@ -454,7 +453,7 @@
                             syntax_pos::DUMMY_SP)
 }
 
-pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                t: Ty<'tcx>,
                                usage_site_span: Span)
                                -> DIType {
@@ -499,7 +498,7 @@
                 Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span))
             }
             ty::TyStr => {
-                Ok(vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span))
+                Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span))
             }
             ty::TyDynamic(..) => {
                 Ok(MetadataCreationResult::new(
@@ -539,7 +538,7 @@
             fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span)
         }
         ty::TyStr => {
-            fixed_vec_metadata(cx, unique_type_id, t, cx.tcx().types.i8, usage_site_span)
+            fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span)
         }
         ty::TyDynamic(..) => {
             MetadataCreationResult::new(
@@ -567,7 +566,7 @@
         ty::TyFnDef(..) | ty::TyFnPtr(_) => {
             let fn_metadata = subroutine_type_metadata(cx,
                                                        unique_type_id,
-                                                       t.fn_sig(cx.tcx()),
+                                                       t.fn_sig(cx.tcx),
                                                        usage_site_span).metadata;
             match debug_context(cx).type_map
                                    .borrow()
@@ -581,7 +580,7 @@
 
         }
         ty::TyClosure(def_id, substs) => {
-            let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx()).collect();
+            let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect();
             prepare_tuple_metadata(cx,
                                    t,
                                    &upvar_tys,
@@ -589,8 +588,8 @@
                                    usage_site_span).finalize(cx)
         }
         ty::TyGenerator(def_id, substs, _) => {
-            let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx()).map(|t| {
-                cx.tcx().fully_normalize_associated_types_in(&t)
+            let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| {
+                cx.tcx.fully_normalize_associated_types_in(&t)
             }).collect();
             prepare_tuple_metadata(cx,
                                    t,
@@ -674,7 +673,7 @@
     metadata
 }
 
-pub fn file_metadata(cx: &CrateContext,
+pub fn file_metadata(cx: &CodegenCx,
                      file_name: &FileName,
                      defining_crate: CrateNum) -> DIFile {
     debug!("file_metadata: file_name: {}, defining_crate: {}",
@@ -692,11 +691,11 @@
     file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy())
 }
 
-pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile {
+pub fn unknown_file_metadata(cx: &CodegenCx) -> DIFile {
     file_metadata_raw(cx, "<unknown>", "")
 }
 
-fn file_metadata_raw(cx: &CrateContext,
+fn file_metadata_raw(cx: &CodegenCx,
                      file_name: &str,
                      directory: &str)
                      -> DIFile {
@@ -722,7 +721,7 @@
     file_metadata
 }
 
-fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                  t: Ty<'tcx>) -> DIType {
 
     debug!("basic_type_metadata: {:?}", t);
@@ -759,7 +758,7 @@
     return ty_metadata;
 }
 
-fn foreign_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn foreign_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                    t: Ty<'tcx>,
                                    unique_type_id: UniqueTypeId) -> DIType {
     debug!("foreign_type_metadata: {:?}", t);
@@ -768,7 +767,7 @@
     create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA)
 }
 
-fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                    pointer_type: Ty<'tcx>,
                                    pointee_type_metadata: DIType)
                                    -> DIType {
@@ -785,21 +784,20 @@
     }
 }
 
-pub fn compile_unit_metadata(scc: &SharedCrateContext,
+pub fn compile_unit_metadata(tcx: TyCtxt,
                              codegen_unit_name: &str,
-                             debug_context: &CrateDebugContext,
-                             sess: &Session)
+                             debug_context: &CrateDebugContext)
                              -> DIDescriptor {
-    let mut name_in_debuginfo = match sess.local_crate_source_file {
+    let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
         Some(ref path) => path.clone(),
-        None => PathBuf::from(&*scc.tcx().crate_name(LOCAL_CRATE).as_str()),
+        None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
     };
 
     // The OSX linker has an idiosyncrasy where it will ignore some debuginfo
     // if multiple object files with the same DW_AT_name are linked together.
     // As a workaround we generate unique names for each object file. Those do
     // not correspond to an actual source file but that should be harmless.
-    if scc.sess().target.target.options.is_like_osx {
+    if tcx.sess.target.target.options.is_like_osx {
         name_in_debuginfo.push("@");
         name_in_debuginfo.push(codegen_unit_name);
     }
@@ -811,7 +809,7 @@
 
     let name_in_debuginfo = name_in_debuginfo.to_string_lossy().into_owned();
     let name_in_debuginfo = CString::new(name_in_debuginfo).unwrap();
-    let work_dir = CString::new(&sess.working_dir.0.to_string_lossy()[..]).unwrap();
+    let work_dir = CString::new(&tcx.sess.working_dir.0.to_string_lossy()[..]).unwrap();
     let producer = CString::new(producer).unwrap();
     let flags = "\0";
     let split_name = "\0";
@@ -825,20 +823,20 @@
             DW_LANG_RUST,
             file_metadata,
             producer.as_ptr(),
-            sess.opts.optimize != config::OptLevel::No,
+            tcx.sess.opts.optimize != config::OptLevel::No,
             flags.as_ptr() as *const _,
             0,
             split_name.as_ptr() as *const _);
 
-        if sess.opts.debugging_opts.profile {
+        if tcx.sess.opts.debugging_opts.profile {
             let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext,
                                                                  unit_metadata);
 
             let gcov_cu_info = [
                 path_to_mdstring(debug_context.llcontext,
-                                 &scc.tcx().output_filenames(LOCAL_CRATE).with_extension("gcno")),
+                                 &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno")),
                 path_to_mdstring(debug_context.llcontext,
-                                 &scc.tcx().output_filenames(LOCAL_CRATE).with_extension("gcda")),
+                                 &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda")),
                 cu_desc_metadata,
             ];
             let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext,
@@ -903,7 +901,7 @@
 }
 
 impl<'tcx> MemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
         match *self {
             StructMDF(ref this) => {
@@ -937,7 +935,7 @@
 }
 
 impl<'tcx> StructMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
         let layout = cx.layout_of(self.ty);
         self.variant.fields.iter().enumerate().map(|(i, f)| {
@@ -961,7 +959,7 @@
 }
 
 
-fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                      struct_type: Ty<'tcx>,
                                      unique_type_id: UniqueTypeId,
                                      span: Span)
@@ -969,7 +967,7 @@
     let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
 
     let (struct_def_id, variant) = match struct_type.sty {
-        ty::TyAdt(def, _) => (def.did, def.struct_variant()),
+        ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
         _ => bug!("prepare_struct_metadata on a non-ADT")
     };
 
@@ -1006,7 +1004,7 @@
 }
 
 impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
         let layout = cx.layout_of(self.ty);
         self.component_types.iter().enumerate().map(|(i, &component_type)| {
@@ -1023,7 +1021,7 @@
     }
 }
 
-fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_tuple_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                     tuple_type: Ty<'tcx>,
                                     component_types: &[Ty<'tcx>],
                                     unique_type_id: UniqueTypeId,
@@ -1059,7 +1057,7 @@
 }
 
 impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
         self.variant.fields.iter().enumerate().map(|(i, f)| {
             let field = self.layout.field(cx, i);
@@ -1076,7 +1074,7 @@
     }
 }
 
-fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                     union_type: Ty<'tcx>,
                                     unique_type_id: UniqueTypeId,
                                     span: Span)
@@ -1084,7 +1082,7 @@
     let union_name = compute_debuginfo_type_name(cx, union_type, false);
 
     let (union_def_id, variant) = match union_type.sty {
-        ty::TyAdt(def, _) => (def.did, def.struct_variant()),
+        ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
         _ => bug!("prepare_union_metadata on a non-ADT")
     };
 
@@ -1127,7 +1125,7 @@
 }
 
 impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
         let adt = &self.enum_type.ty_adt_def().unwrap();
         match self.layout.variants {
@@ -1212,7 +1210,7 @@
                 // of discriminant instead of us having to recover its path.
                 // Right now it's not even going to work for `niche_start > 0`,
                 // and for multiple niche variants it only supports the first.
-                fn compute_field_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                                 name: &mut String,
                                                 layout: TyLayout<'tcx>,
                                                 offset: Size,
@@ -1223,10 +1221,10 @@
                             continue;
                         }
                         let inner_offset = offset - field_offset;
-                        let field = layout.field(ccx, i);
+                        let field = layout.field(cx, i);
                         if inner_offset + size <= field.size {
                             write!(name, "{}$", i).unwrap();
-                            compute_field_path(ccx, name, field, inner_offset, size);
+                            compute_field_path(cx, name, field, inner_offset, size);
                         }
                     }
                 }
@@ -1262,7 +1260,7 @@
 }
 
 impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
         self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
             let (size, align) = cx.size_and_align_of(ty);
@@ -1292,7 +1290,7 @@
 // of the variant, and (3) a MemberDescriptionFactory for producing the
 // descriptions of the fields of the variant. This is a rudimentary version of a
 // full RecursiveTypeDescription.
-fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                    layout: layout::TyLayout<'tcx>,
                                    variant: &'tcx ty::VariantDef,
                                    discriminant_info: EnumDiscriminantInfo,
@@ -1352,7 +1350,7 @@
     (metadata_stub, member_description_factory)
 }
 
-fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                    enum_type: Ty<'tcx>,
                                    enum_def_id: DefId,
                                    unique_type_id: UniqueTypeId,
@@ -1370,7 +1368,7 @@
     let file_metadata = unknown_file_metadata(cx);
 
     let def = enum_type.ty_adt_def().unwrap();
-    let enumerators_metadata: Vec<DIDescriptor> = def.discriminants(cx.tcx())
+    let enumerators_metadata: Vec<DIDescriptor> = def.discriminants(cx.tcx)
         .zip(&def.variants)
         .map(|(discr, v)| {
             let token = v.name.as_str();
@@ -1396,7 +1394,7 @@
                 let (discriminant_size, discriminant_align) =
                     (discr.size(cx), discr.align(cx));
                 let discriminant_base_type_metadata =
-                    type_metadata(cx, discr.to_ty(cx.tcx()), syntax_pos::DUMMY_SP);
+                    type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
                 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
 
                 let name = CString::new(discriminant_name.as_bytes()).unwrap();
@@ -1472,10 +1470,10 @@
         }),
     );
 
-    fn get_enum_discriminant_name(cx: &CrateContext,
+    fn get_enum_discriminant_name(cx: &CodegenCx,
                                   def_id: DefId)
                                   -> InternedString {
-        cx.tcx().item_name(def_id)
+        cx.tcx.item_name(def_id)
     }
 }
 
@@ -1483,7 +1481,7 @@
 /// results in a LLVM struct.
 ///
 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
-fn composite_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                      composite_type: Ty<'tcx>,
                                      composite_type_name: &str,
                                      composite_type_unique_id: UniqueTypeId,
@@ -1509,7 +1507,7 @@
     return composite_type_metadata;
 }
 
-fn set_members_of_composite_type(cx: &CrateContext,
+fn set_members_of_composite_type(cx: &CodegenCx,
                                  composite_type_metadata: DICompositeType,
                                  member_descriptions: &[MemberDescription]) {
     // In some rare cases LLVM metadata uniquing would lead to an existing type
@@ -1560,7 +1558,7 @@
 // A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do
 // any caching, does not add any fields to the struct. This can be done later
 // with set_members_of_composite_type().
-fn create_struct_stub<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 struct_type: Ty<'tcx>,
                                 struct_type_name: &str,
                                 unique_type_id: UniqueTypeId,
@@ -1597,7 +1595,7 @@
     return metadata_stub;
 }
 
-fn create_union_stub<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                union_type: Ty<'tcx>,
                                union_type_name: &str,
                                unique_type_id: UniqueTypeId,
@@ -1635,20 +1633,20 @@
 /// Creates debug information for the given global variable.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_global_var_metadata(cx: &CrateContext,
+pub fn create_global_var_metadata(cx: &CodegenCx,
                                   node_id: ast::NodeId,
                                   global: ValueRef) {
-    if cx.dbg_cx().is_none() {
+    if cx.dbg_cx.is_none() {
         return;
     }
 
-    let tcx = cx.tcx();
+    let tcx = cx.tcx;
     let node_def_id = tcx.hir.local_def_id(node_id);
     let no_mangle = attr::contains_name(&tcx.get_attrs(node_def_id), "no_mangle");
     // We may want to remove the namespace scope if we're in an extern block, see:
     // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952
     let var_scope = get_namespace_for_item(cx, node_def_id);
-    let span = cx.tcx().def_span(node_def_id);
+    let span = cx.tcx.def_span(node_def_id);
 
     let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP {
         let loc = span_start(cx, span);
@@ -1658,15 +1656,15 @@
     };
 
     let is_local_to_unit = is_node_local_to_unit(cx, node_id);
-    let variable_type = Instance::mono(cx.tcx(), node_def_id).ty(cx.tcx());
+    let variable_type = Instance::mono(cx.tcx, node_def_id).ty(cx.tcx);
     let type_metadata = type_metadata(cx, variable_type, span);
     let var_name = tcx.item_name(node_def_id).to_string();
     let var_name = CString::new(var_name).unwrap();
     let linkage_name = if no_mangle {
         None
     } else {
-        let linkage_name = mangled_name_of_item(cx, node_def_id, "");
-        Some(CString::new(linkage_name).unwrap())
+        let linkage_name = mangled_name_of_item(cx, node_id);
+        Some(CString::new(linkage_name.to_string()).unwrap())
     };
 
     let global_align = cx.align_of(variable_type);
@@ -1691,15 +1689,15 @@
 }
 
 // Creates an "extension" of an existing DIScope into another file.
-pub fn extend_scope_to_file(ccx: &CrateContext,
+pub fn extend_scope_to_file(cx: &CodegenCx,
                             scope_metadata: DIScope,
                             file: &syntax_pos::FileMap,
                             defining_crate: CrateNum)
                             -> DILexicalBlock {
-    let file_metadata = file_metadata(ccx, &file.name, defining_crate);
+    let file_metadata = file_metadata(cx, &file.name, defining_crate);
     unsafe {
         llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
-            DIB(ccx),
+            DIB(cx),
             scope_metadata,
             file_metadata)
     }
@@ -1709,10 +1707,10 @@
 /// given type.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_vtable_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                         ty: ty::Ty<'tcx>,
                                         vtable: ValueRef) {
-    if cx.dbg_cx().is_none() {
+    if cx.dbg_cx.is_none() {
         return;
     }
 
@@ -1736,7 +1734,7 @@
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
             Size::from_bytes(0).bits(),
-            cx.tcx().data_layout.pointer_align.abi_bits() as u32,
+            cx.tcx.data_layout.pointer_align.abi_bits() as u32,
             DIFlags::FlagArtificial,
             ptr::null_mut(),
             empty_array,
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index ae202f3..b46e12d 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -15,7 +15,7 @@
 use self::VariableKind::*;
 
 use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
-use self::namespace::mangled_name_of_item;
+use self::namespace::mangled_name_of_instance;
 use self::type_names::compute_debuginfo_type_name;
 use self::metadata::{type_metadata, file_metadata, TypeMap};
 use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
@@ -27,7 +27,7 @@
 use rustc::ty::subst::Substs;
 
 use abi::Abi;
-use common::CrateContext;
+use common::CodegenCx;
 use builder::Builder;
 use monomorphize::Instance;
 use rustc::ty::{self, Ty};
@@ -150,8 +150,8 @@
 }
 
 /// Create any deferred debug metadata nodes
-pub fn finalize(cx: &CrateContext) {
-    if cx.dbg_cx().is_none() {
+pub fn finalize(cx: &CodegenCx) {
+    if cx.dbg_cx.is_none() {
         return;
     }
 
@@ -176,21 +176,21 @@
         // Android has the same issue (#22398)
         if cx.sess().target.target.options.is_like_osx ||
            cx.sess().target.target.options.is_like_android {
-            llvm::LLVMRustAddModuleFlag(cx.llmod(),
+            llvm::LLVMRustAddModuleFlag(cx.llmod,
                                         "Dwarf Version\0".as_ptr() as *const _,
                                         2)
         }
 
         // Indicate that we want CodeView debug information on MSVC
         if cx.sess().target.target.options.is_like_msvc {
-            llvm::LLVMRustAddModuleFlag(cx.llmod(),
+            llvm::LLVMRustAddModuleFlag(cx.llmod,
                                         "CodeView\0".as_ptr() as *const _,
                                         1)
         }
 
         // Prevent bitcode readers from deleting the debug info.
         let ptr = "Debug Info Version\0".as_ptr();
-        llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
+        llvm::LLVMRustAddModuleFlag(cx.llmod, ptr as *const _,
                                     llvm::LLVMRustDebugMetadataVersion());
     };
 }
@@ -201,7 +201,7 @@
 /// for debug info creation. The function may also return another variant of the
 /// FunctionDebugContext enum which indicates why no debuginfo should be created
 /// for the function.
-pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                                instance: Instance<'tcx>,
                                                sig: ty::FnSig<'tcx>,
                                                llfn: ValueRef,
@@ -210,7 +210,7 @@
         return FunctionDebugContext::DebugInfoDisabled;
     }
 
-    for attr in instance.def.attrs(cx.tcx()).iter() {
+    for attr in instance.def.attrs(cx.tcx).iter() {
         if attr.check_name("no_debug") {
             return FunctionDebugContext::FunctionWithoutDebugInfo;
         }
@@ -235,32 +235,31 @@
     };
 
     // Find the enclosing function, in case this is a closure.
-    let def_key = cx.tcx().def_key(def_id);
+    let def_key = cx.tcx.def_key(def_id);
     let mut name = def_key.disambiguated_data.data.to_string();
-    let name_len = name.len();
 
-    let enclosing_fn_def_id = cx.tcx().closure_base_def_id(def_id);
+    let enclosing_fn_def_id = cx.tcx.closure_base_def_id(def_id);
 
     // Get_template_parameters() will append a `<...>` clause to the function
     // name if necessary.
-    let generics = cx.tcx().generics_of(enclosing_fn_def_id);
-    let substs = instance.substs.truncate_to(cx.tcx(), generics);
+    let generics = cx.tcx.generics_of(enclosing_fn_def_id);
+    let substs = instance.substs.truncate_to(cx.tcx, generics);
     let template_parameters = get_template_parameters(cx,
                                                       &generics,
                                                       substs,
                                                       file_metadata,
                                                       &mut name);
 
-    // Build the linkage_name out of the item path and "template" parameters.
-    let linkage_name = mangled_name_of_item(cx, instance.def_id(), &name[name_len..]);
+    // Get the linkage_name, which is just the symbol name
+    let linkage_name = mangled_name_of_instance(cx, instance);
 
     let scope_line = span_start(cx, span).line;
 
-    let local_id = cx.tcx().hir.as_local_node_id(instance.def_id());
+    let local_id = cx.tcx.hir.as_local_node_id(instance.def_id());
     let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id));
 
     let function_name = CString::new(name).unwrap();
-    let linkage_name = CString::new(linkage_name).unwrap();
+    let linkage_name = CString::new(linkage_name.to_string()).unwrap();
 
     let mut flags = DIFlags::FlagPrototyped;
     match *cx.sess().entry_fn.borrow() {
@@ -300,7 +299,7 @@
 
     return FunctionDebugContext::RegularContext(fn_debug_context);
 
-    fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+    fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                         sig: ty::FnSig<'tcx>) -> DIArray {
         if cx.sess().opts.debuginfo == LimitedDebugInfo {
             return create_DIArray(DIB(cx), &[]);
@@ -335,8 +334,8 @@
             signature.extend(inputs.iter().map(|&t| {
                 let t = match t.sty {
                     ty::TyArray(ct, _)
-                        if (ct == cx.tcx().types.u8) || cx.layout_of(ct).is_zst() => {
-                        cx.tcx().mk_imm_ptr(ct)
+                        if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => {
+                        cx.tcx.mk_imm_ptr(ct)
                     }
                     _ => t
                 };
@@ -359,7 +358,7 @@
         return create_DIArray(DIB(cx), &signature[..]);
     }
 
-    fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+    fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                          generics: &ty::Generics,
                                          substs: &Substs<'tcx>,
                                          file_metadata: DIFile,
@@ -376,7 +375,7 @@
                 name_to_append_suffix_to.push_str(",");
             }
 
-            let actual_type = cx.tcx().fully_normalize_associated_types_in(&actual_type);
+            let actual_type = cx.tcx.fully_normalize_associated_types_in(&actual_type);
             // Add actual type name to <...> clause of function name
             let actual_type_name = compute_debuginfo_type_name(cx,
                                                                actual_type,
@@ -389,7 +388,7 @@
         let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
             let names = get_type_parameter_names(cx, generics);
             substs.types().zip(names).map(|(ty, name)| {
-                let actual_type = cx.tcx().fully_normalize_associated_types_in(&ty);
+                let actual_type = cx.tcx.fully_normalize_associated_types_in(&ty);
                 let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
                 let name = CString::new(name.as_str().as_bytes()).unwrap();
                 unsafe {
@@ -410,24 +409,24 @@
         return create_DIArray(DIB(cx), &template_params[..]);
     }
 
-    fn get_type_parameter_names(cx: &CrateContext, generics: &ty::Generics) -> Vec<ast::Name> {
+    fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<ast::Name> {
         let mut names = generics.parent.map_or(vec![], |def_id| {
-            get_type_parameter_names(cx, cx.tcx().generics_of(def_id))
+            get_type_parameter_names(cx, cx.tcx.generics_of(def_id))
         });
         names.extend(generics.types.iter().map(|param| param.name));
         names
     }
 
-    fn get_containing_scope<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
+    fn get_containing_scope<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
                                         instance: Instance<'tcx>)
                                         -> DIScope {
         // First, let's see if this is a method within an inherent impl. Because
         // if yes, we want to make the result subroutine DIE a child of the
         // subroutine's self-type.
-        let self_type = cx.tcx().impl_of_method(instance.def_id()).and_then(|impl_def_id| {
+        let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
             // If the method does *not* belong to a trait, proceed
-            if cx.tcx().trait_id_of_impl(impl_def_id).is_none() {
-                let impl_self_ty = cx.tcx().trans_impl_self_ty(impl_def_id, instance.substs);
+            if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
+                let impl_self_ty = cx.tcx.trans_impl_self_ty(impl_def_id, instance.substs);
 
                 // Only "class" methods are generally understood by LLVM,
                 // so avoid methods on other types (e.g. `<*mut T>::null`).
@@ -447,7 +446,7 @@
         self_type.unwrap_or_else(|| {
             namespace::item_namespace(cx, DefId {
                 krate: instance.def_id().krate,
-                index: cx.tcx()
+                index: cx.tcx
                          .def_key(instance.def_id())
                          .parent
                          .expect("get_containing_scope: missing parent?")
@@ -456,7 +455,7 @@
     }
 }
 
-pub fn declare_local<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+pub fn declare_local<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                                dbg_context: &FunctionDebugContext,
                                variable_name: ast::Name,
                                variable_type: Ty<'tcx>,
@@ -464,7 +463,7 @@
                                variable_access: VariableAccess,
                                variable_kind: VariableKind,
                                span: Span) {
-    let cx = bcx.ccx;
+    let cx = bx.cx;
 
     let file = span_start(cx, span).file;
     let file_metadata = file_metadata(cx,
@@ -500,10 +499,10 @@
                     align.abi() as u32,
                 )
             };
-            source_loc::set_debug_location(bcx,
+            source_loc::set_debug_location(bx,
                 InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
             unsafe {
-                let debug_loc = llvm::LLVMGetCurrentDebugLocation(bcx.llbuilder);
+                let debug_loc = llvm::LLVMGetCurrentDebugLocation(bx.llbuilder);
                 let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
                     DIB(cx),
                     alloca,
@@ -511,9 +510,9 @@
                     address_operations.as_ptr(),
                     address_operations.len() as c_uint,
                     debug_loc,
-                    bcx.llbb());
+                    bx.llbb());
 
-                llvm::LLVMSetInstDebugLocation(bcx.llbuilder, instr);
+                llvm::LLVMSetInstDebugLocation(bx.llbuilder, instr);
             }
         }
     }
@@ -521,7 +520,7 @@
     match variable_kind {
         ArgumentVariable(_) | CapturedVariable => {
             assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
-            source_loc::set_debug_location(bcx, UnknownLocation);
+            source_loc::set_debug_location(bx, UnknownLocation);
         }
         _ => { /* nothing to do */ }
     }
diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs
index d4dd112..46067a4 100644
--- a/src/librustc_trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/debuginfo/namespace.rs
@@ -12,57 +12,52 @@
 
 use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER};
 use super::utils::{DIB, debug_context};
+use monomorphize::Instance;
+use rustc::ty;
+use syntax::ast;
 
 use llvm;
 use llvm::debuginfo::DIScope;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
-use common::CrateContext;
+use common::CodegenCx;
 
 use std::ffi::CString;
 use std::ptr;
 
-pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> String {
-    fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut String) {
-        let def_key = ccx.tcx().def_key(def_id);
-        if let Some(parent) = def_key.parent {
-            fill_nested(ccx, DefId {
-                krate: def_id.krate,
-                index: parent
-            }, "", output);
-        }
-
-        let name = match def_key.disambiguated_data.data {
-            DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate).as_str(),
-            data => data.as_interned_str()
-        };
-
-        output.push_str(&(name.len() + extra.len()).to_string());
-        output.push_str(&name);
-        output.push_str(extra);
-    }
-
-    let mut name = String::from("_ZN");
-    fill_nested(ccx, def_id, extra, &mut name);
-    name.push('E');
-    name
+pub fn mangled_name_of_instance<'a, 'tcx>(
+    cx: &CodegenCx<'a, 'tcx>,
+    instance: Instance<'tcx>,
+) -> ty::SymbolName {
+     let tcx = cx.tcx;
+     tcx.symbol_name(instance)
 }
 
-pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
-    if let Some(&scope) = debug_context(ccx).namespace_map.borrow().get(&def_id) {
+pub fn mangled_name_of_item<'a, 'tcx>(
+    cx: &CodegenCx<'a, 'tcx>,
+    node_id: ast::NodeId,
+) -> ty::SymbolName {
+    let tcx = cx.tcx;
+    let node_def_id = tcx.hir.local_def_id(node_id);
+    let instance = Instance::mono(tcx, node_def_id);
+    tcx.symbol_name(instance)
+}
+
+pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
+    if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) {
         return scope;
     }
 
-    let def_key = ccx.tcx().def_key(def_id);
+    let def_key = cx.tcx.def_key(def_id);
     let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| {
-        item_namespace(ccx, DefId {
+        item_namespace(cx, DefId {
             krate: def_id.krate,
             index: parent
         })
     });
 
     let namespace_name = match def_key.disambiguated_data.data {
-        DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate).as_str(),
+        DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(),
         data => data.as_interned_str()
     };
 
@@ -70,13 +65,13 @@
 
     let scope = unsafe {
         llvm::LLVMRustDIBuilderCreateNameSpace(
-            DIB(ccx),
+            DIB(cx),
             parent_scope,
             namespace_name.as_ptr(),
-            unknown_file_metadata(ccx),
+            unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER)
     };
 
-    debug_context(ccx).namespace_map.borrow_mut().insert(def_id, scope);
+    debug_context(cx).namespace_map.borrow_mut().insert(def_id, scope);
     scope
 }
diff --git a/src/librustc_trans/debuginfo/source_loc.rs b/src/librustc_trans/debuginfo/source_loc.rs
index 7393802..7440296 100644
--- a/src/librustc_trans/debuginfo/source_loc.rs
+++ b/src/librustc_trans/debuginfo/source_loc.rs
@@ -26,25 +26,25 @@
 ///
 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
 pub fn set_source_location(
-    debug_context: &FunctionDebugContext, builder: &Builder, scope: DIScope, span: Span
+    debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span
 ) {
     let function_debug_context = match *debug_context {
         FunctionDebugContext::DebugInfoDisabled => return,
         FunctionDebugContext::FunctionWithoutDebugInfo => {
-            set_debug_location(builder, UnknownLocation);
+            set_debug_location(bx, UnknownLocation);
             return;
         }
         FunctionDebugContext::RegularContext(ref data) => data
     };
 
     let dbg_loc = if function_debug_context.source_locations_enabled.get() {
-        debug!("set_source_location: {}", builder.sess().codemap().span_to_string(span));
-        let loc = span_start(builder.ccx, span);
+        debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span));
+        let loc = span_start(bx.cx, span);
         InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
     } else {
         UnknownLocation
     };
-    set_debug_location(builder, dbg_loc);
+    set_debug_location(bx, dbg_loc);
 }
 
 /// Enables emitting source locations for the given functions.
@@ -79,7 +79,7 @@
     }
 }
 
-pub fn set_debug_location(builder: &Builder, debug_location: InternalDebugLocation) {
+pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
     let metadata_node = match debug_location {
         KnownLocation { scope, line, .. } => {
             // Always set the column to zero like Clang and GCC
@@ -88,7 +88,7 @@
 
             unsafe {
                 llvm::LLVMRustDIBuilderCreateDebugLocation(
-                    debug_context(builder.ccx).llcontext,
+                    debug_context(bx.cx).llcontext,
                     line as c_uint,
                     col as c_uint,
                     scope,
@@ -102,6 +102,6 @@
     };
 
     unsafe {
-        llvm::LLVMSetCurrentDebugLocation(builder.llbuilder, metadata_node);
+        llvm::LLVMSetCurrentDebugLocation(bx.llbuilder, metadata_node);
     }
 }
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 85467f5..6490d10 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -10,7 +10,7 @@
 
 // Type Names for Debug Info.
 
-use common::CrateContext;
+use common::CodegenCx;
 use rustc::hir::def_id::DefId;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty};
@@ -21,7 +21,7 @@
 // any caching, i.e. calling the function twice with the same type will also do
 // the work twice. The `qualified` parameter only affects the first level of the
 // type name, further levels (i.e. type parameters) are always fully qualified.
-pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                              t: Ty<'tcx>,
                                              qualified: bool)
                                              -> String {
@@ -32,7 +32,7 @@
 
 // Pushes the name of the type as it should be stored in debuginfo on the
 // `output` String. See also compute_debuginfo_type_name().
-pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                           t: Ty<'tcx>,
                                           qualified: bool,
                                           output: &mut String) {
@@ -117,14 +117,14 @@
         },
         ty::TyDynamic(ref trait_data, ..) => {
             if let Some(principal) = trait_data.principal() {
-                let principal = cx.tcx().erase_late_bound_regions_and_normalize(
+                let principal = cx.tcx.erase_late_bound_regions_and_normalize(
                     &principal);
                 push_item_name(cx, principal.def_id, false, output);
                 push_type_params(cx, principal.substs, output);
             }
         },
         ty::TyFnDef(..) | ty::TyFnPtr(_) => {
-            let sig = t.fn_sig(cx.tcx());
+            let sig = t.fn_sig(cx.tcx);
             if sig.unsafety() == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
             }
@@ -138,7 +138,7 @@
 
             output.push_str("fn(");
 
-            let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig);
+            let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
             if !sig.inputs().is_empty() {
                 for &parameter_type in sig.inputs() {
                     push_debuginfo_type_name(cx, parameter_type, true, output);
@@ -173,24 +173,25 @@
         ty::TyInfer(_) |
         ty::TyProjection(..) |
         ty::TyAnon(..) |
+        ty::TyGeneratorWitness(..) |
         ty::TyParam(_) => {
             bug!("debuginfo: Trying to create type name for \
                 unexpected type: {:?}", t);
         }
     }
 
-    fn push_item_name(cx: &CrateContext,
+    fn push_item_name(cx: &CodegenCx,
                       def_id: DefId,
                       qualified: bool,
                       output: &mut String) {
         if qualified {
-            output.push_str(&cx.tcx().crate_name(def_id.krate).as_str());
-            for path_element in cx.tcx().def_path(def_id).data {
+            output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
+            for path_element in cx.tcx.def_path(def_id).data {
                 output.push_str("::");
                 output.push_str(&path_element.data.as_interned_str());
             }
         } else {
-            output.push_str(&cx.tcx().item_name(def_id));
+            output.push_str(&cx.tcx.item_name(def_id));
         }
     }
 
@@ -199,7 +200,7 @@
     // reconstructed for items from non-local crates. For local crates, this
     // would be possible but with inlining and LTO we have to use the least
     // common denominator - otherwise we would run into conflicts.
-    fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+    fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                   substs: &Substs<'tcx>,
                                   output: &mut String) {
         if substs.types().next().is_none() {
diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs
index 95427d9..c571b84 100644
--- a/src/librustc_trans/debuginfo/utils.rs
+++ b/src/librustc_trans/debuginfo/utils.rs
@@ -18,12 +18,12 @@
 
 use llvm;
 use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
-use common::{CrateContext};
+use common::{CodegenCx};
 
 use syntax_pos::{self, Span};
 use syntax::ast;
 
-pub fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
+pub fn is_node_local_to_unit(cx: &CodegenCx, node_id: ast::NodeId) -> bool
 {
     // The is_local_to_unit flag indicates whether a function is local to the
     // current compilation unit (i.e. if it is *static* in the C-sense). The
@@ -33,8 +33,8 @@
     // visible). It might better to use the `exported_items` set from
     // `driver::CrateAnalysis` in the future, but (atm) this set is not
     // available in the translation pass.
-    let def_id = cx.tcx().hir.local_def_id(node_id);
-    !cx.tcx().is_exported_symbol(def_id)
+    let def_id = cx.tcx.hir.local_def_id(node_id);
+    !cx.tcx.is_exported_symbol(def_id)
 }
 
 #[allow(non_snake_case)]
@@ -45,23 +45,23 @@
 }
 
 /// Return syntax_pos::Loc corresponding to the beginning of the span
-pub fn span_start(cx: &CrateContext, span: Span) -> syntax_pos::Loc {
+pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc {
     cx.sess().codemap().lookup_char_pos(span.lo())
 }
 
 #[inline]
-pub fn debug_context<'a, 'tcx>(cx: &'a CrateContext<'a, 'tcx>)
+pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>)
                            -> &'a CrateDebugContext<'tcx> {
-    cx.dbg_cx().as_ref().unwrap()
+    cx.dbg_cx.as_ref().unwrap()
 }
 
 #[inline]
 #[allow(non_snake_case)]
-pub fn DIB(cx: &CrateContext) -> DIBuilderRef {
-    cx.dbg_cx().as_ref().unwrap().builder
+pub fn DIB(cx: &CodegenCx) -> DIBuilderRef {
+    cx.dbg_cx.as_ref().unwrap().builder
 }
 
-pub fn get_namespace_for_item(cx: &CrateContext, def_id: DefId) -> DIScope {
-    item_namespace(cx, cx.tcx().parent(def_id)
+pub fn get_namespace_for_item(cx: &CodegenCx, def_id: DefId) -> DIScope {
+    item_namespace(cx, cx.tcx.parent(def_id)
         .expect("get_namespace_for_item: missing parent?"))
 }
diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs
index f894bdf..aa1cd0c 100644
--- a/src/librustc_trans/declare.rs
+++ b/src/librustc_trans/declare.rs
@@ -27,7 +27,7 @@
 use rustc_back::PanicStrategy;
 use abi::{Abi, FnType};
 use attributes;
-use context::CrateContext;
+use context::CodegenCx;
 use common;
 use type_::Type;
 use value::Value;
@@ -39,13 +39,13 @@
 ///
 /// If there’s a value with the same name already declared, the function will
 /// return its ValueRef instead.
-pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef {
+pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef {
     debug!("declare_global(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
     unsafe {
-        llvm::LLVMRustGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty.to_ref())
     }
 }
 
@@ -54,13 +54,13 @@
 ///
 /// If there’s a value with the same name already declared, the function will
 /// update the declaration and return existing ValueRef instead.
-fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
+fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
     debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
     let llfn = unsafe {
-        llvm::LLVMRustGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty.to_ref())
     };
 
     llvm::SetFunctionCallConv(llfn, callconv);
@@ -68,12 +68,12 @@
     // be merged.
     llvm::SetUnnamedAddr(llfn, true);
 
-    if ccx.tcx().sess.opts.cg.no_redzone
-        .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
+    if cx.tcx.sess.opts.cg.no_redzone
+        .unwrap_or(cx.tcx.sess.target.target.options.disable_redzone) {
         llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);
     }
 
-    if let Some(ref sanitizer) = ccx.tcx().sess.opts.debugging_opts.sanitizer {
+    if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer {
         match *sanitizer {
             Sanitizer::Address => {
                 llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
@@ -88,7 +88,7 @@
         }
     }
 
-    match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
+    match cx.tcx.sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
         Some("s") => {
             llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
         },
@@ -99,7 +99,7 @@
         _ => {},
     }
 
-    if ccx.tcx().sess.panic_strategy() != PanicStrategy::Unwind {
+    if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind {
         attributes::unwind(llfn, false);
     }
 
@@ -114,8 +114,8 @@
 ///
 /// If there’s a value with the same name already declared, the function will
 /// update the declaration and return existing ValueRef instead.
-pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef {
-    declare_raw_fn(ccx, name, llvm::CCallConv, fn_type)
+pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef {
+    declare_raw_fn(cx, name, llvm::CCallConv, fn_type)
 }
 
 
@@ -123,15 +123,15 @@
 ///
 /// If there’s a value with the same name already declared, the function will
 /// update the declaration and return existing ValueRef instead.
-pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
+pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
                             fn_type: Ty<'tcx>) -> ValueRef {
     debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type);
-    let sig = common::ty_fn_sig(ccx, fn_type);
-    let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
+    let sig = common::ty_fn_sig(cx, fn_type);
+    let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
     debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
 
-    let fty = FnType::new(ccx, sig, &[]);
-    let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
+    let fty = FnType::new(cx, sig, &[]);
+    let llfn = declare_raw_fn(cx, name, fty.cconv, fty.llvm_type(cx));
 
     // FIXME(canndrew): This is_never should really be an is_uninhabited
     if sig.output().is_never() {
@@ -154,11 +154,11 @@
 /// return None if the name already has a definition associated with it. In that
 /// case an error should be reported to the user, because it usually happens due
 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
-pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRef> {
-    if get_defined_value(ccx, name).is_some() {
+pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option<ValueRef> {
+    if get_defined_value(cx, name).is_some() {
         None
     } else {
-        Some(declare_global(ccx, name, ty))
+        Some(declare_global(cx, name, ty))
     }
 }
 
@@ -167,13 +167,13 @@
 /// Use this function when you intend to define a function. This function will
 /// return panic if the name already has a definition associated with it. This
 /// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                            name: &str,
                            fn_type: Ty<'tcx>) -> ValueRef {
-    if get_defined_value(ccx, name).is_some() {
-        ccx.sess().fatal(&format!("symbol `{}` already defined", name))
+    if get_defined_value(cx, name).is_some() {
+        cx.sess().fatal(&format!("symbol `{}` already defined", name))
     } else {
-        declare_fn(ccx, name, fn_type)
+        declare_fn(cx, name, fn_type)
     }
 }
 
@@ -182,22 +182,22 @@
 /// Use this function when you intend to define a function. This function will
 /// return panic if the name already has a definition associated with it. This
 /// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                     name: &str,
                                     fn_type: Ty<'tcx>) -> ValueRef {
-    let llfn = define_fn(ccx, name, fn_type);
+    let llfn = define_fn(cx, name, fn_type);
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
     llfn
 }
 
 
 /// Get declared value by name.
-pub fn get_declared_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
+pub fn get_declared_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
     debug!("get_declared_value(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
-    let val = unsafe { llvm::LLVMRustGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
+    let val = unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) };
     if val.is_null() {
         debug!("get_declared_value: {:?} value is null", name);
         None
@@ -209,8 +209,8 @@
 
 /// Get defined or externally defined (AvailableExternally linkage) value by
 /// name.
-pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
-    get_declared_value(ccx, name).and_then(|val|{
+pub fn get_defined_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+    get_declared_value(cx, name).and_then(|val|{
         let declaration = unsafe {
             llvm::LLVMIsDeclaration(val) != 0
         };
diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs
index 8f5d836..57cc33d 100644
--- a/src/librustc_trans/diagnostics.rs
+++ b/src/librustc_trans/diagnostics.rs
@@ -47,27 +47,9 @@
 ```
 "##,
 
-E0558: r##"
-The `export_name` attribute was malformed.
+}
 
-Erroneous code example:
 
-```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
-#[export_name] // error: export_name attribute has invalid format
-pub fn something() {}
-
-fn main() {}
-```
-
-The `export_name` attribute expects a string in order to determine the name of
-the exported symbol. Example:
-
-```
-#[export_name = "some_function"] // ok!
-pub fn something() {}
-
-fn main() {}
-```
-"##,
-
+register_diagnostics! {
+    E0558
 }
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index 9477adc..c7275d0 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -23,39 +23,39 @@
 use rustc::ty::{self, Ty};
 use value::Value;
 
-pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
+pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
                                        -> (ValueRef, ValueRef) {
     debug!("calculate size of DST: {}; with lost info: {:?}",
            t, Value(info));
-    if bcx.ccx.shared().type_is_sized(t) {
-        let (size, align) = bcx.ccx.size_and_align_of(t);
+    if bx.cx.type_is_sized(t) {
+        let (size, align) = bx.cx.size_and_align_of(t);
         debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
                t, Value(info), size, align);
-        let size = C_usize(bcx.ccx, size.bytes());
-        let align = C_usize(bcx.ccx, align.abi());
+        let size = C_usize(bx.cx, size.bytes());
+        let align = C_usize(bx.cx, align.abi());
         return (size, align);
     }
     assert!(!info.is_null());
     match t.sty {
         ty::TyDynamic(..) => {
             // load size/align from vtable
-            (meth::SIZE.get_usize(bcx, info), meth::ALIGN.get_usize(bcx, info))
+            (meth::SIZE.get_usize(bx, info), meth::ALIGN.get_usize(bx, info))
         }
         ty::TySlice(_) | ty::TyStr => {
-            let unit = t.sequence_element_type(bcx.tcx());
+            let unit = t.sequence_element_type(bx.tcx());
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
-            let (size, align) = bcx.ccx.size_and_align_of(unit);
-            (bcx.mul(info, C_usize(bcx.ccx, size.bytes())),
-             C_usize(bcx.ccx, align.abi()))
+            let (size, align) = bx.cx.size_and_align_of(unit);
+            (bx.mul(info, C_usize(bx.cx, size.bytes())),
+             C_usize(bx.cx, align.abi()))
         }
         _ => {
-            let ccx = bcx.ccx;
+            let cx = bx.cx;
             // First get the size of all statically known fields.
             // Don't use size_of because it also rounds up to alignment, which we
             // want to avoid, as the unsized field's alignment could be smaller.
             assert!(!t.is_simd());
-            let layout = ccx.layout_of(t);
+            let layout = cx.layout_of(t);
             debug!("DST {} layout: {:?}", t, layout);
 
             let i = layout.fields.count() - 1;
@@ -63,13 +63,13 @@
             let sized_align = layout.align.abi();
             debug!("DST {} statically sized prefix size: {} align: {}",
                    t, sized_size, sized_align);
-            let sized_size = C_usize(ccx, sized_size);
-            let sized_align = C_usize(ccx, sized_align);
+            let sized_size = C_usize(cx, sized_size);
+            let sized_align = C_usize(cx, sized_align);
 
             // Recurse to get the size of the dynamically sized field (must be
             // the last field).
-            let field_ty = layout.field(ccx, i).ty;
-            let (unsized_size, mut unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
+            let field_ty = layout.field(cx, i).ty;
+            let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info);
 
             // FIXME (#26403, #27023): We should be adding padding
             // to `sized_size` (to accommodate the `unsized_align`
@@ -79,7 +79,7 @@
             // here. But this is where the add would go.)
 
             // Return the sum of sizes and max of aligns.
-            let size = bcx.add(sized_size, unsized_size);
+            let size = bx.add(sized_size, unsized_size);
 
             // Packed types ignore the alignment of their fields.
             if let ty::TyAdt(def, _) = t.sty {
@@ -95,9 +95,9 @@
                 (Some(sized_align), Some(unsized_align)) => {
                     // If both alignments are constant, (the sized_align should always be), then
                     // pick the correct alignment statically.
-                    C_usize(ccx, std::cmp::max(sized_align, unsized_align) as u64)
+                    C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
                 }
-                _ => bcx.select(bcx.icmp(llvm::IntUGT, sized_align, unsized_align),
+                _ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align),
                                 sized_align,
                                 unsized_align)
             };
@@ -113,8 +113,8 @@
             //
             //   `(size + (align-1)) & -align`
 
-            let addend = bcx.sub(align, C_usize(bcx.ccx, 1));
-            let size = bcx.and(bcx.add(size, addend), bcx.neg(align));
+            let addend = bx.sub(align, C_usize(bx.cx, 1));
+            let size = bx.and(bx.add(size, addend), bx.neg(align));
 
             (size, align)
         }
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 3cd60e7..b1f1fb5 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -35,7 +35,7 @@
 use std::cmp::Ordering;
 use std::iter;
 
-fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
+fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
     let llvm_name = match name {
         "sqrtf32" => "llvm.sqrt.f32",
         "sqrtf64" => "llvm.sqrt.f64",
@@ -79,20 +79,20 @@
         "abort" => "llvm.trap",
         _ => return None
     };
-    Some(ccx.get_intrinsic(&llvm_name))
+    Some(cx.get_intrinsic(&llvm_name))
 }
 
 /// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
 /// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
 /// add them to librustc_trans/trans/context.rs
-pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                                       callee_ty: Ty<'tcx>,
                                       fn_ty: &FnType<'tcx>,
                                       args: &[OperandRef<'tcx>],
                                       llresult: ValueRef,
                                       span: Span) {
-    let ccx = bcx.ccx;
-    let tcx = ccx.tcx();
+    let cx = bx.cx;
+    let tcx = cx.tcx;
 
     let (def_id, substs) = match callee_ty.sty {
         ty::TyFnDef(def_id, substs) => (def_id, substs),
@@ -105,13 +105,13 @@
     let ret_ty = sig.output();
     let name = &*tcx.item_name(def_id);
 
-    let llret_ty = ccx.layout_of(ret_ty).llvm_type(ccx);
+    let llret_ty = cx.layout_of(ret_ty).llvm_type(cx);
     let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align);
 
-    let simple = get_simple_intrinsic(ccx, name);
+    let simple = get_simple_intrinsic(cx, name);
     let llval = match name {
         _ if simple.is_some() => {
-            bcx.call(simple.unwrap(),
+            bx.call(simple.unwrap(),
                      &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
                      None)
         }
@@ -119,15 +119,15 @@
             return;
         },
         "likely" => {
-            let expect = ccx.get_intrinsic(&("llvm.expect.i1"));
-            bcx.call(expect, &[args[0].immediate(), C_bool(ccx, true)], None)
+            let expect = cx.get_intrinsic(&("llvm.expect.i1"));
+            bx.call(expect, &[args[0].immediate(), C_bool(cx, true)], None)
         }
         "unlikely" => {
-            let expect = ccx.get_intrinsic(&("llvm.expect.i1"));
-            bcx.call(expect, &[args[0].immediate(), C_bool(ccx, false)], None)
+            let expect = cx.get_intrinsic(&("llvm.expect.i1"));
+            bx.call(expect, &[args[0].immediate(), C_bool(cx, false)], None)
         }
         "try" => {
-            try_intrinsic(bcx, ccx,
+            try_intrinsic(bx, cx,
                           args[0].immediate(),
                           args[1].immediate(),
                           args[2].immediate(),
@@ -135,57 +135,57 @@
             return;
         }
         "breakpoint" => {
-            let llfn = ccx.get_intrinsic(&("llvm.debugtrap"));
-            bcx.call(llfn, &[], None)
+            let llfn = cx.get_intrinsic(&("llvm.debugtrap"));
+            bx.call(llfn, &[], None)
         }
         "size_of" => {
             let tp_ty = substs.type_at(0);
-            C_usize(ccx, ccx.size_of(tp_ty).bytes())
+            C_usize(cx, cx.size_of(tp_ty).bytes())
         }
         "size_of_val" => {
             let tp_ty = substs.type_at(0);
             if let OperandValue::Pair(_, meta) = args[0].val {
                 let (llsize, _) =
-                    glue::size_and_align_of_dst(bcx, tp_ty, meta);
+                    glue::size_and_align_of_dst(bx, tp_ty, meta);
                 llsize
             } else {
-                C_usize(ccx, ccx.size_of(tp_ty).bytes())
+                C_usize(cx, cx.size_of(tp_ty).bytes())
             }
         }
         "min_align_of" => {
             let tp_ty = substs.type_at(0);
-            C_usize(ccx, ccx.align_of(tp_ty).abi())
+            C_usize(cx, cx.align_of(tp_ty).abi())
         }
         "min_align_of_val" => {
             let tp_ty = substs.type_at(0);
             if let OperandValue::Pair(_, meta) = args[0].val {
                 let (_, llalign) =
-                    glue::size_and_align_of_dst(bcx, tp_ty, meta);
+                    glue::size_and_align_of_dst(bx, tp_ty, meta);
                 llalign
             } else {
-                C_usize(ccx, ccx.align_of(tp_ty).abi())
+                C_usize(cx, cx.align_of(tp_ty).abi())
             }
         }
         "pref_align_of" => {
             let tp_ty = substs.type_at(0);
-            C_usize(ccx, ccx.align_of(tp_ty).pref())
+            C_usize(cx, cx.align_of(tp_ty).pref())
         }
         "type_name" => {
             let tp_ty = substs.type_at(0);
             let ty_name = Symbol::intern(&tp_ty.to_string()).as_str();
-            C_str_slice(ccx, ty_name)
+            C_str_slice(cx, ty_name)
         }
         "type_id" => {
-            C_u64(ccx, ccx.tcx().type_id_hash(substs.type_at(0)))
+            C_u64(cx, cx.tcx.type_id_hash(substs.type_at(0)))
         }
         "init" => {
             let ty = substs.type_at(0);
-            if !ccx.layout_of(ty).is_zst() {
+            if !cx.layout_of(ty).is_zst() {
                 // Just zero out the stack slot.
                 // If we store a zero constant, LLVM will drown in vreg allocation for large data
                 // structures, and the generated code will be awful. (A telltale sign of this is
                 // large quantities of `mov [byte ptr foo],0` in the generated code.)
-                memset_intrinsic(bcx, false, ty, llresult, C_u8(ccx, 0), C_usize(ccx, 1));
+                memset_intrinsic(bx, false, ty, llresult, C_u8(cx, 0), C_usize(cx, 1));
             }
             return;
         }
@@ -196,82 +196,82 @@
         "needs_drop" => {
             let tp_ty = substs.type_at(0);
 
-            C_bool(ccx, bcx.ccx.shared().type_needs_drop(tp_ty))
+            C_bool(cx, bx.cx.type_needs_drop(tp_ty))
         }
         "offset" => {
             let ptr = args[0].immediate();
             let offset = args[1].immediate();
-            bcx.inbounds_gep(ptr, &[offset])
+            bx.inbounds_gep(ptr, &[offset])
         }
         "arith_offset" => {
             let ptr = args[0].immediate();
             let offset = args[1].immediate();
-            bcx.gep(ptr, &[offset])
+            bx.gep(ptr, &[offset])
         }
 
         "copy_nonoverlapping" => {
-            copy_intrinsic(bcx, false, false, substs.type_at(0),
+            copy_intrinsic(bx, false, false, substs.type_at(0),
                            args[1].immediate(), args[0].immediate(), args[2].immediate())
         }
         "copy" => {
-            copy_intrinsic(bcx, true, false, substs.type_at(0),
+            copy_intrinsic(bx, true, false, substs.type_at(0),
                            args[1].immediate(), args[0].immediate(), args[2].immediate())
         }
         "write_bytes" => {
-            memset_intrinsic(bcx, false, substs.type_at(0),
+            memset_intrinsic(bx, false, substs.type_at(0),
                              args[0].immediate(), args[1].immediate(), args[2].immediate())
         }
 
         "volatile_copy_nonoverlapping_memory" => {
-            copy_intrinsic(bcx, false, true, substs.type_at(0),
+            copy_intrinsic(bx, false, true, substs.type_at(0),
                            args[0].immediate(), args[1].immediate(), args[2].immediate())
         }
         "volatile_copy_memory" => {
-            copy_intrinsic(bcx, true, true, substs.type_at(0),
+            copy_intrinsic(bx, true, true, substs.type_at(0),
                            args[0].immediate(), args[1].immediate(), args[2].immediate())
         }
         "volatile_set_memory" => {
-            memset_intrinsic(bcx, true, substs.type_at(0),
+            memset_intrinsic(bx, true, substs.type_at(0),
                              args[0].immediate(), args[1].immediate(), args[2].immediate())
         }
         "volatile_load" => {
             let tp_ty = substs.type_at(0);
             let mut ptr = args[0].immediate();
             if let PassMode::Cast(ty) = fn_ty.ret.mode {
-                ptr = bcx.pointercast(ptr, ty.llvm_type(ccx).ptr_to());
+                ptr = bx.pointercast(ptr, ty.llvm_type(cx).ptr_to());
             }
-            let load = bcx.volatile_load(ptr);
+            let load = bx.volatile_load(ptr);
             unsafe {
-                llvm::LLVMSetAlignment(load, ccx.align_of(tp_ty).abi() as u32);
+                llvm::LLVMSetAlignment(load, cx.align_of(tp_ty).abi() as u32);
             }
-            to_immediate(bcx, load, ccx.layout_of(tp_ty))
+            to_immediate(bx, load, cx.layout_of(tp_ty))
         },
         "volatile_store" => {
             let tp_ty = substs.type_at(0);
-            let dst = args[0].deref(bcx.ccx);
+            let dst = args[0].deref(bx.cx);
             if let OperandValue::Pair(a, b) = args[1].val {
-                bcx.volatile_store(a, dst.project_field(bcx, 0).llval);
-                bcx.volatile_store(b, dst.project_field(bcx, 1).llval);
+                bx.volatile_store(a, dst.project_field(bx, 0).llval);
+                bx.volatile_store(b, dst.project_field(bx, 1).llval);
             } else {
                 let val = if let OperandValue::Ref(ptr, align) = args[1].val {
-                    bcx.load(ptr, align)
+                    bx.load(ptr, align)
                 } else {
                     if dst.layout.is_zst() {
                         return;
                     }
-                    from_immediate(bcx, args[1].immediate())
+                    from_immediate(bx, args[1].immediate())
                 };
-                let ptr = bcx.pointercast(dst.llval, val_ty(val).ptr_to());
-                let store = bcx.volatile_store(val, ptr);
+                let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to());
+                let store = bx.volatile_store(val, ptr);
                 unsafe {
-                    llvm::LLVMSetAlignment(store, ccx.align_of(tp_ty).abi() as u32);
+                    llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32);
                 }
             }
             return;
         },
         "prefetch_read_data" | "prefetch_write_data" |
         "prefetch_read_instruction" | "prefetch_write_instruction" => {
-            let expect = ccx.get_intrinsic(&("llvm.prefetch"));
+            let expect = cx.get_intrinsic(&("llvm.prefetch"));
             let (rw, cache_type) = match name {
                 "prefetch_read_data" => (0, 1),
                 "prefetch_write_data" => (1, 1),
@@ -279,11 +279,11 @@
                 "prefetch_write_instruction" => (1, 0),
                 _ => bug!()
             };
-            bcx.call(expect, &[
+            bx.call(expect, &[
                 args[0].immediate(),
-                C_i32(ccx, rw),
+                C_i32(cx, rw),
                 args[1].immediate(),
-                C_i32(ccx, cache_type)
+                C_i32(cx, cache_type)
             ], None)
         },
         "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
@@ -291,27 +291,27 @@
         "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
         "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => {
             let ty = arg_tys[0];
-            match int_type_width_signed(ty, ccx) {
+            match int_type_width_signed(ty, cx) {
                 Some((width, signed)) =>
                     match name {
                         "ctlz" | "cttz" => {
-                            let y = C_bool(bcx.ccx, false);
-                            let llfn = ccx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
-                            bcx.call(llfn, &[args[0].immediate(), y], None)
+                            let y = C_bool(bx.cx, false);
+                            let llfn = cx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
+                            bx.call(llfn, &[args[0].immediate(), y], None)
                         }
                         "ctlz_nonzero" | "cttz_nonzero" => {
-                            let y = C_bool(bcx.ccx, true);
+                            let y = C_bool(bx.cx, true);
                             let llvm_name = &format!("llvm.{}.i{}", &name[..4], width);
-                            let llfn = ccx.get_intrinsic(llvm_name);
-                            bcx.call(llfn, &[args[0].immediate(), y], None)
+                            let llfn = cx.get_intrinsic(llvm_name);
+                            bx.call(llfn, &[args[0].immediate(), y], None)
                         }
-                        "ctpop" => bcx.call(ccx.get_intrinsic(&format!("llvm.ctpop.i{}", width)),
+                        "ctpop" => bx.call(cx.get_intrinsic(&format!("llvm.ctpop.i{}", width)),
                                         &[args[0].immediate()], None),
                         "bswap" => {
                             if width == 8 {
                                 args[0].immediate() // byte swap a u8/i8 is just a no-op
                             } else {
-                                bcx.call(ccx.get_intrinsic(&format!("llvm.bswap.i{}", width)),
+                                bx.call(cx.get_intrinsic(&format!("llvm.bswap.i{}", width)),
                                         &[args[0].immediate()], None)
                             }
                         }
@@ -319,44 +319,44 @@
                             let intrinsic = format!("llvm.{}{}.with.overflow.i{}",
                                                     if signed { 's' } else { 'u' },
                                                     &name[..3], width);
-                            let llfn = bcx.ccx.get_intrinsic(&intrinsic);
+                            let llfn = bx.cx.get_intrinsic(&intrinsic);
 
                             // Convert `i1` to a `bool`, and write it to the out parameter
-                            let pair = bcx.call(llfn, &[
+                            let pair = bx.call(llfn, &[
                                 args[0].immediate(),
                                 args[1].immediate()
                             ], None);
-                            let val = bcx.extract_value(pair, 0);
-                            let overflow = bcx.zext(bcx.extract_value(pair, 1), Type::bool(ccx));
+                            let val = bx.extract_value(pair, 0);
+                            let overflow = bx.zext(bx.extract_value(pair, 1), Type::bool(cx));
 
-                            let dest = result.project_field(bcx, 0);
-                            bcx.store(val, dest.llval, dest.align);
-                            let dest = result.project_field(bcx, 1);
-                            bcx.store(overflow, dest.llval, dest.align);
+                            let dest = result.project_field(bx, 0);
+                            bx.store(val, dest.llval, dest.align);
+                            let dest = result.project_field(bx, 1);
+                            bx.store(overflow, dest.llval, dest.align);
 
                             return;
                         },
-                        "overflowing_add" => bcx.add(args[0].immediate(), args[1].immediate()),
-                        "overflowing_sub" => bcx.sub(args[0].immediate(), args[1].immediate()),
-                        "overflowing_mul" => bcx.mul(args[0].immediate(), args[1].immediate()),
+                        "overflowing_add" => bx.add(args[0].immediate(), args[1].immediate()),
+                        "overflowing_sub" => bx.sub(args[0].immediate(), args[1].immediate()),
+                        "overflowing_mul" => bx.mul(args[0].immediate(), args[1].immediate()),
                         "unchecked_div" =>
                             if signed {
-                                bcx.sdiv(args[0].immediate(), args[1].immediate())
+                                bx.sdiv(args[0].immediate(), args[1].immediate())
                             } else {
-                                bcx.udiv(args[0].immediate(), args[1].immediate())
+                                bx.udiv(args[0].immediate(), args[1].immediate())
                             },
                         "unchecked_rem" =>
                             if signed {
-                                bcx.srem(args[0].immediate(), args[1].immediate())
+                                bx.srem(args[0].immediate(), args[1].immediate())
                             } else {
-                                bcx.urem(args[0].immediate(), args[1].immediate())
+                                bx.urem(args[0].immediate(), args[1].immediate())
                             },
-                        "unchecked_shl" => bcx.shl(args[0].immediate(), args[1].immediate()),
+                        "unchecked_shl" => bx.shl(args[0].immediate(), args[1].immediate()),
                         "unchecked_shr" =>
                             if signed {
-                                bcx.ashr(args[0].immediate(), args[1].immediate())
+                                bx.ashr(args[0].immediate(), args[1].immediate())
                             } else {
-                                bcx.lshr(args[0].immediate(), args[1].immediate())
+                                bx.lshr(args[0].immediate(), args[1].immediate())
                             },
                         _ => bug!(),
                     },
@@ -375,11 +375,11 @@
             match float_type_width(sty) {
                 Some(_width) =>
                     match name {
-                        "fadd_fast" => bcx.fadd_fast(args[0].immediate(), args[1].immediate()),
-                        "fsub_fast" => bcx.fsub_fast(args[0].immediate(), args[1].immediate()),
-                        "fmul_fast" => bcx.fmul_fast(args[0].immediate(), args[1].immediate()),
-                        "fdiv_fast" => bcx.fdiv_fast(args[0].immediate(), args[1].immediate()),
-                        "frem_fast" => bcx.frem_fast(args[0].immediate(), args[1].immediate()),
+                        "fadd_fast" => bx.fadd_fast(args[0].immediate(), args[1].immediate()),
+                        "fsub_fast" => bx.fsub_fast(args[0].immediate(), args[1].immediate()),
+                        "fmul_fast" => bx.fmul_fast(args[0].immediate(), args[1].immediate()),
+                        "fdiv_fast" => bx.fdiv_fast(args[0].immediate(), args[1].immediate()),
+                        "frem_fast" => bx.frem_fast(args[0].immediate(), args[1].immediate()),
                         _ => bug!(),
                     },
                 None => {
@@ -394,23 +394,23 @@
         },
 
         "discriminant_value" => {
-            args[0].deref(bcx.ccx).trans_get_discr(bcx, ret_ty)
+            args[0].deref(bx.cx).trans_get_discr(bx, ret_ty)
         }
 
         "align_offset" => {
             // `ptr as usize`
-            let ptr_val = bcx.ptrtoint(args[0].immediate(), bcx.ccx.isize_ty());
+            let ptr_val = bx.ptrtoint(args[0].immediate(), bx.cx.isize_ty);
             // `ptr_val % align`
             let align = args[1].immediate();
-            let offset = bcx.urem(ptr_val, align);
-            let zero = C_null(bcx.ccx.isize_ty());
+            let offset = bx.urem(ptr_val, align);
+            let zero = C_null(bx.cx.isize_ty);
             // `offset == 0`
-            let is_zero = bcx.icmp(llvm::IntPredicate::IntEQ, offset, zero);
+            let is_zero = bx.icmp(llvm::IntPredicate::IntEQ, offset, zero);
             // `if offset == 0 { 0 } else { align - offset }`
-            bcx.select(is_zero, zero, bcx.sub(align, offset))
+            bx.select(is_zero, zero, bx.sub(align, offset))
         }
         name if name.starts_with("simd_") => {
-            match generic_simd_intrinsic(bcx, name,
+            match generic_simd_intrinsic(bx, name,
                                          callee_ty,
                                          args,
                                          ret_ty, llret_ty,
@@ -439,16 +439,16 @@
                         (SequentiallyConsistent, Monotonic),
                     "failacq" if is_cxchg =>
                         (SequentiallyConsistent, Acquire),
-                    _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
+                    _ => cx.sess().fatal("unknown ordering in atomic intrinsic")
                 },
                 4 => match (split[2], split[3]) {
                     ("acq", "failrelaxed") if is_cxchg =>
                         (Acquire, Monotonic),
                     ("acqrel", "failrelaxed") if is_cxchg =>
                         (AcquireRelease, Monotonic),
-                    _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
+                    _ => cx.sess().fatal("unknown ordering in atomic intrinsic")
                 },
-                _ => ccx.sess().fatal("Atomic intrinsic not in correct format"),
+                _ => cx.sess().fatal("Atomic intrinsic not in correct format"),
             };
 
             let invalid_monomorphization = |ty| {
@@ -460,22 +460,22 @@
             match split[1] {
                 "cxchg" | "cxchgweak" => {
                     let ty = substs.type_at(0);
-                    if int_type_width_signed(ty, ccx).is_some() {
+                    if int_type_width_signed(ty, cx).is_some() {
                         let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False };
-                        let pair = bcx.atomic_cmpxchg(
+                        let pair = bx.atomic_cmpxchg(
                             args[0].immediate(),
                             args[1].immediate(),
                             args[2].immediate(),
                             order,
                             failorder,
                             weak);
-                        let val = bcx.extract_value(pair, 0);
-                        let success = bcx.zext(bcx.extract_value(pair, 1), Type::bool(bcx.ccx));
+                        let val = bx.extract_value(pair, 0);
+                        let success = bx.zext(bx.extract_value(pair, 1), Type::bool(bx.cx));
 
-                        let dest = result.project_field(bcx, 0);
-                        bcx.store(val, dest.llval, dest.align);
-                        let dest = result.project_field(bcx, 1);
-                        bcx.store(success, dest.llval, dest.align);
+                        let dest = result.project_field(bx, 0);
+                        bx.store(val, dest.llval, dest.align);
+                        let dest = result.project_field(bx, 1);
+                        bx.store(success, dest.llval, dest.align);
                         return;
                     } else {
                         return invalid_monomorphization(ty);
@@ -484,9 +484,9 @@
 
                 "load" => {
                     let ty = substs.type_at(0);
-                    if int_type_width_signed(ty, ccx).is_some() {
-                        let align = ccx.align_of(ty);
-                        bcx.atomic_load(args[0].immediate(), order, align)
+                    if int_type_width_signed(ty, cx).is_some() {
+                        let align = cx.align_of(ty);
+                        bx.atomic_load(args[0].immediate(), order, align)
                     } else {
                         return invalid_monomorphization(ty);
                     }
@@ -494,9 +494,9 @@
 
                 "store" => {
                     let ty = substs.type_at(0);
-                    if int_type_width_signed(ty, ccx).is_some() {
-                        let align = ccx.align_of(ty);
-                        bcx.atomic_store(args[1].immediate(), args[0].immediate(), order, align);
+                    if int_type_width_signed(ty, cx).is_some() {
+                        let align = cx.align_of(ty);
+                        bx.atomic_store(args[1].immediate(), args[0].immediate(), order, align);
                         return;
                     } else {
                         return invalid_monomorphization(ty);
@@ -504,12 +504,12 @@
                 }
 
                 "fence" => {
-                    bcx.atomic_fence(order, llvm::SynchronizationScope::CrossThread);
+                    bx.atomic_fence(order, llvm::SynchronizationScope::CrossThread);
                     return;
                 }
 
                 "singlethreadfence" => {
-                    bcx.atomic_fence(order, llvm::SynchronizationScope::SingleThread);
+                    bx.atomic_fence(order, llvm::SynchronizationScope::SingleThread);
                     return;
                 }
 
@@ -527,12 +527,12 @@
                         "min"   => llvm::AtomicMin,
                         "umax"  => llvm::AtomicUMax,
                         "umin"  => llvm::AtomicUMin,
-                        _ => ccx.sess().fatal("unknown atomic operation")
+                        _ => cx.sess().fatal("unknown atomic operation")
                     };
 
                     let ty = substs.type_at(0);
-                    if int_type_width_signed(ty, ccx).is_some() {
-                        bcx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order)
+                    if int_type_width_signed(ty, cx).is_some() {
+                        bx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order)
                     } else {
                         return invalid_monomorphization(ty);
                     }
@@ -542,16 +542,16 @@
 
         "nontemporal_store" => {
             let tp_ty = substs.type_at(0);
-            let dst = args[0].deref(bcx.ccx);
+            let dst = args[0].deref(bx.cx);
             let val = if let OperandValue::Ref(ptr, align) = args[1].val {
-                bcx.load(ptr, align)
+                bx.load(ptr, align)
             } else {
-                from_immediate(bcx, args[1].immediate())
+                from_immediate(bx, args[1].immediate())
             };
-            let ptr = bcx.pointercast(dst.llval, val_ty(val).ptr_to());
-            let store = bcx.nontemporal_store(val, ptr);
+            let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to());
+            let store = bx.nontemporal_store(val, ptr);
             unsafe {
-                llvm::LLVMSetAlignment(store, ccx.align_of(tp_ty).abi() as u32);
+                llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32);
             }
             return
         }
@@ -565,39 +565,39 @@
                 assert_eq!(x.len(), 1);
                 x.into_iter().next().unwrap()
             }
-            fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type) -> Vec<Type> {
+            fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec<Type> {
                 use intrinsics::Type::*;
                 match *t {
-                    Void => vec![Type::void(ccx)],
+                    Void => vec![Type::void(cx)],
                     Integer(_signed, _width, llvm_width) => {
-                        vec![Type::ix(ccx, llvm_width as u64)]
+                        vec![Type::ix(cx, llvm_width as u64)]
                     }
                     Float(x) => {
                         match x {
-                            32 => vec![Type::f32(ccx)],
-                            64 => vec![Type::f64(ccx)],
+                            32 => vec![Type::f32(cx)],
+                            64 => vec![Type::f64(cx)],
                             _ => bug!()
                         }
                     }
                     Pointer(ref t, ref llvm_elem, _const) => {
                         let t = llvm_elem.as_ref().unwrap_or(t);
-                        let elem = one(ty_to_type(ccx, t));
+                        let elem = one(ty_to_type(cx, t));
                         vec![elem.ptr_to()]
                     }
                     Vector(ref t, ref llvm_elem, length) => {
                         let t = llvm_elem.as_ref().unwrap_or(t);
-                        let elem = one(ty_to_type(ccx, t));
+                        let elem = one(ty_to_type(cx, t));
                         vec![Type::vector(&elem, length as u64)]
                     }
                     Aggregate(false, ref contents) => {
                         let elems = contents.iter()
-                                            .map(|t| one(ty_to_type(ccx, t)))
+                                            .map(|t| one(ty_to_type(cx, t)))
                                             .collect::<Vec<_>>();
-                        vec![Type::struct_(ccx, &elems, false)]
+                        vec![Type::struct_(cx, &elems, false)]
                     }
                     Aggregate(true, ref contents) => {
                         contents.iter()
-                                .flat_map(|t| ty_to_type(ccx, t))
+                                .flat_map(|t| ty_to_type(cx, t))
                                 .collect()
                     }
                 }
@@ -607,7 +607,7 @@
             // qux` to be converted into `foo, bar, baz, qux`, integer
             // arguments to be truncated as needed and pointers to be
             // cast.
-            fn modify_as_needed<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+            fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                                           t: &intrinsics::Type,
                                           arg: &OperandRef<'tcx>)
                                           -> Vec<ValueRef>
@@ -620,29 +620,29 @@
                         // This assumes the type is "simple", i.e. no
                         // destructors, and the contents are SIMD
                         // etc.
-                        assert!(!bcx.ccx.shared().type_needs_drop(arg.layout.ty));
+                        assert!(!bx.cx.type_needs_drop(arg.layout.ty));
                         let (ptr, align) = match arg.val {
                             OperandValue::Ref(ptr, align) => (ptr, align),
                             _ => bug!()
                         };
                         let arg = PlaceRef::new_sized(ptr, arg.layout, align);
                         (0..contents.len()).map(|i| {
-                            arg.project_field(bcx, i).load(bcx).immediate()
+                            arg.project_field(bx, i).load(bx).immediate()
                         }).collect()
                     }
                     intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
-                        let llvm_elem = one(ty_to_type(bcx.ccx, llvm_elem));
-                        vec![bcx.pointercast(arg.immediate(), llvm_elem.ptr_to())]
+                        let llvm_elem = one(ty_to_type(bx.cx, llvm_elem));
+                        vec![bx.pointercast(arg.immediate(), llvm_elem.ptr_to())]
                     }
                     intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => {
-                        let llvm_elem = one(ty_to_type(bcx.ccx, llvm_elem));
-                        vec![bcx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))]
+                        let llvm_elem = one(ty_to_type(bx.cx, llvm_elem));
+                        vec![bx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))]
                     }
                     intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
                         // the LLVM intrinsic uses a smaller integer
                         // size than the C intrinsic's signature, so
                         // we have to trim it down here.
-                        vec![bcx.trunc(arg.immediate(), Type::ix(bcx.ccx, llvm_width as u64))]
+                        vec![bx.trunc(arg.immediate(), Type::ix(bx.cx, llvm_width as u64))]
                     }
                     _ => vec![arg.immediate()],
                 }
@@ -650,22 +650,22 @@
 
 
             let inputs = intr.inputs.iter()
-                                    .flat_map(|t| ty_to_type(ccx, t))
+                                    .flat_map(|t| ty_to_type(cx, t))
                                     .collect::<Vec<_>>();
 
-            let outputs = one(ty_to_type(ccx, &intr.output));
+            let outputs = one(ty_to_type(cx, &intr.output));
 
             let llargs: Vec<_> = intr.inputs.iter().zip(args).flat_map(|(t, arg)| {
-                modify_as_needed(bcx, t, arg)
+                modify_as_needed(bx, t, arg)
             }).collect();
             assert_eq!(inputs.len(), llargs.len());
 
             let val = match intr.definition {
                 intrinsics::IntrinsicDef::Named(name) => {
-                    let f = declare::declare_cfn(ccx,
+                    let f = declare::declare_cfn(cx,
                                                  name,
                                                  Type::func(&inputs, &outputs));
-                    bcx.call(f, &llargs, None)
+                    bx.call(f, &llargs, None)
                 }
             };
 
@@ -675,9 +675,9 @@
                     assert!(!flatten);
 
                     for i in 0..elems.len() {
-                        let dest = result.project_field(bcx, i);
-                        let val = bcx.extract_value(val, i as u64);
-                        bcx.store(val, dest.llval, dest.align);
+                        let dest = result.project_field(bx, i);
+                        let val = bx.extract_value(val, i as u64);
+                        bx.store(val, dest.llval, dest.align);
                     }
                     return;
                 }
@@ -688,16 +688,16 @@
 
     if !fn_ty.ret.is_ignore() {
         if let PassMode::Cast(ty) = fn_ty.ret.mode {
-            let ptr = bcx.pointercast(result.llval, ty.llvm_type(ccx).ptr_to());
-            bcx.store(llval, ptr, result.align);
+            let ptr = bx.pointercast(result.llval, ty.llvm_type(cx).ptr_to());
+            bx.store(llval, ptr, result.align);
         } else {
-            OperandRef::from_immediate_or_packed_pair(bcx, llval, result.layout)
-                .val.store(bcx, result);
+            OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
+                .val.store(bx, result);
         }
     }
 }
 
-fn copy_intrinsic<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
+fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                             allow_overlap: bool,
                             volatile: bool,
                             ty: Ty<'tcx>,
@@ -705,10 +705,10 @@
                             src: ValueRef,
                             count: ValueRef)
                             -> ValueRef {
-    let ccx = bcx.ccx;
-    let (size, align) = ccx.size_and_align_of(ty);
-    let size = C_usize(ccx, size.bytes());
-    let align = C_i32(ccx, align.abi() as i32);
+    let cx = bx.cx;
+    let (size, align) = cx.size_and_align_of(ty);
+    let size = C_usize(cx, size.bytes());
+    let align = C_i32(cx, align.abi() as i32);
 
     let operation = if allow_overlap {
         "memmove"
@@ -717,53 +717,53 @@
     };
 
     let name = format!("llvm.{}.p0i8.p0i8.i{}", operation,
-                       ccx.data_layout().pointer_size.bits());
+                       cx.data_layout().pointer_size.bits());
 
-    let dst_ptr = bcx.pointercast(dst, Type::i8p(ccx));
-    let src_ptr = bcx.pointercast(src, Type::i8p(ccx));
-    let llfn = ccx.get_intrinsic(&name);
+    let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
+    let src_ptr = bx.pointercast(src, Type::i8p(cx));
+    let llfn = cx.get_intrinsic(&name);
 
-    bcx.call(llfn,
+    bx.call(llfn,
         &[dst_ptr,
         src_ptr,
-        bcx.mul(size, count),
+        bx.mul(size, count),
         align,
-        C_bool(ccx, volatile)],
+        C_bool(cx, volatile)],
         None)
 }
 
 fn memset_intrinsic<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     volatile: bool,
     ty: Ty<'tcx>,
     dst: ValueRef,
     val: ValueRef,
     count: ValueRef
 ) -> ValueRef {
-    let ccx = bcx.ccx;
-    let (size, align) = ccx.size_and_align_of(ty);
-    let size = C_usize(ccx, size.bytes());
-    let align = C_i32(ccx, align.abi() as i32);
-    let dst = bcx.pointercast(dst, Type::i8p(ccx));
-    call_memset(bcx, dst, val, bcx.mul(size, count), align, volatile)
+    let cx = bx.cx;
+    let (size, align) = cx.size_and_align_of(ty);
+    let size = C_usize(cx, size.bytes());
+    let align = C_i32(cx, align.abi() as i32);
+    let dst = bx.pointercast(dst, Type::i8p(cx));
+    call_memset(bx, dst, val, bx.mul(size, count), align, volatile)
 }
 
 fn try_intrinsic<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
-    ccx: &CrateContext,
+    bx: &Builder<'a, 'tcx>,
+    cx: &CodegenCx,
     func: ValueRef,
     data: ValueRef,
     local_ptr: ValueRef,
     dest: ValueRef,
 ) {
-    if bcx.sess().no_landing_pads() {
-        bcx.call(func, &[data], None);
-        let ptr_align = bcx.tcx().data_layout.pointer_align;
-        bcx.store(C_null(Type::i8p(&bcx.ccx)), dest, ptr_align);
-    } else if wants_msvc_seh(bcx.sess()) {
-        trans_msvc_try(bcx, ccx, func, data, local_ptr, dest);
+    if bx.sess().no_landing_pads() {
+        bx.call(func, &[data], None);
+        let ptr_align = bx.tcx().data_layout.pointer_align;
+        bx.store(C_null(Type::i8p(&bx.cx)), dest, ptr_align);
+    } else if wants_msvc_seh(bx.sess()) {
+        trans_msvc_try(bx, cx, func, data, local_ptr, dest);
     } else {
-        trans_gnu_try(bcx, ccx, func, data, local_ptr, dest);
+        trans_gnu_try(bx, cx, func, data, local_ptr, dest);
     }
 }
 
@@ -774,25 +774,25 @@
 // instructions are meant to work for all targets, as of the time of this
 // writing, however, LLVM does not recommend the usage of these new instructions
 // as the old ones are still more optimized.
-fn trans_msvc_try<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
-                            ccx: &CrateContext,
+fn trans_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
+                            cx: &CodegenCx,
                             func: ValueRef,
                             data: ValueRef,
                             local_ptr: ValueRef,
                             dest: ValueRef) {
-    let llfn = get_rust_try_fn(ccx, &mut |bcx| {
-        let ccx = bcx.ccx;
+    let llfn = get_rust_try_fn(cx, &mut |bx| {
+        let cx = bx.cx;
 
-        bcx.set_personality_fn(bcx.ccx.eh_personality());
+        bx.set_personality_fn(bx.cx.eh_personality());
 
-        let normal = bcx.build_sibling_block("normal");
-        let catchswitch = bcx.build_sibling_block("catchswitch");
-        let catchpad = bcx.build_sibling_block("catchpad");
-        let caught = bcx.build_sibling_block("caught");
+        let normal = bx.build_sibling_block("normal");
+        let catchswitch = bx.build_sibling_block("catchswitch");
+        let catchpad = bx.build_sibling_block("catchpad");
+        let caught = bx.build_sibling_block("caught");
 
-        let func = llvm::get_param(bcx.llfn(), 0);
-        let data = llvm::get_param(bcx.llfn(), 1);
-        let local_ptr = llvm::get_param(bcx.llfn(), 2);
+        let func = llvm::get_param(bx.llfn(), 0);
+        let data = llvm::get_param(bx.llfn(), 1);
+        let local_ptr = llvm::get_param(bx.llfn(), 2);
 
         // We're generating an IR snippet that looks like:
         //
@@ -833,42 +833,42 @@
         //      }
         //
         // More information can be found in libstd's seh.rs implementation.
-        let i64p = Type::i64(ccx).ptr_to();
-        let ptr_align = bcx.tcx().data_layout.pointer_align;
-        let slot = bcx.alloca(i64p, "slot", ptr_align);
-        bcx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
+        let i64p = Type::i64(cx).ptr_to();
+        let ptr_align = bx.tcx().data_layout.pointer_align;
+        let slot = bx.alloca(i64p, "slot", ptr_align);
+        bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
             None);
 
-        normal.ret(C_i32(ccx, 0));
+        normal.ret(C_i32(cx, 0));
 
         let cs = catchswitch.catch_switch(None, None, 1);
         catchswitch.add_handler(cs, catchpad.llbb());
 
-        let tcx = ccx.tcx();
+        let tcx = cx.tcx;
         let tydesc = match tcx.lang_items().msvc_try_filter() {
-            Some(did) => ::consts::get_static(ccx, did),
+            Some(did) => ::consts::get_static(cx, did),
             None => bug!("msvc_try_filter not defined"),
         };
-        let tok = catchpad.catch_pad(cs, &[tydesc, C_i32(ccx, 0), slot]);
+        let tok = catchpad.catch_pad(cs, &[tydesc, C_i32(cx, 0), slot]);
         let addr = catchpad.load(slot, ptr_align);
 
-        let i64_align = bcx.tcx().data_layout.i64_align;
+        let i64_align = bx.tcx().data_layout.i64_align;
         let arg1 = catchpad.load(addr, i64_align);
-        let val1 = C_i32(ccx, 1);
+        let val1 = C_i32(cx, 1);
         let arg2 = catchpad.load(catchpad.inbounds_gep(addr, &[val1]), i64_align);
         let local_ptr = catchpad.bitcast(local_ptr, i64p);
         catchpad.store(arg1, local_ptr, i64_align);
         catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align);
         catchpad.catch_ret(tok, caught.llbb());
 
-        caught.ret(C_i32(ccx, 1));
+        caught.ret(C_i32(cx, 1));
     });
 
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
-    let ret = bcx.call(llfn, &[func, data, local_ptr], None);
-    let i32_align = bcx.tcx().data_layout.i32_align;
-    bcx.store(ret, dest, i32_align);
+    let ret = bx.call(llfn, &[func, data, local_ptr], None);
+    let i32_align = bx.tcx().data_layout.i32_align;
+    bx.store(ret, dest, i32_align);
 }
 
 // Definition of the standard "try" function for Rust using the GNU-like model
@@ -882,18 +882,18 @@
 // function calling it, and that function may already have other personality
 // functions in play. By calling a shim we're guaranteed that our shim will have
 // the right personality function.
-fn trans_gnu_try<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
-                           ccx: &CrateContext,
+fn trans_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
+                           cx: &CodegenCx,
                            func: ValueRef,
                            data: ValueRef,
                            local_ptr: ValueRef,
                            dest: ValueRef) {
-    let llfn = get_rust_try_fn(ccx, &mut |bcx| {
-        let ccx = bcx.ccx;
+    let llfn = get_rust_try_fn(cx, &mut |bx| {
+        let cx = bx.cx;
 
         // Translates the shims described above:
         //
-        //   bcx:
+        //   bx:
         //      invoke %func(%args...) normal %normal unwind %catch
         //
         //   normal:
@@ -908,14 +908,14 @@
         // expected to be `*mut *mut u8` for this to actually work, but that's
         // managed by the standard library.
 
-        let then = bcx.build_sibling_block("then");
-        let catch = bcx.build_sibling_block("catch");
+        let then = bx.build_sibling_block("then");
+        let catch = bx.build_sibling_block("catch");
 
-        let func = llvm::get_param(bcx.llfn(), 0);
-        let data = llvm::get_param(bcx.llfn(), 1);
-        let local_ptr = llvm::get_param(bcx.llfn(), 2);
-        bcx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
-        then.ret(C_i32(ccx, 0));
+        let func = llvm::get_param(bx.llfn(), 0);
+        let data = llvm::get_param(bx.llfn(), 1);
+        let local_ptr = llvm::get_param(bx.llfn(), 2);
+        bx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
+        then.ret(C_i32(cx, 0));
 
         // Type indicator for the exception being thrown.
         //
@@ -923,41 +923,41 @@
         // being thrown.  The second value is a "selector" indicating which of
         // the landing pad clauses the exception's type had been matched to.
         // rust_try ignores the selector.
-        let lpad_ty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)],
+        let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)],
                                     false);
-        let vals = catch.landing_pad(lpad_ty, bcx.ccx.eh_personality(), 1, catch.llfn());
-        catch.add_clause(vals, C_null(Type::i8p(ccx)));
+        let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
+        catch.add_clause(vals, C_null(Type::i8p(cx)));
         let ptr = catch.extract_value(vals, 0);
-        let ptr_align = bcx.tcx().data_layout.pointer_align;
-        catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(ccx).ptr_to()), ptr_align);
-        catch.ret(C_i32(ccx, 1));
+        let ptr_align = bx.tcx().data_layout.pointer_align;
+        catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(cx).ptr_to()), ptr_align);
+        catch.ret(C_i32(cx, 1));
     });
 
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
-    let ret = bcx.call(llfn, &[func, data, local_ptr], None);
-    let i32_align = bcx.tcx().data_layout.i32_align;
-    bcx.store(ret, dest, i32_align);
+    let ret = bx.call(llfn, &[func, data, local_ptr], None);
+    let i32_align = bx.tcx().data_layout.i32_align;
+    bx.store(ret, dest, i32_align);
 }
 
 // Helper function to give a Block to a closure to translate a shim function.
 // This is currently primarily used for the `try` intrinsic functions above.
-fn gen_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     name: &str,
                     inputs: Vec<Ty<'tcx>>,
                     output: Ty<'tcx>,
                     trans: &mut for<'b> FnMut(Builder<'b, 'tcx>))
                     -> ValueRef {
-    let rust_fn_ty = ccx.tcx().mk_fn_ptr(ty::Binder(ccx.tcx().mk_fn_sig(
+    let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder(cx.tcx.mk_fn_sig(
         inputs.into_iter(),
         output,
         false,
         hir::Unsafety::Unsafe,
         Abi::Rust
     )));
-    let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty);
-    let bcx = Builder::new_block(ccx, llfn, "entry-block");
-    trans(bcx);
+    let llfn = declare::define_internal_fn(cx, name, rust_fn_ty);
+    let bx = Builder::new_block(cx, llfn, "entry-block");
+    trans(bx);
     llfn
 }
 
@@ -965,15 +965,15 @@
 // catch exceptions.
 //
 // This function is only generated once and is then cached.
-fn get_rust_try_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              trans: &mut for<'b> FnMut(Builder<'b, 'tcx>))
                              -> ValueRef {
-    if let Some(llfn) = ccx.rust_try_fn().get() {
+    if let Some(llfn) = cx.rust_try_fn.get() {
         return llfn;
     }
 
     // Define the type up front for the signature of the rust_try function.
-    let tcx = ccx.tcx();
+    let tcx = cx.tcx;
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
     let fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
         iter::once(i8p),
@@ -983,8 +983,8 @@
         Abi::Rust
     )));
     let output = tcx.types.i32;
-    let rust_try = gen_fn(ccx, "__rust_try", vec![fn_ty, i8p, i8p], output, trans);
-    ccx.rust_try_fn().set(Some(rust_try));
+    let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, trans);
+    cx.rust_try_fn.set(Some(rust_try));
     return rust_try
 }
 
@@ -993,7 +993,7 @@
 }
 
 fn generic_simd_intrinsic<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     name: &str,
     callee_ty: Ty<'tcx>,
     args: &[OperandRef<'tcx>],
@@ -1008,7 +1008,7 @@
         };
         ($msg: tt, $($fmt: tt)*) => {
             span_invalid_monomorphization_error(
-                bcx.sess(), span,
+                bx.sess(), span,
                 &format!(concat!("invalid monomorphization of `{}` intrinsic: ",
                                  $msg),
                          name, $($fmt)*));
@@ -1030,7 +1030,7 @@
 
 
 
-    let tcx = bcx.tcx();
+    let tcx = bx.tcx();
     let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx));
     let arg_tys = sig.inputs();
 
@@ -1064,7 +1064,7 @@
                  ret_ty,
                  ret_ty.simd_type(tcx));
 
-        return Ok(compare_simd_types(bcx,
+        return Ok(compare_simd_types(bx,
                                      args[0].immediate(),
                                      args[1].immediate(),
                                      in_elem,
@@ -1109,7 +1109,7 @@
                                     arg_idx, total_len);
                         None
                     }
-                    Some(idx) => Some(C_i32(bcx.ccx, idx as i32)),
+                    Some(idx) => Some(C_i32(bx.cx, idx as i32)),
                 }
             })
             .collect();
@@ -1118,7 +1118,7 @@
             None => return Ok(C_null(llret_ty))
         };
 
-        return Ok(bcx.shuffle_vector(args[0].immediate(),
+        return Ok(bx.shuffle_vector(args[0].immediate(),
                                      args[1].immediate(),
                                      C_vector(&indices)))
     }
@@ -1127,7 +1127,7 @@
         require!(in_elem == arg_tys[2],
                  "expected inserted type `{}` (element of input `{}`), found `{}`",
                  in_elem, in_ty, arg_tys[2]);
-        return Ok(bcx.insert_element(args[0].immediate(),
+        return Ok(bx.insert_element(args[0].immediate(),
                                      args[2].immediate(),
                                      args[1].immediate()))
     }
@@ -1135,7 +1135,7 @@
         require!(ret_ty == in_elem,
                  "expected return type `{}` (element of input `{}`), found `{}`",
                  in_elem, in_ty, ret_ty);
-        return Ok(bcx.extract_element(args[0].immediate(), args[1].immediate()))
+        return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()))
     }
 
     if name == "simd_cast" {
@@ -1171,34 +1171,34 @@
         match (in_style, out_style) {
             (Style::Int(in_is_signed), Style::Int(_)) => {
                 return Ok(match in_width.cmp(&out_width) {
-                    Ordering::Greater => bcx.trunc(args[0].immediate(), llret_ty),
+                    Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty),
                     Ordering::Equal => args[0].immediate(),
                     Ordering::Less => if in_is_signed {
-                        bcx.sext(args[0].immediate(), llret_ty)
+                        bx.sext(args[0].immediate(), llret_ty)
                     } else {
-                        bcx.zext(args[0].immediate(), llret_ty)
+                        bx.zext(args[0].immediate(), llret_ty)
                     }
                 })
             }
             (Style::Int(in_is_signed), Style::Float) => {
                 return Ok(if in_is_signed {
-                    bcx.sitofp(args[0].immediate(), llret_ty)
+                    bx.sitofp(args[0].immediate(), llret_ty)
                 } else {
-                    bcx.uitofp(args[0].immediate(), llret_ty)
+                    bx.uitofp(args[0].immediate(), llret_ty)
                 })
             }
             (Style::Float, Style::Int(out_is_signed)) => {
                 return Ok(if out_is_signed {
-                    bcx.fptosi(args[0].immediate(), llret_ty)
+                    bx.fptosi(args[0].immediate(), llret_ty)
                 } else {
-                    bcx.fptoui(args[0].immediate(), llret_ty)
+                    bx.fptoui(args[0].immediate(), llret_ty)
                 })
             }
             (Style::Float, Style::Float) => {
                 return Ok(match in_width.cmp(&out_width) {
-                    Ordering::Greater => bcx.fptrunc(args[0].immediate(), llret_ty),
+                    Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty),
                     Ordering::Equal => args[0].immediate(),
-                    Ordering::Less => bcx.fpext(args[0].immediate(), llret_ty)
+                    Ordering::Less => bx.fpext(args[0].immediate(), llret_ty)
                 })
             }
             _ => {/* Unsupported. Fallthrough. */}
@@ -1213,7 +1213,7 @@
             $(if name == stringify!($name) {
                 match in_elem.sty {
                     $($(ty::$p(_))|* => {
-                        return Ok(bcx.$call(args[0].immediate(), args[1].immediate()))
+                        return Ok(bx.$call(args[0].immediate(), args[1].immediate()))
                     })*
                     _ => {},
                 }
@@ -1243,11 +1243,11 @@
 // Returns None if the type is not an integer
 // FIXME: there’s multiple of this functions, investigate using some of the already existing
 // stuffs.
-fn int_type_width_signed(ty: Ty, ccx: &CrateContext) -> Option<(u64, bool)> {
+fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
     match ty.sty {
         ty::TyInt(t) => Some((match t {
-            ast::IntTy::Is => {
-                match &ccx.tcx().sess.target.target.target_pointer_width[..] {
+            ast::IntTy::Isize => {
+                match &cx.tcx.sess.target.target.target_pointer_width[..] {
                     "16" => 16,
                     "32" => 32,
                     "64" => 64,
@@ -1261,8 +1261,8 @@
             ast::IntTy::I128 => 128,
         }, true)),
         ty::TyUint(t) => Some((match t {
-            ast::UintTy::Us => {
-                match &ccx.tcx().sess.target.target.target_pointer_width[..] {
+            ast::UintTy::Usize => {
+                match &cx.tcx.sess.target.target.target_pointer_width[..] {
                     "16" => 16,
                     "32" => 32,
                     "64" => 64,
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index c4849c6..b679970 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -22,6 +22,7 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(custom_attribute)]
+#![feature(fs_read_write)]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
 #![feature(i128)]
@@ -32,6 +33,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
+#![feature(optin_builtin_traits)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
@@ -65,11 +67,9 @@
 extern crate cc; // Used to locate MSVC
 extern crate tempdir;
 
-pub use base::trans_crate;
 use back::bytecode::RLIB_BYTECODE_EXTENSION;
 
-pub use metadata::LlvmMetadataLoader;
-pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
+pub use llvm_util::{target_features, print_version, print_passes};
 
 use std::any::Any;
 use std::path::PathBuf;
@@ -80,24 +80,24 @@
 use rustc::hir::def_id::CrateNum;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
-use rustc::session::Session;
-use rustc::session::config::{OutputFilenames, OutputType};
+use rustc::session::{Session, CompileIncomplete};
+use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
 use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
-
 use rustc_mir::monomorphize;
+use rustc_trans_utils::trans_crate::TransCrate;
 
 mod diagnostics;
 
-pub mod back {
+mod back {
+    pub use rustc_trans_utils::symbol_names;
     mod archive;
     pub mod bytecode;
     mod command;
-    pub(crate) mod linker;
+    pub mod linker;
     pub mod link;
     mod lto;
-    pub(crate) mod symbol_export;
-    pub(crate) mod symbol_names;
+    pub mod symbol_export;
     pub mod write;
     mod rpath;
 }
@@ -105,7 +105,6 @@
 mod abi;
 mod allocator;
 mod asm;
-mod assert_module_sources;
 mod attributes;
 mod base;
 mod builder;
@@ -138,7 +137,6 @@
 mod metadata;
 mod meth;
 mod mir;
-mod symbol_names_test;
 mod time_graph;
 mod trans_item;
 mod type_;
@@ -147,56 +145,118 @@
 
 pub struct LlvmTransCrate(());
 
+impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
+impl !Sync for LlvmTransCrate {}
+
 impl LlvmTransCrate {
-    pub fn new() -> Self {
-        LlvmTransCrate(())
+    pub fn new(sess: &Session) -> Box<TransCrate> {
+        llvm_util::init(sess); // Make sure llvm is inited
+        box LlvmTransCrate(())
     }
 }
 
-impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate {
-    type MetadataLoader = metadata::LlvmMetadataLoader;
-    type OngoingCrateTranslation = back::write::OngoingCrateTranslation;
-    type TranslatedCrate = CrateTranslation;
+impl TransCrate for LlvmTransCrate {
+    fn print(&self, req: PrintRequest, sess: &Session) {
+        match req {
+            PrintRequest::RelocationModels => {
+                println!("Available relocation models:");
+                for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
+                    println!("    {}", name);
+                }
+                println!("");
+            }
+            PrintRequest::CodeModels => {
+                println!("Available code models:");
+                for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
+                    println!("    {}", name);
+                }
+                println!("");
+            }
+            PrintRequest::TlsModels => {
+                println!("Available TLS models:");
+                for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
+                    println!("    {}", name);
+                }
+                println!("");
+            }
+            req => llvm_util::print(req, sess),
+        }
+    }
 
-    fn metadata_loader() -> Box<MetadataLoader> {
+    fn target_features(&self, sess: &Session) -> Vec<Symbol> {
+        target_features(sess)
+    }
+
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
         box metadata::LlvmMetadataLoader
     }
 
-    fn provide(providers: &mut ty::maps::Providers) {
+    fn provide(&self, providers: &mut ty::maps::Providers) {
         back::symbol_names::provide(providers);
         back::symbol_export::provide(providers);
         base::provide(providers);
+        attributes::provide(providers);
     }
 
-    fn provide_extern(providers: &mut ty::maps::Providers) {
+    fn provide_extern(&self, providers: &mut ty::maps::Providers) {
         back::symbol_export::provide_extern(providers);
     }
 
     fn trans_crate<'a, 'tcx>(
+        &self,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation {
-        base::trans_crate(tcx, rx)
+    ) -> Box<Any> {
+        box base::trans_crate(tcx, rx)
     }
 
-    fn join_trans(
-        trans: Self::OngoingCrateTranslation,
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
         sess: &Session,
-        dep_graph: &DepGraph
-    ) -> Self::TranslatedCrate {
-        trans.join(sess, dep_graph)
-    }
+        dep_graph: &DepGraph,
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete>{
+        use rustc::util::common::time;
+        let trans = trans.downcast::<::back::write::OngoingCrateTranslation>()
+            .expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box<Any>")
+            .join(sess, dep_graph);
+        if sess.opts.debugging_opts.incremental_info {
+            back::write::dump_incremental_data(&trans);
+        }
 
-    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
-        back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str());
-    }
+        time(sess.time_passes(),
+             "serialize work products",
+             move || rustc_incremental::save_work_products(sess, &dep_graph));
 
-    fn dump_incremental_data(trans: &Self::TranslatedCrate) {
-        back::write::dump_incremental_data(trans);
+        sess.compile_status()?;
+
+        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
+                                                   i == OutputType::Metadata) {
+            return Ok(());
+        }
+
+        // Run the linker on any artifacts that resulted from the LLVM run.
+        // This should produce either a finished executable or library.
+        time(sess.time_passes(), "linking", || {
+            back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str());
+        });
+
+        // Now that we won't touch anything in the incremental compilation directory
+        // any more, we can finalize it (which involves renaming it)
+        rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
+
+        Ok(())
     }
 }
 
-pub struct ModuleTranslation {
+/// This is the entrypoint for a hot plugged rustc_trans
+#[no_mangle]
+pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
+    LlvmTransCrate::new(sess)
+}
+
+struct ModuleTranslation {
     /// The name of the module. When the crate may be saved between
     /// compilations, incremental compilation requires that name be
     /// unique amongst **all** crates.  Therefore, it should contain
@@ -204,26 +264,26 @@
     /// as the crate name and disambiguator.
     name: String,
     llmod_id: String,
-    pub source: ModuleSource,
-    pub kind: ModuleKind,
+    source: ModuleSource,
+    kind: ModuleKind,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub enum ModuleKind {
+enum ModuleKind {
     Regular,
     Metadata,
     Allocator,
 }
 
 impl ModuleTranslation {
-    pub fn llvm(&self) -> Option<&ModuleLlvm> {
+    fn llvm(&self) -> Option<&ModuleLlvm> {
         match self.source {
             ModuleSource::Translated(ref llvm) => Some(llvm),
             ModuleSource::Preexisting(_) => None,
         }
     }
 
-    pub fn into_compiled_module(self,
+    fn into_compiled_module(self,
                                 emit_obj: bool,
                                 emit_bc: bool,
                                 emit_bc_compressed: bool,
@@ -262,17 +322,17 @@
 }
 
 #[derive(Debug)]
-pub struct CompiledModule {
-    pub name: String,
-    pub llmod_id: String,
-    pub kind: ModuleKind,
-    pub pre_existing: bool,
-    pub object: Option<PathBuf>,
-    pub bytecode: Option<PathBuf>,
-    pub bytecode_compressed: Option<PathBuf>,
+struct CompiledModule {
+    name: String,
+    llmod_id: String,
+    kind: ModuleKind,
+    pre_existing: bool,
+    object: Option<PathBuf>,
+    bytecode: Option<PathBuf>,
+    bytecode_compressed: Option<PathBuf>,
 }
 
-pub enum ModuleSource {
+enum ModuleSource {
     /// Copy the `.o` files or whatever from the incr. comp. directory.
     Preexisting(WorkProduct),
 
@@ -281,9 +341,9 @@
 }
 
 #[derive(Debug)]
-pub struct ModuleLlvm {
+struct ModuleLlvm {
     llcx: llvm::ContextRef,
-    pub llmod: llvm::ModuleRef,
+    llmod: llvm::ModuleRef,
     tm: llvm::TargetMachineRef,
 }
 
@@ -300,20 +360,20 @@
     }
 }
 
-pub struct CrateTranslation {
-    pub crate_name: Symbol,
-    pub modules: Vec<CompiledModule>,
+struct CrateTranslation {
+    crate_name: Symbol,
+    modules: Vec<CompiledModule>,
     allocator_module: Option<CompiledModule>,
     metadata_module: CompiledModule,
-    pub link: rustc::middle::cstore::LinkMeta,
-    pub metadata: rustc::middle::cstore::EncodedMetadata,
+    link: rustc::middle::cstore::LinkMeta,
+    metadata: rustc::middle::cstore::EncodedMetadata,
     windows_subsystem: Option<String>,
     linker_info: back::linker::LinkerInfo,
     crate_info: CrateInfo,
 }
 
 // Misc info we load from metadata to persist beyond the tcx
-pub struct CrateInfo {
+struct CrateInfo {
     panic_runtime: Option<CrateNum>,
     compiler_builtins: Option<CrateNum>,
     profiler_runtime: Option<CrateNum>,
@@ -328,4 +388,5 @@
     used_crates_dynamic: Vec<(CrateNum, LibSource)>,
 }
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index a9ea961..1598800 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -13,17 +13,18 @@
 use llvm;
 use rustc::session::Session;
 use rustc::session::config::PrintRequest;
-use libc::{c_int, c_char};
-use std::ffi::CString;
+use libc::c_int;
+use std::ffi::{CStr, CString};
 
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Once;
 
-pub fn init(sess: &Session) {
+static POISONED: AtomicBool = AtomicBool::new(false);
+static INIT: Once = Once::new();
+
+pub(crate) fn init(sess: &Session) {
     unsafe {
         // Before we touch LLVM, make sure that multithreading is enabled.
-        static POISONED: AtomicBool = AtomicBool::new(false);
-        static INIT: Once = Once::new();
         INIT.call_once(|| {
             if llvm::LLVMStartMultithreaded() != 1 {
                 // use an extra bool to make sure that all future usage of LLVM
@@ -40,6 +41,13 @@
     }
 }
 
+fn require_inited() {
+    INIT.call_once(|| bug!("llvm is not initialized"));
+    if POISONED.load(Ordering::SeqCst) {
+        bug!("couldn't enable multi-threaded LLVM");
+    }
+}
+
 unsafe fn configure_llvm(sess: &Session) {
     let mut llvm_c_strs = Vec::new();
     let mut llvm_args = Vec::new();
@@ -85,7 +93,8 @@
                                                  "avx512dq\0", "avx512er\0",
                                                  "avx512f\0", "avx512ifma\0",
                                                  "avx512pf\0", "avx512vbmi\0",
-                                                 "avx512vl\0", "avx512vpopcntdq\0", "mmx\0"];
+                                                 "avx512vl\0", "avx512vpopcntdq\0",
+                                                 "mmx\0", "fxsr\0"];
 
 const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];
 
@@ -97,8 +106,18 @@
 const MIPS_WHITELIST: &'static [&'static str] = &["msa\0"];
 
 pub fn target_features(sess: &Session) -> Vec<Symbol> {
+    let whitelist = target_feature_whitelist(sess);
     let target_machine = create_target_machine(sess);
+    let mut features = Vec::new();
+    for feat in whitelist {
+        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr()) } {
+            features.push(Symbol::intern(feat.to_str().unwrap()));
+        }
+    }
+    features
+}
 
+pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
     let whitelist = match &*sess.target.target.arch {
         "arm" => ARM_WHITELIST,
         "aarch64" => AARCH64_WHITELIST,
@@ -108,18 +127,13 @@
         "powerpc" | "powerpc64" => POWERPC_WHITELIST,
         _ => &[],
     };
-
-    let mut features = Vec::new();
-    for feat in whitelist {
-        assert_eq!(feat.chars().last(), Some('\0'));
-        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
-            features.push(Symbol::intern(&feat[..feat.len() - 1]));
-        }
-    }
-    features
+    whitelist.iter().map(|m| {
+        CStr::from_bytes_with_nul(m.as_bytes()).unwrap()
+    }).collect()
 }
 
 pub fn print_version() {
+    // Can be called without initializing LLVM
     unsafe {
         println!("LLVM version: {}.{}",
                  llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
@@ -127,10 +141,12 @@
 }
 
 pub fn print_passes() {
+    // Can be called without initializing LLVM
     unsafe { llvm::LLVMRustPrintPasses(); }
 }
 
-pub fn print(req: PrintRequest, sess: &Session) {
+pub(crate) fn print(req: PrintRequest, sess: &Session) {
+    require_inited();
     let tm = create_target_machine(sess);
     unsafe {
         match req {
@@ -140,7 +156,3 @@
         }
     }
 }
-
-pub fn enable_llvm_debug() {
-    unsafe { llvm::LLVMRustSetDebug(1); }
-}
diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs
index 4be2774..6b542ae 100644
--- a/src/librustc_trans/meth.rs
+++ b/src/librustc_trans/meth.rs
@@ -33,30 +33,30 @@
         VirtualIndex(index as u64 + 3)
     }
 
-    pub fn get_fn(self, bcx: &Builder<'a, 'tcx>,
+    pub fn get_fn(self, bx: &Builder<'a, 'tcx>,
                   llvtable: ValueRef,
                   fn_ty: &FnType<'tcx>) -> ValueRef {
         // Load the data pointer from the object.
         debug!("get_fn({:?}, {:?})", Value(llvtable), self);
 
-        let llvtable = bcx.pointercast(llvtable, fn_ty.llvm_type(bcx.ccx).ptr_to().ptr_to());
-        let ptr_align = bcx.tcx().data_layout.pointer_align;
-        let ptr = bcx.load(bcx.inbounds_gep(llvtable, &[C_usize(bcx.ccx, self.0)]), ptr_align);
-        bcx.nonnull_metadata(ptr);
+        let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to());
+        let ptr_align = bx.tcx().data_layout.pointer_align;
+        let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), ptr_align);
+        bx.nonnull_metadata(ptr);
         // Vtable loads are invariant
-        bcx.set_invariant_load(ptr);
+        bx.set_invariant_load(ptr);
         ptr
     }
 
-    pub fn get_usize(self, bcx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
+    pub fn get_usize(self, bx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
         // Load the data pointer from the object.
         debug!("get_int({:?}, {:?})", Value(llvtable), self);
 
-        let llvtable = bcx.pointercast(llvtable, Type::isize(bcx.ccx).ptr_to());
-        let usize_align = bcx.tcx().data_layout.pointer_align;
-        let ptr = bcx.load(bcx.inbounds_gep(llvtable, &[C_usize(bcx.ccx, self.0)]), usize_align);
+        let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to());
+        let usize_align = bx.tcx().data_layout.pointer_align;
+        let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), usize_align);
         // Vtable loads are invariant
-        bcx.set_invariant_load(ptr);
+        bx.set_invariant_load(ptr);
         ptr
     }
 }
@@ -69,28 +69,28 @@
 /// The `trait_ref` encodes the erased self type. Hence if we are
 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
 /// `trait_ref` would map `T:Trait`.
-pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+pub fn get_vtable<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                             ty: Ty<'tcx>,
                             trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
                             -> ValueRef
 {
-    let tcx = ccx.tcx();
+    let tcx = cx.tcx;
 
     debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
 
     // Check the cache.
-    if let Some(&val) = ccx.vtables().borrow().get(&(ty, trait_ref)) {
+    if let Some(&val) = cx.vtables.borrow().get(&(ty, trait_ref)) {
         return val;
     }
 
     // Not in the cache. Build it.
-    let nullptr = C_null(Type::i8p(ccx));
+    let nullptr = C_null(Type::i8p(cx));
 
-    let (size, align) = ccx.size_and_align_of(ty);
+    let (size, align) = cx.size_and_align_of(ty);
     let mut components: Vec<_> = [
-        callee::get_fn(ccx, monomorphize::resolve_drop_in_place(ccx.tcx(), ty)),
-        C_usize(ccx, size.bytes()),
-        C_usize(ccx, align.abi())
+        callee::get_fn(cx, monomorphize::resolve_drop_in_place(cx.tcx, ty)),
+        C_usize(cx, size.bytes()),
+        C_usize(cx, align.abi())
     ].iter().cloned().collect();
 
     if let Some(trait_ref) = trait_ref {
@@ -98,18 +98,18 @@
         let methods = tcx.vtable_methods(trait_ref);
         let methods = methods.iter().cloned().map(|opt_mth| {
             opt_mth.map_or(nullptr, |(def_id, substs)| {
-                callee::resolve_and_get_fn(ccx, def_id, substs)
+                callee::resolve_and_get_fn(cx, def_id, substs)
             })
         });
         components.extend(methods);
     }
 
-    let vtable_const = C_struct(ccx, &components, false);
-    let align = ccx.data_layout().pointer_align;
-    let vtable = consts::addr_of(ccx, vtable_const, align, "vtable");
+    let vtable_const = C_struct(cx, &components, false);
+    let align = cx.data_layout().pointer_align;
+    let vtable = consts::addr_of(cx, vtable_const, align, "vtable");
 
-    debuginfo::create_vtable_metadata(ccx, ty, vtable);
+    debuginfo::create_vtable_metadata(cx, ty, vtable);
 
-    ccx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
+    cx.vtables.borrow_mut().insert((ty, trait_ref), vtable);
     vtable
 }
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index cfe55ab..bf82e1d 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -20,18 +20,18 @@
 use rustc::ty;
 use rustc::ty::layout::LayoutOf;
 use type_of::LayoutLlvmExt;
-use super::MirContext;
+use super::FunctionCx;
 
-pub fn memory_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
-    let mir = mircx.mir;
-    let mut analyzer = LocalAnalyzer::new(mircx);
+pub fn memory_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector {
+    let mir = fx.mir;
+    let mut analyzer = LocalAnalyzer::new(fx);
 
     analyzer.visit_mir(mir);
 
     for (index, ty) in mir.local_decls.iter().map(|l| l.ty).enumerate() {
-        let ty = mircx.monomorphize(&ty);
+        let ty = fx.monomorphize(&ty);
         debug!("local {} has type {:?}", index, ty);
-        let layout = mircx.ccx.layout_of(ty);
+        let layout = fx.cx.layout_of(ty);
         if layout.is_llvm_immediate() {
             // These sorts of types are immediates that we can store
             // in an ValueRef without an alloca.
@@ -52,21 +52,21 @@
 }
 
 struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
-    cx: &'mir MirContext<'a, 'tcx>,
+    fx: &'mir FunctionCx<'a, 'tcx>,
     memory_locals: BitVector,
     seen_assigned: BitVector
 }
 
 impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
-    fn new(mircx: &'mir MirContext<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
+    fn new(fx: &'mir FunctionCx<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
         let mut analyzer = LocalAnalyzer {
-            cx: mircx,
-            memory_locals: BitVector::new(mircx.mir.local_decls.len()),
-            seen_assigned: BitVector::new(mircx.mir.local_decls.len())
+            fx,
+            memory_locals: BitVector::new(fx.mir.local_decls.len()),
+            seen_assigned: BitVector::new(fx.mir.local_decls.len())
         };
 
         // Arguments get assigned to by means of the function being called
-        for idx in 0..mircx.mir.arg_count {
+        for idx in 0..fx.mir.arg_count {
             analyzer.seen_assigned.insert(idx + 1);
         }
 
@@ -95,7 +95,7 @@
 
         if let mir::Place::Local(index) = *place {
             self.mark_assigned(index);
-            if !self.cx.rvalue_creates_operand(rvalue) {
+            if !self.fx.rvalue_creates_operand(rvalue) {
                 self.mark_as_memory(index);
             }
         } else {
@@ -117,7 +117,7 @@
                     }, ..
                 }),
                 ref args, ..
-            } if Some(def_id) == self.cx.ccx.tcx().lang_items().box_free_fn() => {
+            } if Some(def_id) == self.fx.cx.tcx.lang_items().box_free_fn() => {
                 // box_free(x) shares with `drop x` the property that it
                 // is not guaranteed to be statically dominated by the
                 // definition of x, so x must always be in an alloca.
@@ -136,7 +136,7 @@
                     context: PlaceContext<'tcx>,
                     location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
-        let ccx = self.cx.ccx;
+        let cx = self.fx.cx;
 
         if let mir::Place::Projection(ref proj) = *place {
             // Allow uses of projections that are ZSTs or from scalar fields.
@@ -145,18 +145,18 @@
                 _ => false
             };
             if is_consume {
-                let base_ty = proj.base.ty(self.cx.mir, ccx.tcx());
-                let base_ty = self.cx.monomorphize(&base_ty);
+                let base_ty = proj.base.ty(self.fx.mir, cx.tcx);
+                let base_ty = self.fx.monomorphize(&base_ty);
 
                 // ZSTs don't require any actual memory access.
-                let elem_ty = base_ty.projection_ty(ccx.tcx(), &proj.elem).to_ty(ccx.tcx());
-                let elem_ty = self.cx.monomorphize(&elem_ty);
-                if ccx.layout_of(elem_ty).is_zst() {
+                let elem_ty = base_ty.projection_ty(cx.tcx, &proj.elem).to_ty(cx.tcx);
+                let elem_ty = self.fx.monomorphize(&elem_ty);
+                if cx.layout_of(elem_ty).is_zst() {
                     return;
                 }
 
                 if let mir::ProjectionElem::Field(..) = proj.elem {
-                    let layout = ccx.layout_of(base_ty.to_ty(ccx.tcx()));
+                    let layout = cx.layout_of(base_ty.to_ty(cx.tcx));
                     if layout.is_llvm_immediate() || layout.is_llvm_scalar_pair() {
                         // Recurse with the same context, instead of `Projection`,
                         // potentially stopping at non-operand projections,
@@ -200,11 +200,11 @@
             }
 
             PlaceContext::Drop => {
-                let ty = mir::Place::Local(index).ty(self.cx.mir, self.cx.ccx.tcx());
-                let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx()));
+                let ty = mir::Place::Local(index).ty(self.fx.mir, self.fx.cx.tcx);
+                let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx));
 
                 // Only need the place if we're actually dropping it.
-                if self.cx.ccx.shared().type_needs_drop(ty) {
+                if self.fx.cx.type_needs_drop(ty) {
                     self.mark_as_memory(index);
                 }
             }
@@ -236,6 +236,7 @@
             match data.terminator().kind {
                 TerminatorKind::Goto { .. } |
                 TerminatorKind::Resume |
+                TerminatorKind::Abort |
                 TerminatorKind::Return |
                 TerminatorKind::GeneratorDrop |
                 TerminatorKind::Unreachable |
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 1cb3a66..af1e30a 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -29,35 +29,35 @@
 use syntax::symbol::Symbol;
 use syntax_pos::Pos;
 
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
 use super::constant::Const;
 use super::place::PlaceRef;
 use super::operand::OperandRef;
 use super::operand::OperandValue::{Pair, Ref, Immediate};
 
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     pub fn trans_block(&mut self, bb: mir::BasicBlock) {
-        let mut bcx = self.get_builder(bb);
+        let mut bx = self.build_block(bb);
         let data = &self.mir[bb];
 
         debug!("trans_block({:?}={:?})", bb, data);
 
         for statement in &data.statements {
-            bcx = self.trans_statement(bcx, statement);
+            bx = self.trans_statement(bx, statement);
         }
 
-        self.trans_terminator(bcx, bb, data.terminator());
+        self.trans_terminator(bx, bb, data.terminator());
     }
 
     fn trans_terminator(&mut self,
-                        mut bcx: Builder<'a, 'tcx>,
+                        mut bx: Builder<'a, 'tcx>,
                         bb: mir::BasicBlock,
                         terminator: &mir::Terminator<'tcx>)
     {
         debug!("trans_terminator: {:?}", terminator);
 
         // Create the cleanup bundle, if needed.
-        let tcx = bcx.tcx();
+        let tcx = bx.tcx();
         let span = terminator.source_info.span;
         let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb);
         let funclet = funclet_bb.and_then(|funclet_bb| self.funclets[funclet_bb].as_ref());
@@ -99,20 +99,20 @@
             }
         };
 
-        let funclet_br = |this: &mut Self, bcx: Builder, target: mir::BasicBlock| {
+        let funclet_br = |this: &mut Self, bx: Builder, target: mir::BasicBlock| {
             let (lltarget, is_cleanupret) = lltarget(this, target);
             if is_cleanupret {
                 // micro-optimization: generate a `ret` rather than a jump
                 // to a trampoline.
-                bcx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget));
+                bx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget));
             } else {
-                bcx.br(lltarget);
+                bx.br(lltarget);
             }
         };
 
         let do_call = |
             this: &mut Self,
-            bcx: Builder<'a, 'tcx>,
+            bx: Builder<'a, 'tcx>,
             fn_ty: FnType<'tcx>,
             fn_ptr: ValueRef,
             llargs: &[ValueRef],
@@ -120,25 +120,25 @@
             cleanup: Option<mir::BasicBlock>
         | {
             if let Some(cleanup) = cleanup {
-                let ret_bcx = if let Some((_, target)) = destination {
+                let ret_bx = if let Some((_, target)) = destination {
                     this.blocks[target]
                 } else {
                     this.unreachable_block()
                 };
-                let invokeret = bcx.invoke(fn_ptr,
+                let invokeret = bx.invoke(fn_ptr,
                                            &llargs,
-                                           ret_bcx,
+                                           ret_bx,
                                            llblock(this, cleanup),
                                            cleanup_bundle);
                 fn_ty.apply_attrs_callsite(invokeret);
 
                 if let Some((ret_dest, target)) = destination {
-                    let ret_bcx = this.get_builder(target);
-                    this.set_debug_loc(&ret_bcx, terminator.source_info);
-                    this.store_return(&ret_bcx, ret_dest, &fn_ty.ret, invokeret);
+                    let ret_bx = this.build_block(target);
+                    this.set_debug_loc(&ret_bx, terminator.source_info);
+                    this.store_return(&ret_bx, ret_dest, &fn_ty.ret, invokeret);
                 }
             } else {
-                let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle);
+                let llret = bx.call(fn_ptr, &llargs, cleanup_bundle);
                 fn_ty.apply_attrs_callsite(llret);
                 if this.mir[bb].is_cleanup {
                     // Cleanup is always the cold path. Don't inline
@@ -149,59 +149,66 @@
                 }
 
                 if let Some((ret_dest, target)) = destination {
-                    this.store_return(&bcx, ret_dest, &fn_ty.ret, llret);
-                    funclet_br(this, bcx, target);
+                    this.store_return(&bx, ret_dest, &fn_ty.ret, llret);
+                    funclet_br(this, bx, target);
                 } else {
-                    bcx.unreachable();
+                    bx.unreachable();
                 }
             }
         };
 
-        self.set_debug_loc(&bcx, terminator.source_info);
+        self.set_debug_loc(&bx, terminator.source_info);
         match terminator.kind {
             mir::TerminatorKind::Resume => {
                 if let Some(cleanup_pad) = cleanup_pad {
-                    bcx.cleanup_ret(cleanup_pad, None);
+                    bx.cleanup_ret(cleanup_pad, None);
                 } else {
-                    let slot = self.get_personality_slot(&bcx);
-                    let lp0 = slot.project_field(&bcx, 0).load(&bcx).immediate();
-                    let lp1 = slot.project_field(&bcx, 1).load(&bcx).immediate();
-                    slot.storage_dead(&bcx);
+                    let slot = self.get_personality_slot(&bx);
+                    let lp0 = slot.project_field(&bx, 0).load(&bx).immediate();
+                    let lp1 = slot.project_field(&bx, 1).load(&bx).immediate();
+                    slot.storage_dead(&bx);
 
-                    if !bcx.sess().target.target.options.custom_unwind_resume {
+                    if !bx.sess().target.target.options.custom_unwind_resume {
                         let mut lp = C_undef(self.landing_pad_type());
-                        lp = bcx.insert_value(lp, lp0, 0);
-                        lp = bcx.insert_value(lp, lp1, 1);
-                        bcx.resume(lp);
+                        lp = bx.insert_value(lp, lp0, 0);
+                        lp = bx.insert_value(lp, lp1, 1);
+                        bx.resume(lp);
                     } else {
-                        bcx.call(bcx.ccx.eh_unwind_resume(), &[lp0], cleanup_bundle);
-                        bcx.unreachable();
+                        bx.call(bx.cx.eh_unwind_resume(), &[lp0], cleanup_bundle);
+                        bx.unreachable();
                     }
                 }
             }
 
+            mir::TerminatorKind::Abort => {
+                // Call core::intrinsics::abort()
+                let fnname = bx.cx.get_intrinsic(&("llvm.trap"));
+                bx.call(fnname, &[], None);
+                bx.unreachable();
+            }
+
             mir::TerminatorKind::Goto { target } => {
-                funclet_br(self, bcx, target);
+                funclet_br(self, bx, target);
             }
 
             mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
-                let discr = self.trans_operand(&bcx, discr);
-                if switch_ty == bcx.tcx().types.bool {
+                let discr = self.trans_operand(&bx, discr);
+                if switch_ty == bx.tcx().types.bool {
                     let lltrue = llblock(self, targets[0]);
                     let llfalse = llblock(self, targets[1]);
                     if let [ConstInt::U8(0)] = values[..] {
-                        bcx.cond_br(discr.immediate(), llfalse, lltrue);
+                        bx.cond_br(discr.immediate(), llfalse, lltrue);
                     } else {
-                        bcx.cond_br(discr.immediate(), lltrue, llfalse);
+                        bx.cond_br(discr.immediate(), lltrue, llfalse);
                     }
                 } else {
                     let (otherwise, targets) = targets.split_last().unwrap();
-                    let switch = bcx.switch(discr.immediate(),
+                    let switch = bx.switch(discr.immediate(),
                                             llblock(self, *otherwise), values.len());
                     for (value, target) in values.iter().zip(targets) {
-                        let val = Const::from_constint(bcx.ccx, value);
+                        let val = Const::from_constint(bx.cx, value);
                         let llbb = llblock(self, *target);
-                        bcx.add_case(switch, val.llval, llbb)
+                        bx.add_case(switch, val.llval, llbb)
                     }
                 }
             }
@@ -209,16 +216,16 @@
             mir::TerminatorKind::Return => {
                 let llval = match self.fn_ty.ret.mode {
                     PassMode::Ignore | PassMode::Indirect(_) => {
-                        bcx.ret_void();
+                        bx.ret_void();
                         return;
                     }
 
                     PassMode::Direct(_) | PassMode::Pair(..) => {
-                        let op = self.trans_consume(&bcx, &mir::Place::Local(mir::RETURN_PLACE));
+                        let op = self.trans_consume(&bx, &mir::Place::Local(mir::RETURN_PLACE));
                         if let Ref(llval, align) = op.val {
-                            bcx.load(llval, align)
+                            bx.load(llval, align)
                         } else {
-                            op.immediate_or_packed_pair(&bcx)
+                            op.immediate_or_packed_pair(&bx)
                         }
                     }
 
@@ -235,8 +242,8 @@
                         };
                         let llslot = match op.val {
                             Immediate(_) | Pair(..) => {
-                                let scratch = PlaceRef::alloca(&bcx, self.fn_ty.ret.layout, "ret");
-                                op.val.store(&bcx, scratch);
+                                let scratch = PlaceRef::alloca(&bx, self.fn_ty.ret.layout, "ret");
+                                op.val.store(&bx, scratch);
                                 scratch.llval
                             }
                             Ref(llval, align) => {
@@ -245,53 +252,53 @@
                                 llval
                             }
                         };
-                        bcx.load(
-                            bcx.pointercast(llslot, cast_ty.llvm_type(bcx.ccx).ptr_to()),
+                        bx.load(
+                            bx.pointercast(llslot, cast_ty.llvm_type(bx.cx).ptr_to()),
                             self.fn_ty.ret.layout.align)
                     }
                 };
-                bcx.ret(llval);
+                bx.ret(llval);
             }
 
             mir::TerminatorKind::Unreachable => {
-                bcx.unreachable();
+                bx.unreachable();
             }
 
             mir::TerminatorKind::Drop { ref location, target, unwind } => {
-                let ty = location.ty(self.mir, bcx.tcx()).to_ty(bcx.tcx());
+                let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
                 let ty = self.monomorphize(&ty);
-                let drop_fn = monomorphize::resolve_drop_in_place(bcx.ccx.tcx(), ty);
+                let drop_fn = monomorphize::resolve_drop_in_place(bx.cx.tcx, ty);
 
                 if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
                     // we don't actually need to drop anything.
-                    funclet_br(self, bcx, target);
+                    funclet_br(self, bx, target);
                     return
                 }
 
-                let place = self.trans_place(&bcx, location);
+                let place = self.trans_place(&bx, location);
                 let mut args: &[_] = &[place.llval, place.llextra];
                 args = &args[..1 + place.has_extra() as usize];
                 let (drop_fn, fn_ty) = match ty.sty {
                     ty::TyDynamic(..) => {
-                        let fn_ty = drop_fn.ty(bcx.ccx.tcx());
-                        let sig = common::ty_fn_sig(bcx.ccx, fn_ty);
-                        let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
-                        let fn_ty = FnType::new_vtable(bcx.ccx, sig, &[]);
+                        let fn_ty = drop_fn.ty(bx.cx.tcx);
+                        let sig = common::ty_fn_sig(bx.cx, fn_ty);
+                        let sig = bx.tcx().erase_late_bound_regions_and_normalize(&sig);
+                        let fn_ty = FnType::new_vtable(bx.cx, sig, &[]);
                         args = &args[..1];
-                        (meth::DESTRUCTOR.get_fn(&bcx, place.llextra, &fn_ty), fn_ty)
+                        (meth::DESTRUCTOR.get_fn(&bx, place.llextra, &fn_ty), fn_ty)
                     }
                     _ => {
-                        (callee::get_fn(bcx.ccx, drop_fn),
-                         FnType::of_instance(bcx.ccx, &drop_fn))
+                        (callee::get_fn(bx.cx, drop_fn),
+                         FnType::of_instance(bx.cx, &drop_fn))
                     }
                 };
-                do_call(self, bcx, fn_ty, drop_fn, args,
+                do_call(self, bx, fn_ty, drop_fn, args,
                         Some((ReturnDest::Nothing, target)),
                         unwind);
             }
 
             mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
-                let cond = self.trans_operand(&bcx, cond).immediate();
+                let cond = self.trans_operand(&bx, cond).immediate();
                 let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
 
                 // This case can currently arise only from functions marked
@@ -301,7 +308,7 @@
                 // NOTE: Unlike binops, negation doesn't have its own
                 // checked operation, just a comparison with the minimum
                 // value, so we have to check for the assert message.
-                if !bcx.ccx.check_overflow() {
+                if !bx.cx.check_overflow {
                     use rustc_const_math::ConstMathErr::Overflow;
                     use rustc_const_math::Op::Neg;
 
@@ -312,33 +319,33 @@
 
                 // Don't translate the panic block if success if known.
                 if const_cond == Some(expected) {
-                    funclet_br(self, bcx, target);
+                    funclet_br(self, bx, target);
                     return;
                 }
 
                 // Pass the condition through llvm.expect for branch hinting.
-                let expect = bcx.ccx.get_intrinsic(&"llvm.expect.i1");
-                let cond = bcx.call(expect, &[cond, C_bool(bcx.ccx, expected)], None);
+                let expect = bx.cx.get_intrinsic(&"llvm.expect.i1");
+                let cond = bx.call(expect, &[cond, C_bool(bx.cx, expected)], None);
 
                 // Create the failure block and the conditional branch to it.
                 let lltarget = llblock(self, target);
                 let panic_block = self.new_block("panic");
                 if expected {
-                    bcx.cond_br(cond, lltarget, panic_block.llbb());
+                    bx.cond_br(cond, lltarget, panic_block.llbb());
                 } else {
-                    bcx.cond_br(cond, panic_block.llbb(), lltarget);
+                    bx.cond_br(cond, panic_block.llbb(), lltarget);
                 }
 
-                // After this point, bcx is the block for the call to panic.
-                bcx = panic_block;
-                self.set_debug_loc(&bcx, terminator.source_info);
+                // After this point, bx is the block for the call to panic.
+                bx = panic_block;
+                self.set_debug_loc(&bx, terminator.source_info);
 
                 // Get the location information.
-                let loc = bcx.sess().codemap().lookup_char_pos(span.lo());
+                let loc = bx.sess().codemap().lookup_char_pos(span.lo());
                 let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
-                let filename = C_str_slice(bcx.ccx, filename);
-                let line = C_u32(bcx.ccx, loc.line as u32);
-                let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1);
+                let filename = C_str_slice(bx.cx, filename);
+                let line = C_u32(bx.cx, loc.line as u32);
+                let col = C_u32(bx.cx, loc.col.to_usize() as u32 + 1);
                 let align = tcx.data_layout.aggregate_align
                     .max(tcx.data_layout.i32_align)
                     .max(tcx.data_layout.pointer_align);
@@ -346,8 +353,8 @@
                 // Put together the arguments to the panic entry point.
                 let (lang_item, args, const_err) = match *msg {
                     mir::AssertMessage::BoundsCheck { ref len, ref index } => {
-                        let len = self.trans_operand(&mut bcx, len).immediate();
-                        let index = self.trans_operand(&mut bcx, index).immediate();
+                        let len = self.trans_operand(&mut bx, len).immediate();
+                        let index = self.trans_operand(&mut bx, index).immediate();
 
                         let const_err = common::const_to_opt_u128(len, false)
                             .and_then(|len| common::const_to_opt_u128(index, false)
@@ -356,8 +363,8 @@
                                     index: index as u64
                                 }));
 
-                        let file_line_col = C_struct(bcx.ccx, &[filename, line, col], false);
-                        let file_line_col = consts::addr_of(bcx.ccx,
+                        let file_line_col = C_struct(bx.cx, &[filename, line, col], false);
+                        let file_line_col = consts::addr_of(bx.cx,
                                                             file_line_col,
                                                             align,
                                                             "panic_bounds_check_loc");
@@ -367,11 +374,11 @@
                     }
                     mir::AssertMessage::Math(ref err) => {
                         let msg_str = Symbol::intern(err.description()).as_str();
-                        let msg_str = C_str_slice(bcx.ccx, msg_str);
-                        let msg_file_line_col = C_struct(bcx.ccx,
+                        let msg_str = C_str_slice(bx.cx, msg_str);
+                        let msg_file_line_col = C_struct(bx.cx,
                                                      &[msg_str, filename, line, col],
                                                      false);
-                        let msg_file_line_col = consts::addr_of(bcx.ccx,
+                        let msg_file_line_col = consts::addr_of(bx.cx,
                                                                 msg_file_line_col,
                                                                 align,
                                                                 "panic_loc");
@@ -387,11 +394,11 @@
                             "generator resumed after panicking"
                         };
                         let msg_str = Symbol::intern(str).as_str();
-                        let msg_str = C_str_slice(bcx.ccx, msg_str);
-                        let msg_file_line_col = C_struct(bcx.ccx,
+                        let msg_str = C_str_slice(bx.cx, msg_str);
+                        let msg_file_line_col = C_struct(bx.cx,
                                                      &[msg_str, filename, line, col],
                                                      false);
-                        let msg_file_line_col = consts::addr_of(bcx.ccx,
+                        let msg_file_line_col = consts::addr_of(bx.cx,
                                                                 msg_file_line_col,
                                                                 align,
                                                                 "panic_loc");
@@ -406,21 +413,21 @@
                 if const_cond == Some(!expected) {
                     if let Some(err) = const_err {
                         let err = ConstEvalErr{ span: span, kind: err };
-                        let mut diag = bcx.tcx().sess.struct_span_warn(
+                        let mut diag = bx.tcx().sess.struct_span_warn(
                             span, "this expression will panic at run-time");
-                        err.note(bcx.tcx(), span, "expression", &mut diag);
+                        err.note(bx.tcx(), span, "expression", &mut diag);
                         diag.emit();
                     }
                 }
 
                 // Obtain the panic entry point.
-                let def_id = common::langcall(bcx.tcx(), Some(span), "", lang_item);
-                let instance = ty::Instance::mono(bcx.tcx(), def_id);
-                let fn_ty = FnType::of_instance(bcx.ccx, &instance);
-                let llfn = callee::get_fn(bcx.ccx, instance);
+                let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
+                let instance = ty::Instance::mono(bx.tcx(), def_id);
+                let fn_ty = FnType::of_instance(bx.cx, &instance);
+                let llfn = callee::get_fn(bx.cx, instance);
 
                 // Translate the actual panic invoke/call.
-                do_call(self, bcx, fn_ty, llfn, &args, None, cleanup);
+                do_call(self, bx, fn_ty, llfn, &args, None, cleanup);
             }
 
             mir::TerminatorKind::DropAndReplace { .. } => {
@@ -429,11 +436,11 @@
 
             mir::TerminatorKind::Call { ref func, ref args, ref destination, cleanup } => {
                 // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
-                let callee = self.trans_operand(&bcx, func);
+                let callee = self.trans_operand(&bx, func);
 
                 let (instance, mut llfn) = match callee.layout.ty.sty {
                     ty::TyFnDef(def_id, substs) => {
-                        (Some(ty::Instance::resolve(bcx.ccx.tcx(),
+                        (Some(ty::Instance::resolve(bx.cx.tcx,
                                                     ty::ParamEnv::empty(traits::Reveal::All),
                                                     def_id,
                                                     substs).unwrap()),
@@ -445,42 +452,42 @@
                     _ => bug!("{} is not callable", callee.layout.ty)
                 };
                 let def = instance.map(|i| i.def);
-                let sig = callee.layout.ty.fn_sig(bcx.tcx());
-                let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
+                let sig = callee.layout.ty.fn_sig(bx.tcx());
+                let sig = bx.tcx().erase_late_bound_regions_and_normalize(&sig);
                 let abi = sig.abi;
 
                 // Handle intrinsics old trans wants Expr's for, ourselves.
                 let intrinsic = match def {
                     Some(ty::InstanceDef::Intrinsic(def_id))
-                        => Some(bcx.tcx().item_name(def_id)),
+                        => Some(bx.tcx().item_name(def_id)),
                     _ => None
                 };
                 let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
 
                 if intrinsic == Some("transmute") {
                     let &(ref dest, target) = destination.as_ref().unwrap();
-                    self.trans_transmute(&bcx, &args[0], dest);
-                    funclet_br(self, bcx, target);
+                    self.trans_transmute(&bx, &args[0], dest);
+                    funclet_br(self, bx, target);
                     return;
                 }
 
                 let extra_args = &args[sig.inputs().len()..];
                 let extra_args = extra_args.iter().map(|op_arg| {
-                    let op_ty = op_arg.ty(self.mir, bcx.tcx());
+                    let op_ty = op_arg.ty(self.mir, bx.tcx());
                     self.monomorphize(&op_ty)
                 }).collect::<Vec<_>>();
 
                 let fn_ty = match def {
                     Some(ty::InstanceDef::Virtual(..)) => {
-                        FnType::new_vtable(bcx.ccx, sig, &extra_args)
+                        FnType::new_vtable(bx.cx, sig, &extra_args)
                     }
                     Some(ty::InstanceDef::DropGlue(_, None)) => {
                         // empty drop glue - a nop.
                         let &(_, target) = destination.as_ref().unwrap();
-                        funclet_br(self, bcx, target);
+                        funclet_br(self, bx, target);
                         return;
                     }
-                    _ => FnType::new(bcx.ccx, sig, &extra_args)
+                    _ => FnType::new(bx.cx, sig, &extra_args)
                 };
 
                 // The arguments we'll be passing. Plus one to account for outptr, if used.
@@ -490,7 +497,7 @@
                 // Prepare the return value destination
                 let ret_dest = if let Some((ref dest, _)) = *destination {
                     let is_intrinsic = intrinsic.is_some();
-                    self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs,
+                    self.make_return_dest(&bx, dest, &fn_ty.ret, &mut llargs,
                                           is_intrinsic)
                 } else {
                     ReturnDest::Nothing
@@ -502,7 +509,7 @@
                     let dest = match ret_dest {
                         _ if fn_ty.ret.is_indirect() => llargs[0],
                         ReturnDest::Nothing => {
-                            C_undef(fn_ty.ret.memory_ty(bcx.ccx).ptr_to())
+                            C_undef(fn_ty.ret.memory_ty(bx.cx).ptr_to())
                         }
                         ReturnDest::IndirectOperand(dst, _) |
                         ReturnDest::Store(dst) => dst.llval,
@@ -522,31 +529,31 @@
                                     span_bug!(span, "shuffle indices must be constant");
                                 }
                                 mir::Operand::Constant(ref constant) => {
-                                    let val = self.trans_constant(&bcx, constant);
+                                    let val = self.trans_constant(&bx, constant);
                                     return OperandRef {
                                         val: Immediate(val.llval),
-                                        layout: bcx.ccx.layout_of(val.ty)
+                                        layout: bx.cx.layout_of(val.ty)
                                     };
                                 }
                             }
                         }
 
-                        self.trans_operand(&bcx, arg)
+                        self.trans_operand(&bx, arg)
                     }).collect();
 
 
-                    let callee_ty = instance.as_ref().unwrap().ty(bcx.ccx.tcx());
-                    trans_intrinsic_call(&bcx, callee_ty, &fn_ty, &args, dest,
+                    let callee_ty = instance.as_ref().unwrap().ty(bx.cx.tcx);
+                    trans_intrinsic_call(&bx, callee_ty, &fn_ty, &args, dest,
                                          terminator.source_info.span);
 
                     if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
-                        self.store_return(&bcx, ret_dest, &fn_ty.ret, dst.llval);
+                        self.store_return(&bx, ret_dest, &fn_ty.ret, dst.llval);
                     }
 
                     if let Some((_, target)) = *destination {
-                        funclet_br(self, bcx, target);
+                        funclet_br(self, bx, target);
                     } else {
-                        bcx.unreachable();
+                        bx.unreachable();
                     }
 
                     return;
@@ -561,11 +568,11 @@
                 };
 
                 for (i, arg) in first_args.iter().enumerate() {
-                    let mut op = self.trans_operand(&bcx, arg);
+                    let mut op = self.trans_operand(&bx, arg);
                     if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
                         if let Pair(data_ptr, meta) = op.val {
                             llfn = Some(meth::VirtualIndex::from_index(idx)
-                                .get_fn(&bcx, meta, &fn_ty));
+                                .get_fn(&bx, meta, &fn_ty));
                             llargs.push(data_ptr);
                             continue;
                         }
@@ -576,27 +583,27 @@
                     match (arg, op.val) {
                         (&mir::Operand::Copy(_), Ref(..)) |
                         (&mir::Operand::Constant(_), Ref(..)) => {
-                            let tmp = PlaceRef::alloca(&bcx, op.layout, "const");
-                            op.val.store(&bcx, tmp);
+                            let tmp = PlaceRef::alloca(&bx, op.layout, "const");
+                            op.val.store(&bx, tmp);
                             op.val = Ref(tmp.llval, tmp.align);
                         }
                         _ => {}
                     }
 
-                    self.trans_argument(&bcx, op, &mut llargs, &fn_ty.args[i]);
+                    self.trans_argument(&bx, op, &mut llargs, &fn_ty.args[i]);
                 }
                 if let Some(tup) = untuple {
-                    self.trans_arguments_untupled(&bcx, tup, &mut llargs,
+                    self.trans_arguments_untupled(&bx, tup, &mut llargs,
                         &fn_ty.args[first_args.len()..])
                 }
 
                 let fn_ptr = match (llfn, instance) {
                     (Some(llfn), _) => llfn,
-                    (None, Some(instance)) => callee::get_fn(bcx.ccx, instance),
+                    (None, Some(instance)) => callee::get_fn(bx.cx, instance),
                     _ => span_bug!(span, "no llfn for call"),
                 };
 
-                do_call(self, bcx, fn_ty, fn_ptr, &llargs,
+                do_call(self, bx, fn_ty, fn_ptr, &llargs,
                         destination.as_ref().map(|&(_, target)| (ret_dest, target)),
                         cleanup);
             }
@@ -607,13 +614,13 @@
     }
 
     fn trans_argument(&mut self,
-                      bcx: &Builder<'a, 'tcx>,
+                      bx: &Builder<'a, 'tcx>,
                       op: OperandRef<'tcx>,
                       llargs: &mut Vec<ValueRef>,
                       arg: &ArgType<'tcx>) {
         // Fill padding with undef value, where applicable.
         if let Some(ty) = arg.pad {
-            llargs.push(C_undef(ty.llvm_type(bcx.ccx)));
+            llargs.push(C_undef(ty.llvm_type(bx.cx)));
         }
 
         if arg.is_ignore() {
@@ -636,12 +643,12 @@
             Immediate(_) | Pair(..) => {
                 match arg.mode {
                     PassMode::Indirect(_) | PassMode::Cast(_) => {
-                        let scratch = PlaceRef::alloca(bcx, arg.layout, "arg");
-                        op.val.store(bcx, scratch);
+                        let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
+                        op.val.store(bx, scratch);
                         (scratch.llval, scratch.align, true)
                     }
                     _ => {
-                        (op.immediate_or_packed_pair(bcx), arg.layout.align, false)
+                        (op.immediate_or_packed_pair(bx), arg.layout.align, false)
                     }
                 }
             }
@@ -651,8 +658,8 @@
                     // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't
                     // have scary latent bugs around.
 
-                    let scratch = PlaceRef::alloca(bcx, arg.layout, "arg");
-                    base::memcpy_ty(bcx, scratch.llval, llval, op.layout, align);
+                    let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
+                    base::memcpy_ty(bx, scratch.llval, llval, op.layout, align);
                     (scratch.llval, scratch.align, true)
                 } else {
                     (llval, align, true)
@@ -663,7 +670,7 @@
         if by_ref && !arg.is_indirect() {
             // Have to load the argument, maybe while casting it.
             if let PassMode::Cast(ty) = arg.mode {
-                llval = bcx.load(bcx.pointercast(llval, ty.llvm_type(bcx.ccx).ptr_to()),
+                llval = bx.load(bx.pointercast(llval, ty.llvm_type(bx.cx).ptr_to()),
                                  align.min(arg.layout.align));
             } else {
                 // We can't use `PlaceRef::load` here because the argument
@@ -671,14 +678,14 @@
                 // used for this call is passing it by-value. In that case,
                 // the load would just produce `OperandValue::Ref` instead
                 // of the `OperandValue::Immediate` we need for the call.
-                llval = bcx.load(llval, align);
+                llval = bx.load(llval, align);
                 if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
                     if scalar.is_bool() {
-                        bcx.range_metadata(llval, 0..2);
+                        bx.range_metadata(llval, 0..2);
                     }
                 }
                 // We store bools as i8 so we need to truncate to i1.
-                llval = base::to_immediate(bcx, llval, arg.layout);
+                llval = base::to_immediate(bx, llval, arg.layout);
             }
         }
 
@@ -686,38 +693,38 @@
     }
 
     fn trans_arguments_untupled(&mut self,
-                                bcx: &Builder<'a, 'tcx>,
+                                bx: &Builder<'a, 'tcx>,
                                 operand: &mir::Operand<'tcx>,
                                 llargs: &mut Vec<ValueRef>,
                                 args: &[ArgType<'tcx>]) {
-        let tuple = self.trans_operand(bcx, operand);
+        let tuple = self.trans_operand(bx, operand);
 
         // Handle both by-ref and immediate tuples.
         if let Ref(llval, align) = tuple.val {
             let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align);
             for i in 0..tuple.layout.fields.count() {
-                let field_ptr = tuple_ptr.project_field(bcx, i);
-                self.trans_argument(bcx, field_ptr.load(bcx), llargs, &args[i]);
+                let field_ptr = tuple_ptr.project_field(bx, i);
+                self.trans_argument(bx, field_ptr.load(bx), llargs, &args[i]);
             }
         } else {
             // If the tuple is immediate, the elements are as well.
             for i in 0..tuple.layout.fields.count() {
-                let op = tuple.extract_field(bcx, i);
-                self.trans_argument(bcx, op, llargs, &args[i]);
+                let op = tuple.extract_field(bx, i);
+                self.trans_argument(bx, op, llargs, &args[i]);
             }
         }
     }
 
-    fn get_personality_slot(&mut self, bcx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
-        let ccx = bcx.ccx;
+    fn get_personality_slot(&mut self, bx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
+        let cx = bx.cx;
         if let Some(slot) = self.personality_slot {
             slot
         } else {
-            let layout = ccx.layout_of(ccx.tcx().intern_tup(&[
-                ccx.tcx().mk_mut_ptr(ccx.tcx().types.u8),
-                ccx.tcx().types.i32
+            let layout = cx.layout_of(cx.tcx.intern_tup(&[
+                cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
+                cx.tcx.types.i32
             ], false));
-            let slot = PlaceRef::alloca(bcx, layout, "personalityslot");
+            let slot = PlaceRef::alloca(bx, layout, "personalityslot");
             self.personality_slot = Some(slot);
             slot
         }
@@ -738,28 +745,28 @@
     }
 
     fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef {
-        if base::wants_msvc_seh(self.ccx.sess()) {
+        if base::wants_msvc_seh(self.cx.sess()) {
             span_bug!(self.mir.span, "landing pad was not inserted?")
         }
 
-        let bcx = self.new_block("cleanup");
+        let bx = self.new_block("cleanup");
 
-        let llpersonality = self.ccx.eh_personality();
+        let llpersonality = self.cx.eh_personality();
         let llretty = self.landing_pad_type();
-        let lp = bcx.landing_pad(llretty, llpersonality, 1, self.llfn);
-        bcx.set_cleanup(lp);
+        let lp = bx.landing_pad(llretty, llpersonality, 1);
+        bx.set_cleanup(lp);
 
-        let slot = self.get_personality_slot(&bcx);
-        slot.storage_live(&bcx);
-        Pair(bcx.extract_value(lp, 0), bcx.extract_value(lp, 1)).store(&bcx, slot);
+        let slot = self.get_personality_slot(&bx);
+        slot.storage_live(&bx);
+        Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&bx, slot);
 
-        bcx.br(target_bb);
-        bcx.llbb()
+        bx.br(target_bb);
+        bx.llbb()
     }
 
     fn landing_pad_type(&self) -> Type {
-        let ccx = self.ccx;
-        Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false)
+        let cx = self.cx;
+        Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false)
     }
 
     fn unreachable_block(&mut self) -> BasicBlockRef {
@@ -772,16 +779,16 @@
     }
 
     pub fn new_block(&self, name: &str) -> Builder<'a, 'tcx> {
-        Builder::new_block(self.ccx, self.llfn, name)
+        Builder::new_block(self.cx, self.llfn, name)
     }
 
-    pub fn get_builder(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> {
-        let builder = Builder::with_ccx(self.ccx);
-        builder.position_at_end(self.blocks[bb]);
-        builder
+    pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> {
+        let bx = Builder::with_cx(self.cx);
+        bx.position_at_end(self.blocks[bb]);
+        bx
     }
 
-    fn make_return_dest(&mut self, bcx: &Builder<'a, 'tcx>,
+    fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>,
                         dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx>,
                         llargs: &mut Vec<ValueRef>, is_intrinsic: bool)
                         -> ReturnDest<'tcx> {
@@ -798,16 +805,16 @@
                     return if fn_ret.is_indirect() {
                         // Odd, but possible, case, we have an operand temporary,
                         // but the calling convention has an indirect return.
-                        let tmp = PlaceRef::alloca(bcx, fn_ret.layout, "tmp_ret");
-                        tmp.storage_live(bcx);
+                        let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret");
+                        tmp.storage_live(bx);
                         llargs.push(tmp.llval);
                         ReturnDest::IndirectOperand(tmp, index)
                     } else if is_intrinsic {
                         // Currently, intrinsics always need a location to store
                         // the result. so we create a temporary alloca for the
                         // result
-                        let tmp = PlaceRef::alloca(bcx, fn_ret.layout, "tmp_ret");
-                        tmp.storage_live(bcx);
+                        let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret");
+                        tmp.storage_live(bx);
                         ReturnDest::IndirectOperand(tmp, index)
                     } else {
                         ReturnDest::DirectOperand(index)
@@ -818,7 +825,7 @@
                 }
             }
         } else {
-            self.trans_place(bcx, dest)
+            self.trans_place(bx, dest)
         };
         if fn_ret.is_indirect() {
             if dest.align.abi() < dest.layout.align.abi() {
@@ -837,20 +844,20 @@
         }
     }
 
-    fn trans_transmute(&mut self, bcx: &Builder<'a, 'tcx>,
+    fn trans_transmute(&mut self, bx: &Builder<'a, 'tcx>,
                        src: &mir::Operand<'tcx>,
                        dst: &mir::Place<'tcx>) {
         if let mir::Place::Local(index) = *dst {
             match self.locals[index] {
-                LocalRef::Place(place) => self.trans_transmute_into(bcx, src, place),
+                LocalRef::Place(place) => self.trans_transmute_into(bx, src, place),
                 LocalRef::Operand(None) => {
-                    let dst_layout = bcx.ccx.layout_of(self.monomorphized_place_ty(dst));
+                    let dst_layout = bx.cx.layout_of(self.monomorphized_place_ty(dst));
                     assert!(!dst_layout.ty.has_erasable_regions());
-                    let place = PlaceRef::alloca(bcx, dst_layout, "transmute_temp");
-                    place.storage_live(bcx);
-                    self.trans_transmute_into(bcx, src, place);
-                    let op = place.load(bcx);
-                    place.storage_dead(bcx);
+                    let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
+                    place.storage_live(bx);
+                    self.trans_transmute_into(bx, src, place);
+                    let op = place.load(bx);
+                    place.storage_dead(bx);
                     self.locals[index] = LocalRef::Operand(Some(op));
                 }
                 LocalRef::Operand(Some(op)) => {
@@ -859,25 +866,25 @@
                 }
             }
         } else {
-            let dst = self.trans_place(bcx, dst);
-            self.trans_transmute_into(bcx, src, dst);
+            let dst = self.trans_place(bx, dst);
+            self.trans_transmute_into(bx, src, dst);
         }
     }
 
-    fn trans_transmute_into(&mut self, bcx: &Builder<'a, 'tcx>,
+    fn trans_transmute_into(&mut self, bx: &Builder<'a, 'tcx>,
                             src: &mir::Operand<'tcx>,
                             dst: PlaceRef<'tcx>) {
-        let src = self.trans_operand(bcx, src);
-        let llty = src.layout.llvm_type(bcx.ccx);
-        let cast_ptr = bcx.pointercast(dst.llval, llty.ptr_to());
+        let src = self.trans_operand(bx, src);
+        let llty = src.layout.llvm_type(bx.cx);
+        let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to());
         let align = src.layout.align.min(dst.layout.align);
-        src.val.store(bcx, PlaceRef::new_sized(cast_ptr, src.layout, align));
+        src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align));
     }
 
 
     // Stores the return value of a function call into it's final location.
     fn store_return(&mut self,
-                    bcx: &Builder<'a, 'tcx>,
+                    bx: &Builder<'a, 'tcx>,
                     dest: ReturnDest<'tcx>,
                     ret_ty: &ArgType<'tcx>,
                     llval: ValueRef) {
@@ -885,23 +892,23 @@
 
         match dest {
             Nothing => (),
-            Store(dst) => ret_ty.store(bcx, llval, dst),
+            Store(dst) => ret_ty.store(bx, llval, dst),
             IndirectOperand(tmp, index) => {
-                let op = tmp.load(bcx);
-                tmp.storage_dead(bcx);
+                let op = tmp.load(bx);
+                tmp.storage_dead(bx);
                 self.locals[index] = LocalRef::Operand(Some(op));
             }
             DirectOperand(index) => {
                 // If there is a cast, we have to store and reload.
                 let op = if let PassMode::Cast(_) = ret_ty.mode {
-                    let tmp = PlaceRef::alloca(bcx, ret_ty.layout, "tmp_ret");
-                    tmp.storage_live(bcx);
-                    ret_ty.store(bcx, llval, tmp);
-                    let op = tmp.load(bcx);
-                    tmp.storage_dead(bcx);
+                    let tmp = PlaceRef::alloca(bx, ret_ty.layout, "tmp_ret");
+                    tmp.storage_live(bx);
+                    ret_ty.store(bx, llval, tmp);
+                    let op = tmp.load(bx);
+                    tmp.storage_dead(bx);
                     op
                 } else {
-                    OperandRef::from_immediate_or_packed_pair(bcx, llval, ret_ty.layout)
+                    OperandRef::from_immediate_or_packed_pair(bx, llval, ret_ty.layout)
                 };
                 self.locals[index] = LocalRef::Operand(Some(op));
             }
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index d836d79..71ce0aa 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -27,7 +27,7 @@
 use abi::{self, Abi};
 use callee;
 use builder::Builder;
-use common::{self, CrateContext, const_get_elt, val_ty};
+use common::{self, CodegenCx, const_get_elt, val_ty};
 use common::{C_array, C_bool, C_bytes, C_int, C_uint, C_uint_big, C_u32, C_u64};
 use common::{C_null, C_struct, C_str_slice, C_undef, C_usize, C_vector, C_fat_ptr};
 use common::const_to_opt_u128;
@@ -43,7 +43,7 @@
 use std::ptr;
 
 use super::operand::{OperandRef, OperandValue};
-use super::MirContext;
+use super::FunctionCx;
 
 /// A sized constant rvalue.
 /// The LLVM type might not be the same for a single Rust type,
@@ -62,46 +62,46 @@
         }
     }
 
-    pub fn from_constint(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt) -> Const<'tcx> {
-        let tcx = ccx.tcx();
+    pub fn from_constint(cx: &CodegenCx<'a, 'tcx>, ci: &ConstInt) -> Const<'tcx> {
+        let tcx = cx.tcx;
         let (llval, ty) = match *ci {
-            I8(v) => (C_int(Type::i8(ccx), v as i64), tcx.types.i8),
-            I16(v) => (C_int(Type::i16(ccx), v as i64), tcx.types.i16),
-            I32(v) => (C_int(Type::i32(ccx), v as i64), tcx.types.i32),
-            I64(v) => (C_int(Type::i64(ccx), v as i64), tcx.types.i64),
-            I128(v) => (C_uint_big(Type::i128(ccx), v as u128), tcx.types.i128),
-            Isize(v) => (C_int(Type::isize(ccx), v.as_i64()), tcx.types.isize),
-            U8(v) => (C_uint(Type::i8(ccx), v as u64), tcx.types.u8),
-            U16(v) => (C_uint(Type::i16(ccx), v as u64), tcx.types.u16),
-            U32(v) => (C_uint(Type::i32(ccx), v as u64), tcx.types.u32),
-            U64(v) => (C_uint(Type::i64(ccx), v), tcx.types.u64),
-            U128(v) => (C_uint_big(Type::i128(ccx), v), tcx.types.u128),
-            Usize(v) => (C_uint(Type::isize(ccx), v.as_u64()), tcx.types.usize),
+            I8(v) => (C_int(Type::i8(cx), v as i64), tcx.types.i8),
+            I16(v) => (C_int(Type::i16(cx), v as i64), tcx.types.i16),
+            I32(v) => (C_int(Type::i32(cx), v as i64), tcx.types.i32),
+            I64(v) => (C_int(Type::i64(cx), v as i64), tcx.types.i64),
+            I128(v) => (C_uint_big(Type::i128(cx), v as u128), tcx.types.i128),
+            Isize(v) => (C_int(Type::isize(cx), v.as_i64()), tcx.types.isize),
+            U8(v) => (C_uint(Type::i8(cx), v as u64), tcx.types.u8),
+            U16(v) => (C_uint(Type::i16(cx), v as u64), tcx.types.u16),
+            U32(v) => (C_uint(Type::i32(cx), v as u64), tcx.types.u32),
+            U64(v) => (C_uint(Type::i64(cx), v), tcx.types.u64),
+            U128(v) => (C_uint_big(Type::i128(cx), v), tcx.types.u128),
+            Usize(v) => (C_uint(Type::isize(cx), v.as_u64()), tcx.types.usize),
         };
         Const { llval: llval, ty: ty }
     }
 
     /// Translate ConstVal into a LLVM constant value.
-    pub fn from_constval(ccx: &CrateContext<'a, 'tcx>,
+    pub fn from_constval(cx: &CodegenCx<'a, 'tcx>,
                          cv: &ConstVal,
                          ty: Ty<'tcx>)
                          -> Const<'tcx> {
-        let llty = ccx.layout_of(ty).llvm_type(ccx);
+        let llty = cx.layout_of(ty).llvm_type(cx);
         let val = match *cv {
             ConstVal::Float(v) => {
                 let bits = match v.ty {
-                    ast::FloatTy::F32 => C_u32(ccx, v.bits as u32),
-                    ast::FloatTy::F64 => C_u64(ccx, v.bits as u64)
+                    ast::FloatTy::F32 => C_u32(cx, v.bits as u32),
+                    ast::FloatTy::F64 => C_u64(cx, v.bits as u64)
                 };
                 consts::bitcast(bits, llty)
             }
-            ConstVal::Bool(v) => C_bool(ccx, v),
-            ConstVal::Integral(ref i) => return Const::from_constint(ccx, i),
-            ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
+            ConstVal::Bool(v) => C_bool(cx, v),
+            ConstVal::Integral(ref i) => return Const::from_constint(cx, i),
+            ConstVal::Str(ref v) => C_str_slice(cx, v.clone()),
             ConstVal::ByteStr(v) => {
-                consts::addr_of(ccx, C_bytes(ccx, v.data), ccx.align_of(ty), "byte_str")
+                consts::addr_of(cx, C_bytes(cx, v.data), cx.align_of(ty), "byte_str")
             }
-            ConstVal::Char(c) => C_uint(Type::char(ccx), c as u64),
+            ConstVal::Char(c) => C_uint(Type::char(cx), c as u64),
             ConstVal::Function(..) => C_undef(llty),
             ConstVal::Variant(_) |
             ConstVal::Aggregate(..) |
@@ -115,11 +115,11 @@
         Const::new(val, ty)
     }
 
-    fn get_field(&self, ccx: &CrateContext<'a, 'tcx>, i: usize) -> ValueRef {
-        let layout = ccx.layout_of(self.ty);
-        let field = layout.field(ccx, i);
+    fn get_field(&self, cx: &CodegenCx<'a, 'tcx>, i: usize) -> ValueRef {
+        let layout = cx.layout_of(self.ty);
+        let field = layout.field(cx, i);
         if field.is_zst() {
-            return C_undef(field.immediate_llvm_type(ccx));
+            return C_undef(field.immediate_llvm_type(cx));
         }
         let offset = layout.fields.offset(i);
         match layout.abi {
@@ -130,12 +130,12 @@
 
             layout::Abi::ScalarPair(ref a, ref b) => {
                 if offset.bytes() == 0 {
-                    assert_eq!(field.size, a.value.size(ccx));
+                    assert_eq!(field.size, a.value.size(cx));
                     const_get_elt(self.llval, 0)
                 } else {
-                    assert_eq!(offset, a.value.size(ccx)
-                        .abi_align(b.value.align(ccx)));
-                    assert_eq!(field.size, b.value.size(ccx));
+                    assert_eq!(offset, a.value.size(cx)
+                        .abi_align(b.value.align(cx)));
+                    assert_eq!(field.size, b.value.size(cx));
                     const_get_elt(self.llval, 1)
                 }
             }
@@ -145,14 +145,14 @@
         }
     }
 
-    fn get_pair(&self, ccx: &CrateContext<'a, 'tcx>) -> (ValueRef, ValueRef) {
-        (self.get_field(ccx, 0), self.get_field(ccx, 1))
+    fn get_pair(&self, cx: &CodegenCx<'a, 'tcx>) -> (ValueRef, ValueRef) {
+        (self.get_field(cx, 0), self.get_field(cx, 1))
     }
 
-    fn get_fat_ptr(&self, ccx: &CrateContext<'a, 'tcx>) -> (ValueRef, ValueRef) {
+    fn get_fat_ptr(&self, cx: &CodegenCx<'a, 'tcx>) -> (ValueRef, ValueRef) {
         assert_eq!(abi::FAT_PTR_ADDR, 0);
         assert_eq!(abi::FAT_PTR_EXTRA, 1);
-        self.get_pair(ccx)
+        self.get_pair(cx)
     }
 
     fn as_place(&self) -> ConstPlace<'tcx> {
@@ -163,9 +163,9 @@
         }
     }
 
-    pub fn to_operand(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
-        let layout = ccx.layout_of(self.ty);
-        let llty = layout.immediate_llvm_type(ccx);
+    pub fn to_operand(&self, cx: &CodegenCx<'a, 'tcx>) -> OperandRef<'tcx> {
+        let layout = cx.layout_of(self.ty);
+        let llty = layout.immediate_llvm_type(cx);
         let llvalty = val_ty(self.llval);
 
         let val = if llty == llvalty && layout.is_llvm_scalar_pair() {
@@ -178,9 +178,9 @@
         } else {
             // Otherwise, or if the value is not immediate, we create
             // a constant LLVM global and cast its address if necessary.
-            let align = ccx.align_of(self.ty);
-            let ptr = consts::addr_of(ccx, self.llval, align, "const");
-            OperandValue::Ref(consts::ptrcast(ptr, layout.llvm_type(ccx).ptr_to()),
+            let align = cx.align_of(self.ty);
+            let ptr = consts::addr_of(cx, self.llval, align, "const");
+            OperandValue::Ref(consts::ptrcast(ptr, layout.llvm_type(cx).ptr_to()),
                               layout.align)
         };
 
@@ -232,10 +232,10 @@
         }
     }
 
-    pub fn len<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
+    pub fn len<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
         match self.ty.sty {
             ty::TyArray(_, n) => {
-                C_usize(ccx, n.val.to_const_int().unwrap().to_u64().unwrap())
+                C_usize(cx, n.val.to_const_int().unwrap().to_u64().unwrap())
             }
             ty::TySlice(_) | ty::TyStr => {
                 assert!(self.llextra != ptr::null_mut());
@@ -249,7 +249,7 @@
 /// Machinery for translating a constant's MIR to LLVM values.
 /// FIXME(eddyb) use miri and lower its allocations to LLVM.
 struct MirConstContext<'a, 'tcx: 'a> {
-    ccx: &'a CrateContext<'a, 'tcx>,
+    cx: &'a CodegenCx<'a, 'tcx>,
     mir: &'a mir::Mir<'tcx>,
 
     /// Type parameters for const fn and associated constants.
@@ -270,13 +270,13 @@
 }
 
 impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
-    fn new(ccx: &'a CrateContext<'a, 'tcx>,
+    fn new(cx: &'a CodegenCx<'a, 'tcx>,
            mir: &'a mir::Mir<'tcx>,
            substs: &'tcx Substs<'tcx>,
            args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
            -> MirConstContext<'a, 'tcx> {
         let mut context = MirConstContext {
-            ccx,
+            cx,
             mir,
             substs,
             locals: (0..mir.local_decls.len()).map(|_| None).collect(),
@@ -289,27 +289,27 @@
         context
     }
 
-    fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
+    fn trans_def(cx: &'a CodegenCx<'a, 'tcx>,
                  def_id: DefId,
                  substs: &'tcx Substs<'tcx>,
                  args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
                  -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
-        let instance = ty::Instance::resolve(ccx.tcx(),
+        let instance = ty::Instance::resolve(cx.tcx,
                                              ty::ParamEnv::empty(traits::Reveal::All),
                                              def_id,
                                              substs).unwrap();
-        let mir = ccx.tcx().instance_mir(instance.def);
-        MirConstContext::new(ccx, &mir, instance.substs, args).trans()
+        let mir = cx.tcx.instance_mir(instance.def);
+        MirConstContext::new(cx, &mir, instance.substs, args).trans()
     }
 
     fn monomorphize<T>(&self, value: &T) -> T
         where T: TransNormalize<'tcx>
     {
-        self.ccx.tcx().trans_apply_param_substs(self.substs, value)
+        self.cx.tcx.trans_apply_param_substs(self.substs, value)
     }
 
     fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
-        let tcx = self.ccx.tcx();
+        let tcx = self.cx.tcx;
         let mut bb = mir::START_BLOCK;
 
         // Make sure to evaluate all statemenets to
@@ -399,13 +399,13 @@
                         let result = if fn_ty.fn_sig(tcx).abi() == Abi::RustIntrinsic {
                             match &tcx.item_name(def_id)[..] {
                                 "size_of" => {
-                                    let llval = C_usize(self.ccx,
-                                        self.ccx.size_of(substs.type_at(0)).bytes());
+                                    let llval = C_usize(self.cx,
+                                        self.cx.size_of(substs.type_at(0)).bytes());
                                     Ok(Const::new(llval, tcx.types.usize))
                                 }
                                 "min_align_of" => {
-                                    let llval = C_usize(self.ccx,
-                                        self.ccx.align_of(substs.type_at(0)).abi());
+                                    let llval = C_usize(self.cx,
+                                        self.cx.align_of(substs.type_at(0)).abi());
                                     Ok(Const::new(llval, tcx.types.usize))
                                 }
                                 _ => span_bug!(span, "{:?} in constant", terminator.kind)
@@ -430,12 +430,12 @@
                                     match const_scalar_checked_binop(tcx, op, lhs, rhs, ty) {
                                         Some((llval, of)) => {
                                             Ok(trans_const_adt(
-                                                self.ccx,
+                                                self.cx,
                                                 binop_ty,
                                                 &mir::AggregateKind::Tuple,
                                                 &[
                                                     Const::new(llval, val_ty),
-                                                    Const::new(C_bool(self.ccx, of), tcx.types.bool)
+                                                    Const::new(C_bool(self.cx, of), tcx.types.bool)
                                                 ]))
                                         }
                                         None => {
@@ -447,7 +447,7 @@
                                 }
                             })()
                         } else {
-                            MirConstContext::trans_def(self.ccx, def_id, substs, arg_vals)
+                            MirConstContext::trans_def(self.cx, def_id, substs, arg_vals)
                         };
                         add_err(&mut failure, &result);
                         self.store(dest, result, span);
@@ -462,7 +462,7 @@
     }
 
     fn is_binop_lang_item(&mut self, def_id: DefId) -> Option<(mir::BinOp, bool)> {
-        let tcx = self.ccx.tcx();
+        let tcx = self.cx.tcx;
         let items = tcx.lang_items();
         let def_id = Some(def_id);
         if items.i128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
@@ -505,7 +505,7 @@
 
     fn const_place(&self, place: &mir::Place<'tcx>, span: Span)
                     -> Result<ConstPlace<'tcx>, ConstEvalErr<'tcx>> {
-        let tcx = self.ccx.tcx();
+        let tcx = self.cx.tcx;
 
         if let mir::Place::Local(index) = *place {
             return self.locals[index].clone().unwrap_or_else(|| {
@@ -517,7 +517,7 @@
             mir::Place::Local(_)  => bug!(), // handled above
             mir::Place::Static(box mir::Static { def_id, ty }) => {
                 ConstPlace {
-                    base: Base::Static(consts::get_static(self.ccx, def_id)),
+                    base: Base::Static(consts::get_static(self.cx, def_id)),
                     llextra: ptr::null_mut(),
                     ty: self.monomorphize(&ty),
                 }
@@ -528,30 +528,30 @@
                     .projection_ty(tcx, &projection.elem);
                 let base = tr_base.to_const(span);
                 let projected_ty = self.monomorphize(&projected_ty).to_ty(tcx);
-                let has_metadata = self.ccx.shared().type_has_metadata(projected_ty);
+                let has_metadata = self.cx.type_has_metadata(projected_ty);
 
                 let (projected, llextra) = match projection.elem {
                     mir::ProjectionElem::Deref => {
                         let (base, extra) = if !has_metadata {
                             (base.llval, ptr::null_mut())
                         } else {
-                            base.get_fat_ptr(self.ccx)
+                            base.get_fat_ptr(self.cx)
                         };
-                        if self.ccx.statics().borrow().contains_key(&base) {
+                        if self.cx.statics.borrow().contains_key(&base) {
                             (Base::Static(base), extra)
                         } else if let ty::TyStr = projected_ty.sty {
                             (Base::Str(base), extra)
                         } else {
                             let v = base;
-                            let v = self.ccx.const_unsized().borrow().get(&v).map_or(v, |&v| v);
+                            let v = self.cx.const_unsized.borrow().get(&v).map_or(v, |&v| v);
                             let mut val = unsafe { llvm::LLVMGetInitializer(v) };
                             if val.is_null() {
                                 span_bug!(span, "dereference of non-constant pointer `{:?}`",
                                           Value(base));
                             }
-                            let layout = self.ccx.layout_of(projected_ty);
+                            let layout = self.cx.layout_of(projected_ty);
                             if let layout::Abi::Scalar(ref scalar) = layout.abi {
-                                let i1_type = Type::i1(self.ccx);
+                                let i1_type = Type::i1(self.cx);
                                 if scalar.is_bool() && val_ty(val) != i1_type {
                                     unsafe {
                                         val = llvm::LLVMConstTrunc(val, i1_type.to_ref());
@@ -562,7 +562,7 @@
                         }
                     }
                     mir::ProjectionElem::Field(ref field, _) => {
-                        let llprojected = base.get_field(self.ccx, field.index());
+                        let llprojected = base.get_field(self.cx, field.index());
                         let llextra = if !has_metadata {
                             ptr::null_mut()
                         } else {
@@ -581,11 +581,11 @@
                         };
 
                         // Produce an undef instead of a LLVM assertion on OOB.
-                        let len = common::const_to_uint(tr_base.len(self.ccx));
+                        let len = common::const_to_uint(tr_base.len(self.cx));
                         let llelem = if iv < len as u128 {
                             const_get_elt(base.llval, iv as u64)
                         } else {
-                            C_undef(self.ccx.layout_of(projected_ty).llvm_type(self.ccx))
+                            C_undef(self.cx.layout_of(projected_ty).llvm_type(self.cx))
                         };
 
                         (Base::Value(llelem), ptr::null_mut())
@@ -616,14 +616,14 @@
                 match constant.literal.clone() {
                     mir::Literal::Promoted { index } => {
                         let mir = &self.mir.promoted[index];
-                        MirConstContext::new(self.ccx, mir, self.substs, IndexVec::new()).trans()
+                        MirConstContext::new(self.cx, mir, self.substs, IndexVec::new()).trans()
                     }
                     mir::Literal::Value { value } => {
                         if let ConstVal::Unevaluated(def_id, substs) = value.val {
                             let substs = self.monomorphize(&substs);
-                            MirConstContext::trans_def(self.ccx, def_id, substs, IndexVec::new())
+                            MirConstContext::trans_def(self.cx, def_id, substs, IndexVec::new())
                         } else {
-                            Ok(Const::from_constval(self.ccx, &value.val, ty))
+                            Ok(Const::from_constval(self.cx, &value.val, ty))
                         }
                     }
                 }
@@ -640,12 +640,12 @@
         let elem_ty = array_ty.builtin_index().unwrap_or_else(|| {
             bug!("bad array type {:?}", array_ty)
         });
-        let llunitty = self.ccx.layout_of(elem_ty).llvm_type(self.ccx);
+        let llunitty = self.cx.layout_of(elem_ty).llvm_type(self.cx);
         // If the array contains enums, an LLVM array won't work.
         let val = if fields.iter().all(|&f| val_ty(f) == llunitty) {
             C_array(llunitty, fields)
         } else {
-            C_struct(self.ccx, fields, false)
+            C_struct(self.cx, fields, false)
         };
         Const::new(val, array_ty)
     }
@@ -653,7 +653,7 @@
     fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                     dest_ty: Ty<'tcx>, span: Span)
                     -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
-        let tcx = self.ccx.tcx();
+        let tcx = self.cx.tcx;
         debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span);
         let val = match *rvalue {
             mir::Rvalue::Use(ref operand) => self.const_operand(operand, span)?,
@@ -695,7 +695,7 @@
                 }
                 failure?;
 
-                trans_const_adt(self.ccx, dest_ty, kind, &fields)
+                trans_const_adt(self.cx, dest_ty, kind, &fields)
             }
 
             mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
@@ -706,7 +706,7 @@
                     mir::CastKind::ReifyFnPointer => {
                         match operand.ty.sty {
                             ty::TyFnDef(def_id, substs) => {
-                                callee::resolve_and_get_fn(self.ccx, def_id, substs)
+                                callee::resolve_and_get_fn(self.cx, def_id, substs)
                             }
                             _ => {
                                 span_bug!(span, "{} cannot be reified to a fn ptr",
@@ -728,7 +728,7 @@
                                 let input = tcx.erase_late_bound_regions_and_normalize(&input);
                                 let substs = tcx.mk_substs([operand.ty, input]
                                     .iter().cloned().map(Kind::from));
-                                callee::resolve_and_get_fn(self.ccx, call_once, substs)
+                                callee::resolve_and_get_fn(self.cx, call_once, substs)
                             }
                             _ => {
                                 bug!("{} cannot be cast to a fn ptr", operand.ty)
@@ -742,14 +742,14 @@
                     mir::CastKind::Unsize => {
                         let pointee_ty = operand.ty.builtin_deref(true, ty::NoPreference)
                             .expect("consts: unsizing got non-pointer type").ty;
-                        let (base, old_info) = if !self.ccx.shared().type_is_sized(pointee_ty) {
+                        let (base, old_info) = if !self.cx.type_is_sized(pointee_ty) {
                             // Normally, the source is a thin pointer and we are
                             // adding extra info to make a fat pointer. The exception
                             // is when we are upcasting an existing object fat pointer
                             // to use a different vtable. In that case, we want to
                             // load out the original data pointer so we can repackage
                             // it.
-                            let (base, extra) = operand.get_fat_ptr(self.ccx);
+                            let (base, extra) = operand.get_fat_ptr(self.cx);
                             (base, Some(extra))
                         } else {
                             (operand.llval, None)
@@ -757,28 +757,28 @@
 
                         let unsized_ty = cast_ty.builtin_deref(true, ty::NoPreference)
                             .expect("consts: unsizing got non-pointer target type").ty;
-                        let ptr_ty = self.ccx.layout_of(unsized_ty).llvm_type(self.ccx).ptr_to();
+                        let ptr_ty = self.cx.layout_of(unsized_ty).llvm_type(self.cx).ptr_to();
                         let base = consts::ptrcast(base, ptr_ty);
-                        let info = base::unsized_info(self.ccx, pointee_ty,
+                        let info = base::unsized_info(self.cx, pointee_ty,
                                                       unsized_ty, old_info);
 
                         if old_info.is_none() {
-                            let prev_const = self.ccx.const_unsized().borrow_mut()
+                            let prev_const = self.cx.const_unsized.borrow_mut()
                                                      .insert(base, operand.llval);
                             assert!(prev_const.is_none() || prev_const == Some(operand.llval));
                         }
-                        C_fat_ptr(self.ccx, base, info)
+                        C_fat_ptr(self.cx, base, info)
                     }
-                    mir::CastKind::Misc if self.ccx.layout_of(operand.ty).is_llvm_immediate() => {
+                    mir::CastKind::Misc if self.cx.layout_of(operand.ty).is_llvm_immediate() => {
                         let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
                         let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
-                        let cast_layout = self.ccx.layout_of(cast_ty);
+                        let cast_layout = self.cx.layout_of(cast_ty);
                         assert!(cast_layout.is_llvm_immediate());
-                        let ll_t_out = cast_layout.immediate_llvm_type(self.ccx);
+                        let ll_t_out = cast_layout.immediate_llvm_type(self.cx);
                         let llval = operand.llval;
 
                         let mut signed = false;
-                        let l = self.ccx.layout_of(operand.ty);
+                        let l = self.cx.layout_of(operand.ty);
                         if let layout::Abi::Scalar(ref scalar) = l.abi {
                             if let layout::Int(_, true) = scalar.value {
                                 signed = true;
@@ -792,17 +792,17 @@
                                     llvm::LLVMConstIntCast(llval, ll_t_out.to_ref(), s)
                                 }
                                 (CastTy::Int(_), CastTy::Float) => {
-                                    cast_const_int_to_float(self.ccx, llval, signed, ll_t_out)
+                                    cast_const_int_to_float(self.cx, llval, signed, ll_t_out)
                                 }
                                 (CastTy::Float, CastTy::Float) => {
                                     llvm::LLVMConstFPCast(llval, ll_t_out.to_ref())
                                 }
                                 (CastTy::Float, CastTy::Int(IntTy::I)) => {
-                                    cast_const_float_to_int(self.ccx, &operand,
+                                    cast_const_float_to_int(self.cx, &operand,
                                                             true, ll_t_out, span)
                                 }
                                 (CastTy::Float, CastTy::Int(_)) => {
-                                    cast_const_float_to_int(self.ccx, &operand,
+                                    cast_const_float_to_int(self.cx, &operand,
                                                             false, ll_t_out, span)
                                 }
                                 (CastTy::Ptr(_), CastTy::Ptr(_)) |
@@ -811,7 +811,10 @@
                                     consts::ptrcast(llval, ll_t_out)
                                 }
                                 (CastTy::Int(_), CastTy::Ptr(_)) => {
-                                    llvm::LLVMConstIntToPtr(llval, ll_t_out.to_ref())
+                                    let s = signed as llvm::Bool;
+                                    let usize_llval = llvm::LLVMConstIntCast(llval,
+                                        self.cx.isize_ty.to_ref(), s);
+                                    llvm::LLVMConstIntToPtr(usize_llval, ll_t_out.to_ref())
                                 }
                                 (CastTy::Ptr(_), CastTy::Int(_)) |
                                 (CastTy::FnPtr, CastTy::Int(_)) => {
@@ -822,18 +825,18 @@
                         }
                     }
                     mir::CastKind::Misc => { // Casts from a fat-ptr.
-                        let l = self.ccx.layout_of(operand.ty);
-                        let cast = self.ccx.layout_of(cast_ty);
+                        let l = self.cx.layout_of(operand.ty);
+                        let cast = self.cx.layout_of(cast_ty);
                         if l.is_llvm_scalar_pair() {
-                            let (data_ptr, meta) = operand.get_fat_ptr(self.ccx);
+                            let (data_ptr, meta) = operand.get_fat_ptr(self.cx);
                             if cast.is_llvm_scalar_pair() {
                                 let data_cast = consts::ptrcast(data_ptr,
-                                    cast.scalar_pair_element_llvm_type(self.ccx, 0));
-                                C_fat_ptr(self.ccx, data_cast, meta)
+                                    cast.scalar_pair_element_llvm_type(self.cx, 0));
+                                C_fat_ptr(self.cx, data_cast, meta)
                             } else { // cast to thin-ptr
                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
                                 // pointer-cast of that pointer to desired pointer type.
-                                let llcast_ty = cast.immediate_llvm_type(self.ccx);
+                                let llcast_ty = cast.immediate_llvm_type(self.cx);
                                 consts::ptrcast(data_ptr, llcast_ty)
                             }
                         } else {
@@ -854,32 +857,32 @@
                 let base = match tr_place.base {
                     Base::Value(llval) => {
                         // FIXME: may be wrong for &*(&simd_vec as &fmt::Debug)
-                        let align = if self.ccx.shared().type_is_sized(ty) {
-                            self.ccx.align_of(ty)
+                        let align = if self.cx.type_is_sized(ty) {
+                            self.cx.align_of(ty)
                         } else {
-                            self.ccx.tcx().data_layout.pointer_align
+                            self.cx.tcx.data_layout.pointer_align
                         };
                         if bk == mir::BorrowKind::Mut {
-                            consts::addr_of_mut(self.ccx, llval, align, "ref_mut")
+                            consts::addr_of_mut(self.cx, llval, align, "ref_mut")
                         } else {
-                            consts::addr_of(self.ccx, llval, align, "ref")
+                            consts::addr_of(self.cx, llval, align, "ref")
                         }
                     }
                     Base::Str(llval) |
                     Base::Static(llval) => llval
                 };
 
-                let ptr = if self.ccx.shared().type_is_sized(ty) {
+                let ptr = if self.cx.type_is_sized(ty) {
                     base
                 } else {
-                    C_fat_ptr(self.ccx, base, tr_place.llextra)
+                    C_fat_ptr(self.cx, base, tr_place.llextra)
                 };
                 Const::new(ptr, ref_ty)
             }
 
             mir::Rvalue::Len(ref place) => {
                 let tr_place = self.const_place(place, span)?;
-                Const::new(tr_place.len(self.ccx), tcx.types.usize)
+                Const::new(tr_place.len(self.cx), tcx.types.usize)
             }
 
             mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
@@ -902,9 +905,9 @@
 
                 match const_scalar_checked_binop(tcx, op, lhs, rhs, ty) {
                     Some((llval, of)) => {
-                        trans_const_adt(self.ccx, binop_ty, &mir::AggregateKind::Tuple, &[
+                        trans_const_adt(self.cx, binop_ty, &mir::AggregateKind::Tuple, &[
                             Const::new(llval, val_ty),
-                            Const::new(C_bool(self.ccx, of), tcx.types.bool)
+                            Const::new(C_bool(self.cx, of), tcx.types.bool)
                         ])
                     }
                     None => {
@@ -938,8 +941,8 @@
             }
 
             mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
-                assert!(self.ccx.shared().type_is_sized(ty));
-                let llval = C_usize(self.ccx, self.ccx.size_of(ty).bytes());
+                assert!(self.cx.type_is_sized(ty));
+                let llval = C_usize(self.cx, self.cx.size_of(ty).bytes());
                 Const::new(llval, tcx.types.usize)
             }
 
@@ -1057,7 +1060,7 @@
     }
 }
 
-unsafe fn cast_const_float_to_int(ccx: &CrateContext,
+unsafe fn cast_const_float_to_int(cx: &CodegenCx,
                                   operand: &Const,
                                   signed: bool,
                                   int_ty: Type,
@@ -1071,7 +1074,7 @@
     // One way that might happen would be if addresses could be turned into integers in constant
     // expressions, but that doesn't appear to be possible?
     // In any case, an ICE is better than producing undef.
-    let llval_bits = consts::bitcast(llval, Type::ix(ccx, float_bits as u64));
+    let llval_bits = consts::bitcast(llval, Type::ix(cx, float_bits as u64));
     let bits = const_to_opt_u128(llval_bits, false).unwrap_or_else(|| {
         panic!("could not get bits of constant float {:?}",
                Value(llval));
@@ -1087,12 +1090,12 @@
     };
     if cast_result.status.contains(Status::INVALID_OP) {
         let err = ConstEvalErr { span: span, kind: ErrKind::CannotCast };
-        err.report(ccx.tcx(), span, "expression");
+        err.report(cx.tcx, span, "expression");
     }
     C_uint_big(int_ty, cast_result.value)
 }
 
-unsafe fn cast_const_int_to_float(ccx: &CrateContext,
+unsafe fn cast_const_int_to_float(cx: &CodegenCx,
                                   llval: ValueRef,
                                   signed: bool,
                                   float_ty: Type) -> ValueRef {
@@ -1108,16 +1111,16 @@
         llvm::LLVMConstSIToFP(llval, float_ty.to_ref())
     } else if float_ty.float_width() == 32 && value >= MAX_F32_PLUS_HALF_ULP {
         // We're casting to f32 and the value is > f32::MAX + 0.5 ULP -> round up to infinity.
-        let infinity_bits = C_u32(ccx, ieee::Single::INFINITY.to_bits() as u32);
+        let infinity_bits = C_u32(cx, ieee::Single::INFINITY.to_bits() as u32);
         consts::bitcast(infinity_bits, float_ty)
     } else {
         llvm::LLVMConstUIToFP(llval, float_ty.to_ref())
     }
 }
 
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     pub fn trans_constant(&mut self,
-                          bcx: &Builder<'a, 'tcx>,
+                          bx: &Builder<'a, 'tcx>,
                           constant: &mir::Constant<'tcx>)
                           -> Const<'tcx>
     {
@@ -1126,21 +1129,21 @@
         let result = match constant.literal.clone() {
             mir::Literal::Promoted { index } => {
                 let mir = &self.mir.promoted[index];
-                MirConstContext::new(bcx.ccx, mir, self.param_substs, IndexVec::new()).trans()
+                MirConstContext::new(bx.cx, mir, self.param_substs, IndexVec::new()).trans()
             }
             mir::Literal::Value { value } => {
                 if let ConstVal::Unevaluated(def_id, substs) = value.val {
                     let substs = self.monomorphize(&substs);
-                    MirConstContext::trans_def(bcx.ccx, def_id, substs, IndexVec::new())
+                    MirConstContext::trans_def(bx.cx, def_id, substs, IndexVec::new())
                 } else {
-                    Ok(Const::from_constval(bcx.ccx, &value.val, ty))
+                    Ok(Const::from_constval(bx.cx, &value.val, ty))
                 }
             }
         };
 
         let result = result.unwrap_or_else(|_| {
             // We've errored, so we don't have to produce working code.
-            let llty = bcx.ccx.layout_of(ty).llvm_type(bcx.ccx);
+            let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
             Const::new(C_undef(llty), ty)
         });
 
@@ -1151,11 +1154,11 @@
 
 
 pub fn trans_static_initializer<'a, 'tcx>(
-    ccx: &CrateContext<'a, 'tcx>,
+    cx: &CodegenCx<'a, 'tcx>,
     def_id: DefId)
     -> Result<ValueRef, ConstEvalErr<'tcx>>
 {
-    MirConstContext::trans_def(ccx, def_id, Substs::empty(), IndexVec::new())
+    MirConstContext::trans_def(cx, def_id, Substs::empty(), IndexVec::new())
         .map(|c| c.llval)
 }
 
@@ -1179,19 +1182,19 @@
 /// this could be changed in the future to avoid allocating unnecessary
 /// space after values of shorter-than-maximum cases.
 fn trans_const_adt<'a, 'tcx>(
-    ccx: &CrateContext<'a, 'tcx>,
+    cx: &CodegenCx<'a, 'tcx>,
     t: Ty<'tcx>,
     kind: &mir::AggregateKind,
     vals: &[Const<'tcx>]
 ) -> Const<'tcx> {
-    let l = ccx.layout_of(t);
+    let l = cx.layout_of(t);
     let variant_index = match *kind {
         mir::AggregateKind::Adt(_, index, _, _) => index,
         _ => 0,
     };
 
     if let layout::Abi::Uninhabited = l.abi {
-        return Const::new(C_undef(l.llvm_type(ccx)), t);
+        return Const::new(C_undef(l.llvm_type(cx)), t);
     }
 
     match l.variants {
@@ -1200,14 +1203,14 @@
             if let layout::FieldPlacement::Union(_) = l.fields {
                 assert_eq!(variant_index, 0);
                 assert_eq!(vals.len(), 1);
-                let (field_size, field_align) = ccx.size_and_align_of(vals[0].ty);
+                let (field_size, field_align) = cx.size_and_align_of(vals[0].ty);
                 let contents = [
                     vals[0].llval,
-                    padding(ccx, l.size - field_size)
+                    padding(cx, l.size - field_size)
                 ];
 
                 let packed = l.align.abi() < field_align.abi();
-                Const::new(C_struct(ccx, &contents, packed), t)
+                Const::new(C_struct(cx, &contents, packed), t)
             } else {
                 if let layout::Abi::Vector { .. } = l.abi {
                     if let layout::FieldPlacement::Array { .. } = l.fields {
@@ -1215,24 +1218,24 @@
                             .collect::<Vec<_>>()), t);
                     }
                 }
-                build_const_struct(ccx, l, vals, None)
+                build_const_struct(cx, l, vals, None)
             }
         }
         layout::Variants::Tagged { .. } => {
             let discr = match *kind {
                 mir::AggregateKind::Adt(adt_def, _, _, _) => {
-                    adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
+                    adt_def.discriminant_for_variant(cx.tcx, variant_index)
                            .to_u128_unchecked() as u64
                 },
                 _ => 0,
             };
-            let discr_field = l.field(ccx, 0);
-            let discr = C_int(discr_field.llvm_type(ccx), discr as i64);
+            let discr_field = l.field(cx, 0);
+            let discr = C_int(discr_field.llvm_type(cx), discr as i64);
             if let layout::Abi::Scalar(_) = l.abi {
                 Const::new(discr, t)
             } else {
                 let discr = Const::new(discr, discr_field.ty);
-                build_const_struct(ccx, l.for_variant(ccx, variant_index), vals, Some(discr))
+                build_const_struct(cx, l.for_variant(cx, variant_index), vals, Some(discr))
             }
         }
         layout::Variants::NicheFilling {
@@ -1242,10 +1245,10 @@
             ..
         } => {
             if variant_index == dataful_variant {
-                build_const_struct(ccx, l.for_variant(ccx, dataful_variant), vals, None)
+                build_const_struct(cx, l.for_variant(cx, dataful_variant), vals, None)
             } else {
-                let niche = l.field(ccx, 0);
-                let niche_llty = niche.llvm_type(ccx);
+                let niche = l.field(cx, 0);
+                let niche_llty = niche.llvm_type(cx);
                 let niche_value = ((variant_index - niche_variants.start) as u128)
                     .wrapping_add(niche_start);
                 // FIXME(eddyb) Check the actual primitive type here.
@@ -1255,7 +1258,7 @@
                 } else {
                     C_uint_big(niche_llty, niche_value)
                 };
-                build_const_struct(ccx, l, &[Const::new(niche_llval, niche.ty)], None)
+                build_const_struct(cx, l, &[Const::new(niche_llval, niche.ty)], None)
             }
         }
     }
@@ -1269,7 +1272,7 @@
 /// initializer is 4-byte aligned then simply translating the tuple as
 /// a two-element struct will locate it at offset 4, and accesses to it
 /// will read the wrong memory.
-fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn build_const_struct<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 layout: layout::TyLayout<'tcx>,
                                 vals: &[Const<'tcx>],
                                 discr: Option<Const<'tcx>>)
@@ -1282,16 +1285,16 @@
         layout::Abi::Vector { .. } if discr.is_none() => {
             let mut non_zst_fields = vals.iter().enumerate().map(|(i, f)| {
                 (f, layout.fields.offset(i))
-            }).filter(|&(f, _)| !ccx.layout_of(f.ty).is_zst());
+            }).filter(|&(f, _)| !cx.layout_of(f.ty).is_zst());
             match (non_zst_fields.next(), non_zst_fields.next()) {
                 (Some((x, offset)), None) if offset.bytes() == 0 => {
                     return Const::new(x.llval, layout.ty);
                 }
                 (Some((a, a_offset)), Some((b, _))) if a_offset.bytes() == 0 => {
-                    return Const::new(C_struct(ccx, &[a.llval, b.llval], false), layout.ty);
+                    return Const::new(C_struct(cx, &[a.llval, b.llval], false), layout.ty);
                 }
                 (Some((a, _)), Some((b, b_offset))) if b_offset.bytes() == 0 => {
-                    return Const::new(C_struct(ccx, &[b.llval, a.llval], false), layout.ty);
+                    return Const::new(C_struct(cx, &[b.llval, a.llval], false), layout.ty);
                 }
                 _ => {}
             }
@@ -1306,7 +1309,7 @@
     cfields.reserve(discr.is_some() as usize + 1 + layout.fields.count() * 2);
 
     if let Some(discr) = discr {
-        let (field_size, field_align) = ccx.size_and_align_of(discr.ty);
+        let (field_size, field_align) = cx.size_and_align_of(discr.ty);
         packed |= layout.align.abi() < field_align.abi();
         cfields.push(discr.llval);
         offset = field_size;
@@ -1316,19 +1319,19 @@
         (vals[i], layout.fields.offset(i))
     });
     for (val, target_offset) in parts {
-        let (field_size, field_align) = ccx.size_and_align_of(val.ty);
+        let (field_size, field_align) = cx.size_and_align_of(val.ty);
         packed |= layout.align.abi() < field_align.abi();
-        cfields.push(padding(ccx, target_offset - offset));
+        cfields.push(padding(cx, target_offset - offset));
         cfields.push(val.llval);
         offset = target_offset + field_size;
     }
 
     // Pad to the size of the whole type, not e.g. the variant.
-    cfields.push(padding(ccx, ccx.size_of(layout.ty) - offset));
+    cfields.push(padding(cx, cx.size_of(layout.ty) - offset));
 
-    Const::new(C_struct(ccx, &cfields, packed), layout.ty)
+    Const::new(C_struct(cx, &cfields, packed), layout.ty)
 }
 
-fn padding(ccx: &CrateContext, size: Size) -> ValueRef {
-    C_undef(Type::array(&Type::i8(ccx), size.bytes()))
+fn padding(cx: &CodegenCx, size: Size) -> ValueRef {
+    C_undef(Type::array(&Type::i8(cx), size.bytes()))
 }
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 917ff87..b367eb6 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -19,7 +19,7 @@
 use rustc::session::config::FullDebugInfo;
 use base;
 use builder::Builder;
-use common::{CrateContext, Funclet};
+use common::{CodegenCx, Funclet};
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
 use monomorphize::Instance;
 use abi::{ArgAttribute, FnType, PassMode};
@@ -41,14 +41,14 @@
 use self::operand::{OperandRef, OperandValue};
 
 /// Master context for translating MIR.
-pub struct MirContext<'a, 'tcx:'a> {
+pub struct FunctionCx<'a, 'tcx:'a> {
     mir: &'a mir::Mir<'tcx>,
 
     debug_context: debuginfo::FunctionDebugContext,
 
     llfn: ValueRef,
 
-    ccx: &'a CrateContext<'a, 'tcx>,
+    cx: &'a CodegenCx<'a, 'tcx>,
 
     fn_ty: FnType<'tcx>,
 
@@ -102,16 +102,16 @@
     param_substs: &'tcx Substs<'tcx>,
 }
 
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     pub fn monomorphize<T>(&self, value: &T) -> T
         where T: TransNormalize<'tcx>
     {
-        self.ccx.tcx().trans_apply_param_substs(self.param_substs, value)
+        self.cx.tcx.trans_apply_param_substs(self.param_substs, value)
     }
 
-    pub fn set_debug_loc(&mut self, bcx: &Builder, source_info: mir::SourceInfo) {
+    pub fn set_debug_loc(&mut self, bx: &Builder, source_info: mir::SourceInfo) {
         let (scope, span) = self.debug_loc(source_info);
-        debuginfo::set_source_location(&self.debug_context, bcx, scope, span);
+        debuginfo::set_source_location(&self.debug_context, bx, scope, span);
     }
 
     pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
@@ -128,7 +128,7 @@
         // locations of macro expansions with that of the outermost expansion site
         // (unless the crate is being compiled with `-Z debug-macros`).
         if source_info.span.ctxt() == NO_EXPANSION ||
-           self.ccx.sess().opts.debugging_opts.debug_macros {
+           self.cx.sess().opts.debugging_opts.debug_macros {
             let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
             (scope, source_info.span)
         } else {
@@ -158,9 +158,9 @@
         let scope_metadata = self.scopes[scope_id].scope_metadata;
         if pos < self.scopes[scope_id].file_start_pos ||
            pos >= self.scopes[scope_id].file_end_pos {
-            let cm = self.ccx.sess().codemap();
+            let cm = self.cx.sess().codemap();
             let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
-            debuginfo::extend_scope_to_file(self.ccx,
+            debuginfo::extend_scope_to_file(self.cx,
                                             scope_metadata,
                                             &cm.lookup_char_pos(pos).file,
                                             defining_crate)
@@ -176,12 +176,12 @@
 }
 
 impl<'a, 'tcx> LocalRef<'tcx> {
-    fn new_operand(ccx: &CrateContext<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> {
+    fn new_operand(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> {
         if layout.is_zst() {
             // Zero-size temporaries aren't always initialized, which
             // doesn't matter because they don't contain data, but
             // we need something in the operand.
-            LocalRef::Operand(Some(OperandRef::new_zst(ccx, layout)))
+            LocalRef::Operand(Some(OperandRef::new_zst(cx, layout)))
         } else {
             LocalRef::Operand(None)
         }
@@ -191,46 +191,46 @@
 ///////////////////////////////////////////////////////////////////////////
 
 pub fn trans_mir<'a, 'tcx: 'a>(
-    ccx: &'a CrateContext<'a, 'tcx>,
+    cx: &'a CodegenCx<'a, 'tcx>,
     llfn: ValueRef,
     mir: &'a Mir<'tcx>,
     instance: Instance<'tcx>,
     sig: ty::FnSig<'tcx>,
 ) {
-    let fn_ty = FnType::new(ccx, sig, &[]);
+    let fn_ty = FnType::new(cx, sig, &[]);
     debug!("fn_ty: {:?}", fn_ty);
     let debug_context =
-        debuginfo::create_function_debug_context(ccx, instance, sig, llfn, mir);
-    let bcx = Builder::new_block(ccx, llfn, "start");
+        debuginfo::create_function_debug_context(cx, instance, sig, llfn, mir);
+    let bx = Builder::new_block(cx, llfn, "start");
 
     if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) {
-        bcx.set_personality_fn(ccx.eh_personality());
+        bx.set_personality_fn(cx.eh_personality());
     }
 
     let cleanup_kinds = analyze::cleanup_kinds(&mir);
     // Allocate a `Block` for every basic block, except
     // the start block, if nothing loops back to it.
     let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
-    let block_bcxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
+    let block_bxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
         mir.basic_blocks().indices().map(|bb| {
             if bb == mir::START_BLOCK && !reentrant_start_block {
-                bcx.llbb()
+                bx.llbb()
             } else {
-                bcx.build_sibling_block(&format!("{:?}", bb)).llbb()
+                bx.build_sibling_block(&format!("{:?}", bb)).llbb()
             }
         }).collect();
 
     // Compute debuginfo scopes from MIR scopes.
-    let scopes = debuginfo::create_mir_scopes(ccx, mir, &debug_context);
-    let (landing_pads, funclets) = create_funclets(&bcx, &cleanup_kinds, &block_bcxs);
+    let scopes = debuginfo::create_mir_scopes(cx, mir, &debug_context);
+    let (landing_pads, funclets) = create_funclets(&bx, &cleanup_kinds, &block_bxs);
 
-    let mut mircx = MirContext {
+    let mut fx = FunctionCx {
         mir,
         llfn,
         fn_ty,
-        ccx,
+        cx,
         personality_slot: None,
-        blocks: block_bcxs,
+        blocks: block_bxs,
         unreachable_block: None,
         cleanup_kinds,
         landing_pads,
@@ -244,51 +244,51 @@
         },
     };
 
-    let memory_locals = analyze::memory_locals(&mircx);
+    let memory_locals = analyze::memory_locals(&fx);
 
     // Allocate variable and temp allocas
-    mircx.locals = {
-        let args = arg_local_refs(&bcx, &mircx, &mircx.scopes, &memory_locals);
+    fx.locals = {
+        let args = arg_local_refs(&bx, &fx, &fx.scopes, &memory_locals);
 
         let mut allocate_local = |local| {
             let decl = &mir.local_decls[local];
-            let layout = bcx.ccx.layout_of(mircx.monomorphize(&decl.ty));
+            let layout = bx.cx.layout_of(fx.monomorphize(&decl.ty));
             assert!(!layout.ty.has_erasable_regions());
 
             if let Some(name) = decl.name {
                 // User variable
-                let debug_scope = mircx.scopes[decl.source_info.scope];
-                let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
+                let debug_scope = fx.scopes[decl.source_info.scope];
+                let dbg = debug_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo;
 
                 if !memory_locals.contains(local.index()) && !dbg {
                     debug!("alloc: {:?} ({}) -> operand", local, name);
-                    return LocalRef::new_operand(bcx.ccx, layout);
+                    return LocalRef::new_operand(bx.cx, layout);
                 }
 
                 debug!("alloc: {:?} ({}) -> place", local, name);
-                let place = PlaceRef::alloca(&bcx, layout, &name.as_str());
+                let place = PlaceRef::alloca(&bx, layout, &name.as_str());
                 if dbg {
-                    let (scope, span) = mircx.debug_loc(decl.source_info);
-                    declare_local(&bcx, &mircx.debug_context, name, layout.ty, scope,
+                    let (scope, span) = fx.debug_loc(decl.source_info);
+                    declare_local(&bx, &fx.debug_context, name, layout.ty, scope,
                         VariableAccess::DirectVariable { alloca: place.llval },
                         VariableKind::LocalVariable, span);
                 }
                 LocalRef::Place(place)
             } else {
                 // Temporary or return place
-                if local == mir::RETURN_PLACE && mircx.fn_ty.ret.is_indirect() {
+                if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
                     debug!("alloc: {:?} (return place) -> place", local);
                     let llretptr = llvm::get_param(llfn, 0);
                     LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align))
                 } else if memory_locals.contains(local.index()) {
                     debug!("alloc: {:?} -> place", local);
-                    LocalRef::Place(PlaceRef::alloca(&bcx, layout, &format!("{:?}", local)))
+                    LocalRef::Place(PlaceRef::alloca(&bx, layout, &format!("{:?}", local)))
                 } else {
                     // If this is an immediate local, we do not create an
                     // alloca in advance. Instead we wait until we see the
                     // definition and update the operand there.
                     debug!("alloc: {:?} -> operand", local);
-                    LocalRef::new_operand(bcx.ccx, layout)
+                    LocalRef::new_operand(bx.cx, layout)
                 }
             }
         };
@@ -302,13 +302,13 @@
 
     // Branch to the START block, if it's not the entry block.
     if reentrant_start_block {
-        bcx.br(mircx.blocks[mir::START_BLOCK]);
+        bx.br(fx.blocks[mir::START_BLOCK]);
     }
 
     // Up until here, IR instructions for this function have explicitly not been annotated with
     // source code location, so we don't step into call setup code. From here on, source location
     // emitting should be enabled.
-    debuginfo::start_emitting_source_locations(&mircx.debug_context);
+    debuginfo::start_emitting_source_locations(&fx.debug_context);
 
     let rpo = traversal::reverse_postorder(&mir);
     let mut visited = BitVector::new(mir.basic_blocks().len());
@@ -316,7 +316,7 @@
     // Translate the body of each block using reverse postorder
     for (bb, _) in rpo {
         visited.insert(bb.index());
-        mircx.trans_block(bb);
+        fx.trans_block(bb);
     }
 
     // Remove blocks that haven't been visited, or have no
@@ -326,26 +326,26 @@
         if !visited.contains(bb.index()) {
             debug!("trans_mir: block {:?} was not visited", bb);
             unsafe {
-                llvm::LLVMDeleteBasicBlock(mircx.blocks[bb]);
+                llvm::LLVMDeleteBasicBlock(fx.blocks[bb]);
             }
         }
     }
 }
 
 fn create_funclets<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'tcx>,
     cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
-    block_bcxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
+    block_bxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
     -> (IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
         IndexVec<mir::BasicBlock, Option<Funclet>>)
 {
-    block_bcxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
+    block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
         match *cleanup_kind {
-            CleanupKind::Funclet if base::wants_msvc_seh(bcx.sess()) => {
-                let cleanup_bcx = bcx.build_sibling_block(&format!("funclet_{:?}", bb));
-                let cleanup = cleanup_bcx.cleanup_pad(None, &[]);
-                cleanup_bcx.br(llbb);
-                (Some(cleanup_bcx.llbb()), Some(Funclet::new(cleanup)))
+            CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {
+                let cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb));
+                let cleanup = cleanup_bx.cleanup_pad(None, &[]);
+                cleanup_bx.br(llbb);
+                (Some(cleanup_bx.llbb()), Some(Funclet::new(cleanup)))
             }
             _ => (None, None)
         }
@@ -355,19 +355,19 @@
 /// Produce, for each argument, a `ValueRef` pointing at the
 /// argument's value. As arguments are places, these are always
 /// indirect.
-fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
-                            mircx: &MirContext<'a, 'tcx>,
+fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
+                            fx: &FunctionCx<'a, 'tcx>,
                             scopes: &IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
                             memory_locals: &BitVector)
                             -> Vec<LocalRef<'tcx>> {
-    let mir = mircx.mir;
-    let tcx = bcx.tcx();
+    let mir = fx.mir;
+    let tcx = bx.tcx();
     let mut idx = 0;
-    let mut llarg_idx = mircx.fn_ty.ret.is_indirect() as usize;
+    let mut llarg_idx = fx.fn_ty.ret.is_indirect() as usize;
 
     // Get the argument scope, if it exists and if we need it.
     let arg_scope = scopes[mir::ARGUMENT_VISIBILITY_SCOPE];
-    let arg_scope = if arg_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo {
+    let arg_scope = if arg_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo {
         Some(arg_scope.scope_metadata)
     } else {
         None
@@ -392,17 +392,20 @@
             // to reconstruct it into a tuple local variable, from multiple
             // individual LLVM function arguments.
 
-            let arg_ty = mircx.monomorphize(&arg_decl.ty);
+            let arg_ty = fx.monomorphize(&arg_decl.ty);
             let tupled_arg_tys = match arg_ty.sty {
                 ty::TyTuple(ref tys, _) => tys,
                 _ => bug!("spread argument isn't a tuple?!")
             };
 
-            let place = PlaceRef::alloca(bcx, bcx.ccx.layout_of(arg_ty), &name);
+            let place = PlaceRef::alloca(bx, bx.cx.layout_of(arg_ty), &name);
             for i in 0..tupled_arg_tys.len() {
-                let arg = &mircx.fn_ty.args[idx];
+                let arg = &fx.fn_ty.args[idx];
                 idx += 1;
-                arg.store_fn_arg(bcx, &mut llarg_idx, place.project_field(bcx, i));
+                if arg.pad.is_some() {
+                    llarg_idx += 1;
+                }
+                arg.store_fn_arg(bx, &mut llarg_idx, place.project_field(bx, i));
             }
 
             // Now that we have one alloca that contains the aggregate value,
@@ -412,8 +415,8 @@
                     alloca: place.llval
                 };
                 declare_local(
-                    bcx,
-                    &mircx.debug_context,
+                    bx,
+                    &fx.debug_context,
                     arg_decl.name.unwrap_or(keywords::Invalid.name()),
                     arg_ty, scope,
                     variable_access,
@@ -425,7 +428,7 @@
             return LocalRef::Place(place);
         }
 
-        let arg = &mircx.fn_ty.args[idx];
+        let arg = &fx.fn_ty.args[idx];
         idx += 1;
         if arg.pad.is_some() {
             llarg_idx += 1;
@@ -438,22 +441,22 @@
             let local = |op| LocalRef::Operand(Some(op));
             match arg.mode {
                 PassMode::Ignore => {
-                    return local(OperandRef::new_zst(bcx.ccx, arg.layout));
+                    return local(OperandRef::new_zst(bx.cx, arg.layout));
                 }
                 PassMode::Direct(_) => {
-                    let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
-                    bcx.set_value_name(llarg, &name);
+                    let llarg = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+                    bx.set_value_name(llarg, &name);
                     llarg_idx += 1;
                     return local(
-                        OperandRef::from_immediate_or_packed_pair(bcx, llarg, arg.layout));
+                        OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
                 }
                 PassMode::Pair(..) => {
-                    let a = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
-                    bcx.set_value_name(a, &(name.clone() + ".0"));
+                    let a = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+                    bx.set_value_name(a, &(name.clone() + ".0"));
                     llarg_idx += 1;
 
-                    let b = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
-                    bcx.set_value_name(b, &(name + ".1"));
+                    let b = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+                    bx.set_value_name(b, &(name + ".1"));
                     llarg_idx += 1;
 
                     return local(OperandRef {
@@ -469,13 +472,13 @@
             // Don't copy an indirect argument to an alloca, the caller
             // already put it in a temporary alloca and gave it up.
             // FIXME: lifetimes
-            let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
-            bcx.set_value_name(llarg, &name);
+            let llarg = llvm::get_param(bx.llfn(), llarg_idx as c_uint);
+            bx.set_value_name(llarg, &name);
             llarg_idx += 1;
             PlaceRef::new_sized(llarg, arg.layout, arg.layout.align)
         } else {
-            let tmp = PlaceRef::alloca(bcx, arg.layout, &name);
-            arg.store_fn_arg(bcx, &mut llarg_idx, tmp);
+            let tmp = PlaceRef::alloca(bx, arg.layout, &name);
+            arg.store_fn_arg(bx, &mut llarg_idx, tmp);
             tmp
         };
         arg_scope.map(|scope| {
@@ -498,8 +501,8 @@
                 }
 
                 declare_local(
-                    bcx,
-                    &mircx.debug_context,
+                    bx,
+                    &fx.debug_context,
                     arg_decl.name.unwrap_or(keywords::Invalid.name()),
                     arg.layout.ty,
                     scope,
@@ -512,7 +515,7 @@
 
             // Or is it the closure environment?
             let (closure_layout, env_ref) = match arg.layout.ty.sty {
-                ty::TyRef(_, mt) | ty::TyRawPtr(mt) => (bcx.ccx.layout_of(mt.ty), true),
+                ty::TyRef(_, mt) | ty::TyRawPtr(mt) => (bx.cx.layout_of(mt.ty), true),
                 _ => (arg.layout, false)
             };
 
@@ -530,10 +533,10 @@
             // doesn't actually strip the offset when splitting the closure
             // environment into its components so it ends up out of bounds.
             let env_ptr = if !env_ref {
-                let scratch = PlaceRef::alloca(bcx,
-                    bcx.ccx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
+                let scratch = PlaceRef::alloca(bx,
+                    bx.cx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
                     "__debuginfo_env_ptr");
-                bcx.store(place.llval, scratch.llval, scratch.align);
+                bx.store(place.llval, scratch.llval, scratch.align);
                 scratch.llval
             } else {
                 place.llval
@@ -544,7 +547,7 @@
 
                 let ops = unsafe {
                     [llvm::LLVMRustDIBuilderCreateOpDeref(),
-                     llvm::LLVMRustDIBuilderCreateOpPlus(),
+                     llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
                      byte_offset_of_var_in_env as i64,
                      llvm::LLVMRustDIBuilderCreateOpDeref()]
                 };
@@ -567,8 +570,8 @@
                     address_operations: &ops
                 };
                 declare_local(
-                    bcx,
-                    &mircx.debug_context,
+                    bx,
+                    &fx.debug_context,
                     decl.debug_name,
                     ty,
                     scope,
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index c882353..25db9f9 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -15,7 +15,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 
 use base;
-use common::{self, CrateContext, C_undef, C_usize};
+use common::{self, CodegenCx, C_undef, C_usize};
 use builder::Builder;
 use value::Value;
 use type_of::LayoutLlvmExt;
@@ -24,7 +24,7 @@
 use std::fmt;
 use std::ptr;
 
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
 use super::place::PlaceRef;
 
 /// The representation of a Rust value. The enum variant is in fact
@@ -81,11 +81,11 @@
 }
 
 impl<'a, 'tcx> OperandRef<'tcx> {
-    pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
+    pub fn new_zst(cx: &CodegenCx<'a, 'tcx>,
                    layout: TyLayout<'tcx>) -> OperandRef<'tcx> {
         assert!(layout.is_zst());
         OperandRef {
-            val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(ccx))),
+            val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))),
             layout
         }
     }
@@ -99,7 +99,7 @@
         }
     }
 
-    pub fn deref(self, ccx: &CrateContext<'a, 'tcx>) -> PlaceRef<'tcx> {
+    pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> {
         let projected_ty = self.layout.ty.builtin_deref(true, ty::NoPreference)
             .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty;
         let (llptr, llextra) = match self.val {
@@ -107,7 +107,7 @@
             OperandValue::Pair(llptr, llextra) => (llptr, llextra),
             OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
         };
-        let layout = ccx.layout_of(projected_ty);
+        let layout = cx.layout_of(projected_ty);
         PlaceRef {
             llval: llptr,
             llextra,
@@ -118,15 +118,15 @@
 
     /// If this operand is a `Pair`, we return an aggregate with the two values.
     /// For other cases, see `immediate`.
-    pub fn immediate_or_packed_pair(self, bcx: &Builder<'a, 'tcx>) -> ValueRef {
+    pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef {
         if let OperandValue::Pair(a, b) = self.val {
-            let llty = self.layout.llvm_type(bcx.ccx);
+            let llty = self.layout.llvm_type(bx.cx);
             debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}",
                    self, llty);
             // Reconstruct the immediate aggregate.
             let mut llpair = C_undef(llty);
-            llpair = bcx.insert_value(llpair, a, 0);
-            llpair = bcx.insert_value(llpair, b, 1);
+            llpair = bx.insert_value(llpair, a, 0);
+            llpair = bx.insert_value(llpair, b, 1);
             llpair
         } else {
             self.immediate()
@@ -134,7 +134,7 @@
     }
 
     /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`.
-    pub fn from_immediate_or_packed_pair(bcx: &Builder<'a, 'tcx>,
+    pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>,
                                          llval: ValueRef,
                                          layout: TyLayout<'tcx>)
                                          -> OperandRef<'tcx> {
@@ -143,23 +143,23 @@
                     llval, layout);
 
             // Deconstruct the immediate aggregate.
-            OperandValue::Pair(bcx.extract_value(llval, 0),
-                               bcx.extract_value(llval, 1))
+            OperandValue::Pair(bx.extract_value(llval, 0),
+                               bx.extract_value(llval, 1))
         } else {
             OperandValue::Immediate(llval)
         };
         OperandRef { val, layout }
     }
 
-    pub fn extract_field(&self, bcx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> {
-        let field = self.layout.field(bcx.ccx, i);
+    pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> {
+        let field = self.layout.field(bx.cx, i);
         let offset = self.layout.fields.offset(i);
 
         let mut val = match (self.val, &self.layout.abi) {
             // If we're uninhabited, or the field is ZST, it has no data.
             _ if self.layout.abi == layout::Abi::Uninhabited || field.is_zst() => {
                 return OperandRef {
-                    val: OperandValue::Immediate(C_undef(field.immediate_llvm_type(bcx.ccx))),
+                    val: OperandValue::Immediate(C_undef(field.immediate_llvm_type(bx.cx))),
                     layout: field
                 };
             }
@@ -174,12 +174,12 @@
             // Extract a scalar component from a pair.
             (OperandValue::Pair(a_llval, b_llval), &layout::Abi::ScalarPair(ref a, ref b)) => {
                 if offset.bytes() == 0 {
-                    assert_eq!(field.size, a.value.size(bcx.ccx));
+                    assert_eq!(field.size, a.value.size(bx.cx));
                     OperandValue::Immediate(a_llval)
                 } else {
-                    assert_eq!(offset, a.value.size(bcx.ccx)
-                        .abi_align(b.value.align(bcx.ccx)));
-                    assert_eq!(field.size, b.value.size(bcx.ccx));
+                    assert_eq!(offset, a.value.size(bx.cx)
+                        .abi_align(b.value.align(bx.cx)));
+                    assert_eq!(field.size, b.value.size(bx.cx));
                     OperandValue::Immediate(b_llval)
                 }
             }
@@ -187,7 +187,7 @@
             // `#[repr(simd)]` types are also immediate.
             (OperandValue::Immediate(llval), &layout::Abi::Vector { .. }) => {
                 OperandValue::Immediate(
-                    bcx.extract_element(llval, C_usize(bcx.ccx, i as u64)))
+                    bx.extract_element(llval, C_usize(bx.cx, i as u64)))
             }
 
             _ => bug!("OperandRef::extract_field({:?}): not applicable", self)
@@ -196,11 +196,11 @@
         // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
         match val {
             OperandValue::Immediate(ref mut llval) => {
-                *llval = bcx.bitcast(*llval, field.immediate_llvm_type(bcx.ccx));
+                *llval = bx.bitcast(*llval, field.immediate_llvm_type(bx.cx));
             }
             OperandValue::Pair(ref mut a, ref mut b) => {
-                *a = bcx.bitcast(*a, field.scalar_pair_element_llvm_type(bcx.ccx, 0));
-                *b = bcx.bitcast(*b, field.scalar_pair_element_llvm_type(bcx.ccx, 1));
+                *a = bx.bitcast(*a, field.scalar_pair_element_llvm_type(bx.cx, 0));
+                *b = bx.bitcast(*b, field.scalar_pair_element_llvm_type(bx.cx, 1));
             }
             OperandValue::Ref(..) => bug!()
         }
@@ -213,7 +213,7 @@
 }
 
 impl<'a, 'tcx> OperandValue {
-    pub fn store(self, bcx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+    pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
         debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
         // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
         // value is through `undef`, and store itself is useless.
@@ -222,28 +222,28 @@
         }
         match self {
             OperandValue::Ref(r, source_align) =>
-                base::memcpy_ty(bcx, dest.llval, r, dest.layout,
+                base::memcpy_ty(bx, dest.llval, r, dest.layout,
                                 source_align.min(dest.align)),
             OperandValue::Immediate(s) => {
-                bcx.store(base::from_immediate(bcx, s), dest.llval, dest.align);
+                bx.store(base::from_immediate(bx, s), dest.llval, dest.align);
             }
             OperandValue::Pair(a, b) => {
                 for (i, &x) in [a, b].iter().enumerate() {
-                    let mut llptr = bcx.struct_gep(dest.llval, i as u64);
+                    let mut llptr = bx.struct_gep(dest.llval, i as u64);
                     // Make sure to always store i1 as i8.
-                    if common::val_ty(x) == Type::i1(bcx.ccx) {
-                        llptr = bcx.pointercast(llptr, Type::i8p(bcx.ccx));
+                    if common::val_ty(x) == Type::i1(bx.cx) {
+                        llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
                     }
-                    bcx.store(base::from_immediate(bcx, x), llptr, dest.align);
+                    bx.store(base::from_immediate(bx, x), llptr, dest.align);
                 }
             }
         }
     }
 }
 
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     fn maybe_trans_consume_direct(&mut self,
-                                  bcx: &Builder<'a, 'tcx>,
+                                  bx: &Builder<'a, 'tcx>,
                                   place: &mir::Place<'tcx>)
                                    -> Option<OperandRef<'tcx>>
     {
@@ -267,9 +267,22 @@
 
         // Moves out of scalar and scalar pair fields are trivial.
         if let &mir::Place::Projection(ref proj) = place {
-            if let mir::ProjectionElem::Field(ref f, _) = proj.elem {
-                if let Some(o) = self.maybe_trans_consume_direct(bcx, &proj.base) {
-                    return Some(o.extract_field(bcx, f.index()));
+            if let Some(o) = self.maybe_trans_consume_direct(bx, &proj.base) {
+                match proj.elem {
+                    mir::ProjectionElem::Field(ref f, _) => {
+                        return Some(o.extract_field(bx, f.index()));
+                    }
+                    mir::ProjectionElem::Index(_) |
+                    mir::ProjectionElem::ConstantIndex { .. } => {
+                        // ZSTs don't require any actual memory access.
+                        // FIXME(eddyb) deduplicate this with the identical
+                        // checks in `trans_consume` and `extract_field`.
+                        let elem = o.layout.field(bx.cx, 0);
+                        if elem.is_zst() {
+                            return Some(OperandRef::new_zst(bx.cx, elem));
+                        }
+                    }
+                    _ => {}
                 }
             }
         }
@@ -278,31 +291,31 @@
     }
 
     pub fn trans_consume(&mut self,
-                         bcx: &Builder<'a, 'tcx>,
+                         bx: &Builder<'a, 'tcx>,
                          place: &mir::Place<'tcx>)
                          -> OperandRef<'tcx>
     {
         debug!("trans_consume(place={:?})", place);
 
         let ty = self.monomorphized_place_ty(place);
-        let layout = bcx.ccx.layout_of(ty);
+        let layout = bx.cx.layout_of(ty);
 
         // ZSTs don't require any actual memory access.
         if layout.is_zst() {
-            return OperandRef::new_zst(bcx.ccx, layout);
+            return OperandRef::new_zst(bx.cx, layout);
         }
 
-        if let Some(o) = self.maybe_trans_consume_direct(bcx, place) {
+        if let Some(o) = self.maybe_trans_consume_direct(bx, place) {
             return o;
         }
 
         // for most places, to consume them we just load them
         // out from their home
-        self.trans_place(bcx, place).load(bcx)
+        self.trans_place(bx, place).load(bx)
     }
 
     pub fn trans_operand(&mut self,
-                         bcx: &Builder<'a, 'tcx>,
+                         bx: &Builder<'a, 'tcx>,
                          operand: &mir::Operand<'tcx>)
                          -> OperandRef<'tcx>
     {
@@ -311,15 +324,15 @@
         match *operand {
             mir::Operand::Copy(ref place) |
             mir::Operand::Move(ref place) => {
-                self.trans_consume(bcx, place)
+                self.trans_consume(bx, place)
             }
 
             mir::Operand::Constant(ref constant) => {
-                let val = self.trans_constant(&bcx, constant);
-                let operand = val.to_operand(bcx.ccx);
+                let val = self.trans_constant(&bx, constant);
+                let operand = val.to_operand(bx.cx);
                 if let OperandValue::Ref(ptr, align) = operand.val {
                     // If this is a OperandValue::Ref to an immediate constant, load it.
-                    PlaceRef::new_sized(ptr, operand.layout, align).load(bcx)
+                    PlaceRef::new_sized(ptr, operand.layout, align).load(bx)
                 } else {
                     operand
                 }
diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs
index b556b6a..9977047 100644
--- a/src/librustc_trans/mir/place.rs
+++ b/src/librustc_trans/mir/place.rs
@@ -16,7 +16,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 use base;
 use builder::Builder;
-use common::{CrateContext, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big};
+use common::{CodegenCx, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big};
 use consts;
 use type_of::LayoutLlvmExt;
 use type_::Type;
@@ -25,7 +25,7 @@
 
 use std::ptr;
 
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
 use super::operand::{OperandRef, OperandValue};
 
 #[derive(Copy, Clone, Debug)]
@@ -56,21 +56,21 @@
         }
     }
 
-    pub fn alloca(bcx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
+    pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
                   -> PlaceRef<'tcx> {
         debug!("alloca({:?}: {:?})", name, layout);
-        let tmp = bcx.alloca(layout.llvm_type(bcx.ccx), name, layout.align);
+        let tmp = bx.alloca(layout.llvm_type(bx.cx), name, layout.align);
         Self::new_sized(tmp, layout, layout.align)
     }
 
-    pub fn len(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
+    pub fn len(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
         if let layout::FieldPlacement::Array { count, .. } = self.layout.fields {
             if self.layout.is_unsized() {
                 assert!(self.has_extra());
                 assert_eq!(count, 0);
                 self.llextra
             } else {
-                C_usize(ccx, count)
+                C_usize(cx, count)
             }
         } else {
             bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout)
@@ -81,19 +81,19 @@
         !self.llextra.is_null()
     }
 
-    pub fn load(&self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
+    pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
         debug!("PlaceRef::load: {:?}", self);
 
         assert!(!self.has_extra());
 
         if self.layout.is_zst() {
-            return OperandRef::new_zst(bcx.ccx, self.layout);
+            return OperandRef::new_zst(bx.cx, self.layout);
         }
 
         let scalar_load_metadata = |load, scalar: &layout::Scalar| {
             let (min, max) = (scalar.valid_range.start, scalar.valid_range.end);
             let max_next = max.wrapping_add(1);
-            let bits = scalar.value.size(bcx.ccx).bits();
+            let bits = scalar.value.size(bx.cx).bits();
             assert!(bits <= 128);
             let mask = !0u128 >> (128 - bits);
             // For a (max) value of -1, max will be `-1 as usize`, which overflows.
@@ -106,10 +106,10 @@
                 layout::Int(..) if max_next & mask != min & mask => {
                     // llvm::ConstantRange can deal with ranges that wrap around,
                     // so an overflow on (max + 1) is fine.
-                    bcx.range_metadata(load, min..max_next);
+                    bx.range_metadata(load, min..max_next);
                 }
                 layout::Pointer if 0 < min && min < max => {
-                    bcx.nonnull_metadata(load);
+                    bx.nonnull_metadata(load);
                 }
                 _ => {}
             }
@@ -127,24 +127,24 @@
             let llval = if !const_llval.is_null() {
                 const_llval
             } else {
-                let load = bcx.load(self.llval, self.align);
+                let load = bx.load(self.llval, self.align);
                 if let layout::Abi::Scalar(ref scalar) = self.layout.abi {
                     scalar_load_metadata(load, scalar);
                 }
                 load
             };
-            OperandValue::Immediate(base::to_immediate(bcx, llval, self.layout))
+            OperandValue::Immediate(base::to_immediate(bx, llval, self.layout))
         } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi {
             let load = |i, scalar: &layout::Scalar| {
-                let mut llptr = bcx.struct_gep(self.llval, i as u64);
+                let mut llptr = bx.struct_gep(self.llval, i as u64);
                 // Make sure to always load i1 as i8.
                 if scalar.is_bool() {
-                    llptr = bcx.pointercast(llptr, Type::i8p(bcx.ccx));
+                    llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
                 }
-                let load = bcx.load(llptr, self.align);
+                let load = bx.load(llptr, self.align);
                 scalar_load_metadata(load, scalar);
                 if scalar.is_bool() {
-                    bcx.trunc(load, Type::i1(bcx.ccx))
+                    bx.trunc(load, Type::i1(bx.cx))
                 } else {
                     load
                 }
@@ -158,9 +158,9 @@
     }
 
     /// Access a field, at a point when the value's case is known.
-    pub fn project_field(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> {
-        let ccx = bcx.ccx;
-        let field = self.layout.field(ccx, ix);
+    pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> {
+        let cx = bx.cx;
+        let field = self.layout.field(cx, ix);
         let offset = self.layout.fields.offset(ix);
         let align = self.align.min(self.layout.align).min(field.align);
 
@@ -170,15 +170,15 @@
                 self.llval
             } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi {
                 // Offsets have to match either first or second field.
-                assert_eq!(offset, a.value.size(ccx).abi_align(b.value.align(ccx)));
-                bcx.struct_gep(self.llval, 1)
+                assert_eq!(offset, a.value.size(cx).abi_align(b.value.align(cx)));
+                bx.struct_gep(self.llval, 1)
             } else {
-                bcx.struct_gep(self.llval, self.layout.llvm_field_index(ix))
+                bx.struct_gep(self.llval, self.layout.llvm_field_index(ix))
             };
             PlaceRef {
                 // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
-                llval: bcx.pointercast(llval, field.llvm_type(ccx).ptr_to()),
-                llextra: if ccx.shared().type_has_metadata(field.ty) {
+                llval: bx.pointercast(llval, field.llvm_type(cx).ptr_to()),
+                llextra: if cx.type_has_metadata(field.ty) {
                     self.llextra
                 } else {
                     ptr::null_mut()
@@ -228,10 +228,10 @@
 
         let meta = self.llextra;
 
-        let unaligned_offset = C_usize(ccx, offset.bytes());
+        let unaligned_offset = C_usize(cx, offset.bytes());
 
         // Get the alignment of the field
-        let (_, unsized_align) = glue::size_and_align_of_dst(bcx, field.ty, meta);
+        let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
 
         // Bump the unaligned offset up to the appropriate alignment using the
         // following expression:
@@ -239,22 +239,22 @@
         //   (unaligned offset + (align - 1)) & -align
 
         // Calculate offset
-        let align_sub_1 = bcx.sub(unsized_align, C_usize(ccx, 1u64));
-        let offset = bcx.and(bcx.add(unaligned_offset, align_sub_1),
-        bcx.neg(unsized_align));
+        let align_sub_1 = bx.sub(unsized_align, C_usize(cx, 1u64));
+        let offset = bx.and(bx.add(unaligned_offset, align_sub_1),
+        bx.neg(unsized_align));
 
         debug!("struct_field_ptr: DST field offset: {:?}", Value(offset));
 
         // Cast and adjust pointer
-        let byte_ptr = bcx.pointercast(self.llval, Type::i8p(ccx));
-        let byte_ptr = bcx.gep(byte_ptr, &[offset]);
+        let byte_ptr = bx.pointercast(self.llval, Type::i8p(cx));
+        let byte_ptr = bx.gep(byte_ptr, &[offset]);
 
         // Finally, cast back to the type expected
-        let ll_fty = field.llvm_type(ccx);
+        let ll_fty = field.llvm_type(cx);
         debug!("struct_field_ptr: Field type is {:?}", ll_fty);
 
         PlaceRef {
-            llval: bcx.pointercast(byte_ptr, ll_fty.ptr_to()),
+            llval: bx.pointercast(byte_ptr, ll_fty.ptr_to()),
             llextra: self.llextra,
             layout: field,
             align,
@@ -262,8 +262,8 @@
     }
 
     /// Obtain the actual discriminant of a value.
-    pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
-        let cast_to = bcx.ccx.layout_of(cast_to).immediate_llvm_type(bcx.ccx);
+    pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
+        let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
         match self.layout.variants {
             layout::Variants::Single { index } => {
                 return C_uint(cast_to, index as u64);
@@ -272,8 +272,8 @@
             layout::Variants::NicheFilling { .. } => {},
         }
 
-        let discr = self.project_field(bcx, 0);
-        let lldiscr = discr.load(bcx).immediate();
+        let discr = self.project_field(bx, 0);
+        let lldiscr = discr.load(bx).immediate();
         match self.layout.variants {
             layout::Variants::Single { .. } => bug!(),
             layout::Variants::Tagged { ref discr, .. } => {
@@ -281,7 +281,7 @@
                     layout::Int(_, signed) => signed,
                     _ => false
                 };
-                bcx.intcast(lldiscr, cast_to, signed)
+                bx.intcast(lldiscr, cast_to, signed)
             }
             layout::Variants::NicheFilling {
                 dataful_variant,
@@ -289,7 +289,7 @@
                 niche_start,
                 ..
             } => {
-                let niche_llty = discr.layout.immediate_llvm_type(bcx.ccx);
+                let niche_llty = discr.layout.immediate_llvm_type(bx.cx);
                 if niche_variants.start == niche_variants.end {
                     // FIXME(eddyb) Check the actual primitive type here.
                     let niche_llval = if niche_start == 0 {
@@ -298,16 +298,16 @@
                     } else {
                         C_uint_big(niche_llty, niche_start)
                     };
-                    bcx.select(bcx.icmp(llvm::IntEQ, lldiscr, niche_llval),
+                    bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
                         C_uint(cast_to, niche_variants.start as u64),
                         C_uint(cast_to, dataful_variant as u64))
                 } else {
                     // Rebase from niche values to discriminant values.
                     let delta = niche_start.wrapping_sub(niche_variants.start as u128);
-                    let lldiscr = bcx.sub(lldiscr, C_uint_big(niche_llty, delta));
+                    let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
                     let lldiscr_max = C_uint(niche_llty, niche_variants.end as u64);
-                    bcx.select(bcx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
-                        bcx.intcast(lldiscr, cast_to, false),
+                    bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
+                        bx.intcast(lldiscr, cast_to, false),
                         C_uint(cast_to, dataful_variant as u64))
                 }
             }
@@ -316,8 +316,8 @@
 
     /// Set the discriminant for a new value of the given case of the given
     /// representation.
-    pub fn trans_set_discr(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize) {
-        if self.layout.for_variant(bcx.ccx, variant_index).abi == layout::Abi::Uninhabited {
+    pub fn trans_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) {
+        if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
             return;
         }
         match self.layout.variants {
@@ -325,11 +325,11 @@
                 assert_eq!(index, variant_index);
             }
             layout::Variants::Tagged { .. } => {
-                let ptr = self.project_field(bcx, 0);
+                let ptr = self.project_field(bx, 0);
                 let to = self.layout.ty.ty_adt_def().unwrap()
-                    .discriminant_for_variant(bcx.tcx(), variant_index)
+                    .discriminant_for_variant(bx.tcx(), variant_index)
                     .to_u128_unchecked() as u64;
-                bcx.store(C_int(ptr.layout.llvm_type(bcx.ccx), to as i64),
+                bx.store(C_int(ptr.layout.llvm_type(bx.cx), to as i64),
                     ptr.llval, ptr.align);
             }
             layout::Variants::NicheFilling {
@@ -339,20 +339,20 @@
                 ..
             } => {
                 if variant_index != dataful_variant {
-                    if bcx.sess().target.target.arch == "arm" ||
-                       bcx.sess().target.target.arch == "aarch64" {
+                    if bx.sess().target.target.arch == "arm" ||
+                       bx.sess().target.target.arch == "aarch64" {
                         // Issue #34427: As workaround for LLVM bug on ARM,
                         // use memset of 0 before assigning niche value.
-                        let llptr = bcx.pointercast(self.llval, Type::i8(bcx.ccx).ptr_to());
-                        let fill_byte = C_u8(bcx.ccx, 0);
+                        let llptr = bx.pointercast(self.llval, Type::i8(bx.cx).ptr_to());
+                        let fill_byte = C_u8(bx.cx, 0);
                         let (size, align) = self.layout.size_and_align();
-                        let size = C_usize(bcx.ccx, size.bytes());
-                        let align = C_u32(bcx.ccx, align.abi() as u32);
-                        base::call_memset(bcx, llptr, fill_byte, size, align, false);
+                        let size = C_usize(bx.cx, size.bytes());
+                        let align = C_u32(bx.cx, align.abi() as u32);
+                        base::call_memset(bx, llptr, fill_byte, size, align, false);
                     }
 
-                    let niche = self.project_field(bcx, 0);
-                    let niche_llty = niche.layout.immediate_llvm_type(bcx.ccx);
+                    let niche = self.project_field(bx, 0);
+                    let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
                     let niche_value = ((variant_index - niche_variants.start) as u128)
                         .wrapping_add(niche_start);
                     // FIXME(eddyb) Check the actual primitive type here.
@@ -362,52 +362,52 @@
                     } else {
                         C_uint_big(niche_llty, niche_value)
                     };
-                    OperandValue::Immediate(niche_llval).store(bcx, niche);
+                    OperandValue::Immediate(niche_llval).store(bx, niche);
                 }
             }
         }
     }
 
-    pub fn project_index(&self, bcx: &Builder<'a, 'tcx>, llindex: ValueRef)
+    pub fn project_index(&self, bx: &Builder<'a, 'tcx>, llindex: ValueRef)
                          -> PlaceRef<'tcx> {
         PlaceRef {
-            llval: bcx.inbounds_gep(self.llval, &[C_usize(bcx.ccx, 0), llindex]),
+            llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]),
             llextra: ptr::null_mut(),
-            layout: self.layout.field(bcx.ccx, 0),
+            layout: self.layout.field(bx.cx, 0),
             align: self.align
         }
     }
 
-    pub fn project_downcast(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize)
+    pub fn project_downcast(&self, bx: &Builder<'a, 'tcx>, variant_index: usize)
                             -> PlaceRef<'tcx> {
         let mut downcast = *self;
-        downcast.layout = self.layout.for_variant(bcx.ccx, variant_index);
+        downcast.layout = self.layout.for_variant(bx.cx, variant_index);
 
         // Cast to the appropriate variant struct type.
-        let variant_ty = downcast.layout.llvm_type(bcx.ccx);
-        downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
+        let variant_ty = downcast.layout.llvm_type(bx.cx);
+        downcast.llval = bx.pointercast(downcast.llval, variant_ty.ptr_to());
 
         downcast
     }
 
-    pub fn storage_live(&self, bcx: &Builder<'a, 'tcx>) {
-        bcx.lifetime_start(self.llval, self.layout.size);
+    pub fn storage_live(&self, bx: &Builder<'a, 'tcx>) {
+        bx.lifetime_start(self.llval, self.layout.size);
     }
 
-    pub fn storage_dead(&self, bcx: &Builder<'a, 'tcx>) {
-        bcx.lifetime_end(self.llval, self.layout.size);
+    pub fn storage_dead(&self, bx: &Builder<'a, 'tcx>) {
+        bx.lifetime_end(self.llval, self.layout.size);
     }
 }
 
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     pub fn trans_place(&mut self,
-                        bcx: &Builder<'a, 'tcx>,
+                        bx: &Builder<'a, 'tcx>,
                         place: &mir::Place<'tcx>)
                         -> PlaceRef<'tcx> {
         debug!("trans_place(place={:?})", place);
 
-        let ccx = bcx.ccx;
-        let tcx = ccx.tcx();
+        let cx = bx.cx;
+        let tcx = cx.tcx;
 
         if let mir::Place::Local(index) = *place {
             match self.locals[index] {
@@ -423,66 +423,66 @@
         let result = match *place {
             mir::Place::Local(_) => bug!(), // handled above
             mir::Place::Static(box mir::Static { def_id, ty }) => {
-                let layout = ccx.layout_of(self.monomorphize(&ty));
-                PlaceRef::new_sized(consts::get_static(ccx, def_id), layout, layout.align)
+                let layout = cx.layout_of(self.monomorphize(&ty));
+                PlaceRef::new_sized(consts::get_static(cx, def_id), layout, layout.align)
             },
             mir::Place::Projection(box mir::Projection {
                 ref base,
                 elem: mir::ProjectionElem::Deref
             }) => {
                 // Load the pointer from its location.
-                self.trans_consume(bcx, base).deref(bcx.ccx)
+                self.trans_consume(bx, base).deref(bx.cx)
             }
             mir::Place::Projection(ref projection) => {
-                let tr_base = self.trans_place(bcx, &projection.base);
+                let tr_base = self.trans_place(bx, &projection.base);
 
                 match projection.elem {
                     mir::ProjectionElem::Deref => bug!(),
                     mir::ProjectionElem::Field(ref field, _) => {
-                        tr_base.project_field(bcx, field.index())
+                        tr_base.project_field(bx, field.index())
                     }
                     mir::ProjectionElem::Index(index) => {
                         let index = &mir::Operand::Copy(mir::Place::Local(index));
-                        let index = self.trans_operand(bcx, index);
+                        let index = self.trans_operand(bx, index);
                         let llindex = index.immediate();
-                        tr_base.project_index(bcx, llindex)
+                        tr_base.project_index(bx, llindex)
                     }
                     mir::ProjectionElem::ConstantIndex { offset,
                                                          from_end: false,
                                                          min_length: _ } => {
-                        let lloffset = C_usize(bcx.ccx, offset as u64);
-                        tr_base.project_index(bcx, lloffset)
+                        let lloffset = C_usize(bx.cx, offset as u64);
+                        tr_base.project_index(bx, lloffset)
                     }
                     mir::ProjectionElem::ConstantIndex { offset,
                                                          from_end: true,
                                                          min_length: _ } => {
-                        let lloffset = C_usize(bcx.ccx, offset as u64);
-                        let lllen = tr_base.len(bcx.ccx);
-                        let llindex = bcx.sub(lllen, lloffset);
-                        tr_base.project_index(bcx, llindex)
+                        let lloffset = C_usize(bx.cx, offset as u64);
+                        let lllen = tr_base.len(bx.cx);
+                        let llindex = bx.sub(lllen, lloffset);
+                        tr_base.project_index(bx, llindex)
                     }
                     mir::ProjectionElem::Subslice { from, to } => {
-                        let mut subslice = tr_base.project_index(bcx,
-                            C_usize(bcx.ccx, from as u64));
+                        let mut subslice = tr_base.project_index(bx,
+                            C_usize(bx.cx, from as u64));
                         let projected_ty = PlaceTy::Ty { ty: tr_base.layout.ty }
-                            .projection_ty(tcx, &projection.elem).to_ty(bcx.tcx());
-                        subslice.layout = bcx.ccx.layout_of(self.monomorphize(&projected_ty));
+                            .projection_ty(tcx, &projection.elem).to_ty(bx.tcx());
+                        subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
                             assert!(tr_base.has_extra());
-                            subslice.llextra = bcx.sub(tr_base.llextra,
-                                C_usize(bcx.ccx, (from as u64) + (to as u64)));
+                            subslice.llextra = bx.sub(tr_base.llextra,
+                                C_usize(bx.cx, (from as u64) + (to as u64)));
                         }
 
                         // Cast the place pointer type to the new
                         // array or slice type (*[%_; new_len]).
-                        subslice.llval = bcx.pointercast(subslice.llval,
-                            subslice.layout.llvm_type(bcx.ccx).ptr_to());
+                        subslice.llval = bx.pointercast(subslice.llval,
+                            subslice.layout.llvm_type(bx.cx).ptr_to());
 
                         subslice
                     }
                     mir::ProjectionElem::Downcast(_, v) => {
-                        tr_base.project_downcast(bcx, v)
+                        tr_base.project_downcast(bx, v)
                     }
                 }
             }
@@ -492,7 +492,7 @@
     }
 
     pub fn monomorphized_place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
-        let tcx = self.ccx.tcx();
+        let tcx = self.cx.tcx;
         let place_ty = place.ty(self.mir, tcx);
         self.monomorphize(&place_ty.to_ty(tcx))
     }
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 9d705ed..d1bc4fe 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -29,14 +29,14 @@
 use type_of::LayoutLlvmExt;
 use value::Value;
 
-use super::{MirContext, LocalRef};
+use super::{FunctionCx, LocalRef};
 use super::constant::const_scalar_checked_binop;
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
 
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     pub fn trans_rvalue(&mut self,
-                        bcx: Builder<'a, 'tcx>,
+                        bx: Builder<'a, 'tcx>,
                         dest: PlaceRef<'tcx>,
                         rvalue: &mir::Rvalue<'tcx>)
                         -> Builder<'a, 'tcx>
@@ -46,11 +46,11 @@
 
         match *rvalue {
            mir::Rvalue::Use(ref operand) => {
-               let tr_operand = self.trans_operand(&bcx, operand);
+               let tr_operand = self.trans_operand(&bx, operand);
                // FIXME: consider not copying constants through stack. (fixable by translating
                // constants into OperandValue::Ref, why don’t we do that yet if we don’t?)
-               tr_operand.val.store(&bcx, dest);
-               bcx
+               tr_operand.val.store(&bx, dest);
+               bx
            }
 
             mir::Rvalue::Cast(mir::CastKind::Unsize, ref source, _) => {
@@ -59,16 +59,16 @@
                 if dest.layout.is_llvm_scalar_pair() {
                     // into-coerce of a thin pointer to a fat pointer - just
                     // use the operand path.
-                    let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                    temp.val.store(&bcx, dest);
-                    return bcx;
+                    let (bx, temp) = self.trans_rvalue_operand(bx, rvalue);
+                    temp.val.store(&bx, dest);
+                    return bx;
                 }
 
                 // Unsize of a nontrivial struct. I would prefer for
                 // this to be eliminated by MIR translation, but
                 // `CoerceUnsized` can be passed by a where-clause,
                 // so the (generic) MIR may not be able to expand it.
-                let operand = self.trans_operand(&bcx, source);
+                let operand = self.trans_operand(&bx, source);
                 match operand.val {
                     OperandValue::Pair(..) |
                     OperandValue::Immediate(_) => {
@@ -79,79 +79,79 @@
                         // index into the struct, and this case isn't
                         // important enough for it.
                         debug!("trans_rvalue: creating ugly alloca");
-                        let scratch = PlaceRef::alloca(&bcx, operand.layout, "__unsize_temp");
-                        scratch.storage_live(&bcx);
-                        operand.val.store(&bcx, scratch);
-                        base::coerce_unsized_into(&bcx, scratch, dest);
-                        scratch.storage_dead(&bcx);
+                        let scratch = PlaceRef::alloca(&bx, operand.layout, "__unsize_temp");
+                        scratch.storage_live(&bx);
+                        operand.val.store(&bx, scratch);
+                        base::coerce_unsized_into(&bx, scratch, dest);
+                        scratch.storage_dead(&bx);
                     }
                     OperandValue::Ref(llref, align) => {
                         let source = PlaceRef::new_sized(llref, operand.layout, align);
-                        base::coerce_unsized_into(&bcx, source, dest);
+                        base::coerce_unsized_into(&bx, source, dest);
                     }
                 }
-                bcx
+                bx
             }
 
             mir::Rvalue::Repeat(ref elem, count) => {
-                let tr_elem = self.trans_operand(&bcx, elem);
+                let tr_elem = self.trans_operand(&bx, elem);
 
                 // Do not generate the loop for zero-sized elements or empty arrays.
                 if dest.layout.is_zst() {
-                    return bcx;
+                    return bx;
                 }
 
-                let start = dest.project_index(&bcx, C_usize(bcx.ccx, 0)).llval;
+                let start = dest.project_index(&bx, C_usize(bx.cx, 0)).llval;
 
                 if let OperandValue::Immediate(v) = tr_elem.val {
-                    let align = C_i32(bcx.ccx, dest.align.abi() as i32);
-                    let size = C_usize(bcx.ccx, dest.layout.size.bytes());
+                    let align = C_i32(bx.cx, dest.align.abi() as i32);
+                    let size = C_usize(bx.cx, dest.layout.size.bytes());
 
                     // Use llvm.memset.p0i8.* to initialize all zero arrays
                     if common::is_const_integral(v) && common::const_to_uint(v) == 0 {
-                        let fill = C_u8(bcx.ccx, 0);
-                        base::call_memset(&bcx, start, fill, size, align, false);
-                        return bcx;
+                        let fill = C_u8(bx.cx, 0);
+                        base::call_memset(&bx, start, fill, size, align, false);
+                        return bx;
                     }
 
                     // Use llvm.memset.p0i8.* to initialize byte arrays
-                    let v = base::from_immediate(&bcx, v);
-                    if common::val_ty(v) == Type::i8(bcx.ccx) {
-                        base::call_memset(&bcx, start, v, size, align, false);
-                        return bcx;
+                    let v = base::from_immediate(&bx, v);
+                    if common::val_ty(v) == Type::i8(bx.cx) {
+                        base::call_memset(&bx, start, v, size, align, false);
+                        return bx;
                     }
                 }
 
                 let count = count.as_u64();
-                let count = C_usize(bcx.ccx, count);
-                let end = dest.project_index(&bcx, count).llval;
+                let count = C_usize(bx.cx, count);
+                let end = dest.project_index(&bx, count).llval;
 
-                let header_bcx = bcx.build_sibling_block("repeat_loop_header");
-                let body_bcx = bcx.build_sibling_block("repeat_loop_body");
-                let next_bcx = bcx.build_sibling_block("repeat_loop_next");
+                let header_bx = bx.build_sibling_block("repeat_loop_header");
+                let body_bx = bx.build_sibling_block("repeat_loop_body");
+                let next_bx = bx.build_sibling_block("repeat_loop_next");
 
-                bcx.br(header_bcx.llbb());
-                let current = header_bcx.phi(common::val_ty(start), &[start], &[bcx.llbb()]);
+                bx.br(header_bx.llbb());
+                let current = header_bx.phi(common::val_ty(start), &[start], &[bx.llbb()]);
 
-                let keep_going = header_bcx.icmp(llvm::IntNE, current, end);
-                header_bcx.cond_br(keep_going, body_bcx.llbb(), next_bcx.llbb());
+                let keep_going = header_bx.icmp(llvm::IntNE, current, end);
+                header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
 
-                tr_elem.val.store(&body_bcx,
+                tr_elem.val.store(&body_bx,
                     PlaceRef::new_sized(current, tr_elem.layout, dest.align));
 
-                let next = body_bcx.inbounds_gep(current, &[C_usize(bcx.ccx, 1)]);
-                body_bcx.br(header_bcx.llbb());
-                header_bcx.add_incoming_to_phi(current, next, body_bcx.llbb());
+                let next = body_bx.inbounds_gep(current, &[C_usize(bx.cx, 1)]);
+                body_bx.br(header_bx.llbb());
+                header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
 
-                next_bcx
+                next_bx
             }
 
             mir::Rvalue::Aggregate(ref kind, ref operands) => {
                 let (dest, active_field_index) = match **kind {
                     mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
-                        dest.trans_set_discr(&bcx, variant_index);
+                        dest.trans_set_discr(&bx, variant_index);
                         if adt_def.is_enum() {
-                            (dest.project_downcast(&bcx, variant_index), active_field_index)
+                            (dest.project_downcast(&bx, variant_index), active_field_index)
                         } else {
                             (dest, active_field_index)
                         }
@@ -159,27 +159,27 @@
                     _ => (dest, None)
                 };
                 for (i, operand) in operands.iter().enumerate() {
-                    let op = self.trans_operand(&bcx, operand);
+                    let op = self.trans_operand(&bx, operand);
                     // Do not generate stores and GEPis for zero-sized fields.
                     if !op.layout.is_zst() {
                         let field_index = active_field_index.unwrap_or(i);
-                        op.val.store(&bcx, dest.project_field(&bcx, field_index));
+                        op.val.store(&bx, dest.project_field(&bx, field_index));
                     }
                 }
-                bcx
+                bx
             }
 
             _ => {
                 assert!(self.rvalue_creates_operand(rvalue));
-                let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                temp.val.store(&bcx, dest);
-                bcx
+                let (bx, temp) = self.trans_rvalue_operand(bx, rvalue);
+                temp.val.store(&bx, dest);
+                bx
             }
         }
     }
 
     pub fn trans_rvalue_operand(&mut self,
-                                bcx: Builder<'a, 'tcx>,
+                                bx: Builder<'a, 'tcx>,
                                 rvalue: &mir::Rvalue<'tcx>)
                                 -> (Builder<'a, 'tcx>, OperandRef<'tcx>)
     {
@@ -187,16 +187,16 @@
 
         match *rvalue {
             mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => {
-                let operand = self.trans_operand(&bcx, source);
+                let operand = self.trans_operand(&bx, source);
                 debug!("cast operand is {:?}", operand);
-                let cast = bcx.ccx.layout_of(self.monomorphize(&mir_cast_ty));
+                let cast = bx.cx.layout_of(self.monomorphize(&mir_cast_ty));
 
                 let val = match *kind {
                     mir::CastKind::ReifyFnPointer => {
                         match operand.layout.ty.sty {
                             ty::TyFnDef(def_id, substs) => {
                                 OperandValue::Immediate(
-                                    callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
+                                    callee::resolve_and_get_fn(bx.cx, def_id, substs))
                             }
                             _ => {
                                 bug!("{} cannot be reified to a fn ptr", operand.layout.ty)
@@ -207,8 +207,8 @@
                         match operand.layout.ty.sty {
                             ty::TyClosure(def_id, substs) => {
                                 let instance = monomorphize::resolve_closure(
-                                    bcx.ccx.tcx(), def_id, substs, ty::ClosureKind::FnOnce);
-                                OperandValue::Immediate(callee::get_fn(bcx.ccx, instance))
+                                    bx.cx.tcx, def_id, substs, ty::ClosureKind::FnOnce);
+                                OperandValue::Immediate(callee::get_fn(bx.cx, instance))
                             }
                             _ => {
                                 bug!("{} cannot be cast to a fn ptr", operand.layout.ty)
@@ -230,13 +230,13 @@
 
                                 // HACK(eddyb) have to bitcast pointers
                                 // until LLVM removes pointee types.
-                                let lldata = bcx.pointercast(lldata,
-                                    cast.scalar_pair_element_llvm_type(bcx.ccx, 0));
+                                let lldata = bx.pointercast(lldata,
+                                    cast.scalar_pair_element_llvm_type(bx.cx, 0));
                                 OperandValue::Pair(lldata, llextra)
                             }
                             OperandValue::Immediate(lldata) => {
                                 // "standard" unsize
-                                let (lldata, llextra) = base::unsize_thin_ptr(&bcx, lldata,
+                                let (lldata, llextra) = base::unsize_thin_ptr(&bx, lldata,
                                     operand.layout.ty, cast.ty);
                                 OperandValue::Pair(lldata, llextra)
                             }
@@ -249,14 +249,14 @@
                     mir::CastKind::Misc if operand.layout.is_llvm_scalar_pair() => {
                         if let OperandValue::Pair(data_ptr, meta) = operand.val {
                             if cast.is_llvm_scalar_pair() {
-                                let data_cast = bcx.pointercast(data_ptr,
-                                    cast.scalar_pair_element_llvm_type(bcx.ccx, 0));
+                                let data_cast = bx.pointercast(data_ptr,
+                                    cast.scalar_pair_element_llvm_type(bx.cx, 0));
                                 OperandValue::Pair(data_cast, meta)
                             } else { // cast to thin-ptr
                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
                                 // pointer-cast of that pointer to desired pointer type.
-                                let llcast_ty = cast.immediate_llvm_type(bcx.ccx);
-                                let llval = bcx.pointercast(data_ptr, llcast_ty);
+                                let llcast_ty = cast.immediate_llvm_type(bx.cx);
+                                let llval = bx.pointercast(data_ptr, llcast_ty);
                                 OperandValue::Immediate(llval)
                             }
                         } else {
@@ -268,8 +268,8 @@
                         let r_t_in = CastTy::from_ty(operand.layout.ty)
                             .expect("bad input type for cast");
                         let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast");
-                        let ll_t_in = operand.layout.immediate_llvm_type(bcx.ccx);
-                        let ll_t_out = cast.immediate_llvm_type(bcx.ccx);
+                        let ll_t_in = operand.layout.immediate_llvm_type(bx.cx);
+                        let ll_t_out = cast.immediate_llvm_type(bx.cx);
                         let llval = operand.immediate();
 
                         let mut signed = false;
@@ -282,7 +282,7 @@
                                     // have bound checks, and this is the most
                                     // convenient place to put the `assume`.
 
-                                    base::call_assume(&bcx, bcx.icmp(
+                                    base::call_assume(&bx, bx.icmp(
                                         llvm::IntULE,
                                         llval,
                                         C_uint_big(ll_t_in, scalar.valid_range.end)
@@ -293,15 +293,15 @@
 
                         let newval = match (r_t_in, r_t_out) {
                             (CastTy::Int(_), CastTy::Int(_)) => {
-                                bcx.intcast(llval, ll_t_out, signed)
+                                bx.intcast(llval, ll_t_out, signed)
                             }
                             (CastTy::Float, CastTy::Float) => {
                                 let srcsz = ll_t_in.float_width();
                                 let dstsz = ll_t_out.float_width();
                                 if dstsz > srcsz {
-                                    bcx.fpext(llval, ll_t_out)
+                                    bx.fpext(llval, ll_t_out)
                                 } else if srcsz > dstsz {
-                                    bcx.fptrunc(llval, ll_t_out)
+                                    bx.fptrunc(llval, ll_t_out)
                                 } else {
                                     llval
                                 }
@@ -309,66 +309,68 @@
                             (CastTy::Ptr(_), CastTy::Ptr(_)) |
                             (CastTy::FnPtr, CastTy::Ptr(_)) |
                             (CastTy::RPtr(_), CastTy::Ptr(_)) =>
-                                bcx.pointercast(llval, ll_t_out),
+                                bx.pointercast(llval, ll_t_out),
                             (CastTy::Ptr(_), CastTy::Int(_)) |
                             (CastTy::FnPtr, CastTy::Int(_)) =>
-                                bcx.ptrtoint(llval, ll_t_out),
-                            (CastTy::Int(_), CastTy::Ptr(_)) =>
-                                bcx.inttoptr(llval, ll_t_out),
+                                bx.ptrtoint(llval, ll_t_out),
+                            (CastTy::Int(_), CastTy::Ptr(_)) => {
+                                let usize_llval = bx.intcast(llval, bx.cx.isize_ty, signed);
+                                bx.inttoptr(usize_llval, ll_t_out)
+                            }
                             (CastTy::Int(_), CastTy::Float) =>
-                                cast_int_to_float(&bcx, signed, llval, ll_t_in, ll_t_out),
+                                cast_int_to_float(&bx, signed, llval, ll_t_in, ll_t_out),
                             (CastTy::Float, CastTy::Int(IntTy::I)) =>
-                                cast_float_to_int(&bcx, true, llval, ll_t_in, ll_t_out),
+                                cast_float_to_int(&bx, true, llval, ll_t_in, ll_t_out),
                             (CastTy::Float, CastTy::Int(_)) =>
-                                cast_float_to_int(&bcx, false, llval, ll_t_in, ll_t_out),
+                                cast_float_to_int(&bx, false, llval, ll_t_in, ll_t_out),
                             _ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty)
                         };
                         OperandValue::Immediate(newval)
                     }
                 };
-                (bcx, OperandRef {
+                (bx, OperandRef {
                     val,
                     layout: cast
                 })
             }
 
             mir::Rvalue::Ref(_, bk, ref place) => {
-                let tr_place = self.trans_place(&bcx, place);
+                let tr_place = self.trans_place(&bx, place);
 
                 let ty = tr_place.layout.ty;
 
                 // Note: places are indirect, so storing the `llval` into the
                 // destination effectively creates a reference.
-                let val = if !bcx.ccx.shared().type_has_metadata(ty) {
+                let val = if !bx.cx.type_has_metadata(ty) {
                     OperandValue::Immediate(tr_place.llval)
                 } else {
                     OperandValue::Pair(tr_place.llval, tr_place.llextra)
                 };
-                (bcx, OperandRef {
+                (bx, OperandRef {
                     val,
-                    layout: self.ccx.layout_of(self.ccx.tcx().mk_ref(
-                        self.ccx.tcx().types.re_erased,
+                    layout: self.cx.layout_of(self.cx.tcx.mk_ref(
+                        self.cx.tcx.types.re_erased,
                         ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
                     )),
                 })
             }
 
             mir::Rvalue::Len(ref place) => {
-                let size = self.evaluate_array_len(&bcx, place);
+                let size = self.evaluate_array_len(&bx, place);
                 let operand = OperandRef {
                     val: OperandValue::Immediate(size),
-                    layout: bcx.ccx.layout_of(bcx.tcx().types.usize),
+                    layout: bx.cx.layout_of(bx.tcx().types.usize),
                 };
-                (bcx, operand)
+                (bx, operand)
             }
 
             mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
-                let lhs = self.trans_operand(&bcx, lhs);
-                let rhs = self.trans_operand(&bcx, rhs);
+                let lhs = self.trans_operand(&bx, lhs);
+                let rhs = self.trans_operand(&bx, rhs);
                 let llresult = match (lhs.val, rhs.val) {
                     (OperandValue::Pair(lhs_addr, lhs_extra),
                      OperandValue::Pair(rhs_addr, rhs_extra)) => {
-                        self.trans_fat_ptr_binop(&bcx, op,
+                        self.trans_fat_ptr_binop(&bx, op,
                                                  lhs_addr, lhs_extra,
                                                  rhs_addr, rhs_extra,
                                                  lhs.layout.ty)
@@ -376,114 +378,114 @@
 
                     (OperandValue::Immediate(lhs_val),
                      OperandValue::Immediate(rhs_val)) => {
-                        self.trans_scalar_binop(&bcx, op, lhs_val, rhs_val, lhs.layout.ty)
+                        self.trans_scalar_binop(&bx, op, lhs_val, rhs_val, lhs.layout.ty)
                     }
 
                     _ => bug!()
                 };
                 let operand = OperandRef {
                     val: OperandValue::Immediate(llresult),
-                    layout: bcx.ccx.layout_of(
-                        op.ty(bcx.tcx(), lhs.layout.ty, rhs.layout.ty)),
+                    layout: bx.cx.layout_of(
+                        op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty)),
                 };
-                (bcx, operand)
+                (bx, operand)
             }
             mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
-                let lhs = self.trans_operand(&bcx, lhs);
-                let rhs = self.trans_operand(&bcx, rhs);
-                let result = self.trans_scalar_checked_binop(&bcx, op,
+                let lhs = self.trans_operand(&bx, lhs);
+                let rhs = self.trans_operand(&bx, rhs);
+                let result = self.trans_scalar_checked_binop(&bx, op,
                                                              lhs.immediate(), rhs.immediate(),
                                                              lhs.layout.ty);
-                let val_ty = op.ty(bcx.tcx(), lhs.layout.ty, rhs.layout.ty);
-                let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool], false);
+                let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
+                let operand_ty = bx.tcx().intern_tup(&[val_ty, bx.tcx().types.bool], false);
                 let operand = OperandRef {
                     val: result,
-                    layout: bcx.ccx.layout_of(operand_ty)
+                    layout: bx.cx.layout_of(operand_ty)
                 };
 
-                (bcx, operand)
+                (bx, operand)
             }
 
             mir::Rvalue::UnaryOp(op, ref operand) => {
-                let operand = self.trans_operand(&bcx, operand);
+                let operand = self.trans_operand(&bx, operand);
                 let lloperand = operand.immediate();
                 let is_float = operand.layout.ty.is_fp();
                 let llval = match op {
-                    mir::UnOp::Not => bcx.not(lloperand),
+                    mir::UnOp::Not => bx.not(lloperand),
                     mir::UnOp::Neg => if is_float {
-                        bcx.fneg(lloperand)
+                        bx.fneg(lloperand)
                     } else {
-                        bcx.neg(lloperand)
+                        bx.neg(lloperand)
                     }
                 };
-                (bcx, OperandRef {
+                (bx, OperandRef {
                     val: OperandValue::Immediate(llval),
                     layout: operand.layout,
                 })
             }
 
             mir::Rvalue::Discriminant(ref place) => {
-                let discr_ty = rvalue.ty(&*self.mir, bcx.tcx());
-                let discr =  self.trans_place(&bcx, place)
-                    .trans_get_discr(&bcx, discr_ty);
-                (bcx, OperandRef {
+                let discr_ty = rvalue.ty(&*self.mir, bx.tcx());
+                let discr =  self.trans_place(&bx, place)
+                    .trans_get_discr(&bx, discr_ty);
+                (bx, OperandRef {
                     val: OperandValue::Immediate(discr),
-                    layout: self.ccx.layout_of(discr_ty)
+                    layout: self.cx.layout_of(discr_ty)
                 })
             }
 
             mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
-                assert!(bcx.ccx.shared().type_is_sized(ty));
-                let val = C_usize(bcx.ccx, bcx.ccx.size_of(ty).bytes());
-                let tcx = bcx.tcx();
-                (bcx, OperandRef {
+                assert!(bx.cx.type_is_sized(ty));
+                let val = C_usize(bx.cx, bx.cx.size_of(ty).bytes());
+                let tcx = bx.tcx();
+                (bx, OperandRef {
                     val: OperandValue::Immediate(val),
-                    layout: self.ccx.layout_of(tcx.types.usize),
+                    layout: self.cx.layout_of(tcx.types.usize),
                 })
             }
 
             mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
                 let content_ty: Ty<'tcx> = self.monomorphize(&content_ty);
-                let (size, align) = bcx.ccx.size_and_align_of(content_ty);
-                let llsize = C_usize(bcx.ccx, size.bytes());
-                let llalign = C_usize(bcx.ccx, align.abi());
-                let box_layout = bcx.ccx.layout_of(bcx.tcx().mk_box(content_ty));
-                let llty_ptr = box_layout.llvm_type(bcx.ccx);
+                let (size, align) = bx.cx.size_and_align_of(content_ty);
+                let llsize = C_usize(bx.cx, size.bytes());
+                let llalign = C_usize(bx.cx, align.abi());
+                let box_layout = bx.cx.layout_of(bx.tcx().mk_box(content_ty));
+                let llty_ptr = box_layout.llvm_type(bx.cx);
 
                 // Allocate space:
-                let def_id = match bcx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
+                let def_id = match bx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
                     Ok(id) => id,
                     Err(s) => {
-                        bcx.sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
+                        bx.sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
                     }
                 };
-                let instance = ty::Instance::mono(bcx.tcx(), def_id);
-                let r = callee::get_fn(bcx.ccx, instance);
-                let val = bcx.pointercast(bcx.call(r, &[llsize, llalign], None), llty_ptr);
+                let instance = ty::Instance::mono(bx.tcx(), def_id);
+                let r = callee::get_fn(bx.cx, instance);
+                let val = bx.pointercast(bx.call(r, &[llsize, llalign], None), llty_ptr);
 
                 let operand = OperandRef {
                     val: OperandValue::Immediate(val),
                     layout: box_layout,
                 };
-                (bcx, operand)
+                (bx, operand)
             }
             mir::Rvalue::Use(ref operand) => {
-                let operand = self.trans_operand(&bcx, operand);
-                (bcx, operand)
+                let operand = self.trans_operand(&bx, operand);
+                (bx, operand)
             }
             mir::Rvalue::Repeat(..) |
             mir::Rvalue::Aggregate(..) => {
                 // According to `rvalue_creates_operand`, only ZST
                 // aggregate rvalues are allowed to be operands.
-                let ty = rvalue.ty(self.mir, self.ccx.tcx());
-                (bcx, OperandRef::new_zst(self.ccx,
-                    self.ccx.layout_of(self.monomorphize(&ty))))
+                let ty = rvalue.ty(self.mir, self.cx.tcx);
+                (bx, OperandRef::new_zst(self.cx,
+                    self.cx.layout_of(self.monomorphize(&ty))))
             }
         }
     }
 
     fn evaluate_array_len(&mut self,
-                          bcx: &Builder<'a, 'tcx>,
+                          bx: &Builder<'a, 'tcx>,
                           place: &mir::Place<'tcx>) -> ValueRef
     {
         // ZST are passed as operands and require special handling
@@ -492,17 +494,17 @@
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if let ty::TyArray(_, n) = op.layout.ty.sty {
                     let n = n.val.to_const_int().unwrap().to_u64().unwrap();
-                    return common::C_usize(bcx.ccx, n);
+                    return common::C_usize(bx.cx, n);
                 }
             }
         }
         // use common size calculation for non zero-sized types
-        let tr_value = self.trans_place(&bcx, place);
-        return tr_value.len(bcx.ccx);
+        let tr_value = self.trans_place(&bx, place);
+        return tr_value.len(bx.cx);
     }
 
     pub fn trans_scalar_binop(&mut self,
-                              bcx: &Builder<'a, 'tcx>,
+                              bx: &Builder<'a, 'tcx>,
                               op: mir::BinOp,
                               lhs: ValueRef,
                               rhs: ValueRef,
@@ -513,49 +515,49 @@
         let is_bool = input_ty.is_bool();
         match op {
             mir::BinOp::Add => if is_float {
-                bcx.fadd(lhs, rhs)
+                bx.fadd(lhs, rhs)
             } else {
-                bcx.add(lhs, rhs)
+                bx.add(lhs, rhs)
             },
             mir::BinOp::Sub => if is_float {
-                bcx.fsub(lhs, rhs)
+                bx.fsub(lhs, rhs)
             } else {
-                bcx.sub(lhs, rhs)
+                bx.sub(lhs, rhs)
             },
             mir::BinOp::Mul => if is_float {
-                bcx.fmul(lhs, rhs)
+                bx.fmul(lhs, rhs)
             } else {
-                bcx.mul(lhs, rhs)
+                bx.mul(lhs, rhs)
             },
             mir::BinOp::Div => if is_float {
-                bcx.fdiv(lhs, rhs)
+                bx.fdiv(lhs, rhs)
             } else if is_signed {
-                bcx.sdiv(lhs, rhs)
+                bx.sdiv(lhs, rhs)
             } else {
-                bcx.udiv(lhs, rhs)
+                bx.udiv(lhs, rhs)
             },
             mir::BinOp::Rem => if is_float {
-                bcx.frem(lhs, rhs)
+                bx.frem(lhs, rhs)
             } else if is_signed {
-                bcx.srem(lhs, rhs)
+                bx.srem(lhs, rhs)
             } else {
-                bcx.urem(lhs, rhs)
+                bx.urem(lhs, rhs)
             },
-            mir::BinOp::BitOr => bcx.or(lhs, rhs),
-            mir::BinOp::BitAnd => bcx.and(lhs, rhs),
-            mir::BinOp::BitXor => bcx.xor(lhs, rhs),
-            mir::BinOp::Offset => bcx.inbounds_gep(lhs, &[rhs]),
-            mir::BinOp::Shl => common::build_unchecked_lshift(bcx, lhs, rhs),
-            mir::BinOp::Shr => common::build_unchecked_rshift(bcx, input_ty, lhs, rhs),
+            mir::BinOp::BitOr => bx.or(lhs, rhs),
+            mir::BinOp::BitAnd => bx.and(lhs, rhs),
+            mir::BinOp::BitXor => bx.xor(lhs, rhs),
+            mir::BinOp::Offset => bx.inbounds_gep(lhs, &[rhs]),
+            mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs),
+            mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
             mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
             mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_nil {
-                C_bool(bcx.ccx, match op {
+                C_bool(bx.cx, match op {
                     mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false,
                     mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true,
                     _ => unreachable!()
                 })
             } else if is_float {
-                bcx.fcmp(
+                bx.fcmp(
                     base::bin_op_to_fcmp_predicate(op.to_hir_binop()),
                     lhs, rhs
                 )
@@ -563,13 +565,13 @@
                 let (lhs, rhs) = if is_bool {
                     // FIXME(#36856) -- extend the bools into `i8` because
                     // LLVM's i1 comparisons are broken.
-                    (bcx.zext(lhs, Type::i8(bcx.ccx)),
-                     bcx.zext(rhs, Type::i8(bcx.ccx)))
+                    (bx.zext(lhs, Type::i8(bx.cx)),
+                     bx.zext(rhs, Type::i8(bx.cx)))
                 } else {
                     (lhs, rhs)
                 };
 
-                bcx.icmp(
+                bx.icmp(
                     base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed),
                     lhs, rhs
                 )
@@ -578,7 +580,7 @@
     }
 
     pub fn trans_fat_ptr_binop(&mut self,
-                               bcx: &Builder<'a, 'tcx>,
+                               bx: &Builder<'a, 'tcx>,
                                op: mir::BinOp,
                                lhs_addr: ValueRef,
                                lhs_extra: ValueRef,
@@ -588,15 +590,15 @@
                                -> ValueRef {
         match op {
             mir::BinOp::Eq => {
-                bcx.and(
-                    bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
-                    bcx.icmp(llvm::IntEQ, lhs_extra, rhs_extra)
+                bx.and(
+                    bx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
+                    bx.icmp(llvm::IntEQ, lhs_extra, rhs_extra)
                 )
             }
             mir::BinOp::Ne => {
-                bcx.or(
-                    bcx.icmp(llvm::IntNE, lhs_addr, rhs_addr),
-                    bcx.icmp(llvm::IntNE, lhs_extra, rhs_extra)
+                bx.or(
+                    bx.icmp(llvm::IntNE, lhs_addr, rhs_addr),
+                    bx.icmp(llvm::IntNE, lhs_extra, rhs_extra)
                 )
             }
             mir::BinOp::Le | mir::BinOp::Lt |
@@ -610,11 +612,11 @@
                     _ => bug!(),
                 };
 
-                bcx.or(
-                    bcx.icmp(strict_op, lhs_addr, rhs_addr),
-                    bcx.and(
-                        bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
-                        bcx.icmp(op, lhs_extra, rhs_extra)
+                bx.or(
+                    bx.icmp(strict_op, lhs_addr, rhs_addr),
+                    bx.and(
+                        bx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
+                        bx.icmp(op, lhs_extra, rhs_extra)
                     )
                 )
             }
@@ -625,7 +627,7 @@
     }
 
     pub fn trans_scalar_checked_binop(&mut self,
-                                      bcx: &Builder<'a, 'tcx>,
+                                      bx: &Builder<'a, 'tcx>,
                                       op: mir::BinOp,
                                       lhs: ValueRef,
                                       rhs: ValueRef,
@@ -634,17 +636,17 @@
         // with #[rustc_inherit_overflow_checks] and inlined from
         // another crate (mostly core::num generic/#[inline] fns),
         // while the current crate doesn't use overflow checks.
-        if !bcx.ccx.check_overflow() {
-            let val = self.trans_scalar_binop(bcx, op, lhs, rhs, input_ty);
-            return OperandValue::Pair(val, C_bool(bcx.ccx, false));
+        if !bx.cx.check_overflow {
+            let val = self.trans_scalar_binop(bx, op, lhs, rhs, input_ty);
+            return OperandValue::Pair(val, C_bool(bx.cx, false));
         }
 
         // First try performing the operation on constants, which
         // will only succeed if both operands are constant.
         // This is necessary to determine when an overflow Assert
         // will always panic at runtime, and produce a warning.
-        if let Some((val, of)) = const_scalar_checked_binop(bcx.tcx(), op, lhs, rhs, input_ty) {
-            return OperandValue::Pair(val, C_bool(bcx.ccx, of));
+        if let Some((val, of)) = const_scalar_checked_binop(bx.tcx(), op, lhs, rhs, input_ty) {
+            return OperandValue::Pair(val, C_bool(bx.cx, of));
         }
 
         let (val, of) = match op {
@@ -656,20 +658,20 @@
                     mir::BinOp::Mul => OverflowOp::Mul,
                     _ => unreachable!()
                 };
-                let intrinsic = get_overflow_intrinsic(oop, bcx, input_ty);
-                let res = bcx.call(intrinsic, &[lhs, rhs], None);
+                let intrinsic = get_overflow_intrinsic(oop, bx, input_ty);
+                let res = bx.call(intrinsic, &[lhs, rhs], None);
 
-                (bcx.extract_value(res, 0),
-                 bcx.extract_value(res, 1))
+                (bx.extract_value(res, 0),
+                 bx.extract_value(res, 1))
             }
             mir::BinOp::Shl | mir::BinOp::Shr => {
                 let lhs_llty = val_ty(lhs);
                 let rhs_llty = val_ty(rhs);
-                let invert_mask = common::shift_mask_val(&bcx, lhs_llty, rhs_llty, true);
-                let outer_bits = bcx.and(rhs, invert_mask);
+                let invert_mask = common::shift_mask_val(&bx, lhs_llty, rhs_llty, true);
+                let outer_bits = bx.and(rhs, invert_mask);
 
-                let of = bcx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
-                let val = self.trans_scalar_binop(bcx, op, lhs, rhs, input_ty);
+                let of = bx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
+                let val = self.trans_scalar_binop(bx, op, lhs, rhs, input_ty);
 
                 (val, of)
             }
@@ -695,9 +697,9 @@
                 true,
             mir::Rvalue::Repeat(..) |
             mir::Rvalue::Aggregate(..) => {
-                let ty = rvalue.ty(self.mir, self.ccx.tcx());
+                let ty = rvalue.ty(self.mir, self.cx.tcx);
                 let ty = self.monomorphize(&ty);
-                self.ccx.layout_of(ty).is_zst()
+                self.cx.layout_of(ty).is_zst()
             }
         }
 
@@ -710,21 +712,21 @@
     Add, Sub, Mul
 }
 
-fn get_overflow_intrinsic(oop: OverflowOp, bcx: &Builder, ty: Ty) -> ValueRef {
+fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef {
     use syntax::ast::IntTy::*;
     use syntax::ast::UintTy::*;
     use rustc::ty::{TyInt, TyUint};
 
-    let tcx = bcx.tcx();
+    let tcx = bx.tcx();
 
     let new_sty = match ty.sty {
-        TyInt(Is) => match &tcx.sess.target.target.target_pointer_width[..] {
+        TyInt(Isize) => match &tcx.sess.target.target.target_pointer_width[..] {
             "16" => TyInt(I16),
             "32" => TyInt(I32),
             "64" => TyInt(I64),
             _ => panic!("unsupported target word size")
         },
-        TyUint(Us) => match &tcx.sess.target.target.target_pointer_width[..] {
+        TyUint(Usize) => match &tcx.sess.target.target.target_pointer_width[..] {
             "16" => TyUint(U16),
             "32" => TyUint(U32),
             "64" => TyUint(U64),
@@ -782,10 +784,10 @@
         },
     };
 
-    bcx.ccx.get_intrinsic(&name)
+    bx.cx.get_intrinsic(&name)
 }
 
-fn cast_int_to_float(bcx: &Builder,
+fn cast_int_to_float(bx: &Builder,
                      signed: bool,
                      x: ValueRef,
                      int_ty: Type,
@@ -798,31 +800,31 @@
         // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
         // and for everything else LLVM's uitofp works just fine.
         let max = C_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
-        let overflow = bcx.icmp(llvm::IntUGE, x, max);
-        let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
+        let overflow = bx.icmp(llvm::IntUGE, x, max);
+        let infinity_bits = C_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32);
         let infinity = consts::bitcast(infinity_bits, float_ty);
-        bcx.select(overflow, infinity, bcx.uitofp(x, float_ty))
+        bx.select(overflow, infinity, bx.uitofp(x, float_ty))
     } else {
         if signed {
-            bcx.sitofp(x, float_ty)
+            bx.sitofp(x, float_ty)
         } else {
-            bcx.uitofp(x, float_ty)
+            bx.uitofp(x, float_ty)
         }
     }
 }
 
-fn cast_float_to_int(bcx: &Builder,
+fn cast_float_to_int(bx: &Builder,
                      signed: bool,
                      x: ValueRef,
                      float_ty: Type,
                      int_ty: Type) -> ValueRef {
     let fptosui_result = if signed {
-        bcx.fptosi(x, int_ty)
+        bx.fptosi(x, int_ty)
     } else {
-        bcx.fptoui(x, int_ty)
+        bx.fptoui(x, int_ty)
     };
 
-    if !bcx.sess().opts.debugging_opts.saturating_float_casts {
+    if !bx.sess().opts.debugging_opts.saturating_float_casts {
         return fptosui_result;
     }
     // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
@@ -868,8 +870,8 @@
     }
     let float_bits_to_llval = |bits| {
         let bits_llval = match float_ty.float_width() {
-            32 => C_u32(bcx.ccx, bits as u32),
-            64 => C_u64(bcx.ccx, bits as u64),
+            32 => C_u32(bx.cx, bits as u32),
+            64 => C_u64(bx.cx, bits as u64),
             n => bug!("unsupported float width {}", n),
         };
         consts::bitcast(bits_llval, float_ty)
@@ -922,19 +924,19 @@
     // negation, and the negation can be merged into the select. Therefore, it not necessarily any
     // more expensive than a ordered ("normal") comparison. Whether these optimizations will be
     // performed is ultimately up to the backend, but at least x86 does perform them.
-    let less_or_nan = bcx.fcmp(llvm::RealULT, x, f_min);
-    let greater = bcx.fcmp(llvm::RealOGT, x, f_max);
+    let less_or_nan = bx.fcmp(llvm::RealULT, x, f_min);
+    let greater = bx.fcmp(llvm::RealOGT, x, f_max);
     let int_max = C_uint_big(int_ty, int_max(signed, int_ty));
     let int_min = C_uint_big(int_ty, int_min(signed, int_ty) as u128);
-    let s0 = bcx.select(less_or_nan, int_min, fptosui_result);
-    let s1 = bcx.select(greater, int_max, s0);
+    let s0 = bx.select(less_or_nan, int_min, fptosui_result);
+    let s1 = bx.select(greater, int_max, s0);
 
     // Step 3: NaN replacement.
     // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
     // Therefore we only need to execute this step for signed integer types.
     if signed {
         // LLVM has no isNaN predicate, so we use (x == x) instead
-        bcx.select(bcx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
+        bx.select(bx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
     } else {
         s1
     }
diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs
index e0ca5dc..b5b7484 100644
--- a/src/librustc_trans/mir/statement.rs
+++ b/src/librustc_trans/mir/statement.rs
@@ -13,28 +13,28 @@
 use asm;
 use builder::Builder;
 
-use super::MirContext;
+use super::FunctionCx;
 use super::LocalRef;
 
-impl<'a, 'tcx> MirContext<'a, 'tcx> {
+impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     pub fn trans_statement(&mut self,
-                           bcx: Builder<'a, 'tcx>,
+                           bx: Builder<'a, 'tcx>,
                            statement: &mir::Statement<'tcx>)
                            -> Builder<'a, 'tcx> {
         debug!("trans_statement(statement={:?})", statement);
 
-        self.set_debug_loc(&bcx, statement.source_info);
+        self.set_debug_loc(&bx, statement.source_info);
         match statement.kind {
             mir::StatementKind::Assign(ref place, ref rvalue) => {
                 if let mir::Place::Local(index) = *place {
                     match self.locals[index] {
                         LocalRef::Place(tr_dest) => {
-                            self.trans_rvalue(bcx, tr_dest, rvalue)
+                            self.trans_rvalue(bx, tr_dest, rvalue)
                         }
                         LocalRef::Operand(None) => {
-                            let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue);
+                            let (bx, operand) = self.trans_rvalue_operand(bx, rvalue);
                             self.locals[index] = LocalRef::Operand(Some(operand));
-                            bcx
+                            bx
                         }
                         LocalRef::Operand(Some(op)) => {
                             if !op.layout.is_zst() {
@@ -45,46 +45,46 @@
 
                             // If the type is zero-sized, it's already been set here,
                             // but we still need to make sure we translate the operand
-                            self.trans_rvalue_operand(bcx, rvalue).0
+                            self.trans_rvalue_operand(bx, rvalue).0
                         }
                     }
                 } else {
-                    let tr_dest = self.trans_place(&bcx, place);
-                    self.trans_rvalue(bcx, tr_dest, rvalue)
+                    let tr_dest = self.trans_place(&bx, place);
+                    self.trans_rvalue(bx, tr_dest, rvalue)
                 }
             }
             mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
-                self.trans_place(&bcx, place)
-                    .trans_set_discr(&bcx, variant_index);
-                bcx
+                self.trans_place(&bx, place)
+                    .trans_set_discr(&bx, variant_index);
+                bx
             }
             mir::StatementKind::StorageLive(local) => {
                 if let LocalRef::Place(tr_place) = self.locals[local] {
-                    tr_place.storage_live(&bcx);
+                    tr_place.storage_live(&bx);
                 }
-                bcx
+                bx
             }
             mir::StatementKind::StorageDead(local) => {
                 if let LocalRef::Place(tr_place) = self.locals[local] {
-                    tr_place.storage_dead(&bcx);
+                    tr_place.storage_dead(&bx);
                 }
-                bcx
+                bx
             }
             mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
                 let outputs = outputs.iter().map(|output| {
-                    self.trans_place(&bcx, output)
+                    self.trans_place(&bx, output)
                 }).collect();
 
                 let input_vals = inputs.iter().map(|input| {
-                    self.trans_operand(&bcx, input).immediate()
+                    self.trans_operand(&bx, input).immediate()
                 }).collect();
 
-                asm::trans_inline_asm(&bcx, asm, outputs, input_vals);
-                bcx
+                asm::trans_inline_asm(&bx, asm, outputs, input_vals);
+                bx
             }
             mir::StatementKind::EndRegion(_) |
             mir::StatementKind::Validate(..) |
-            mir::StatementKind::Nop => bcx,
+            mir::StatementKind::Nop => bx,
         }
     }
 }
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 31d8e09..5eb6679 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -18,18 +18,17 @@
 use attributes;
 use base;
 use consts;
-use context::CrateContext;
+use context::CodegenCx;
 use declare;
 use llvm;
 use monomorphize::Instance;
 use type_of::LayoutLlvmExt;
 use rustc::hir;
 use rustc::mir::mono::{Linkage, Visibility};
-use rustc::ty::{TyCtxt, TypeFoldable};
+use rustc::ty::TypeFoldable;
 use rustc::ty::layout::LayoutOf;
 use syntax::ast;
 use syntax::attr;
-use syntax_pos::Span;
 use std::fmt;
 
 pub use rustc::mir::mono::MonoItem;
@@ -38,18 +37,18 @@
 pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt;
 
 pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
-    fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
+    fn define(&self, cx: &CodegenCx<'a, 'tcx>) {
         debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
-               self.to_string(ccx.tcx()),
+               self.to_string(cx.tcx),
                self.to_raw_string(),
-               ccx.codegen_unit().name());
+               cx.codegen_unit.name());
 
         match *self.as_mono_item() {
             MonoItem::Static(node_id) => {
-                let tcx = ccx.tcx();
+                let tcx = cx.tcx;
                 let item = tcx.hir.expect_item(node_id);
                 if let hir::ItemStatic(_, m, _) = item.node {
-                    match consts::trans_static(&ccx, m, item.id, &item.attrs) {
+                    match consts::trans_static(&cx, m, item.id, &item.attrs) {
                         Ok(_) => { /* Cool, everything's alright. */ },
                         Err(err) => {
                             err.report(tcx, item.span, "static");
@@ -60,63 +59,51 @@
                 }
             }
             MonoItem::GlobalAsm(node_id) => {
-                let item = ccx.tcx().hir.expect_item(node_id);
+                let item = cx.tcx.hir.expect_item(node_id);
                 if let hir::ItemGlobalAsm(ref ga) = item.node {
-                    asm::trans_global_asm(ccx, ga);
+                    asm::trans_global_asm(cx, ga);
                 } else {
                     span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
                 }
             }
             MonoItem::Fn(instance) => {
-                base::trans_instance(&ccx, instance);
+                base::trans_instance(&cx, instance);
             }
         }
 
         debug!("END IMPLEMENTING '{} ({})' in cgu {}",
-               self.to_string(ccx.tcx()),
+               self.to_string(cx.tcx),
                self.to_raw_string(),
-               ccx.codegen_unit().name());
+               cx.codegen_unit.name());
     }
 
     fn predefine(&self,
-                 ccx: &CrateContext<'a, 'tcx>,
+                 cx: &CodegenCx<'a, 'tcx>,
                  linkage: Linkage,
                  visibility: Visibility) {
         debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
-               self.to_string(ccx.tcx()),
+               self.to_string(cx.tcx),
                self.to_raw_string(),
-               ccx.codegen_unit().name());
+               cx.codegen_unit.name());
 
-        let symbol_name = self.symbol_name(ccx.tcx());
+        let symbol_name = self.symbol_name(cx.tcx);
 
         debug!("symbol {}", &symbol_name);
 
         match *self.as_mono_item() {
             MonoItem::Static(node_id) => {
-                predefine_static(ccx, node_id, linkage, visibility, &symbol_name);
+                predefine_static(cx, node_id, linkage, visibility, &symbol_name);
             }
             MonoItem::Fn(instance) => {
-                predefine_fn(ccx, instance, linkage, visibility, &symbol_name);
+                predefine_fn(cx, instance, linkage, visibility, &symbol_name);
             }
             MonoItem::GlobalAsm(..) => {}
         }
 
         debug!("END PREDEFINING '{} ({})' in cgu {}",
-               self.to_string(ccx.tcx()),
+               self.to_string(cx.tcx),
                self.to_raw_string(),
-               ccx.codegen_unit().name());
-    }
-
-    fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
-        match *self.as_mono_item() {
-            MonoItem::Fn(Instance { def, .. }) => {
-                tcx.hir.as_local_node_id(def.def_id())
-            }
-            MonoItem::Static(node_id) |
-            MonoItem::GlobalAsm(node_id) => {
-                Some(node_id)
-            }
-        }.map(|node_id| tcx.hir.span(node_id))
+               cx.codegen_unit.name());
     }
 
     fn to_raw_string(&self) -> String {
@@ -138,18 +125,18 @@
 
 impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {}
 
-fn predefine_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                               node_id: ast::NodeId,
                               linkage: Linkage,
                               visibility: Visibility,
                               symbol_name: &str) {
-    let def_id = ccx.tcx().hir.local_def_id(node_id);
-    let instance = Instance::mono(ccx.tcx(), def_id);
-    let ty = instance.ty(ccx.tcx());
-    let llty = ccx.layout_of(ty).llvm_type(ccx);
+    let def_id = cx.tcx.hir.local_def_id(node_id);
+    let instance = Instance::mono(cx.tcx, def_id);
+    let ty = instance.ty(cx.tcx);
+    let llty = cx.layout_of(ty).llvm_type(cx);
 
-    let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
-        ccx.sess().span_fatal(ccx.tcx().hir.span(node_id),
+    let g = declare::define_global(cx, symbol_name, llty).unwrap_or_else(|| {
+        cx.sess().span_fatal(cx.tcx.hir.span(node_id),
             &format!("symbol `{}` is already defined", symbol_name))
     });
 
@@ -158,11 +145,11 @@
         llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
     }
 
-    ccx.instances().borrow_mut().insert(instance, g);
-    ccx.statics().borrow_mut().insert(g, def_id);
+    cx.instances.borrow_mut().insert(instance, g);
+    cx.statics.borrow_mut().insert(g, def_id);
 }
 
-fn predefine_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                           instance: Instance<'tcx>,
                           linkage: Linkage,
                           visibility: Visibility,
@@ -170,14 +157,14 @@
     assert!(!instance.substs.needs_infer() &&
             !instance.substs.has_param_types());
 
-    let mono_ty = instance.ty(ccx.tcx());
-    let attrs = instance.def.attrs(ccx.tcx());
-    let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
+    let mono_ty = instance.ty(cx.tcx);
+    let attrs = instance.def.attrs(cx.tcx);
+    let lldecl = declare::declare_fn(cx, symbol_name, mono_ty);
     unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
-    base::set_link_section(ccx, lldecl, &attrs);
+    base::set_link_section(cx, lldecl, &attrs);
     if linkage == Linkage::LinkOnceODR ||
         linkage == Linkage::WeakODR {
-        llvm::SetUniqueComdat(ccx.llmod(), lldecl);
+        llvm::SetUniqueComdat(cx.llmod, lldecl);
     }
 
     // If we're compiling the compiler-builtins crate, e.g. the equivalent of
@@ -185,7 +172,7 @@
     // visibility as we're going to link this object all over the place but
     // don't want the symbols to get exported.
     if linkage != Linkage::Internal && linkage != Linkage::Private &&
-       attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") {
+       attr::contains_name(cx.tcx.hir.krate_attrs(), "compiler_builtins") {
         unsafe {
             llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
         }
@@ -196,10 +183,10 @@
     }
 
     debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
-    if instance.def.is_inline(ccx.tcx()) {
+    if instance.def.is_inline(cx.tcx) {
         attributes::inline(lldecl, attributes::InlineAttr::Hint);
     }
-    attributes::from_fn_attrs(ccx, &attrs, lldecl);
+    attributes::from_fn_attrs(cx, lldecl, instance.def.def_id());
 
-    ccx.instances().borrow_mut().insert(instance, lldecl);
+    cx.instances.borrow_mut().insert(instance, lldecl);
 }
diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs
index b9daaf5..a77acc4 100644
--- a/src/librustc_trans/type_.rs
+++ b/src/librustc_trans/type_.rs
@@ -14,7 +14,7 @@
 use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind};
 use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 
-use context::CrateContext;
+use context::CodegenCx;
 
 use syntax::ast;
 use rustc::ty::layout::{self, Align, Size};
@@ -62,115 +62,115 @@
         unsafe { mem::transmute(slice) }
     }
 
-    pub fn void(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMVoidTypeInContext(ccx.llcx()))
+    pub fn void(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMVoidTypeInContext(cx.llcx))
     }
 
-    pub fn metadata(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMRustMetadataTypeInContext(ccx.llcx()))
+    pub fn metadata(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMRustMetadataTypeInContext(cx.llcx))
     }
 
-    pub fn i1(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMInt1TypeInContext(ccx.llcx()))
+    pub fn i1(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMInt1TypeInContext(cx.llcx))
     }
 
-    pub fn i8(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(ccx.llcx()))
+    pub fn i8(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
     }
 
     pub fn i8_llcx(llcx: ContextRef) -> Type {
         ty!(llvm::LLVMInt8TypeInContext(llcx))
     }
 
-    pub fn i16(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMInt16TypeInContext(ccx.llcx()))
+    pub fn i16(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMInt16TypeInContext(cx.llcx))
     }
 
-    pub fn i32(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMInt32TypeInContext(ccx.llcx()))
+    pub fn i32(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMInt32TypeInContext(cx.llcx))
     }
 
-    pub fn i64(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMInt64TypeInContext(ccx.llcx()))
+    pub fn i64(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMInt64TypeInContext(cx.llcx))
     }
 
-    pub fn i128(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), 128))
+    pub fn i128(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMIntTypeInContext(cx.llcx, 128))
     }
 
     // Creates an integer type with the given number of bits, e.g. i24
-    pub fn ix(ccx: &CrateContext, num_bits: u64) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), num_bits as c_uint))
+    pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type {
+        ty!(llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint))
     }
 
-    pub fn f32(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMFloatTypeInContext(ccx.llcx()))
+    pub fn f32(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMFloatTypeInContext(cx.llcx))
     }
 
-    pub fn f64(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMDoubleTypeInContext(ccx.llcx()))
+    pub fn f64(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMDoubleTypeInContext(cx.llcx))
     }
 
-    pub fn bool(ccx: &CrateContext) -> Type {
-        Type::i8(ccx)
+    pub fn bool(cx: &CodegenCx) -> Type {
+        Type::i8(cx)
     }
 
-    pub fn char(ccx: &CrateContext) -> Type {
-        Type::i32(ccx)
+    pub fn char(cx: &CodegenCx) -> Type {
+        Type::i32(cx)
     }
 
-    pub fn i8p(ccx: &CrateContext) -> Type {
-        Type::i8(ccx).ptr_to()
+    pub fn i8p(cx: &CodegenCx) -> Type {
+        Type::i8(cx).ptr_to()
     }
 
     pub fn i8p_llcx(llcx: ContextRef) -> Type {
         Type::i8_llcx(llcx).ptr_to()
     }
 
-    pub fn isize(ccx: &CrateContext) -> Type {
-        match &ccx.tcx().sess.target.target.target_pointer_width[..] {
-            "16" => Type::i16(ccx),
-            "32" => Type::i32(ccx),
-            "64" => Type::i64(ccx),
+    pub fn isize(cx: &CodegenCx) -> Type {
+        match &cx.tcx.sess.target.target.target_pointer_width[..] {
+            "16" => Type::i16(cx),
+            "32" => Type::i32(cx),
+            "64" => Type::i64(cx),
             tws => bug!("Unsupported target word size for int: {}", tws),
         }
     }
 
-    pub fn c_int(ccx: &CrateContext) -> Type {
-        match &ccx.tcx().sess.target.target.target_c_int_width[..] {
-            "16" => Type::i16(ccx),
-            "32" => Type::i32(ccx),
-            "64" => Type::i64(ccx),
+    pub fn c_int(cx: &CodegenCx) -> Type {
+        match &cx.tcx.sess.target.target.target_c_int_width[..] {
+            "16" => Type::i16(cx),
+            "32" => Type::i32(cx),
+            "64" => Type::i64(cx),
             width => bug!("Unsupported target_c_int_width: {}", width),
         }
     }
 
-    pub fn int_from_ty(ccx: &CrateContext, t: ast::IntTy) -> Type {
+    pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type {
         match t {
-            ast::IntTy::Is => ccx.isize_ty(),
-            ast::IntTy::I8 => Type::i8(ccx),
-            ast::IntTy::I16 => Type::i16(ccx),
-            ast::IntTy::I32 => Type::i32(ccx),
-            ast::IntTy::I64 => Type::i64(ccx),
-            ast::IntTy::I128 => Type::i128(ccx),
+            ast::IntTy::Isize => cx.isize_ty,
+            ast::IntTy::I8 => Type::i8(cx),
+            ast::IntTy::I16 => Type::i16(cx),
+            ast::IntTy::I32 => Type::i32(cx),
+            ast::IntTy::I64 => Type::i64(cx),
+            ast::IntTy::I128 => Type::i128(cx),
         }
     }
 
-    pub fn uint_from_ty(ccx: &CrateContext, t: ast::UintTy) -> Type {
+    pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type {
         match t {
-            ast::UintTy::Us => ccx.isize_ty(),
-            ast::UintTy::U8 => Type::i8(ccx),
-            ast::UintTy::U16 => Type::i16(ccx),
-            ast::UintTy::U32 => Type::i32(ccx),
-            ast::UintTy::U64 => Type::i64(ccx),
-            ast::UintTy::U128 => Type::i128(ccx),
+            ast::UintTy::Usize => cx.isize_ty,
+            ast::UintTy::U8 => Type::i8(cx),
+            ast::UintTy::U16 => Type::i16(cx),
+            ast::UintTy::U32 => Type::i32(cx),
+            ast::UintTy::U64 => Type::i64(cx),
+            ast::UintTy::U128 => Type::i128(cx),
         }
     }
 
-    pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
+    pub fn float_from_ty(cx: &CodegenCx, t: ast::FloatTy) -> Type {
         match t {
-            ast::FloatTy::F32 => Type::f32(ccx),
-            ast::FloatTy::F64 => Type::f64(ccx),
+            ast::FloatTy::F32 => Type::f32(cx),
+            ast::FloatTy::F64 => Type::f64(cx),
         }
     }
 
@@ -186,16 +186,16 @@
                                    args.len() as c_uint, True))
     }
 
-    pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
+    pub fn struct_(cx: &CodegenCx, els: &[Type], packed: bool) -> Type {
         let els: &[TypeRef] = Type::to_ref_slice(els);
-        ty!(llvm::LLVMStructTypeInContext(ccx.llcx(), els.as_ptr(),
+        ty!(llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
                                           els.len() as c_uint,
                                           packed as Bool))
     }
 
-    pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
+    pub fn named_struct(cx: &CodegenCx, name: &str) -> Type {
         let name = CString::new(name).unwrap();
-        ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
+        ty!(llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()))
     }
 
 
@@ -265,7 +265,7 @@
         }
     }
 
-    pub fn from_integer(cx: &CrateContext, i: layout::Integer) -> Type {
+    pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type {
         use rustc::ty::layout::Integer::*;
         match i {
             I8 => Type::i8(cx),
@@ -278,23 +278,23 @@
 
     /// Return a LLVM type that has at most the required alignment,
     /// as a conservative approximation for unknown pointee types.
-    pub fn pointee_for_abi_align(ccx: &CrateContext, align: Align) -> Type {
+    pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type {
         // FIXME(eddyb) We could find a better approximation if ity.align < align.
-        let ity = layout::Integer::approximate_abi_align(ccx, align);
-        Type::from_integer(ccx, ity)
+        let ity = layout::Integer::approximate_abi_align(cx, align);
+        Type::from_integer(cx, ity)
     }
 
     /// Return a LLVM type that has at most the required alignment,
     /// and exactly the required size, as a best-effort padding array.
-    pub fn padding_filler(ccx: &CrateContext, size: Size, align: Align) -> Type {
-        let unit = layout::Integer::approximate_abi_align(ccx, align);
+    pub fn padding_filler(cx: &CodegenCx, size: Size, align: Align) -> Type {
+        let unit = layout::Integer::approximate_abi_align(cx, align);
         let size = size.bytes();
         let unit_size = unit.size().bytes();
         assert_eq!(size % unit_size, 0);
-        Type::array(&Type::from_integer(ccx, unit), size / unit_size)
+        Type::array(&Type::from_integer(cx, unit), size / unit_size)
     }
 
-    pub fn x86_mmx(ccx: &CrateContext) -> Type {
-        ty!(llvm::LLVMX86MMXTypeInContext(ccx.llcx()))
+    pub fn x86_mmx(cx: &CodegenCx) -> Type {
+        ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx))
     }
 }
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index 8d9bc07..b1533cf 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -19,7 +19,7 @@
 
 use std::fmt::Write;
 
-fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 layout: TyLayout<'tcx>,
                                 defer: &mut Option<(Type, TyLayout<'tcx>)>)
                                 -> Type {
@@ -34,19 +34,19 @@
             // one-element SIMD vectors, so it's assumed this won't clash with
             // much else.
             let use_x86_mmx = count == 1 && layout.size.bits() == 64 &&
-                (ccx.sess().target.target.arch == "x86" ||
-                 ccx.sess().target.target.arch == "x86_64");
+                (cx.sess().target.target.arch == "x86" ||
+                 cx.sess().target.target.arch == "x86_64");
             if use_x86_mmx {
-                return Type::x86_mmx(ccx)
+                return Type::x86_mmx(cx)
             } else {
-                let element = layout.scalar_llvm_type_at(ccx, element, Size::from_bytes(0));
+                let element = layout.scalar_llvm_type_at(cx, element, Size::from_bytes(0));
                 return Type::vector(&element, count);
             }
         }
         layout::Abi::ScalarPair(..) => {
-            return Type::struct_(ccx, &[
-                layout.scalar_pair_element_llvm_type(ccx, 0),
-                layout.scalar_pair_element_llvm_type(ccx, 1),
+            return Type::struct_(cx, &[
+                layout.scalar_pair_element_llvm_type(cx, 0),
+                layout.scalar_pair_element_llvm_type(cx, 1),
             ], false);
         }
         layout::Abi::Uninhabited |
@@ -61,7 +61,7 @@
         ty::TyForeign(..) |
         ty::TyStr => {
             let mut name = String::with_capacity(32);
-            let printer = DefPathBasedNames::new(ccx.tcx(), true, true);
+            let printer = DefPathBasedNames::new(cx.tcx, true, true);
             printer.push_type_name(layout.ty, &mut name);
             match (&layout.ty.sty, &layout.variants) {
                 (&ty::TyAdt(def, _), &layout::Variants::Single { index }) => {
@@ -78,30 +78,30 @@
 
     match layout.fields {
         layout::FieldPlacement::Union(_) => {
-            let fill = Type::padding_filler(ccx, layout.size, layout.align);
+            let fill = Type::padding_filler(cx, layout.size, layout.align);
             let packed = false;
             match name {
                 None => {
-                    Type::struct_(ccx, &[fill], packed)
+                    Type::struct_(cx, &[fill], packed)
                 }
                 Some(ref name) => {
-                    let mut llty = Type::named_struct(ccx, name);
+                    let mut llty = Type::named_struct(cx, name);
                     llty.set_struct_body(&[fill], packed);
                     llty
                 }
             }
         }
         layout::FieldPlacement::Array { count, .. } => {
-            Type::array(&layout.field(ccx, 0).llvm_type(ccx), count)
+            Type::array(&layout.field(cx, 0).llvm_type(cx), count)
         }
         layout::FieldPlacement::Arbitrary { .. } => {
             match name {
                 None => {
-                    let (llfields, packed) = struct_llfields(ccx, layout);
-                    Type::struct_(ccx, &llfields, packed)
+                    let (llfields, packed) = struct_llfields(cx, layout);
+                    Type::struct_(cx, &llfields, packed)
                 }
                 Some(ref name) => {
-                    let llty = Type::named_struct(ccx, name);
+                    let llty = Type::named_struct(cx, name);
                     *defer = Some((llty, layout));
                     llty
                 }
@@ -110,7 +110,7 @@
     }
 }
 
-fn struct_llfields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              layout: TyLayout<'tcx>)
                              -> (Vec<Type>, bool) {
     debug!("struct_llfields: {:#?}", layout);
@@ -121,7 +121,7 @@
     let mut prev_align = layout.align;
     let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
     for i in layout.fields.index_by_increasing_offset() {
-        let field = layout.field(ccx, i);
+        let field = layout.field(cx, i);
         packed |= layout.align.abi() < field.align.abi();
 
         let target_offset = layout.fields.offset(i as usize);
@@ -131,10 +131,10 @@
         let padding = target_offset - offset;
         let padding_align = layout.align.min(prev_align).min(field.align);
         assert_eq!(offset.abi_align(padding_align) + padding, target_offset);
-        result.push(Type::padding_filler(ccx, padding, padding_align));
+        result.push(Type::padding_filler(cx, padding, padding_align));
         debug!("    padding before: {:?}", padding);
 
-        result.push(field.llvm_type(ccx));
+        result.push(field.llvm_type(cx));
         offset = target_offset + field.size;
         prev_align = field.align;
     }
@@ -148,7 +148,7 @@
         assert_eq!(offset.abi_align(padding_align) + padding, layout.size);
         debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
                padding, offset, layout.size);
-        result.push(Type::padding_filler(ccx, padding, padding_align));
+        result.push(Type::padding_filler(cx, padding, padding_align));
         assert!(result.len() == 1 + field_count * 2);
     } else {
         debug!("struct_llfields: offset: {:?} stride: {:?}",
@@ -158,7 +158,7 @@
     (result, packed)
 }
 
-impl<'a, 'tcx> CrateContext<'a, 'tcx> {
+impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
     pub fn align_of(&self, ty: Ty<'tcx>) -> Align {
         self.layout_of(ty).align
     }
@@ -197,14 +197,14 @@
 pub trait LayoutLlvmExt<'tcx> {
     fn is_llvm_immediate(&self) -> bool;
     fn is_llvm_scalar_pair<'a>(&self) -> bool;
-    fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
-    fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
-    fn scalar_llvm_type_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
                                scalar: &layout::Scalar, offset: Size) -> Type;
-    fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+    fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
                                          index: usize) -> Type;
     fn llvm_field_index(&self, index: usize) -> u64;
-    fn pointee_info_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>, offset: Size)
+    fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
                            -> Option<PointeeInfo>;
 }
 
@@ -240,28 +240,28 @@
     /// with the inner-most trailing unsized field using the "minimal unit"
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
-    fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             // Use a different cache for scalars because pointers to DSTs
             // can be either fat or thin (data pointers of fat pointers).
-            if let Some(&llty) = ccx.scalar_lltypes().borrow().get(&self.ty) {
+            if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
                 return llty;
             }
             let llty = match self.ty.sty {
                 ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
                 ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
-                    ccx.layout_of(ty).llvm_type(ccx).ptr_to()
+                    cx.layout_of(ty).llvm_type(cx).ptr_to()
                 }
                 ty::TyAdt(def, _) if def.is_box() => {
-                    ccx.layout_of(self.ty.boxed_ty()).llvm_type(ccx).ptr_to()
+                    cx.layout_of(self.ty.boxed_ty()).llvm_type(cx).ptr_to()
                 }
                 ty::TyFnPtr(sig) => {
-                    let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
-                    FnType::new(ccx, sig, &[]).llvm_type(ccx).ptr_to()
+                    let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig);
+                    FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
                 }
-                _ => self.scalar_llvm_type_at(ccx, scalar, Size::from_bytes(0))
+                _ => self.scalar_llvm_type_at(cx, scalar, Size::from_bytes(0))
             };
-            ccx.scalar_lltypes().borrow_mut().insert(self.ty, llty);
+            cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
             return llty;
         }
 
@@ -271,7 +271,7 @@
             layout::Variants::Single { index } => Some(index),
             _ => None
         };
-        if let Some(&llty) = ccx.lltypes().borrow().get(&(self.ty, variant_index)) {
+        if let Some(&llty) = cx.lltypes.borrow().get(&(self.ty, variant_index)) {
             return llty;
         }
 
@@ -281,69 +281,69 @@
 
         // Make sure lifetimes are erased, to avoid generating distinct LLVM
         // types for Rust types that only differ in the choice of lifetimes.
-        let normal_ty = ccx.tcx().erase_regions(&self.ty);
+        let normal_ty = cx.tcx.erase_regions(&self.ty);
 
         let mut defer = None;
         let llty = if self.ty != normal_ty {
-            let mut layout = ccx.layout_of(normal_ty);
+            let mut layout = cx.layout_of(normal_ty);
             if let Some(v) = variant_index {
-                layout = layout.for_variant(ccx, v);
+                layout = layout.for_variant(cx, v);
             }
-            layout.llvm_type(ccx)
+            layout.llvm_type(cx)
         } else {
-            uncached_llvm_type(ccx, *self, &mut defer)
+            uncached_llvm_type(cx, *self, &mut defer)
         };
         debug!("--> mapped {:#?} to llty={:?}", self, llty);
 
-        ccx.lltypes().borrow_mut().insert((self.ty, variant_index), llty);
+        cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty);
 
         if let Some((mut llty, layout)) = defer {
-            let (llfields, packed) = struct_llfields(ccx, layout);
+            let (llfields, packed) = struct_llfields(cx, layout);
             llty.set_struct_body(&llfields, packed)
         }
 
         llty
     }
 
-    fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             if scalar.is_bool() {
-                return Type::i1(ccx);
+                return Type::i1(cx);
             }
         }
-        self.llvm_type(ccx)
+        self.llvm_type(cx)
     }
 
-    fn scalar_llvm_type_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+    fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
                                scalar: &layout::Scalar, offset: Size) -> Type {
         match scalar.value {
-            layout::Int(i, _) => Type::from_integer(ccx, i),
-            layout::F32 => Type::f32(ccx),
-            layout::F64 => Type::f64(ccx),
+            layout::Int(i, _) => Type::from_integer(cx, i),
+            layout::F32 => Type::f32(cx),
+            layout::F64 => Type::f64(cx),
             layout::Pointer => {
                 // If we know the alignment, pick something better than i8.
-                let pointee = if let Some(pointee) = self.pointee_info_at(ccx, offset) {
-                    Type::pointee_for_abi_align(ccx, pointee.align)
+                let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
+                    Type::pointee_for_abi_align(cx, pointee.align)
                 } else {
-                    Type::i8(ccx)
+                    Type::i8(cx)
                 };
                 pointee.ptr_to()
             }
         }
     }
 
-    fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
+    fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
                                          index: usize) -> Type {
         // HACK(eddyb) special-case fat pointers until LLVM removes
         // pointee types, to avoid bitcasting every `OperandRef::deref`.
         match self.ty.sty {
             ty::TyRef(..) |
             ty::TyRawPtr(_) => {
-                return self.field(ccx, index).llvm_type(ccx);
+                return self.field(cx, index).llvm_type(cx);
             }
             ty::TyAdt(def, _) if def.is_box() => {
-                let ptr_ty = ccx.tcx().mk_mut_ptr(self.ty.boxed_ty());
-                return ccx.layout_of(ptr_ty).scalar_pair_element_llvm_type(ccx, index);
+                let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
+                return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index);
             }
             _ => {}
         }
@@ -362,15 +362,15 @@
         // load/store `bool` as `i8` to avoid crippling LLVM optimizations,
         // `i1` in a LLVM aggregate is valid and mostly equivalent to `i8`.
         if scalar.is_bool() {
-            return Type::i1(ccx);
+            return Type::i1(cx);
         }
 
         let offset = if index == 0 {
             Size::from_bytes(0)
         } else {
-            a.value.size(ccx).abi_align(b.value.align(ccx))
+            a.value.size(cx).abi_align(b.value.align(cx))
         };
-        self.scalar_llvm_type_at(ccx, scalar, offset)
+        self.scalar_llvm_type_at(cx, scalar, offset)
     }
 
     fn llvm_field_index(&self, index: usize) -> u64 {
@@ -396,16 +396,16 @@
         }
     }
 
-    fn pointee_info_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>, offset: Size)
+    fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
                            -> Option<PointeeInfo> {
-        if let Some(&pointee) = ccx.pointee_infos().borrow().get(&(self.ty, offset)) {
+        if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) {
             return pointee;
         }
 
         let mut result = None;
         match self.ty.sty {
             ty::TyRawPtr(mt) if offset.bytes() == 0 => {
-                let (size, align) = ccx.size_and_align_of(mt.ty);
+                let (size, align) = cx.size_and_align_of(mt.ty);
                 result = Some(PointeeInfo {
                     size,
                     align,
@@ -414,17 +414,17 @@
             }
 
             ty::TyRef(_, mt) if offset.bytes() == 0 => {
-                let (size, align) = ccx.size_and_align_of(mt.ty);
+                let (size, align) = cx.size_and_align_of(mt.ty);
 
                 let kind = match mt.mutbl {
-                    hir::MutImmutable => if ccx.shared().type_is_freeze(mt.ty) {
+                    hir::MutImmutable => if cx.type_is_freeze(mt.ty) {
                         PointerKind::Frozen
                     } else {
                         PointerKind::Shared
                     },
                     hir::MutMutable => {
-                        if ccx.shared().tcx().sess.opts.debugging_opts.mutable_noalias ||
-                           ccx.shared().tcx().sess.panic_strategy() == PanicStrategy::Abort {
+                        if cx.tcx.sess.opts.debugging_opts.mutable_noalias ||
+                           cx.tcx.sess.panic_strategy() == PanicStrategy::Abort {
                             PointerKind::UniqueBorrowed
                         } else {
                             PointerKind::Shared
@@ -454,7 +454,7 @@
                         // niches than just null (e.g. the first page
                         // of the address space, or unaligned pointers).
                         if self.fields.offset(0) == offset {
-                            Some(self.for_variant(ccx, dataful_variant))
+                            Some(self.for_variant(cx, dataful_variant))
                         } else {
                             None
                         }
@@ -470,14 +470,14 @@
                 }
 
                 if let Some(variant) = data_variant {
-                    let ptr_end = offset + layout::Pointer.size(ccx);
+                    let ptr_end = offset + layout::Pointer.size(cx);
                     for i in 0..variant.fields.count() {
                         let field_start = variant.fields.offset(i);
                         if field_start <= offset {
-                            let field = variant.field(ccx, i);
+                            let field = variant.field(cx, i);
                             if ptr_end <= field_start + field.size {
                                 // We found the right field, look inside it.
-                                result = field.pointee_info_at(ccx, offset - field_start);
+                                result = field.pointee_info_at(cx, offset - field_start);
                                 break;
                             }
                         }
@@ -495,7 +495,7 @@
             }
         }
 
-        ccx.pointee_infos().borrow_mut().insert((self.ty, offset), result);
+        cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
         result
     }
 }
diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml
index cab4477..7a01b6d 100644
--- a/src/librustc_trans_utils/Cargo.toml
+++ b/src/librustc_trans_utils/Cargo.toml
@@ -11,11 +11,13 @@
 
 [dependencies]
 ar = "0.3.0"
-flate2 = "0.2"
-log = "0.3"
+flate2 = "1.0"
+log = "0.4"
 
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_mir = { path = "../librustc_mir" }
+rustc_incremental = { path = "../librustc_incremental" }
diff --git a/src/librustc_trans_utils/diagnostics.rs b/src/librustc_trans_utils/diagnostics.rs
new file mode 100644
index 0000000..13fa15f
--- /dev/null
+++ b/src/librustc_trans_utils/diagnostics.rs
@@ -0,0 +1,38 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_snake_case)]
+
+register_long_diagnostics! {
+
+E0558: r##"
+The `export_name` attribute was malformed.
+
+Erroneous code example:
+
+```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
+#[export_name] // error: export_name attribute has invalid format
+pub fn something() {}
+
+fn main() {}
+```
+
+The `export_name` attribute expects a string in order to determine the name of
+the exported symbol. Example:
+
+```
+#[export_name = "some_function"] // ok!
+pub fn something() {}
+
+fn main() {}
+```
+"##,
+
+}
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index 77afc28..9b7ab20 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -35,18 +35,26 @@
 #[macro_use]
 extern crate rustc;
 extern crate rustc_back;
+extern crate rustc_mir;
+extern crate rustc_incremental;
+#[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_data_structures;
 
+pub extern crate rustc as __rustc;
+
 use rustc::ty::{TyCtxt, Instance};
 use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir::map as hir_map;
 use rustc::util::nodemap::NodeSet;
 
+pub mod diagnostics;
 pub mod link;
 pub mod trans_crate;
+pub mod symbol_names;
+pub mod symbol_names_test;
 
 /// check for the #[rustc_error] annotation, which forces an
 /// error in trans. This is used to write compile-fail tests
@@ -110,3 +118,6 @@
         }
     }).collect()
 }
+
+#[cfg(not(stage0))] // remove after the next snapshot
+__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS }
diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs
index c1e670c..aabe931 100644
--- a/src/librustc_trans_utils/link.rs
+++ b/src/librustc_trans_utils/link.rs
@@ -8,13 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ich::Fingerprint;
 use rustc::session::config::{self, OutputFilenames, Input, OutputType};
 use rustc::session::Session;
 use rustc::middle::cstore::{self, LinkMeta};
 use rustc::hir::svh::Svh;
 use std::path::{Path, PathBuf};
-use syntax::ast;
+use syntax::{ast, attr};
 use syntax_pos::Span;
 
 pub fn out_filename(sess: &Session,
@@ -50,9 +49,9 @@
     }
 }
 
-pub fn build_link_meta(crate_hash: Fingerprint) -> LinkMeta {
+pub fn build_link_meta(crate_hash: Svh) -> LinkMeta {
     let r = LinkMeta {
-        crate_hash: Svh::new(crate_hash.to_smaller_hash()),
+        crate_hash,
     };
     info!("{:?}", r);
     return r;
@@ -70,8 +69,8 @@
     // as used. After doing this, however, we still prioritize a crate name from
     // the command line over one found in the #[crate_name] attribute. If we
     // find both we ensure that they're the same later on as well.
-    let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
-                               .and_then(|at| at.value_str().map(|s| (at, s)));
+    let attr_crate_name = attr::find_by_name(attrs, "crate_name")
+        .and_then(|at| at.value_str().map(|s| (at, s)));
 
     if let Some(sess) = sess {
         if let Some(ref s) = sess.opts.crate_name {
diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs
similarity index 98%
rename from src/librustc_trans/back/symbol_names.rs
rename to src/librustc_trans_utils/symbol_names.rs
index 825f306..fb299bf 100644
--- a/src/librustc_trans/back/symbol_names.rs
+++ b/src/librustc_trans_utils/symbol_names.rs
@@ -97,11 +97,9 @@
 //! virtually impossible. Thus, symbol hash generation exclusively relies on
 //! DefPaths which are much more robust in the face of changes to the code base.
 
-use monomorphize::Instance;
-use trans_item::{BaseMonoItemExt, InstantiationMode};
-
 use rustc::middle::weak_lang_items;
-use rustc::mir::mono::MonoItem;
+use rustc_mir::monomorphize::Instance;
+use rustc_mir::monomorphize::item::{MonoItem, MonoItemExt, InstantiationMode};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map as hir_map;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -257,14 +255,12 @@
 
     if let Some(id) = node_id {
         if tcx.sess.plugin_registrar_fn.get() == Some(id) {
-            let idx = def_id.index;
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return tcx.sess.generate_plugin_registrar_symbol(disambiguator, idx);
+            return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
         if tcx.sess.derive_registrar_fn.get() == Some(id) {
-            let idx = def_id.index;
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
+            return tcx.sess.generate_derive_registrar_symbol(disambiguator);
         }
     }
 
diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs
similarity index 90%
rename from src/librustc_trans/symbol_names_test.rs
rename to src/librustc_trans_utils/symbol_names_test.rs
index d96757b..5d7d4f3 100644
--- a/src/librustc_trans/symbol_names_test.rs
+++ b/src/librustc_trans_utils/symbol_names_test.rs
@@ -19,7 +19,7 @@
 use rustc::ty::TyCtxt;
 use syntax::ast;
 
-use monomorphize::Instance;
+use rustc_mir::monomorphize::Instance;
 
 const SYMBOL_NAME: &'static str = "rustc_symbol_name";
 const ITEM_PATH: &'static str = "rustc_item_path";
@@ -32,10 +32,11 @@
         return;
     }
 
-    let _ignore = tcx.dep_graph.in_ignore();
-    let mut visitor = SymbolNamesTest { tcx: tcx };
-    // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
-    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+    tcx.dep_graph.with_ignore(|| {
+        let mut visitor = SymbolNamesTest { tcx: tcx };
+        // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
+        tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+    })
 }
 
 struct SymbolNamesTest<'a, 'tcx:'a> {
diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs
index 800c306..49756d7 100644
--- a/src/librustc_trans_utils/trans_crate.rs
+++ b/src/librustc_trans_utils/trans_crate.rs
@@ -26,6 +26,7 @@
 use std::io::{self, Cursor};
 use std::fs::File;
 use std::path::Path;
+use std::rc::Rc;
 use std::sync::mpsc;
 
 use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
@@ -35,83 +36,81 @@
 
 use syntax::symbol::Symbol;
 use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::session::Session;
-use rustc::session::config::{CrateType, OutputFilenames};
+use rustc::session::{Session, CompileIncomplete};
+use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
 use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc::middle::cstore::EncodedMetadata;
-use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
-use rustc::dep_graph::{DepGraph, DepNode, DepKind};
+use rustc::middle::cstore::MetadataLoader;
+use rustc::dep_graph::DepGraph;
 use rustc_back::target::Target;
+use rustc_mir::monomorphize::collector;
 use link::{build_link_meta, out_filename};
 
 pub trait TransCrate {
-    type MetadataLoader: MetadataLoaderTrait;
-    type OngoingCrateTranslation;
-    type TranslatedCrate;
+    fn print(&self, _req: PrintRequest, _sess: &Session) {}
+    fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
 
-    fn metadata_loader() -> Box<MetadataLoaderTrait>;
-    fn provide(_providers: &mut Providers);
-    fn provide_extern(_providers: &mut Providers);
+    fn metadata_loader(&self) -> Box<MetadataLoader>;
+    fn provide(&self, _providers: &mut Providers);
+    fn provide_extern(&self, _providers: &mut Providers);
     fn trans_crate<'a, 'tcx>(
+        &self,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation;
-    fn join_trans(
-        trans: Self::OngoingCrateTranslation,
+    ) -> Box<Any>;
+
+    /// This is called on the returned `Box<Any>` from `trans_crate`
+    ///
+    /// # Panics
+    ///
+    /// Panics when the passed `Box<Any>` was not returned by `trans_crate`.
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
         sess: &Session,
-        dep_graph: &DepGraph
-    ) -> Self::TranslatedCrate;
-    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames);
-    fn dump_incremental_data(trans: &Self::TranslatedCrate);
+        dep_graph: &DepGraph,
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete>;
 }
 
 pub struct DummyTransCrate;
 
 impl TransCrate for DummyTransCrate {
-    type MetadataLoader = DummyMetadataLoader;
-    type OngoingCrateTranslation = ();
-    type TranslatedCrate = ();
-
-    fn metadata_loader() -> Box<MetadataLoaderTrait> {
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
         box DummyMetadataLoader(())
     }
 
-    fn provide(_providers: &mut Providers) {
+    fn provide(&self, _providers: &mut Providers) {
         bug!("DummyTransCrate::provide");
     }
 
-    fn provide_extern(_providers: &mut Providers) {
+    fn provide_extern(&self, _providers: &mut Providers) {
         bug!("DummyTransCrate::provide_extern");
     }
 
     fn trans_crate<'a, 'tcx>(
+        &self,
         _tcx: TyCtxt<'a, 'tcx, 'tcx>,
         _rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation {
+    ) -> Box<Any> {
         bug!("DummyTransCrate::trans_crate");
     }
 
-    fn join_trans(
-        _trans: Self::OngoingCrateTranslation,
+    fn join_trans_and_link(
+        &self,
+        _trans: Box<Any>,
         _sess: &Session,
-        _dep_graph: &DepGraph
-    ) -> Self::TranslatedCrate {
-        bug!("DummyTransCrate::join_trans");
-    }
-
-    fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) {
-        bug!("DummyTransCrate::link_binary");
-    }
-
-    fn dump_incremental_data(_trans: &Self::TranslatedCrate) {
-        bug!("DummyTransCrate::dump_incremental_data");
+        _dep_graph: &DepGraph,
+        _outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete> {
+        bug!("DummyTransCrate::join_trans_and_link");
     }
 }
 
 pub struct DummyMetadataLoader(());
 
-impl MetadataLoaderTrait for DummyMetadataLoader {
+impl MetadataLoader for DummyMetadataLoader {
     fn get_rlib_metadata(
         &self,
         _target: &Target,
@@ -131,7 +130,7 @@
 
 pub struct NoLlvmMetadataLoader;
 
-impl MetadataLoaderTrait for NoLlvmMetadataLoader {
+impl MetadataLoader for NoLlvmMetadataLoader {
     fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
         let file = File::open(filename)
             .map_err(|e| format!("metadata file open err: {:?}", e))?;
@@ -161,89 +160,132 @@
     }
 }
 
-pub struct MetadataOnlyTransCrate;
+pub struct MetadataOnlyTransCrate(());
 pub struct OngoingCrateTranslation {
     metadata: EncodedMetadata,
     metadata_version: Vec<u8>,
     crate_name: Symbol,
 }
-pub struct TranslatedCrate(OngoingCrateTranslation);
 
 impl MetadataOnlyTransCrate {
-    #[allow(dead_code)]
-    pub fn new() -> Self {
-        MetadataOnlyTransCrate
+    pub fn new(sess: &Session) -> Box<TransCrate> {
+        for cty in sess.opts.crate_types.iter() {
+            match *cty {
+                CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
+                CrateType::CrateTypeExecutable => {},
+                _ => {
+                    sess.parse_sess.span_diagnostic.warn(
+                        &format!("LLVM unsupported, so output type {} is not supported", cty)
+                    );
+                },
+            }
+        }
+
+        box MetadataOnlyTransCrate(())
     }
 }
 
 impl TransCrate for MetadataOnlyTransCrate {
-    type MetadataLoader = NoLlvmMetadataLoader;
-    type OngoingCrateTranslation = OngoingCrateTranslation;
-    type TranslatedCrate = TranslatedCrate;
-
-    fn metadata_loader() -> Box<MetadataLoaderTrait> {
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
         box NoLlvmMetadataLoader
     }
 
-    fn provide(_providers: &mut Providers) {}
-    fn provide_extern(_providers: &mut Providers) {}
+    fn provide(&self, providers: &mut Providers) {
+        ::symbol_names::provide(providers);
+        providers.target_features_enabled = |_tcx, _id| {
+            Rc::new(Vec::new()) // Just a dummy
+        };
+    }
+    fn provide_extern(&self, _providers: &mut Providers) {}
 
     fn trans_crate<'a, 'tcx>(
+        &self,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         _rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation {
+    ) -> Box<Any> {
+        use rustc_mir::monomorphize::item::MonoItem;
+
         ::check_for_rustc_errors_attr(tcx);
+        ::symbol_names_test::report_symbol_names(tcx);
+        ::rustc_incremental::assert_dep_graph(tcx);
+        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
+        ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx,
+            collector::collect_crate_mono_items(
+                tcx,
+                collector::MonoItemCollectionMode::Eager
+            ).0.iter()
+        );
+        ::rustc::middle::dependency_format::calculate(tcx);
         let _ = tcx.link_args(LOCAL_CRATE);
         let _ = tcx.native_libraries(LOCAL_CRATE);
+        for trans_item in
+            collector::collect_crate_mono_items(
+                tcx,
+                collector::MonoItemCollectionMode::Eager
+            ).0 {
+            match trans_item {
+                MonoItem::Fn(inst) => {
+                    let def_id = inst.def_id();
+                    if def_id.is_local()  {
+                        let _ = tcx.export_name(def_id);
+                        let _ = tcx.contains_extern_indicator(def_id);
+                        let _ = inst.def.is_inline(tcx);
+                        let attrs = inst.def.attrs(tcx);
+                        let _ =
+                            ::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
+                    }
+                }
+                _ => {}
+            }
+        }
         tcx.sess.abort_if_errors();
 
-        let crate_hash = tcx.dep_graph
-                        .fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
-        let link_meta = build_link_meta(crate_hash);
+        let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
         let exported_symbols = ::find_exported_symbols(tcx);
         let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
 
-        OngoingCrateTranslation {
+        box OngoingCrateTranslation {
             metadata: metadata,
             metadata_version: tcx.metadata_encoding_version().to_vec(),
             crate_name: tcx.crate_name(LOCAL_CRATE),
         }
     }
 
-    fn join_trans(
-        trans: Self::OngoingCrateTranslation,
-        _sess: &Session,
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
+        sess: &Session,
         _dep_graph: &DepGraph,
-    ) -> Self::TranslatedCrate {
-        TranslatedCrate(trans)
-    }
-
-    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete> {
+        let trans = trans.downcast::<OngoingCrateTranslation>()
+            .expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box<Any>");
         for &crate_type in sess.opts.crate_types.iter() {
             if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
                 continue;
             }
             let output_name =
-                out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str());
-            let mut compressed = trans.0.metadata_version.clone();
+                out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str());
+            let mut compressed = trans.metadata_version.clone();
             let metadata = if crate_type == CrateType::CrateTypeDylib {
-                DeflateEncoder::new(&mut compressed, Compression::Fast)
-                    .write_all(&trans.0.metadata.raw_data)
+                DeflateEncoder::new(&mut compressed, Compression::fast())
+                    .write_all(&trans.metadata.raw_data)
                     .unwrap();
                 &compressed
             } else {
-                &trans.0.metadata.raw_data
+                &trans.metadata.raw_data
             };
             let mut builder = Builder::new(File::create(&output_name).unwrap());
             let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
             builder.append(&header, Cursor::new(metadata)).unwrap();
         }
 
+        sess.abort_if_errors();
         if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
-            && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) {
+            && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib)
+        {
             sess.fatal("Executables are not supported by the metadata-only backend.");
         }
+        Ok(())
     }
-
-    fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}
 }
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index c324584..c7868cc 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -10,7 +10,7 @@
 test = false
 
 [dependencies]
-log = "0.3"
+log = "0.4"
 syntax = { path = "../libsyntax" }
 arena = { path = "../libarena" }
 fmt_macros = { path = "../libfmt_macros" }
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 7832db7..169959d 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -14,6 +14,7 @@
 use super::method::MethodCallee;
 
 use rustc::infer::InferOk;
+use rustc::session::DiagnosticMessageId;
 use rustc::traits;
 use rustc::ty::{self, Ty, TraitRef};
 use rustc::ty::{ToPredicate, TypeFoldable};
@@ -56,19 +57,25 @@
             return Some((self.cur_ty, 0));
         }
 
-        if self.steps.len() == tcx.sess.recursion_limit.get() {
+        if self.steps.len() >= tcx.sess.recursion_limit.get() {
             // We've reached the recursion limit, error gracefully.
             let suggested_limit = tcx.sess.recursion_limit.get() * 2;
-            struct_span_err!(tcx.sess,
-                             self.span,
-                             E0055,
-                             "reached the recursion limit while auto-dereferencing {:?}",
-                             self.cur_ty)
-                .span_label(self.span, "deref recursion limit reached")
-                .help(&format!(
-                        "consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate",
+            let msg = format!("reached the recursion limit while auto-dereferencing {:?}",
+                              self.cur_ty);
+            let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg.clone());
+            let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+            if fresh {
+                struct_span_err!(tcx.sess,
+                                 self.span,
+                                 E0055,
+                                 "reached the recursion limit while auto-dereferencing {:?}",
+                                 self.cur_ty)
+                    .span_label(self.span, "deref recursion limit reached")
+                    .help(&format!(
+                        "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                         suggested_limit))
-                .emit();
+                    .emit();
+            }
             return None;
         }
 
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index df1694a..5c5e5f2 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -210,15 +210,25 @@
                         }
                     }
                 }
-                let mut err = type_error_struct!(self.tcx.sess, call_expr.span, callee_ty, E0618,
-                                                 "expected function, found `{}`",
-                                                 if let Some(ref path) = unit_variant {
-                                                     path.to_string()
-                                                 } else {
-                                                     callee_ty.to_string()
-                                                 });
-                if let Some(path) = unit_variant {
-                    err.help(&format!("did you mean to write `{}`?", path));
+
+                let mut err = type_error_struct!(
+                    self.tcx.sess,
+                    call_expr.span,
+                    callee_ty,
+                    E0618,
+                    "expected function, found {}",
+                    match unit_variant {
+                        Some(ref path) => format!("enum variant `{}`", path),
+                        None => format!("`{}`", callee_ty),
+                    });
+
+                err.span_label(call_expr.span, "not a function");
+
+                if let Some(ref path) = unit_variant {
+                    err.span_suggestion(call_expr.span,
+                                        &format!("`{}` is a unit variant, you need to write it \
+                                                  without the parenthesis", path),
+                                        path.to_string());
                 }
 
                 if let hir::ExprCall(ref expr, _) = call_expr.node {
@@ -235,7 +245,11 @@
                         _ => self.tcx.hir.span_if_local(def.def_id())
                     };
                     if let Some(span) = def_span {
-                        err.span_note(span, "defined here");
+                        let name = match unit_variant {
+                            Some(path) => path,
+                            None => callee_ty.to_string(),
+                        };
+                        err.span_label(span, format!("`{}` defined here", name));
                     }
                 }
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index d68c139..992a510 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -48,6 +48,7 @@
 use rustc::traits;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::cast::{CastKind, CastTy};
+use rustc::ty::subst::Substs;
 use rustc::middle::lang_items;
 use syntax::ast;
 use syntax_pos::Span;
@@ -77,6 +78,8 @@
     Length,
     /// The unsize info of this projection
     OfProjection(&'tcx ty::ProjectionTy<'tcx>),
+    /// The unsize info of this anon ty
+    OfAnon(DefId, &'tcx Substs<'tcx>),
     /// The unsize info of this parameter
     OfParam(&'tcx ty::ParamTy),
 }
@@ -84,36 +87,65 @@
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     /// Returns the kind of unsize information of t, or None
     /// if t is unknown.
-    fn pointer_kind(&self, t: Ty<'tcx>, span: Span) -> Option<PointerKind<'tcx>> {
-        if self.type_is_known_to_be_sized(t, span) {
-            return Some(PointerKind::Thin);
+    fn pointer_kind(&self, t: Ty<'tcx>, span: Span) ->
+        Result<Option<PointerKind<'tcx>>, ErrorReported>
+    {
+        debug!("pointer_kind({:?}, {:?})", t, span);
+
+        let t = self.resolve_type_vars_if_possible(&t);
+
+        if t.references_error() {
+            return Err(ErrorReported);
         }
 
-        match t.sty {
+        if self.type_is_known_to_be_sized(t, span) {
+            return Ok(Some(PointerKind::Thin));
+        }
+
+        Ok(match t.sty {
             ty::TySlice(_) | ty::TyStr => Some(PointerKind::Length),
             ty::TyDynamic(ref tty, ..) =>
                 Some(PointerKind::Vtable(tty.principal().map(|p| p.def_id()))),
             ty::TyAdt(def, substs) if def.is_struct() => {
-                // FIXME(arielb1): do some kind of normalization
-                match def.struct_variant().fields.last() {
+                match def.non_enum_variant().fields.last() {
                     None => Some(PointerKind::Thin),
-                    Some(f) => self.pointer_kind(f.ty(self.tcx, substs), span),
+                    Some(f) => {
+                        let field_ty = self.field_ty(span, f, substs);
+                        self.pointer_kind(field_ty, span)?
+                    }
                 }
             }
+            ty::TyTuple(fields, _) => match fields.last() {
+                None => Some(PointerKind::Thin),
+                Some(f) => self.pointer_kind(f, span)?
+            },
+
             // Pointers to foreign types are thin, despite being unsized
             ty::TyForeign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
             ty::TyProjection(ref pi) => Some(PointerKind::OfProjection(pi)),
+            ty::TyAnon(def_id, substs) => Some(PointerKind::OfAnon(def_id, substs)),
             ty::TyParam(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
             ty::TyInfer(_) => None,
-            _ => panic!(),
-        }
+
+            ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
+            ty::TyFloat(_) | ty::TyArray(..) | ty::TyGeneratorWitness(..) |
+            ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyFnDef(..) |
+            ty::TyFnPtr(..) | ty::TyClosure(..) | ty::TyGenerator(..) |
+            ty::TyAdt(..) | ty::TyNever | ty::TyError => {
+                self.tcx.sess.delay_span_bug(
+                    span, &format!("`{:?}` should be sized but is not?", t));
+                return Err(ErrorReported);
+            }
+        })
     }
 }
 
 #[derive(Copy, Clone)]
 enum CastError {
+    ErrorReported,
+
     CastToBool,
     CastToChar,
     DifferingKinds,
@@ -129,6 +161,12 @@
     UnknownCastPtrKind,
 }
 
+impl From<ErrorReported> for CastError {
+    fn from(ErrorReported: ErrorReported) -> Self {
+        CastError::ErrorReported
+    }
+}
+
 fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
                                               span: Span,
                                               expr_ty: Ty<'tcx>,
@@ -173,6 +211,9 @@
 
     fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
         match e {
+            CastError::ErrorReported => {
+                // an error has already been reported
+            }
             CastError::NeedDeref => {
                 let error_span = self.span;
                 let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
@@ -192,7 +233,7 @@
             CastError::NeedViaPtr => {
                 let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
                                                          self.cast_ty, fcx);
-                if self.cast_ty.is_uint() {
+                if self.cast_ty.is_integral() {
                     err.help(&format!("cast through {} first",
                                       match e {
                                           CastError::NeedViaPtr => "a raw pointer",
@@ -480,8 +521,8 @@
         debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}", m_expr, m_cast);
         // ptr-ptr cast. vtables must match.
 
-        let expr_kind = fcx.pointer_kind(m_expr.ty, self.span);
-        let cast_kind = fcx.pointer_kind(m_cast.ty, self.span);
+        let expr_kind = fcx.pointer_kind(m_expr.ty, self.span)?;
+        let cast_kind = fcx.pointer_kind(m_cast.ty, self.span)?;
 
         let cast_kind = match cast_kind {
             // We can't cast if target pointer kind is unknown
@@ -519,7 +560,7 @@
                            -> Result<CastKind, CastError> {
         // fptr-ptr cast. must be to thin ptr
 
-        match fcx.pointer_kind(m_cast.ty, self.span) {
+        match fcx.pointer_kind(m_cast.ty, self.span)? {
             None => Err(CastError::UnknownCastPtrKind),
             Some(PointerKind::Thin) => Ok(CastKind::FnPtrPtrCast),
             _ => Err(CastError::IllegalCast),
@@ -532,7 +573,7 @@
                            -> Result<CastKind, CastError> {
         // ptr-addr cast. must be from thin ptr
 
-        match fcx.pointer_kind(m_expr.ty, self.span) {
+        match fcx.pointer_kind(m_expr.ty, self.span)? {
             None => Err(CastError::UnknownExprPtrKind),
             Some(PointerKind::Thin) => Ok(CastKind::PtrAddrCast),
             _ => Err(CastError::NeedViaThinPtr),
@@ -569,7 +610,7 @@
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError> {
         // ptr-addr cast. pointer must be thin.
-        match fcx.pointer_kind(m_cast.ty, self.span) {
+        match fcx.pointer_kind(m_cast.ty, self.span)? {
             None => Err(CastError::UnknownCastPtrKind),
             Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
             _ => Err(CastError::IllegalCast),
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 147347a..df15f78 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -37,6 +37,7 @@
         _capture: hir::CaptureClause,
         decl: &'gcx hir::FnDecl,
         body_id: hir::BodyId,
+        gen: Option<hir::GeneratorMovability>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
         debug!(
@@ -53,7 +54,7 @@
             None => (None, None),
         };
         let body = self.tcx.hir.body(body_id);
-        self.check_closure(expr, expected_kind, decl, body, expected_sig)
+        self.check_closure(expr, expected_kind, decl, body, gen, expected_sig)
     }
 
     fn check_closure(
@@ -62,6 +63,7 @@
         opt_kind: Option<ty::ClosureKind>,
         decl: &'gcx hir::FnDecl,
         body: &'gcx hir::Body,
+        gen: Option<hir::GeneratorMovability>,
         expected_sig: Option<ty::FnSig<'tcx>>,
     ) -> Ty<'tcx> {
         debug!(
@@ -86,7 +88,7 @@
             decl,
             expr.id,
             body,
-            true,
+            gen,
         ).1;
 
         // Create type variables (for now) to represent the transformed
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 734287f..570eecf 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -518,7 +518,10 @@
                                            self_descr);
             err.span_label(impl_m_span, format!("`{}` used in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
-                err.span_label(span, format!("trait declared without `{}`", self_descr));
+                err.span_label(span, format!("trait method declared without `{}`", self_descr));
+            } else {
+                err.note_trait_signature(trait_m.name.to_string(),
+                                         trait_m.signature(&tcx));
             }
             err.emit();
             return Err(ErrorReported);
@@ -533,8 +536,7 @@
                                             not in the impl",
                                            trait_m.name,
                                            self_descr);
-            err.span_label(impl_m_span,
-                           format!("expected `{}` in impl", self_descr));
+            err.span_label(impl_m_span, format!("expected `{}` in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
                 err.span_label(span, format!("`{}` used in trait", self_descr));
             } else {
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 45ddae5..b6b863c 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -8,12 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::iter;
 
 use check::FnCtxt;
 use rustc::infer::InferOk;
 use rustc::traits::ObligationCause;
 
 use syntax::ast;
+use syntax::util::parser::AssocOp;
 use syntax_pos::{self, Span};
 use rustc::hir;
 use rustc::hir::print;
@@ -136,50 +138,46 @@
 
         if let Some((msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
             err.span_suggestion(expr.span, msg, suggestion);
-        } else {
-            let mode = probe::Mode::MethodCall;
-            let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
-                                                         mode,
-                                                         expected,
-                                                         checked_ty,
-                                                         ast::DUMMY_NODE_ID);
-            if suggestions.len() > 0 {
-                err.help(&format!("here are some functions which \
-                                   might fulfill your needs:\n{}",
-                                  self.get_best_match(&suggestions).join("\n")));
+        } else if !self.check_for_cast(&mut err, expr, expr_ty, expected) {
+            let methods = self.get_conversion_methods(expected, checked_ty);
+            if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+                let suggestions = iter::repeat(expr_text).zip(methods.iter())
+                    .map(|(receiver, method)| format!("{}.{}()", receiver, method.name))
+                    .collect::<Vec<_>>();
+                if !suggestions.is_empty() {
+                    err.span_suggestions(expr.span,
+                                         "try using a conversion method",
+                                         suggestions);
+                }
             }
         }
         (expected, Some(err))
     }
 
-    fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
-        format!("- .{}({})",
-                method.name,
-                if self.has_no_input_arg(method) {
-                    ""
-                } else {
-                    "..."
-                })
-    }
+    fn get_conversion_methods(&self, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
+                              -> Vec<AssociatedItem> {
+        let mut methods = self.probe_for_return_type(syntax_pos::DUMMY_SP,
+                                                     probe::Mode::MethodCall,
+                                                     expected,
+                                                     checked_ty,
+                                                     ast::DUMMY_NODE_ID);
+        methods.retain(|m| {
+            self.has_no_input_arg(m) &&
+                self.tcx.get_attrs(m.def_id).iter()
+                // This special internal attribute is used to whitelist
+                // "identity-like" conversion methods to be suggested here.
+                //
+                // FIXME (#46459 and #46460): ideally
+                // `std::convert::Into::into` and `std::borrow:ToOwned` would
+                // also be `#[rustc_conversion_suggestion]`, if not for
+                // method-probing false-positives and -negatives (respectively).
+                //
+                // FIXME? Other potential candidate methods: `as_ref` and
+                // `as_mut`?
+                .find(|a| a.check_name("rustc_conversion_suggestion")).is_some()
+        });
 
-    fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> Vec<String> {
-        methods.iter()
-               .take(5)
-               .map(|method| self.format_method_suggestion(&*method))
-               .collect::<Vec<String>>()
-    }
-
-    fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
-        let no_argument_methods: Vec<_> =
-            methods.iter()
-                   .filter(|ref x| self.has_no_input_arg(&*x))
-                   .map(|x| x.clone())
-                   .collect();
-        if no_argument_methods.len() > 0 {
-            self.display_suggested_methods(&no_argument_methods)
-        } else {
-            self.display_suggested_methods(&methods)
-        }
+        methods
     }
 
     // This function checks if the method isn't static and takes other arguments than `self`.
@@ -290,8 +288,7 @@
                         // Maybe remove `&`?
                         hir::ExprAddrOf(_, ref expr) => {
                             if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
-                                return Some(("consider removing the borrow",
-                                             code));
+                                return Some(("consider removing the borrow", code));
                             }
                         }
 
@@ -306,7 +303,7 @@
                                                  format!("*{}", code)));
                                 }
                             }
-                        },
+                        }
                     }
                 }
                 None
@@ -314,4 +311,240 @@
             _ => None,
         }
     }
+
+    fn check_for_cast(&self,
+                      err: &mut DiagnosticBuilder<'tcx>,
+                      expr: &hir::Expr,
+                      checked_ty: Ty<'tcx>,
+                      expected_ty: Ty<'tcx>)
+                      -> bool {
+        let will_truncate = "will truncate the source value";
+        let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
+                                  `isize`";
+        let depending_on_usize = "will truncate or zero-extend depending on the bit width of \
+                                  `usize`";
+        let will_sign_extend = "will sign-extend the source value";
+        let will_zero_extend = "will zero-extend the source value";
+
+        // If casting this expression to a given numeric type would be appropriate in case of a type
+        // mismatch.
+        //
+        // We want to minimize the amount of casting operations that are suggested, as it can be a
+        // lossy operation with potentially bad side effects, so we only suggest when encountering
+        // an expression that indicates that the original type couldn't be directly changed.
+        //
+        // For now, don't suggest casting with `as`.
+        let can_cast = false;
+
+        let needs_paren = expr.precedence().order() < (AssocOp::As.precedence() as i8);
+
+        if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+            let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
+            let cast_suggestion = format!("{}{}{} as {}",
+                                          if needs_paren { "(" } else { "" },
+                                          src,
+                                          if needs_paren { ")" } else { "" },
+                                          expected_ty);
+            let into_suggestion = format!("{}{}{}.into()",
+                                          if needs_paren { "(" } else { "" },
+                                          src,
+                                          if needs_paren { ")" } else { "" });
+
+            match (&expected_ty.sty, &checked_ty.sty) {
+                (&ty::TyInt(ref exp), &ty::TyInt(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                        }
+                        (None, _) | (_, None) => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_sign_extend),
+                                                into_suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyUint(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                        }
+                        (None, _) | (_, None) => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_zero_extend),
+                                                into_suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyInt(ref exp), &ty::TyUint(ref found)) => {
+                    if can_cast {
+                        match (found.bit_width(), exp.bit_width()) {
+                            (Some(found), Some(exp)) if found > exp - 1 => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                            (None, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                            (None, _) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                            (_, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                            _ => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_zero_extend),
+                                                    cast_suggestion);
+                            }
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyInt(ref found)) => {
+                    if can_cast {
+                        match (found.bit_width(), exp.bit_width()) {
+                            (Some(found), Some(exp)) if found - 1 > exp => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                            (None, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_sign_extend),
+                                                    cast_suggestion);
+                            }
+                            (None, _) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                            (_, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                            _ => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_sign_extend),
+                                                    cast_suggestion);
+                            }
+                        }
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyFloat(ref found)) => {
+                    if found.bit_width() < exp.bit_width() {
+                        err.span_suggestion(expr.span,
+                                            &format!("{} in a lossless way",
+                                                     msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the closest possible value",
+                                                     msg),
+                                            cast_suggestion);
+                        err.warn("casting here will cause undefined behavior if the value is \
+                                  finite but larger or smaller than the largest or smallest \
+                                  finite value representable by `f32` (this is a bug and will be \
+                                  fixed)");
+                    }
+                    true
+                }
+                (&ty::TyUint(_), &ty::TyFloat(_)) | (&ty::TyInt(_), &ty::TyFloat(_)) => {
+                    if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, rounding the float towards zero",
+                                                     msg),
+                                            cast_suggestion);
+                        err.warn("casting here will cause undefined behavior if the rounded value \
+                                  cannot be represented by the target integer type, including \
+                                  `Inf` and `NaN` (this is a bug and will be fixed)");
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyUint(ref found)) => {
+                    // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
+                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer",
+                                                      msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer, rounded if \
+                                                      necessary",
+                                                      msg),
+                                            cast_suggestion);
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyInt(ref found)) => {
+                    // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
+                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer",
+                                                      msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer, rounded if \
+                                                      necessary",
+                                                      msg),
+                                            cast_suggestion);
+                    }
+                    true
+                }
+                _ => false,
+            }
+        } else {
+            false
+        }
+    }
 }
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 55700c4..4aed688 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -59,11 +59,13 @@
         }
         _ => {
             // Destructors only work on nominal types.  This was
-            // already checked by coherence, so we can panic here.
+            // already checked by coherence, but compilation may
+            // not have been terminated.
             let span = tcx.def_span(drop_impl_did);
-            span_bug!(span,
-                      "should have been rejected by coherence check: {}",
-                      dtor_self_type);
+            tcx.sess.delay_span_bug(span,
+                            &format!("should have been rejected by coherence check: {}",
+                            dtor_self_type));
+            Err(ErrorReported)
         }
     }
 }
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index af12976..781eeae 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -17,8 +17,9 @@
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::{self, Pat, PatKind, Expr};
 use rustc::middle::region;
-use rustc::ty::Ty;
+use rustc::ty::{self, Ty, GeneratorInterior};
 use std::rc::Rc;
+use syntax_pos::Span;
 use super::FnCtxt;
 use util::nodemap::FxHashMap;
 
@@ -30,36 +31,53 @@
 }
 
 impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> {
-    fn record(&mut self, ty: Ty<'tcx>, scope: Option<region::Scope>, expr: Option<&'tcx Expr>) {
+    fn record(&mut self,
+              ty: Ty<'tcx>,
+              scope: Option<region::Scope>,
+              expr: Option<&'tcx Expr>,
+              source_span: Span) {
         use syntax_pos::DUMMY_SP;
 
         let live_across_yield = scope.map_or(Some(DUMMY_SP), |s| {
-            self.region_scope_tree.yield_in_scope(s).and_then(|(span, expr_count)| {
+            self.region_scope_tree.yield_in_scope(s).and_then(|(yield_span, expr_count)| {
                 // If we are recording an expression that is the last yield
                 // in the scope, or that has a postorder CFG index larger
                 // than the one of all of the yields, then its value can't
                 // be storage-live (and therefore live) at any of the yields.
                 //
                 // See the mega-comment at `yield_in_scope` for a proof.
+
+                debug!("comparing counts yield: {} self: {}, source_span = {:?}",
+                    expr_count, self.expr_count, source_span);
+
                 if expr_count >= self.expr_count {
-                    Some(span)
+                    Some(yield_span)
                 } else {
                     None
                 }
             })
         });
 
-        if let Some(span) = live_across_yield {
+        if let Some(yield_span) = live_across_yield {
             let ty = self.fcx.resolve_type_vars_if_possible(&ty);
 
-            debug!("type in expr = {:?}, scope = {:?}, type = {:?}, span = {:?}",
-                   expr, scope, ty, span);
+            debug!("type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}",
+                   expr, scope, ty, self.expr_count, yield_span);
 
-            // Map the type to the number of types added before it
-            let entries = self.types.len();
-            self.types.entry(&ty).or_insert(entries);
+            if self.fcx.any_unresolved_type_vars(&ty) {
+                let mut err = struct_span_err!(self.fcx.tcx.sess, source_span, E0907,
+                    "type inside generator must be known in this context");
+                err.span_note(yield_span,
+                              "the type is part of the generator because of this `yield`");
+                err.emit();
+            } else {
+                // Map the type to the number of types added before it
+                let entries = self.types.len();
+                self.types.entry(&ty).or_insert(entries);
+            }
         } else {
-            debug!("no type in expr = {:?}, span = {:?}", expr, expr.map(|e| e.span));
+            debug!("no type in expr = {:?}, count = {:?}, span = {:?}",
+                   expr, self.expr_count, expr.map(|e| e.span));
         }
     }
 }
@@ -67,7 +85,7 @@
 pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
                                         def_id: DefId,
                                         body_id: hir::BodyId,
-                                        witness: Ty<'tcx>) {
+                                        interior: GeneratorInterior<'tcx>) {
     let body = fcx.tcx.hir.body(body_id);
     let mut visitor = InteriorVisitor {
         fcx,
@@ -87,17 +105,40 @@
     types.sort_by_key(|t| t.1);
 
     // Extract type components
-    let types: Vec<_> = types.into_iter().map(|t| t.0).collect();
+    let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| t.0));
 
-    let tuple = fcx.tcx.intern_tup(&types, false);
+    // The types in the generator interior contain lifetimes local to the generator itself,
+    // which should not be exposed outside of the generator. Therefore, we replace these
+    // lifetimes with existentially-bound lifetimes, which reflect the exact value of the
+    // lifetimes not being known by users.
+    //
+    // These lifetimes are used in auto trait impl checking (for example,
+    // if a Sync generator contains an &'α T, we need to check whether &'α T: Sync),
+    // so knowledge of the exact relationships between them isn't particularly important.
 
-    debug!("Types in generator {:?}, span = {:?}", tuple, body.value.span);
+    debug!("Types in generator {:?}, span = {:?}", type_list, body.value.span);
 
-    // Unify the tuple with the witness
-    match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(witness, tuple) {
+    // Replace all regions inside the generator interior with late bound regions
+    // Note that each region slot in the types gets a new fresh late bound region,
+    // which means that none of the regions inside relate to any other, even if
+    // typeck had previously found contraints that would cause them to be related.
+    let mut counter = 0;
+    let type_list = fcx.tcx.fold_regions(&type_list, &mut false, |_, current_depth| {
+        counter += 1;
+        fcx.tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(current_depth),
+                                        ty::BrAnon(counter)))
+    });
+
+    let witness = fcx.tcx.mk_generator_witness(ty::Binder(type_list));
+
+    debug!("Types in generator after region replacement {:?}, span = {:?}",
+            witness, body.value.span);
+
+    // Unify the type variable inside the generator with the new witness
+    match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior.witness, witness) {
         Ok(ok) => fcx.register_infer_ok_obligations(ok),
         _ => bug!(),
-   }
+    }
 }
 
 // This visitor has to have the same visit_expr calls as RegionResolutionVisitor in
@@ -112,7 +153,7 @@
         if let PatKind::Binding(..) = pat.node {
             let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id);
             let ty = self.fcx.tables.borrow().pat_ty(pat);
-            self.record(ty, Some(scope), None);
+            self.record(ty, Some(scope), None, pat.span);
         }
 
         self.expr_count += 1;
@@ -128,6 +169,6 @@
         let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
 
         let ty = self.fcx.tables.borrow().expr_ty_adjusted(expr);
-        self.record(ty, scope, Some(expr));
+        self.record(ty, scope, Some(expr), expr.span);
     }
 }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index fe30ffb..c88bbd0 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -27,6 +27,7 @@
 use syntax::util::lev_distance::{lev_distance, find_best_match_for_name};
 use syntax_pos::Span;
 use rustc::hir;
+use rustc::lint;
 use std::mem;
 use std::ops::Deref;
 use std::rc::Rc;
@@ -189,7 +190,7 @@
                scope_expr_id);
         let method_names =
             self.probe_op(span, mode, None, Some(return_type), IsSuggestion(true),
-                          self_ty, scope_expr_id, ProbeScope::TraitsInScope,
+                          self_ty, scope_expr_id, ProbeScope::AllTraits,
                           |probe_cx| Ok(probe_cx.candidate_method_names()))
                 .unwrap_or(vec![]);
          method_names
@@ -198,7 +199,7 @@
                  self.probe_op(
                      span, mode, Some(method_name), Some(return_type),
                      IsSuggestion(true), self_ty, scope_expr_id,
-                     ProbeScope::TraitsInScope, |probe_cx| probe_cx.pick()
+                     ProbeScope::AllTraits, |probe_cx| probe_cx.pick()
                  ).ok().map(|pick| pick.item)
              })
             .collect()
@@ -249,7 +250,7 @@
         // think cause spurious errors. Really though this part should
         // take place in the `self.probe` below.
         let steps = if mode == Mode::MethodCall {
-            match self.create_steps(span, self_ty, is_suggestion) {
+            match self.create_steps(span, scope_expr_id, self_ty, is_suggestion) {
                 Some(steps) => steps,
                 None => {
                     return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(),
@@ -291,6 +292,7 @@
 
     fn create_steps(&self,
                     span: Span,
+                    scope_expr_id: ast::NodeId,
                     self_ty: Ty<'tcx>,
                     is_suggestion: IsSuggestion)
                     -> Option<Vec<CandidateStep<'tcx>>> {
@@ -318,18 +320,19 @@
         match final_ty.sty {
             ty::TyInfer(ty::TyVar(_)) => {
                 // Ended in an inference variable. If we are doing
-                // a real method lookup, this is a hard error (it's an
-                // ambiguity and we can't make progress).
+                // a real method lookup, this is a hard error because it's
+                // possible that there will be multiple applicable methods.
                 if !is_suggestion.0 {
                     if reached_raw_pointer
                     && !self.tcx.sess.features.borrow().arbitrary_self_types {
-                        // only produce a warning in this case, because inference variables used to
-                        // be allowed here in some cases for raw pointers
-                        struct_span_warn!(self.tcx.sess, span, E0619,
-                            "the type of this value must be known in this context")
-                        .note("this will be made into a hard error in a future version of \
-                               the compiler")
-                        .emit();
+                        // this case used to be allowed by the compiler,
+                        // so we do a future-compat lint here
+                        // (see https://github.com/rust-lang/rust/issues/46906)
+                        self.tcx.lint_node(
+                            lint::builtin::TYVAR_BEHIND_RAW_POINTER,
+                            scope_expr_id,
+                            span,
+                            &format!("the type of this value must be known in this context"));
                     } else {
                         let t = self.structurally_resolved_type(span, final_ty);
                         assert_eq!(t, self.tcx.types.err);
@@ -491,7 +494,7 @@
                 let lang_def_id = lang_items.i128_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::IntTy::Is) => {
+            ty::TyInt(ast::IntTy::Isize) => {
                 let lang_def_id = lang_items.isize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
@@ -515,7 +518,7 @@
                 let lang_def_id = lang_items.u128_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::UintTy::Us) => {
+            ty::TyUint(ast::UintTy::Usize) => {
                 let lang_def_id = lang_items.usize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index f29009c..3f8792a 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -195,15 +195,76 @@
                     }
                 };
                 let mut err = if !actual.references_error() {
-                    struct_span_err!(
-                        tcx.sess,
-                        span,
-                        E0599,
-                        "no {} named `{}` found for type `{}` in the current scope",
-                        type_str,
-                        item_name,
-                        ty_string
-                    )
+                    // Suggest clamping down the type if the method that is being attempted to
+                    // be used exists at all, and the type is an ambiuous numeric type
+                    // ({integer}/{float}).
+                    let mut candidates = all_traits(self.tcx)
+                        .filter(|info| {
+                            self.associated_item(info.def_id, item_name, Namespace::Value).is_some()
+                        });
+                    if let (true, false, Some(expr), Some(_)) = (actual.is_numeric(),
+                                                                 actual.has_concrete_skeleton(),
+                                                                 rcvr_expr,
+                                                                 candidates.next()) {
+                        let mut err = struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0689,
+                            "can't call {} `{}` on ambiguous numeric type `{}`",
+                            type_str,
+                            item_name,
+                            ty_string
+                        );
+                        let concrete_type = if actual.is_integral() {
+                            "i32"
+                        } else {
+                            "f32"
+                        };
+                        match expr.node {
+                            hir::ExprLit(_) => {  // numeric literal
+                                let snippet = tcx.sess.codemap().span_to_snippet(expr.span)
+                                    .unwrap_or("<numeric literal>".to_string());
+                                // FIXME: use the literal for missing snippet
+
+                                err.span_suggestion(expr.span,
+                                                    &format!("you must specify a concrete type for \
+                                                              this numeric value, like `{}`",
+                                                             concrete_type),
+                                                    format!("{}_{}",
+                                                            snippet,
+                                                            concrete_type));
+                            }
+                            hir::ExprPath(ref qpath) => {  // local binding
+                                if let &hir::QPath::Resolved(_, ref path) = &qpath {
+                                    if let hir::def::Def::Local(node_id) = path.def {
+                                        let span = tcx.hir.span(node_id);
+                                        let snippet = tcx.sess.codemap().span_to_snippet(span)
+                                            .unwrap();
+                                        err.span_suggestion(span,
+                                                            &format!("you must specify a type for \
+                                                                      this binding, like `{}`",
+                                                                     concrete_type),
+                                                            format!("{}: {}",
+                                                                    snippet,
+                                                                    concrete_type));
+                                    }
+                                }
+                            }
+                            _ => {}
+                        }
+                        err.emit();
+                        return;
+                    } else {
+                        struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0599,
+                            "no {} named `{}` found for type `{}` in the current scope",
+                            type_str,
+                            item_name,
+                            ty_string
+                        )
+                    }
                 } else {
                     tcx.sess.diagnostic().struct_dummy()
                 };
@@ -228,7 +289,7 @@
                     for (ty, _) in self.autoderef(span, rcvr_ty) {
                         match ty.sty {
                             ty::TyAdt(def, substs) if !def.is_enum() => {
-                                if let Some(field) = def.struct_variant()
+                                if let Some(field) = def.non_enum_variant()
                                     .find_field_named(item_name) {
                                     let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
                                     let expr_string = match snippet {
@@ -305,12 +366,16 @@
                                       bound_list));
                 }
 
-                self.suggest_traits_to_import(&mut err,
-                                              span,
-                                              rcvr_ty,
-                                              item_name,
-                                              rcvr_expr,
-                                              out_of_scope_traits);
+                if actual.is_numeric() && actual.is_fresh() {
+
+                } else {
+                    self.suggest_traits_to_import(&mut err,
+                                                  span,
+                                                  rcvr_ty,
+                                                  item_name,
+                                                  rcvr_expr,
+                                                  out_of_scope_traits);
+                }
 
                 if let Some(lev_candidate) = lev_candidate {
                     err.help(&format!("did you mean `{}`?", lev_candidate.name));
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index ab81d26..5b7eca7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -96,14 +96,15 @@
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
 use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
-use rustc::ty::{self, Ty, TyCtxt, Visibility};
+use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
 use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
+use rustc::ty::layout::LayoutOf;
 use errors::{DiagnosticBuilder, DiagnosticId};
 use require_c_abi_if_variadic;
-use session::{CompileIncomplete, Session};
+use session::{CompileIncomplete, config, Session};
 use TypeAndSubsts;
 use lint;
 use util::common::{ErrorReported, indenter};
@@ -115,6 +116,7 @@
 use std::cmp;
 use std::fmt::Display;
 use std::mem::replace;
+use std::iter;
 use std::ops::{self, Deref};
 use syntax::abi::Abi;
 use syntax::ast;
@@ -207,7 +209,7 @@
 
     deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
 
-    deferred_generator_interiors: RefCell<Vec<(hir::BodyId, Ty<'tcx>)>>,
+    deferred_generator_interiors: RefCell<Vec<(hir::BodyId, ty::GeneratorInterior<'tcx>)>>,
 
     // Anonymized types found in explicit return types and their
     // associated fresh inference variable. Writeback resolves these
@@ -836,7 +838,7 @@
                                                   param_env,
                                                   &fn_sig);
 
-            let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, false).0;
+            let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
             fcx
         } else {
             let fcx = FnCtxt::new(&inh, param_env, body.value.id);
@@ -971,7 +973,7 @@
                             decl: &'gcx hir::FnDecl,
                             fn_id: ast::NodeId,
                             body: &'gcx hir::Body,
-                            can_be_generator: bool)
+                            can_be_generator: Option<hir::GeneratorMovability>)
                             -> (FnCtxt<'a, 'gcx, 'tcx>, Option<GeneratorTypes<'tcx>>)
 {
     let mut fn_sig = fn_sig.clone();
@@ -997,7 +999,7 @@
 
     let span = body.value.span;
 
-    if body.is_generator && can_be_generator {
+    if body.is_generator && can_be_generator.is_some() {
         fcx.yield_ty = Some(fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)));
     }
 
@@ -1021,17 +1023,24 @@
     }
 
     let fn_hir_id = fcx.tcx.hir.node_to_hir_id(fn_id);
-    let gen_ty = if can_be_generator && body.is_generator {
+    inherited.tables.borrow_mut().liberated_fn_sigs_mut().insert(fn_hir_id, fn_sig);
+
+    fcx.check_return_expr(&body.value);
+
+    // We insert the deferred_generator_interiors entry after visiting the body.
+    // This ensures that all nested generators appear before the entry of this generator.
+    // resolve_generator_interiors relies on this property.
+    let gen_ty = if can_be_generator.is_some() && body.is_generator {
         let witness = fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span));
-        fcx.deferred_generator_interiors.borrow_mut().push((body.id(), witness));
-        let interior = ty::GeneratorInterior::new(witness);
+        let interior = ty::GeneratorInterior {
+            witness,
+            movable: can_be_generator.unwrap() == hir::GeneratorMovability::Movable,
+        };
+        fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior));
         Some(GeneratorTypes { yield_ty: fcx.yield_ty.unwrap(), interior: interior })
     } else {
         None
     };
-    inherited.tables.borrow_mut().liberated_fn_sigs_mut().insert(fn_hir_id, fn_sig);
-
-    fcx.check_return_expr(&body.value);
 
     // Finalize the return check by taking the LUB of the return types
     // we saw and assigning it to the expected return type. This isn't
@@ -1064,6 +1073,30 @@
     }
     fcx.demand_suptype(span, ret_ty, actual_return_ty);
 
+    if fcx.tcx.sess.features.borrow().termination_trait {
+        // If the termination trait language item is activated, check that the main return type
+        // implements the termination trait.
+        if let Some(term_id) = fcx.tcx.lang_items().termination() {
+            if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
+                if id == fn_id {
+                    match fcx.sess().entry_type.get() {
+                        Some(config::EntryMain) => {
+                            let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
+                            let trait_ref = ty::TraitRef::new(term_id, substs);
+                            let cause = traits::ObligationCause::new(
+                                span, fn_id, ObligationCauseCode::MainFunctionType);
+
+                            inherited.register_predicate(
+                                traits::Obligation::new(
+                                    cause, param_env, trait_ref.to_predicate()));
+                        },
+                        _ => {},
+                    }
+                }
+            }
+        }
+    }
+
     (fcx, gen_ty)
 }
 
@@ -1079,6 +1112,7 @@
         check_simd(tcx, span, def_id);
     }
 
+    check_transparent(tcx, span, def_id);
     check_packed(tcx, span, def_id);
 }
 
@@ -1419,7 +1453,7 @@
     let t = tcx.type_of(def_id);
     match t.sty {
         ty::TyAdt(def, substs) if def.is_struct() => {
-            let fields = &def.struct_variant().fields;
+            let fields = &def.non_enum_variant().fields;
             if fields.is_empty() {
                 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
                 return;
@@ -1473,7 +1507,7 @@
             }
             // push struct def_id before checking fields
             stack.push(def_id);
-            for field in &def.struct_variant().fields {
+            for field in &def.non_enum_variant().fields {
                 let f = field.ty(tcx, substs);
                 match f.sty {
                     ty::TyAdt(def, _) => {
@@ -1492,6 +1526,42 @@
     false
 }
 
+fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
+    let adt = tcx.adt_def(def_id);
+    if !adt.repr.transparent() {
+        return;
+    }
+
+    // For each field, figure out if it's known to be a ZST and align(1)
+    let field_infos: Vec<_> = adt.non_enum_variant().fields.iter().map(|field| {
+        let ty = field.ty(tcx, Substs::identity_for_item(tcx, field.did));
+        let param_env = tcx.param_env(field.did);
+        let layout = (tcx, param_env).layout_of(ty);
+        // We are currently checking the type this field came from, so it must be local
+        let span = tcx.hir.span_if_local(field.did).unwrap();
+        let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false);
+        let align1 = layout.map(|layout| layout.align.abi() == 1).unwrap_or(false);
+        (span, zst, align1)
+    }).collect();
+
+    let non_zst_fields = field_infos.iter().filter(|(_span, zst, _align1)| !*zst);
+    let non_zst_count = non_zst_fields.clone().count();
+    if non_zst_count != 1 {
+        let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| *span).collect();
+        struct_span_err!(tcx.sess, sp, E0690,
+                         "transparent struct needs exactly one non-zero-sized field, but has {}",
+                          non_zst_count)
+        .span_note(field_spans, "non-zero-sized field")
+        .emit();
+    }
+    for &(span, zst, align1) in &field_infos {
+        if zst && !align1 {
+            span_err!(tcx.sess, span, E0691,
+                      "zero-sized field in transparent struct has alignment larger than 1");
+        }
+    }
+}
+
 #[allow(trivial_numeric_casts)]
 pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             sp: Span,
@@ -2050,9 +2120,10 @@
     }
 
     fn resolve_generator_interiors(&self, def_id: DefId) {
-        let mut deferred_generator_interiors = self.deferred_generator_interiors.borrow_mut();
-        for (body_id, witness) in deferred_generator_interiors.drain(..) {
-            generator_interior::resolve_interior(self, def_id, body_id, witness);
+        let mut generators = self.deferred_generator_interiors.borrow_mut();
+        for (body_id, interior) in generators.drain(..) {
+            self.select_obligations_where_possible();
+            generator_interior::resolve_interior(self, def_id, body_id, interior);
         }
     }
 
@@ -2192,17 +2263,6 @@
                adjusted_ty,
                index_ty);
 
-        // First, try built-in indexing.
-        match (adjusted_ty.builtin_index(), &index_ty.sty) {
-            (Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
-                debug!("try_index_step: success, using built-in indexing");
-                let adjustments = autoderef.adjust_steps(lvalue_pref);
-                self.apply_adjustments(base_expr, adjustments);
-                return Some((self.tcx.types.usize, ty));
-            }
-            _ => {}
-        }
-
         for &unsize in &[false, true] {
             let mut self_ty = adjusted_ty;
             if unsize {
@@ -2919,7 +2979,7 @@
                     debug!("struct named {:?}",  base_t);
                     let (ident, def_scope) =
                         self.tcx.adjust(field.node, base_def.did, self.body_id);
-                    let fields = &base_def.struct_variant().fields;
+                    let fields = &base_def.non_enum_variant().fields;
                     if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
                         let field_ty = self.field_ty(expr.span, field, substs);
                         if field.vis.is_accessible_from(def_scope, self.tcx) {
@@ -2967,12 +3027,12 @@
                 match expr_t.sty {
                     ty::TyAdt(def, _) if !def.is_enum() => {
                         if let Some(suggested_field_name) =
-                            Self::suggest_field_name(def.struct_variant(), field, vec![]) {
+                            Self::suggest_field_name(def.non_enum_variant(), field, vec![]) {
                                 err.span_label(field.span,
                                                format!("did you mean `{}`?", suggested_field_name));
                             } else {
                                 err.span_label(field.span, "unknown field");
-                                let struct_variant_def = def.struct_variant();
+                                let struct_variant_def = def.non_enum_variant();
                                 let field_names = self.available_field_names(struct_variant_def);
                                 if !field_names.is_empty() {
                                     err.note(&format!("available fields are: {}",
@@ -3054,7 +3114,7 @@
         while let Some((base_t, _)) = autoderef.next() {
             let field = match base_t.sty {
                 ty::TyAdt(base_def, substs) if base_def.is_struct() => {
-                    tuple_like = base_def.struct_variant().ctor_kind == CtorKind::Fn;
+                    tuple_like = base_def.non_enum_variant().ctor_kind == CtorKind::Fn;
                     if !tuple_like { continue }
 
                     debug!("tuple struct named {:?}",  base_t);
@@ -3064,7 +3124,7 @@
                     };
                     let (ident, def_scope) =
                         self.tcx.adjust_ident(ident, base_def.did, self.body_id);
-                    let fields = &base_def.struct_variant().fields;
+                    let fields = &base_def.non_enum_variant().fields;
                     if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
                         let field_ty = self.field_ty(expr.span, field, substs);
                         if field.vis.is_accessible_from(def_scope, self.tcx) {
@@ -3324,7 +3384,7 @@
             Def::AssociatedTy(..) | Def::SelfTy(..) => {
                 match ty.sty {
                     ty::TyAdt(adt, substs) if !adt.is_enum() => {
-                        Some((adt.struct_variant(), adt.did, substs))
+                        Some((adt.non_enum_variant(), adt.did, substs))
                     }
                     _ => None,
                 }
@@ -3386,7 +3446,7 @@
             self.check_expr_has_type_or_error(base_expr, struct_ty);
             match struct_ty.sty {
                 ty::TyAdt(adt, substs) if adt.is_struct() => {
-                    let fru_field_types = adt.struct_variant().fields.iter().map(|f| {
+                    let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| {
                         self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs))
                     }).collect();
 
@@ -3802,8 +3862,8 @@
           hir::ExprMatch(ref discrim, ref arms, match_src) => {
             self.check_match(expr, &discrim, arms, expected, match_src)
           }
-          hir::ExprClosure(capture, ref decl, body_id, _, _) => {
-              self.check_expr_closure(expr, capture, &decl, body_id, expected)
+          hir::ExprClosure(capture, ref decl, body_id, _, gen) => {
+              self.check_expr_closure(expr, capture, &decl, body_id, gen, expected)
           }
           hir::ExprBlock(ref body) => {
             self.check_block_with_expected(&body, expected)
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 2e0d0dd..ab148af 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -74,11 +74,11 @@
 
     fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
         match expr.node {
-            hir::ExprClosure(cc, _, body_id, _, is_generator) => {
+            hir::ExprClosure(cc, _, body_id, _, gen) => {
                 let body = self.fcx.tcx.hir.body(body_id);
                 self.visit_body(body);
                 self.fcx
-                    .analyze_closure(expr.id, expr.hir_id, expr.span, body, cc, is_generator);
+                    .analyze_closure(expr.id, expr.hir_id, expr.span, body, cc, gen);
             }
 
             _ => {}
@@ -96,7 +96,7 @@
         span: Span,
         body: &hir::Body,
         capture_clause: hir::CaptureClause,
-        is_generator: bool,
+        gen: Option<hir::GeneratorMovability>,
     ) {
         /*!
          * Analysis starting point.
@@ -121,7 +121,7 @@
             }
         };
 
-        let infer_kind = if is_generator {
+        let infer_kind = if gen.is_some() {
             false
         } else {
             self.closure_kind(closure_def_id, closure_substs).is_none()
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 385b932..3668fc4 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -107,16 +107,21 @@
             //
             // won't be allowed unless there's an *explicit* implementation of `Send`
             // for `T`
-            hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
-                          ref trait_ref, ref self_ty, _) => {
-                self.check_impl(item, self_ty, trait_ref);
-            }
-            hir::ItemImpl(_, hir::ImplPolarity::Negative, _, _, Some(_), ..) => {
-                // FIXME(#27579) what amount of WF checking do we need for neg impls?
-
-                let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
-                if !tcx.trait_is_auto(trait_ref.def_id) {
-                    error_192(tcx, item.span);
+            hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
+                let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
+                                 .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
+                if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
+                    tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
+                }
+                if polarity == hir::ImplPolarity::Positive {
+                    self.check_impl(item, self_ty, trait_ref);
+                } else {
+                    // FIXME(#27579) what amount of WF checking do we need for neg impls?
+                    if trait_ref.is_some() && !is_auto {
+                        span_err!(tcx.sess, item.span, E0192,
+                                  "negative impls are only allowed for \
+                                   auto traits (e.g., `Send` and `Sync`)")
+                    }
                 }
             }
             hir::ItemFn(..) => {
@@ -130,14 +135,14 @@
             }
             hir::ItemStruct(ref struct_def, ref ast_generics) => {
                 self.check_type_defn(item, false, |fcx| {
-                    vec![fcx.struct_variant(struct_def)]
+                    vec![fcx.non_enum_variant(struct_def)]
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
             }
             hir::ItemUnion(ref struct_def, ref ast_generics) => {
                 self.check_type_defn(item, true, |fcx| {
-                    vec![fcx.struct_variant(struct_def)]
+                    vec![fcx.non_enum_variant(struct_def)]
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
@@ -275,74 +280,8 @@
         });
     }
 
-    fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) {
-        // We want to ensure:
-        //
-        // 1) that there are no items contained within
-        // the trait definition
-        //
-        // 2) that the definition doesn't violate the no-super trait rule
-        // for auto traits.
-        //
-        // 3) that the trait definition does not have any type parameters
-
-        let predicates = self.tcx.predicates_of(trait_def_id);
-
-        // We must exclude the Self : Trait predicate contained by all
-        // traits.
-        let has_predicates =
-            predicates.predicates.iter().any(|predicate| {
-                match predicate {
-                    &ty::Predicate::Trait(ref poly_trait_ref) => {
-                        let self_ty = poly_trait_ref.0.self_ty();
-                        !(self_ty.is_self() && poly_trait_ref.def_id() == trait_def_id)
-                    },
-                    _ => true,
-                }
-            });
-
-        let has_ty_params = self.tcx.generics_of(trait_def_id).types.len() > 1;
-
-        // We use an if-else here, since the generics will also trigger
-        // an extraneous error message when we find predicates like
-        // `T : Sized` for a trait like: `trait Magic<T>`.
-        //
-        // We also put the check on the number of items here,
-        // as it seems confusing to report an error about
-        // extraneous predicates created by things like
-        // an associated type inside the trait.
-        let mut err = None;
-        if !self.tcx.associated_item_def_ids(trait_def_id).is_empty() {
-            error_380(self.tcx, span);
-        } else if has_ty_params {
-            err = Some(struct_span_err!(self.tcx.sess, span, E0567,
-                "traits with auto impls (`e.g. impl \
-                    Trait for ..`) can not have type parameters"));
-        } else if has_predicates {
-            err = Some(struct_span_err!(self.tcx.sess, span, E0568,
-                "traits with auto impls (`e.g. impl \
-                    Trait for ..`) cannot have predicates"));
-        }
-
-        // Finally if either of the above conditions apply we should add a note
-        // indicating that this error is the result of a recent soundness fix.
-        match err {
-            None => {},
-            Some(mut e) => {
-                e.note("the new auto trait rules are the result of a \
-                          recent soundness fix; see #29859 for more details");
-                e.emit();
-            }
-        }
-    }
-
     fn check_trait(&mut self, item: &hir::Item) {
         let trait_def_id = self.tcx.hir.local_def_id(item.id);
-
-        if self.tcx.trait_is_auto(trait_def_id) {
-            self.check_auto_trait(trait_def_id, item.span);
-        }
-
         self.for_item(item).with_fcx(|fcx, this| {
             let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
             let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
@@ -689,7 +628,7 @@
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
+    fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
         let fields =
             struct_def.fields().iter()
             .map(|field| {
@@ -704,7 +643,7 @@
 
     fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> {
         enum_def.variants.iter()
-            .map(|variant| self.struct_variant(&variant.node.data))
+            .map(|variant| self.non_enum_variant(&variant.node.data))
             .collect()
     }
 
@@ -727,18 +666,6 @@
     }
 }
 
-fn error_192(tcx: TyCtxt, span: Span) {
-    span_err!(tcx.sess, span, E0192,
-              "negative impls are only allowed for traits with \
-               default impls (e.g., `Send` and `Sync`)")
-}
-
-fn error_380(tcx: TyCtxt, span: Span) {
-    span_err!(tcx.sess, span, E0380,
-              "traits with default impls (`e.g. impl \
-               Trait for ..`) must have no methods or associated items")
-}
-
 fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name)
                        -> DiagnosticBuilder<'tcx> {
     let mut err = struct_span_err!(tcx.sess, span, E0392,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 29dc983..5e102c7 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -18,6 +18,7 @@
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::infer::InferCtxt;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::adjustment::{Adjust, Adjustment};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::util::nodemap::DefIdSet;
 use syntax::ast;
@@ -159,8 +160,52 @@
             _ => {}
         }
     }
+
+    // Similar to operators, indexing is always assumed to be overloaded
+    // Here, correct cases where an indexing expression can be simplified
+    // to use builtin indexing because the index type is known to be
+    // usize-ish
+    fn fix_index_builtin_expr(&mut self, e: &hir::Expr) {
+        if let hir::ExprIndex(ref base, ref index) = e.node {
+            let mut tables = self.fcx.tables.borrow_mut();
+
+            match tables.expr_ty_adjusted(&base).sty {
+                // All valid indexing looks like this
+                ty::TyRef(_, ty::TypeAndMut { ty: ref base_ty, .. }) => {
+                    let index_ty = tables.expr_ty_adjusted(&index);
+                    let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty);
+
+                    if base_ty.builtin_index().is_some()
+                        && index_ty == self.fcx.tcx.types.usize {
+                        // Remove the method call record
+                        tables.type_dependent_defs_mut().remove(e.hir_id);
+                        tables.node_substs_mut().remove(e.hir_id);
+
+                        tables.adjustments_mut().get_mut(base.hir_id).map(|a| {
+                            // Discard the need for a mutable borrow
+                            match a.pop() {
+                                // Extra adjustment made when indexing causes a drop
+                                // of size information - we need to get rid of it
+                                // Since this is "after" the other adjustment to be
+                                // discarded, we do an extra `pop()`
+                                Some(Adjustment { kind: Adjust::Unsize, .. }) => {
+                                    // So the borrow discard actually happens here
+                                    a.pop();
+                                },
+                                _ => {}
+                            }
+                        });
+                    }
+                },
+                // Might encounter non-valid indexes at this point, so there
+                // has to be a fall-through
+                _ => {},
+            }
+        }
+    }
 }
 
+
 ///////////////////////////////////////////////////////////////////////////
 // Impl of Visitor for Resolver
 //
@@ -176,6 +221,7 @@
 
     fn visit_expr(&mut self, e: &'gcx hir::Expr) {
         self.fix_scalar_builtin_expr(e);
+        self.fix_index_builtin_expr(e);
 
         self.visit_node_id(e.span, e.hir_id);
 
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index d63980e..2f1c42b 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -288,7 +288,7 @@
                 // conversion). This will work out because `U:
                 // Unsize<V>`, and we have a builtin rule that `*mut
                 // U` can be coerced to `*mut V` if `U: Unsize<V>`.
-                let fields = &def_a.struct_variant().fields;
+                let fields = &def_a.non_enum_variant().fields;
                 let diff_fields = fields.iter()
                     .enumerate()
                     .filter_map(|(i, f)| {
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 569b6a2..2b81c82 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -93,23 +93,11 @@
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
-        let (unsafety, ty) = match item.node {
-            hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
+        let ty = match item.node {
+            hir::ItemImpl(.., None, ref ty, _) => ty,
             _ => return
         };
 
-        match unsafety {
-            hir::Unsafety::Normal => {
-                // OK
-            }
-            hir::Unsafety::Unsafe => {
-                span_err!(self.tcx.sess,
-                          item.span,
-                          E0197,
-                          "inherent impls cannot be declared as unsafe");
-            }
-        }
-
         let def_id = self.tcx.hir.local_def_id(item.id);
         let self_ty = self.tcx.type_of(def_id);
         let lang_items = self.tcx.lang_items();
@@ -200,7 +188,7 @@
                                           "i128",
                                           item.span);
             }
-            ty::TyInt(ast::IntTy::Is) => {
+            ty::TyInt(ast::IntTy::Isize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.isize_impl(),
                                           "isize",
@@ -242,7 +230,7 @@
                                           "u128",
                                           item.span);
             }
-            ty::TyUint(ast::UintTy::Us) => {
+            ty::TyUint(ast::UintTy::Usize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.usize_impl(),
                                           "usize",
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 90a0952..f65d627 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -15,8 +15,9 @@
 // done by the orphan and overlap modules. Then we build up various
 // mappings. That mapping code resides here.
 
-use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::ty::{TyCtxt, TypeFoldable};
+use hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::traits;
+use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc::ty::maps::Providers;
 
 use syntax::ast;
@@ -25,7 +26,6 @@
 mod inherent_impls;
 mod inherent_impls_overlap;
 mod orphan;
-mod overlap;
 mod unsafety;
 
 fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
@@ -113,28 +113,69 @@
     };
 }
 
-fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            (_, def_id): (CrateNum, DefId)) {
+fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
     let impls = tcx.hir.trait_impls(def_id);
     for &impl_id in impls {
         check_impl(tcx, impl_id);
     }
     for &impl_id in impls {
-        overlap::check_impl(tcx, impl_id);
+        check_impl_overlap(tcx, impl_id);
     }
     builtin::check_trait(tcx, def_id);
 }
 
 pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     for &trait_def_id in tcx.hir.krate().trait_impls.keys() {
-        tcx.coherent_trait((LOCAL_CRATE, trait_def_id));
+        ty::maps::queries::coherent_trait::ensure(tcx, trait_def_id);
     }
 
     unsafety::check(tcx);
     orphan::check(tcx);
-    overlap::check_auto_impls(tcx);
 
     // these queries are executed for side-effects (error reporting):
-    tcx.crate_inherent_impls(LOCAL_CRATE);
-    tcx.crate_inherent_impls_overlap_check(LOCAL_CRATE);
+    ty::maps::queries::crate_inherent_impls::ensure(tcx, LOCAL_CRATE);
+    ty::maps::queries::crate_inherent_impls_overlap_check::ensure(tcx, LOCAL_CRATE);
+}
+
+/// Overlap: No two impls for the same trait are implemented for the
+/// same type. Likewise, no two inherent impls for a given type
+/// constructor provide a method with the same name.
+fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
+    let impl_def_id = tcx.hir.local_def_id(node_id);
+    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+    let trait_def_id = trait_ref.def_id;
+
+    if trait_ref.references_error() {
+        debug!("coherence: skipping impl {:?} with error {:?}",
+               impl_def_id, trait_ref);
+        return
+    }
+
+    // Trigger building the specialization graph for the trait of this impl.
+    // This will detect any overlap errors.
+    tcx.specialization_graph_of(trait_def_id);
+
+    // check for overlap with the automatic `impl Trait for Trait`
+    if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
+        // This is something like impl Trait1 for Trait2. Illegal
+        // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
+
+        if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
+            // This is an error, but it will be reported by wfcheck.  Ignore it here.
+            // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
+        } else {
+            let mut supertrait_def_ids =
+                traits::supertrait_def_ids(tcx,
+                                           data.principal().unwrap().def_id());
+            if supertrait_def_ids.any(|d| d == trait_def_id) {
+                span_err!(tcx.sess,
+                          tcx.span_of_impl(impl_def_id).unwrap(),
+                          E0371,
+                          "the object type `{}` automatically \
+                           implements the trait `{}`",
+                          trait_ref.self_ty(),
+                          tcx.item_path_str(trait_def_id));
+            }
+        }
+    }
 }
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 9f18397..c2dfd79 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -67,16 +67,15 @@
                     }
                 }
 
-                // In addition to the above rules, we restrict impls of defaulted traits
+                // In addition to the above rules, we restrict impls of auto traits
                 // so that they can only be implemented on nominal types, such as structs,
                 // enums or foreign types. To see why this restriction exists, consider the
-                // following example (#22978). Imagine that crate A defines a defaulted trait
+                // following example (#22978). Imagine that crate A defines an auto trait
                 // `Foo` and a fn that operates on pairs of types:
                 //
                 // ```
                 // // Crate A
-                // trait Foo { }
-                // impl Foo for .. { }
+                // auto trait Foo { }
                 // fn two_foos<A:Foo,B:Foo>(..) {
                 //     one_foo::<(A,B)>(..)
                 // }
@@ -142,24 +141,6 @@
                     }
                 }
             }
-            hir::ItemAutoImpl(_, ref item_trait_ref) => {
-                // "Trait" impl
-                debug!("coherence2::orphan check: default trait impl {}",
-                       self.tcx.hir.node_to_string(item.id));
-                let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
-                if !trait_ref.def_id.is_local() {
-                    struct_span_err!(self.tcx.sess,
-                                     item_trait_ref.path.span,
-                                     E0318,
-                                     "cannot create default implementations for traits outside \
-                                      the crate they're defined in; define a new trait instead")
-                        .span_label(item_trait_ref.path.span,
-                                    format!("`{}` trait not defined in this crate",
-                            self.tcx.hir.node_to_pretty_string(item_trait_ref.ref_id)))
-                        .emit();
-                    return;
-                }
-            }
             _ => {
                 // Not an impl
             }
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
deleted file mode 100644
index 5cc6eaa..0000000
--- a/src/librustc_typeck/coherence/overlap.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Overlap: No two impls for the same trait are implemented for the
-//! same type. Likewise, no two inherent impls for a given type
-//! constructor provide a method with the same name.
-
-use rustc::traits;
-use rustc::ty::{self, TyCtxt, TypeFoldable};
-use syntax::ast;
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-
-pub fn check_auto_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut overlap = OverlapChecker { tcx };
-
-    // this secondary walk specifically checks for some other cases,
-    // like defaulted traits, for which additional overlap rules exist
-    tcx.hir.krate().visit_all_item_likes(&mut overlap);
-}
-
-pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
-    let impl_def_id = tcx.hir.local_def_id(node_id);
-    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-    let trait_def_id = trait_ref.def_id;
-
-    if trait_ref.references_error() {
-        debug!("coherence: skipping impl {:?} with error {:?}",
-               impl_def_id, trait_ref);
-        return
-    }
-
-    // Trigger building the specialization graph for the trait of this impl.
-    // This will detect any overlap errors.
-    tcx.specialization_graph_of(trait_def_id);
-
-
-    // check for overlap with the automatic `impl Trait for Trait`
-    if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
-        // This is something like impl Trait1 for Trait2. Illegal
-        // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
-
-        if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
-            // This is an error, but it will be reported by wfcheck.  Ignore it here.
-            // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
-        } else {
-            let mut supertrait_def_ids =
-                traits::supertrait_def_ids(tcx,
-                                           data.principal().unwrap().def_id());
-            if supertrait_def_ids.any(|d| d == trait_def_id) {
-                span_err!(tcx.sess,
-                          tcx.span_of_impl(impl_def_id).unwrap(),
-                          E0371,
-                          "the object type `{}` automatically \
-                           implements the trait `{}`",
-                          trait_ref.self_ty(),
-                          tcx.item_path_str(trait_def_id));
-            }
-        }
-    }
-}
-
-struct OverlapChecker<'cx, 'tcx: 'cx> {
-    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
-}
-
-impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &'v hir::Item) {
-        match item.node {
-            hir::ItemAutoImpl(..) => {
-                // look for another auto impl; note that due to the
-                // general orphan/coherence rules, it must always be
-                // in this crate.
-                let impl_def_id = self.tcx.hir.local_def_id(item.id);
-                let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
-
-                let prev_id = self.tcx.hir.trait_auto_impl(trait_ref.def_id).unwrap();
-                if prev_id != item.id {
-                    let mut err = struct_span_err!(self.tcx.sess,
-                                                   self.tcx.span_of_impl(impl_def_id).unwrap(),
-                                                   E0521,
-                                                   "redundant auto implementations of trait \
-                                                    `{}`:",
-                                                   trait_ref);
-                    err.span_note(self.tcx
-                                      .span_of_impl(self.tcx.hir.local_def_id(prev_id))
-                                      .unwrap(),
-                                  "redundant implementation is here:");
-                    err.emit();
-                }
-            }
-            hir::ItemImpl(.., Some(_), _, _) => {
-            }
-            _ => {}
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-    }
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-    }
-}
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 280fb04..4aa876e 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -37,14 +37,7 @@
                 let trait_def = self.tcx.trait_def(trait_ref.def_id);
                 let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr());
                 match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
-                    (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
-                        span_err!(self.tcx.sess,
-                                  item.span,
-                                  E0198,
-                                  "negative implementations are not unsafe");
-                    }
-
-                    (Unsafety::Normal, None, Unsafety::Unsafe, _) => {
+                    (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
                         span_err!(self.tcx.sess,
                                   item.span,
                                   E0199,
@@ -69,6 +62,10 @@
                                   g.attr_name());
                     }
 
+                    (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
+                        // Reported in AST validation
+                        self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
+                    }
                     (_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
                     (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
                     (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
@@ -84,9 +81,6 @@
 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            hir::ItemAutoImpl(unsafety, _) => {
-                self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
-            }
             hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
                 self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
             }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 0a6d87e..8d428c8 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -73,7 +73,6 @@
         impl_trait_ref,
         impl_polarity,
         is_foreign_item,
-        is_auto_impl,
         ..*providers
     };
 }
@@ -424,9 +423,6 @@
             tcx.predicates_of(def_id);
             convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
         },
-        hir::ItemAutoImpl(..) => {
-            tcx.impl_trait_ref(def_id);
-        }
         hir::ItemImpl(..) => {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
@@ -716,9 +712,9 @@
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let item = tcx.hir.expect_item(node_id);
 
-    let unsafety = match item.node {
-        hir::ItemTrait(_, unsafety, ..) => unsafety,
-        hir::ItemTraitAlias(..) => hir::Unsafety::Normal,
+    let (is_auto, unsafety) = match item.node {
+        hir::ItemTrait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety),
+        hir::ItemTraitAlias(..) => (false, hir::Unsafety::Normal),
         _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
     };
 
@@ -735,10 +731,6 @@
     }
 
     let def_path_hash = tcx.def_path_hash(def_id);
-    let is_auto = match item.node {
-        hir::ItemTrait(hir::IsAuto::Yes, ..) => true,
-        _ => tcx.hir.trait_is_auto(def_id),
-    };
     let def = ty::TraitDef::new(def_id,
                                 unsafety,
                                 paren_sugar,
@@ -1109,7 +1101,6 @@
                     let substs = Substs::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
-                ItemAutoImpl(..) |
                 ItemTrait(..) | ItemTraitAlias(..) |
                 ItemMod(..) |
                 ItemForeignMod(..) |
@@ -1150,8 +1141,8 @@
 
         NodeField(field) => icx.to_ty(&field.ty),
 
-        NodeExpr(&hir::Expr { node: hir::ExprClosure(.., is_generator), .. }) => {
-            if is_generator {
+        NodeExpr(&hir::Expr { node: hir::ExprClosure(.., gen), .. }) => {
+            if gen.is_some() {
                 let hir_id = tcx.hir.node_to_hir_id(node_id);
                 return tcx.typeck_tables_of(def_id).node_id_to_type(hir_id);
             }
@@ -1278,11 +1269,6 @@
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     match tcx.hir.expect_item(node_id).node {
-        hir::ItemAutoImpl(_, ref ast_trait_ref) => {
-            Some(AstConv::instantiate_mono_trait_ref(&icx,
-                                                     ast_trait_ref,
-                                                     tcx.mk_self_type()))
-        }
         hir::ItemImpl(.., ref opt_trait_ref, _, _) => {
             opt_trait_ref.as_ref().map(|ast_trait_ref| {
                 let selfty = tcx.type_of(def_id);
@@ -1728,14 +1714,3 @@
         _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id)
     }
 }
-
-fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             def_id: DefId)
-                             -> bool {
-    match tcx.hir.get_if_local(def_id) {
-        Some(hir_map::NodeItem(&hir::Item { node: hir::ItemAutoImpl(..), .. }))
-             => true,
-        Some(_) => false,
-        _ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
-    }
-}
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 770d0cd..18d573b 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1715,7 +1715,7 @@
 "##,
 
 E0192: r##"
-Negative impls are only allowed for traits with default impls. For more
+Negative impls are only allowed for auto traits. For more
 information see the [opt-in builtin traits RFC][RFC 19].
 
 [RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
@@ -1821,54 +1821,6 @@
 ```
 "##,
 
-E0197: r##"
-Inherent implementations (one that do not implement a trait but provide
-methods associated with a type) are always safe because they are not
-implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
-implementation will resolve this error.
-
-```compile_fail,E0197
-struct Foo;
-
-// this will cause this error
-unsafe impl Foo { }
-// converting it to this will fix it
-impl Foo { }
-```
-"##,
-
-E0198: r##"
-A negative implementation is one that excludes a type from implementing a
-particular trait. Not being able to use a trait is always a safe operation,
-so negative implementations are always safe and never need to be marked as
-unsafe.
-
-```compile_fail
-#![feature(optin_builtin_traits)]
-
-struct Foo;
-
-// unsafe is unnecessary
-unsafe impl !Clone for Foo { }
-```
-
-This will compile:
-
-```ignore (ignore auto_trait future compatibility warning)
-#![feature(optin_builtin_traits)]
-
-struct Foo;
-
-trait Enterprise {}
-
-impl Enterprise for .. { }
-
-impl !Enterprise for Foo { }
-```
-
-Please note that negative impls are only allowed for traits with default impls.
-"##,
-
 E0199: r##"
 Safe traits should not have unsafe implementations, therefore marking an
 implementation for a safe trait unsafe will cause a compiler error. Removing
@@ -2533,13 +2485,6 @@
 ```
 "##,
 
-E0318: r##"
-Default impls for a trait must be located in the same crate where the trait was
-defined. For more information see the [opt-in builtin traits RFC][RFC 19].
-
-[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
-"##,
-
 E0321: r##"
 A cross-crate opt-out trait was implemented on something which wasn't a struct
 or enum type. Erroneous code example:
@@ -3172,13 +3117,6 @@
 struct.
 "##,
 
-E0380: r##"
-Default impls are only allowed for traits with no methods or associated items.
-For more information see the [opt-in builtin traits RFC][RFC 19].
-
-[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
-"##,
-
 E0390: r##"
 You tried to implement methods for a primitive type. Erroneous code example:
 
@@ -4641,6 +4579,125 @@
 ```
 "##,
 
+E0689: r##"
+This error indicates that the numeric value for the method being passed exists
+but the type of the numeric value or binding could not be identified.
+
+The error happens on numeric literals:
+
+```compile_fail,E0689
+2.0.powi(2);
+```
+
+and on numeric bindings without an identified concrete type:
+
+```compile_fail,E0689
+let x = 2.0;
+x.powi(2);  // same error as above
+```
+
+Because of this, you must give the numeric literal or binding a type:
+
+```
+let _ = 2.0_f32.powi(2);
+let x: f32 = 2.0;
+let _ = x.powi(2);
+let _ = (2.0 as f32).powi(2);
+```
+"##,
+
+E0690: r##"
+A struct with the representation hint `repr(transparent)` had zero or more than
+on fields that were not guaranteed to be zero-sized.
+
+Erroneous code example:
+
+```compile_fail,E0690
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct LengthWithUnit<U> { // error: transparent struct needs exactly one
+    value: f32,            //        non-zero-sized field, but has 2
+    unit: U,
+}
+```
+
+Because transparent structs are represented exactly like one of their fields at
+run time, said field must be uniquely determined. If there is no field, or if
+there are multiple fields, it is not clear how the struct should be represented.
+Note that fields of zero-typed types (e.g., `PhantomData`) can also exist
+alongside the field that contains the actual data, they do not count for this
+error. When generic types are involved (as in the above example), an error is
+reported because the type parameter could be non-zero-sized.
+
+To combine `repr(transparent)` with type parameters, `PhantomData` may be
+useful:
+
+```
+#![feature(repr_transparent)]
+
+use std::marker::PhantomData;
+
+#[repr(transparent)]
+struct LengthWithUnit<U> {
+    value: f32,
+    unit: PhantomData<U>,
+}
+```
+"##,
+
+E0691: r##"
+A struct with the `repr(transparent)` representation hint contains a zero-sized
+field that requires non-trivial alignment.
+
+Erroneous code example:
+
+```compile_fail,E0691
+#![feature(repr_transparent, repr_align, attr_literals)]
+
+#[repr(align(32))]
+struct ForceAlign32;
+
+#[repr(transparent)]
+struct Wrapper(f32, ForceAlign32); // error: zero-sized field in transparent
+                                   //        struct has alignment larger than 1
+```
+
+A transparent struct is supposed to be represented exactly like the piece of
+data it contains. Zero-sized fields with different alignment requirements
+potentially conflict with this property. In the example above, `Wrapper` would
+have to be aligned to 32 bytes even though `f32` has a smaller alignment
+requirement.
+
+Consider removing the over-aligned zero-sized field:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Wrapper(f32);
+```
+
+Alternatively, `PhantomData<T>` has alignment 1 for all `T`, so you can use it
+if you need to keep the field for some reason:
+
+```
+#![feature(repr_transparent, repr_align, attr_literals)]
+
+use std::marker::PhantomData;
+
+#[repr(align(32))]
+struct ForceAlign32;
+
+#[repr(transparent)]
+struct Wrapper(f32, PhantomData<ForceAlign32>);
+```
+
+Note that empty arrays `[T; 0]` have the same alignment requirement as the
+element type `T`. Also note that the error is conservatively reported even when
+the alignment of the zero-sized type is less than or equal to the data field's
+alignment.
+"##,
 }
 
 register_diagnostics! {
@@ -4705,13 +4762,10 @@
 //  E0372, // coherence not object safe
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
-    E0521, // redundant auto implementations of trait
     E0533, // `{}` does not name a unit variant, unit struct or a constant
 //  E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
     E0564, // only named lifetimes are allowed in `impl Trait`,
            // but `{}` was found in the type `{}`
-    E0567, // auto traits can not have type parameters
-    E0568, // auto-traits can not have predicates,
     E0587, // struct has conflicting packed and align representation hints
     E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
     E0592, // duplicate definitions with name `{}`
@@ -4722,4 +4776,5 @@
            // argument position.
     E0641, // cannot cast to/from a pointer with an unknown kind
     E0645, // trait aliases not finished
+    E0907, // type inside generator must be known in this context
 }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 129511e..786a678 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -77,6 +77,7 @@
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
 #![feature(conservative_impl_trait)]
+#![feature(copy_closures, clone_closures)]
 #![feature(from_ref)]
 #![feature(match_default_bindings)]
 #![feature(never_type)]
@@ -116,6 +117,7 @@
 use syntax_pos::Span;
 
 use std::iter;
+
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
 mod diagnostics;
@@ -200,10 +202,22 @@
                 }
                 _ => ()
             }
+
+            let actual = tcx.fn_sig(main_def_id);
+            let expected_return_type = if tcx.lang_items().termination().is_some()
+                && tcx.sess.features.borrow().termination_trait {
+                // we take the return type of the given main function, the real check is done
+                // in `check_fn`
+                actual.output().skip_binder()
+            } else {
+                // standard () main return type
+                tcx.mk_nil()
+            };
+
             let se_ty = tcx.mk_fn_ptr(ty::Binder(
                 tcx.mk_fn_sig(
                     iter::empty(),
-                    tcx.mk_nil(),
+                    expected_return_type,
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust
@@ -214,7 +228,7 @@
                 tcx,
                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
                 se_ty,
-                tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
+                tcx.mk_fn_ptr(actual));
         }
         _ => {
             span_bug!(main_span,
@@ -367,4 +381,5 @@
     (principal, projections)
 }
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index df42d5e..0ed9b14 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -377,6 +377,7 @@
                 // types, where we use TyError as the Self type
             }
 
+            ty::TyGeneratorWitness(..) |
             ty::TyInfer(..) => {
                 bug!("unexpected type encountered in \
                       variance inference: {}",
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 1e57496..608adcb 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -12,7 +12,7 @@
 
 [dependencies]
 pulldown-cmark = { version = "0.1.0", default-features = false }
-html-diff = "0.0.5"
+html-diff = "0.0.6"
 tempdir = "0.3"
 
 [build-dependencies]
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 914365b..9aba399 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -82,9 +82,9 @@
             ret.extend(build_impls(cx, did));
             clean::ForeignTypeItem
         }
-        // Never inline enum variants but leave them shown as reexports.
+        // Never inline enum variants but leave them shown as re-exports.
         Def::Variant(..) => return None,
-        // Assume that enum variants and struct types are reexported next to
+        // Assume that enum variants and struct types are re-exported next to
         // their constructors.
         Def::VariantCtor(..) |
         Def::StructCtor(..) => return Some(Vec::new()),
@@ -135,7 +135,11 @@
             None
         }
     });
-    let fqn = once(crate_name).chain(relative).collect();
+    let fqn = if let clean::TypeKind::Macro = kind {
+        vec![crate_name, relative.last().unwrap()]
+    } else {
+        once(crate_name).chain(relative).collect()
+    };
     cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
 }
 
@@ -146,12 +150,14 @@
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
     let is_spotlight = load_attrs(cx, did).has_doc_flag("spotlight");
+    let is_auto = cx.tcx.trait_is_auto(did);
     clean::Trait {
         unsafety: cx.tcx.trait_def(did).unsafety,
         generics,
         items: trait_items,
         bounds: supertrait_bounds,
         is_spotlight,
+        is_auto,
     }
 }
 
@@ -186,7 +192,7 @@
 
 fn build_struct(cx: &DocContext, did: DefId) -> clean::Struct {
     let predicates = cx.tcx.predicates_of(did);
-    let variant = cx.tcx.adt_def(did).struct_variant();
+    let variant = cx.tcx.adt_def(did).non_enum_variant();
 
     clean::Struct {
         struct_type: match variant.ctor_kind {
@@ -202,7 +208,7 @@
 
 fn build_union(cx: &DocContext, did: DefId) -> clean::Union {
     let predicates = cx.tcx.predicates_of(did);
-    let variant = cx.tcx.adt_def(did).struct_variant();
+    let variant = cx.tcx.adt_def(did).non_enum_variant();
 
     clean::Union {
         struct_type: doctree::Plain,
@@ -300,27 +306,6 @@
         }
     }
 
-    // If this is an auto impl, then bail out early here
-    if tcx.is_auto_impl(did) {
-        return ret.push(clean::Item {
-            inner: clean::AutoImplItem(clean::AutoImpl {
-                // FIXME: this should be decoded
-                unsafety: hir::Unsafety::Normal,
-                trait_: match associated_trait.as_ref().unwrap().clean(cx) {
-                    clean::TraitBound(polyt, _) => polyt.trait_,
-                    clean::RegionBound(..) => unreachable!(),
-                },
-            }),
-            source: tcx.def_span(did).clean(cx),
-            name: None,
-            attrs,
-            visibility: Some(clean::Inherited),
-            stability: tcx.lookup_stability(did).clean(cx),
-            deprecation: tcx.lookup_deprecation(did).clean(cx),
-            def_id: did,
-        });
-    }
-
     let for_ = tcx.type_of(did).clean(cx);
 
     // Only inline impl if the implementing type is
@@ -349,6 +334,9 @@
     if trait_.def_id() == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
+    if let Some(trait_did) = trait_.def_id() {
+        record_extern_trait(cx, trait_did);
+    }
 
     let provided = trait_.def_id().map(|did| {
         tcx.provided_trait_methods(did)
@@ -386,7 +374,7 @@
     };
 
     fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
-        // If we're reexporting a reexport it may actually reexport something in
+        // If we're re-exporting a re-export it may actually re-export something in
         // two namespaces, so the target may be listed twice. Make sure we only
         // visit each node at most once.
         let mut visited = FxHashSet();
@@ -504,3 +492,9 @@
     });
     (g, ty_bounds)
 }
+
+pub fn record_extern_trait(cx: &DocContext, did: DefId) {
+    cx.external_traits.borrow_mut().entry(did).or_insert_with(|| {
+        build_external_trait(cx, did)
+    });
+}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index dc157f6..78b24a8 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -20,9 +20,10 @@
 pub use self::Visibility::*;
 
 use syntax::abi::Abi;
-use syntax::ast;
+use syntax::ast::{self, AttrStyle};
 use syntax::attr;
 use syntax::codemap::Spanned;
+use syntax::feature_gate::UnstableFeatures;
 use syntax::ptr::P;
 use syntax::symbol::keywords;
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
@@ -33,7 +34,6 @@
 use rustc::middle::lang_items;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::traits::Reveal;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, AdtKind};
 use rustc::middle::stability;
@@ -54,6 +54,7 @@
 use doctree;
 use visit_ast;
 use html::item_type::ItemType;
+use html::markdown::markdown_links;
 
 pub mod inline;
 pub mod cfg;
@@ -125,7 +126,7 @@
     pub masked_crates: FxHashSet<CrateNum>,
 }
 
-impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
+impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx> {
     fn clean(&self, cx: &DocContext) -> Crate {
         use ::visit_lib::LibEmbargoVisitor;
 
@@ -306,6 +307,11 @@
     pub fn collapsed_doc_value(&self) -> Option<String> {
         self.attrs.collapsed_doc_value()
     }
+
+    pub fn links(&self) -> Vec<(String, String)> {
+        self.attrs.links()
+    }
+
     pub fn is_crate(&self) -> bool {
         match self.inner {
             StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
@@ -431,7 +437,6 @@
     PrimitiveItem(PrimitiveType),
     AssociatedConstItem(Type, Option<String>),
     AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
-    AutoImplItem(AutoImpl),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemEnum>),
 }
@@ -467,6 +472,23 @@
             "".to_string()
         };
 
+        // maintain a stack of mod ids, for doc comment path resolution
+        // but we also need to resolve the module's own docs based on whether its docs were written
+        // inside or outside the module, so check for that
+        let attrs = if self.attrs.iter()
+                                 .filter(|a| a.check_name("doc"))
+                                 .next()
+                                 .map_or(true, |a| a.style == AttrStyle::Inner) {
+            // inner doc comment, use the module's own scope for resolution
+            cx.mod_ids.borrow_mut().push(self.id);
+            self.attrs.clean(cx)
+        } else {
+            // outer doc comment, use its parent's scope
+            let attrs = self.attrs.clean(cx);
+            cx.mod_ids.borrow_mut().push(self.id);
+            attrs
+        };
+
         let mut items: Vec<Item> = vec![];
         items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
         items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
@@ -482,7 +504,8 @@
         items.extend(self.traits.iter().map(|x| x.clean(cx)));
         items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.macros.iter().map(|x| x.clean(cx)));
-        items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
+
+        cx.mod_ids.borrow_mut().pop();
 
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
@@ -501,7 +524,7 @@
 
         Item {
             name: Some(name),
-            attrs: self.attrs.clean(cx),
+            attrs,
             source: whence.clean(cx),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
@@ -636,6 +659,7 @@
     pub other_attrs: Vec<ast::Attribute>,
     pub cfg: Option<Rc<Cfg>>,
     pub span: Option<syntax_pos::Span>,
+    pub links: Vec<(String, DefId)>,
 }
 
 impl Attributes {
@@ -765,11 +789,13 @@
                 Some(attr.clone())
             })
         }).collect();
+
         Attributes {
             doc_strings,
             other_attrs,
             cfg: if cfg == Cfg::True { None } else { Some(Rc::new(cfg)) },
             span: sp,
+            links: vec![],
         }
     }
 
@@ -788,6 +814,20 @@
             None
         }
     }
+
+    /// Get links as a vector
+    ///
+    /// Cache must be populated before call
+    pub fn links(&self) -> Vec<(String, String)> {
+        use html::format::href;
+        self.links.iter().filter_map(|&(ref s, did)| {
+            if let Some((href, ..)) = href(did) {
+                Some((s.clone(), href))
+            } else {
+                None
+            }
+        }).collect()
+    }
 }
 
 impl AttributesExt for Attributes {
@@ -796,9 +836,243 @@
     }
 }
 
+/// Given a def, returns its name and disambiguator
+/// for a value namespace
+///
+/// Returns None for things which cannot be ambiguous since
+/// they exist in both namespaces (structs and modules)
+fn value_ns_kind(def: Def, path_str: &str) -> Option<(&'static str, String)> {
+    match def {
+        // structs and mods exist in both namespaces. skip them
+        Def::StructCtor(..) | Def::Mod(..) => None,
+        Def::Variant(..) | Def::VariantCtor(..)
+            => Some(("variant", format!("{}()", path_str))),
+        Def::Fn(..)
+            => Some(("function", format!("{}()", path_str))),
+        Def::Method(..)
+            => Some(("method", format!("{}()", path_str))),
+        Def::Const(..)
+            => Some(("const", format!("const@{}", path_str))),
+        Def::Static(..)
+            => Some(("static", format!("static@{}", path_str))),
+        _ => Some(("value", format!("value@{}", path_str))),
+    }
+}
+
+/// Given a def, returns its name, the article to be used, and a disambiguator
+/// for the type namespace
+fn type_ns_kind(def: Def, path_str: &str) -> (&'static str, &'static str, String) {
+    let (kind, article) = match def {
+        // we can still have non-tuple structs
+        Def::Struct(..) => ("struct", "a"),
+        Def::Enum(..) => ("enum", "an"),
+        Def::Trait(..) => ("trait", "a"),
+        Def::Union(..) => ("union", "a"),
+        _ => ("type", "a"),
+    };
+    (kind, article, format!("{}@{}", kind, path_str))
+}
+
+fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
+                   path_str: &str,
+                   article1: &str, kind1: &str, disambig1: &str,
+                   article2: &str, kind2: &str, disambig2: &str) {
+    let sp = attrs.doc_strings.first()
+                  .map_or(DUMMY_SP, |a| a.span());
+    cx.sess()
+      .struct_span_err(sp,
+                       &format!("`{}` is both {} {} and {} {}",
+                                path_str, article1, kind1,
+                                article2, kind2))
+      .help(&format!("try `{}` if you want to select the {}, \
+                      or `{}` if you want to \
+                      select the {}",
+                      disambig1, kind1, disambig2,
+                      kind2))
+             .emit();
+}
+
+/// Resolve a given string as a path, along with whether or not it is
+/// in the value namespace
+fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<hir::Path, ()> {
+    // In case we're in a module, try to resolve the relative
+    // path
+    if let Some(id) = cx.mod_ids.borrow().last() {
+        cx.resolver.borrow_mut()
+                   .with_scope(*id, |resolver| {
+                        resolver.resolve_str_path_error(DUMMY_SP,
+                                                        &path_str, is_val)
+                    })
+    } else {
+        // FIXME(Manishearth) this branch doesn't seem to ever be hit, really
+        cx.resolver.borrow_mut()
+                   .resolve_str_path_error(DUMMY_SP, &path_str, is_val)
+    }
+}
+
+/// Resolve a string as a macro
+fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
+    use syntax::ext::base::MacroKind;
+    use syntax::ext::hygiene::Mark;
+    let segment = ast::PathSegment {
+        identifier: ast::Ident::from_str(path_str),
+        span: DUMMY_SP,
+        parameters: None,
+    };
+    let path = ast::Path {
+        span: DUMMY_SP,
+        segments: vec![segment],
+    };
+
+    let mut resolver = cx.resolver.borrow_mut();
+    let mark = Mark::root();
+    let res = resolver
+        .resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false);
+    if let Ok(def) = res {
+        Some(def)
+    } else if let Some(def) = resolver.all_macros.get(&path_str.into()) {
+        Some(*def)
+    } else {
+        None
+    }
+}
+
+enum PathKind {
+    /// can be either value or type, not a macro
+    Unknown,
+    /// macro
+    Macro,
+    /// values, functions, consts, statics, everything in the value namespace
+    Value,
+    /// types, traits, everything in the type namespace
+    Type
+}
+
 impl Clean<Attributes> for [ast::Attribute] {
     fn clean(&self, cx: &DocContext) -> Attributes {
-        Attributes::from_ast(cx.sess().diagnostic(), self)
+        let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self);
+
+        if UnstableFeatures::from_environment().is_nightly_build() {
+            let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
+            for link in markdown_links(&dox, cx.render_type) {
+                let def = {
+                    let mut kind = PathKind::Unknown;
+                    let path_str = if let Some(prefix) =
+                        ["struct@", "enum@", "type@",
+                         "trait@", "union@"].iter()
+                                          .find(|p| link.starts_with(**p)) {
+                        kind = PathKind::Type;
+                        link.trim_left_matches(prefix)
+                    } else if let Some(prefix) =
+                        ["const@", "static@",
+                         "value@", "function@", "mod@", "fn@", "module@"]
+                            .iter().find(|p| link.starts_with(**p)) {
+                        kind = PathKind::Value;
+                        link.trim_left_matches(prefix)
+                    } else if link.ends_with("()") {
+                        kind = PathKind::Value;
+                        link.trim_right_matches("()")
+                    } else if link.starts_with("macro@") {
+                        kind = PathKind::Macro;
+                        link.trim_left_matches("macro@")
+                    } else if link.ends_with('!') {
+                        kind = PathKind::Macro;
+                        link.trim_right_matches('!')
+                    } else {
+                        &link[..]
+                    }.trim();
+
+                    // avoid resolving things (i.e. regular links) which aren't like paths
+                    // FIXME(Manishearth) given that most links have slashes in them might be worth
+                    // doing a check for slashes first
+                    if path_str.contains(|ch: char| !(ch.is_alphanumeric() ||
+                                                      ch == ':' || ch == '_')) {
+                        continue;
+                    }
+
+
+                    match kind {
+                        PathKind::Value => {
+                            if let Ok(path) = resolve(cx, path_str, true) {
+                                path.def
+                            } else {
+                                // this could just be a normal link or a broken link
+                                // we could potentially check if something is
+                                // "intra-doc-link-like" and warn in that case
+                                continue;
+                            }
+                        }
+                        PathKind::Type => {
+                            if let Ok(path) = resolve(cx, path_str, false) {
+                                path.def
+                            } else {
+                                // this could just be a normal link
+                                continue;
+                            }
+                        }
+                        PathKind::Unknown => {
+                            // try everything!
+                            if let Some(macro_def) = macro_resolve(cx, path_str) {
+                                if let Ok(type_path) = resolve(cx, path_str, false) {
+                                    let (type_kind, article, type_disambig)
+                                        = type_ns_kind(type_path.def, path_str);
+                                    ambiguity_error(cx, &attrs, path_str,
+                                                    article, type_kind, &type_disambig,
+                                                    "a", "macro", &format!("macro@{}", path_str));
+                                    continue;
+                                } else if let Ok(value_path) = resolve(cx, path_str, true) {
+                                    let (value_kind, value_disambig)
+                                        = value_ns_kind(value_path.def, path_str)
+                                            .expect("struct and mod cases should have been \
+                                                     caught in previous branch");
+                                    ambiguity_error(cx, &attrs, path_str,
+                                                    "a", value_kind, &value_disambig,
+                                                    "a", "macro", &format!("macro@{}", path_str));
+                                }
+                                macro_def
+                            } else if let Ok(type_path) = resolve(cx, path_str, false) {
+                                // It is imperative we search for not-a-value first
+                                // Otherwise we will find struct ctors for when we are looking
+                                // for structs, and the link won't work.
+                                // if there is something in both namespaces
+                                if let Ok(value_path) = resolve(cx, path_str, true) {
+                                    let kind = value_ns_kind(value_path.def, path_str);
+                                    if let Some((value_kind, value_disambig)) = kind {
+                                        let (type_kind, article, type_disambig)
+                                            = type_ns_kind(type_path.def, path_str);
+                                        ambiguity_error(cx, &attrs, path_str,
+                                                        article, type_kind, &type_disambig,
+                                                        "a", value_kind, &value_disambig);
+                                        continue;
+                                    }
+                                }
+                                type_path.def
+                            } else if let Ok(value_path) = resolve(cx, path_str, true) {
+                                value_path.def
+                            } else {
+                                // this could just be a normal link
+                                continue;
+                            }
+                        }
+                        PathKind::Macro => {
+                            if let Some(def) = macro_resolve(cx, path_str) {
+                                def
+                            } else {
+                                continue
+                            }
+                        }
+                    }
+                };
+
+
+                let id = register_def(cx, def);
+                attrs.links.push((link, id));
+            }
+
+            cx.sess().abort_if_errors();
+        }
+
+        attrs
     }
 }
 
@@ -1526,6 +1800,7 @@
     pub generics: Generics,
     pub bounds: Vec<TyParamBound>,
     pub is_spotlight: bool,
+    pub is_auto: bool,
 }
 
 impl Clean<Item> for doctree::Trait {
@@ -1546,11 +1821,21 @@
                 generics: self.generics.clean(cx),
                 bounds: self.bounds.clean(cx),
                 is_spotlight: is_spotlight,
+                is_auto: self.is_auto.clean(cx),
             }),
         }
     }
 }
 
+impl Clean<bool> for hir::IsAuto {
+    fn clean(&self, _: &DocContext) -> bool {
+        match *self {
+            hir::IsAuto::Yes => true,
+            hir::IsAuto::No => false,
+        }
+    }
+}
+
 impl Clean<Type> for hir::TraitRef {
     fn clean(&self, cx: &DocContext) -> Type {
         resolve_type(cx, self.path.clean(cx), self.ref_id)
@@ -1856,6 +2141,7 @@
     Variant,
     Typedef,
     Foreign,
+    Macro,
 }
 
 pub trait GetDefId {
@@ -2012,7 +2298,7 @@
 impl From<ast::IntTy> for PrimitiveType {
     fn from(int_ty: ast::IntTy) -> PrimitiveType {
         match int_ty {
-            ast::IntTy::Is => PrimitiveType::Isize,
+            ast::IntTy::Isize => PrimitiveType::Isize,
             ast::IntTy::I8 => PrimitiveType::I8,
             ast::IntTy::I16 => PrimitiveType::I16,
             ast::IntTy::I32 => PrimitiveType::I32,
@@ -2025,7 +2311,7 @@
 impl From<ast::UintTy> for PrimitiveType {
     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
         match uint_ty {
-            ast::UintTy::Us => PrimitiveType::Usize,
+            ast::UintTy::Usize => PrimitiveType::Usize,
             ast::UintTy::U8 => PrimitiveType::U8,
             ast::UintTy::U16 => PrimitiveType::U16,
             ast::UintTy::U32 => PrimitiveType::U32,
@@ -2062,7 +2348,7 @@
             TySlice(ref ty) => Slice(box ty.clean(cx)),
             TyArray(ref ty, n) => {
                 let def_id = cx.tcx.hir.body_owner_def_id(n);
-                let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
+                let param_env = cx.tcx.param_env(def_id);
                 let substs = Substs::identity_for_item(cx.tcx, def_id);
                 let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap();
                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
@@ -2191,6 +2477,11 @@
             ty::TyStr => Primitive(PrimitiveType::Str),
             ty::TySlice(ty) => Slice(box ty.clean(cx)),
             ty::TyArray(ty, n) => {
+                let mut n = cx.tcx.lift(&n).unwrap();
+                if let ConstVal::Unevaluated(def_id, substs) = n.val {
+                    let param_env = cx.tcx.param_env(def_id);
+                    n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap()
+                };
                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
                     n.to_string()
                 } else if let ConstVal::Unevaluated(def_id, _) = n.val {
@@ -2312,6 +2603,7 @@
 
             ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton)
 
+            ty::TyGeneratorWitness(..) => panic!("TyGeneratorWitness"),
             ty::TyInfer(..) => panic!("TyInfer"),
             ty::TyError => panic!("TyError"),
         }
@@ -2937,30 +3229,6 @@
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct AutoImpl {
-    pub unsafety: hir::Unsafety,
-    pub trait_: Type,
-}
-
-impl Clean<Item> for doctree::AutoImpl {
-    fn clean(&self, cx: &DocContext) -> Item {
-        Item {
-            name: None,
-            attrs: self.attrs.clean(cx),
-            source: self.whence.clean(cx),
-            def_id: cx.tcx.hir.local_def_id(self.id),
-            visibility: Some(Public),
-            stability: None,
-            deprecation: None,
-            inner: AutoImplItem(AutoImpl {
-                unsafety: self.unsafety,
-                trait_: self.trait_.clean(cx),
-            }),
-        }
-    }
-}
-
 impl Clean<Item> for doctree::ExternCrate {
     fn clean(&self, cx: &DocContext) -> Item {
         Item {
@@ -3176,6 +3444,7 @@
         Def::TyForeign(i) => (i, TypeKind::Foreign),
         Def::Static(i, _) => (i, TypeKind::Static),
         Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
+        Def::Macro(i, _) => (i, TypeKind::Macro),
         Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
         Def::SelfTy(_, Some(impl_def_id)) => {
             return impl_def_id
@@ -3185,8 +3454,7 @@
     if did.is_local() { return did }
     inline::record_extern_fqn(cx, did, kind);
     if let TypeKind::Trait = kind {
-        let t = inline::build_external_trait(cx, did);
-        cx.external_traits.borrow_mut().insert(did, t);
+        inline::record_extern_trait(cx, did);
     }
     did
 }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b353c0d..5fe4794 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -19,10 +19,11 @@
 use rustc::lint;
 use rustc::util::nodemap::FxHashMap;
 use rustc_trans;
-use rustc_trans::back::link;
 use rustc_resolve as resolve;
+use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::CStore;
 
+use syntax::ast::NodeId;
 use syntax::codemap;
 use syntax::feature_gate::UnstableFeatures;
 use errors;
@@ -36,6 +37,7 @@
 use visit_ast::RustdocVisitor;
 use clean;
 use clean::Clean;
+use html::markdown::RenderType;
 use html::render::RenderInfo;
 
 pub use rustc::session::config::Input;
@@ -43,8 +45,11 @@
 
 pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
 
-pub struct DocContext<'a, 'tcx: 'a> {
+pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
+    /// The stack of module NodeIds up till this point
+    pub mod_ids: RefCell<Vec<NodeId>>,
     pub populated_all_crate_impls: Cell<bool>,
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
@@ -55,6 +60,8 @@
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
     pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
+    /// Which markdown renderer to use when extracting links.
+    pub render_type: RenderType,
 
     // The current set of type and lifetime substitutions,
     // for expanding type aliases at the HIR level:
@@ -65,7 +72,7 @@
     pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
 }
 
-impl<'a, 'tcx> DocContext<'a, 'tcx> {
+impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
     pub fn sess(&self) -> &session::Session {
         &self.tcx.sess
     }
@@ -105,7 +112,8 @@
                 triple: Option<String>,
                 maybe_sysroot: Option<PathBuf>,
                 allow_warnings: bool,
-                force_unstable_if_unmarked: bool) -> (clean::Crate, RenderInfo)
+                force_unstable_if_unmarked: bool,
+                render_type: RenderType) -> (clean::Crate, RenderInfo)
 {
     // Parse, resolve, and typecheck the given crate.
 
@@ -140,33 +148,57 @@
                                                                false,
                                                                Some(codemap.clone()));
 
-    let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, cpath, diagnostic_handler, codemap,
     );
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
-    target_features::add_configuration(&mut cfg, &sess);
+    target_features::add_configuration(&mut cfg, &sess, &*trans);
     sess.parse_sess.config = cfg;
 
     let control = &driver::CompileController::basic();
 
     let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));
 
-    let name = link::find_crate_name(Some(&sess), &krate.attrs, &input);
+    let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input);
 
-    let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = {
-        let result = driver::phase_2_configure_and_expand(&sess,
-                                                          &cstore,
-                                                          krate,
-                                                          None,
-                                                          &name,
-                                                          None,
-                                                          resolve::MakeGlobMap::No,
-                                                          |_| Ok(()));
-        abort_on_err(result, &sess)
+    let mut crate_loader = CrateLoader::new(&sess, &cstore, &name);
+
+    let resolver_arenas = resolve::Resolver::arenas();
+    let result = driver::phase_2_configure_and_expand_inner(&sess,
+                                                      &cstore,
+                                                      krate,
+                                                      None,
+                                                      &name,
+                                                      None,
+                                                      resolve::MakeGlobMap::No,
+                                                      &resolver_arenas,
+                                                      &mut crate_loader,
+                                                      |_| Ok(()));
+    let driver::InnerExpansionResult {
+        mut hir_forest,
+        resolver,
+        ..
+    } = abort_on_err(result, &sess);
+
+    // We need to hold on to the complete resolver, so we clone everything
+    // for the analysis passes to use. Suboptimal, but necessary in the
+    // current architecture.
+    let defs = resolver.definitions.clone();
+    let resolutions = ty::Resolutions {
+        freevars: resolver.freevars.clone(),
+        export_map: resolver.export_map.clone(),
+        trait_map: resolver.trait_map.clone(),
+        maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
+        maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
+    };
+    let analysis = ty::CrateAnalysis {
+        access_levels: Rc::new(AccessLevels::default()),
+        name: name.to_string(),
+        glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None },
     };
 
     let arenas = AllArenas::new();
@@ -177,7 +209,10 @@
                                                           &[],
                                                           &sess);
 
-    abort_on_err(driver::phase_3_run_analysis_passes(control,
+    let resolver = RefCell::new(resolver);
+
+    abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
+                                                     control,
                                                      &sess,
                                                      &*cstore,
                                                      hir_map,
@@ -203,12 +238,15 @@
 
         let ctxt = DocContext {
             tcx,
+            resolver: &resolver,
             populated_all_crate_impls: Cell::new(false),
             access_levels: RefCell::new(access_levels),
             external_traits: Default::default(),
             renderinfo: Default::default(),
+            render_type,
             ty_substs: Default::default(),
             lt_substs: Default::default(),
+            mod_ids: Default::default(),
         };
         debug!("crate: {:?}", tcx.hir.krate());
 
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index c21bfd8..430236f 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -44,7 +44,6 @@
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub impls: Vec<Impl>,
-    pub def_traits: Vec<AutoImpl>,
     pub foreigns: Vec<hir::ForeignMod>,
     pub macros: Vec<Macro>,
     pub is_crate: bool,
@@ -73,7 +72,6 @@
             constants  : Vec::new(),
             traits     : Vec::new(),
             impls      : Vec::new(),
-            def_traits : Vec::new(),
             foreigns   : Vec::new(),
             macros     : Vec::new(),
             is_crate   : false,
@@ -198,6 +196,7 @@
 }
 
 pub struct Trait {
+    pub is_auto: hir::IsAuto,
     pub unsafety: hir::Unsafety,
     pub name: Name,
     pub items: hir::HirVec<hir::TraitItem>,
@@ -227,14 +226,6 @@
     pub id: ast::NodeId,
 }
 
-pub struct AutoImpl {
-    pub unsafety: hir::Unsafety,
-    pub trait_: hir::TraitRef,
-    pub id: ast::NodeId,
-    pub attrs: hir::HirVec<ast::Attribute>,
-    pub whence: Span,
-}
-
 // For Macro we store the DefId instead of the NodeId, since we also create
 // these imported macro_rules (which only have a DUMMY_NODE_ID).
 pub struct Macro {
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index 2f7bd5e..0325054 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fs::File;
-use std::io::prelude::*;
+use std::fs;
 use std::path::Path;
 use std::str;
 use html::markdown::{Markdown, RenderType};
 
 #[derive(Clone)]
-pub struct ExternalHtml{
+pub struct ExternalHtml {
     /// Content that will be included inline in the <head> section of a
     /// rendered Markdown file or generated documentation
     pub in_header: String,
@@ -38,7 +37,7 @@
             )
             .and_then(|(ih, bc)|
                 load_external_files(md_before_content)
-                    .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, render))))
+                    .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[], render))))
             )
             .and_then(|(ih, bc)|
                 load_external_files(after_content)
@@ -46,7 +45,7 @@
             )
             .and_then(|(ih, bc, ac)|
                 load_external_files(md_after_content)
-                    .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, render))))
+                    .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[], render))))
             )
             .map(|(ih, bc, ac)|
                 ExternalHtml {
@@ -65,13 +64,13 @@
 
 pub fn load_string<P: AsRef<Path>>(file_path: P) -> Result<String, LoadStringError> {
     let file_path = file_path.as_ref();
-    let mut contents = vec![];
-    let result = File::open(file_path)
-                      .and_then(|mut f| f.read_to_end(&mut contents));
-    if let Err(e) = result {
-        eprintln!("error reading `{}`: {}", file_path.display(), e);
-        return Err(LoadStringError::ReadFail);
-    }
+    let contents = match fs::read(file_path) {
+        Ok(bytes) => bytes,
+        Err(e) => {
+            eprintln!("error reading `{}`: {}", file_path.display(), e);
+            return Err(LoadStringError::ReadFail);
+        }
+    };
     match str::from_utf8(&contents) {
         Ok(s) => Ok(s.to_string()),
         Err(_) => {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 7300721..92b3a40 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -435,32 +435,10 @@
 fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
                  print_all: bool, use_absolute: bool) -> fmt::Result {
     let last = path.segments.last().unwrap();
-    let rel_root = match &*path.segments[0].name {
-        "self" => Some("./".to_string()),
-        _ => None,
-    };
 
     if print_all {
-        let amt = path.segments.len() - 1;
-        match rel_root {
-            Some(mut root) => {
-                for seg in &path.segments[..amt] {
-                    if "super" == seg.name || "self" == seg.name || w.alternate() {
-                        write!(w, "{}::", seg.name)?;
-                    } else {
-                        root.push_str(&seg.name);
-                        root.push_str("/");
-                        write!(w, "<a class=\"mod\" href=\"{}index.html\">{}</a>::",
-                               root,
-                               seg.name)?;
-                    }
-                }
-            }
-            None => {
-                for seg in &path.segments[..amt] {
-                    write!(w, "{}::", seg.name)?;
-                }
-            }
+        for seg in &path.segments[..path.segments.len() - 1] {
+            write!(w, "{}::", seg.name)?;
         }
     }
     if w.alternate() {
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index c214c15..e9c6488 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -82,7 +82,6 @@
             clean::PrimitiveItem(..)       => ItemType::Primitive,
             clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
             clean::AssociatedTypeItem(..)  => ItemType::AssociatedType,
-            clean::AutoImplItem(..)        => ItemType::Impl,
             clean::ForeignTypeItem         => ItemType::ForeignType,
             clean::StrippedItem(..)        => unreachable!(),
         }
@@ -103,6 +102,7 @@
             clean::TypeKind::Variant  => ItemType::Variant,
             clean::TypeKind::Typedef  => ItemType::Typedef,
             clean::TypeKind::Foreign  => ItemType::ForeignType,
+            clean::TypeKind::Macro  => ItemType::Macro,
         }
     }
 }
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 61de5f4..8395b06 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -10,6 +10,7 @@
 
 use std::fmt;
 use std::io;
+use std::path::PathBuf;
 
 use externalfiles::ExternalHtml;
 
@@ -31,7 +32,7 @@
 
 pub fn render<T: fmt::Display, S: fmt::Display>(
     dst: &mut io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T,
-    css_file_extension: bool)
+    css_file_extension: bool, themes: &[PathBuf])
     -> io::Result<()>
 {
     write!(dst,
@@ -47,8 +48,11 @@
     <title>{title}</title>
 
     <link rel="stylesheet" type="text/css" href="{root_path}normalize.css">
-    <link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css">
-    <link rel="stylesheet" type="text/css" href="{root_path}main.css">
+    <link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css" id="mainThemeStyle">
+    {themes}
+    <link rel="stylesheet" type="text/css" href="{root_path}dark.css">
+    <link rel="stylesheet" type="text/css" href="{root_path}main.css" id="themeStyle">
+    <script src="{root_path}storage.js"></script>
     {css_extension}
 
     {favicon}
@@ -70,6 +74,11 @@
         {sidebar}
     </nav>
 
+    <button id="theme-picker">
+        <img src="{root_path}brush.svg" width="18" alt="Pick another theme!">
+        <div id="theme-choices"></div>
+    </button>
+    <script src="{root_path}theme.js"></script>
     <nav class="sub">
         <form class="search-form js-only">
             <div class="search-container">
@@ -94,20 +103,22 @@
                 <h2>Keyboard Shortcuts</h2>
 
                 <dl>
-                    <dt>?</dt>
+                    <dt><kbd>?</kbd></dt>
                     <dd>Show this help dialog</dd>
-                    <dt>S</dt>
+                    <dt><kbd>S</kbd></dt>
                     <dd>Focus the search field</dd>
-                    <dt>↑</dt>
+                    <dt><kbd>↑</kbd></dt>
                     <dd>Move up in search results</dd>
-                    <dt>↓</dt>
+                    <dt><kbd>↓</kbd></dt>
                     <dd>Move down in search results</dd>
-                    <dt>↹</dt>
+                    <dt><kbd>↹</kbd></dt>
                     <dd>Switch tab</dd>
-                    <dt>&#9166;</dt>
+                    <dt><kbd>&#9166;</kbd></dt>
                     <dd>Go to active search result</dd>
-                    <dt style="width:31px;">+ / -</dt>
-                    <dd>Collapse/expand all sections</dd>
+                    <dt><kbd>+</kbd></dt>
+                    <dd>Expand all sections</dd>
+                    <dt><kbd>-</kbd></dt>
+                    <dd>Collapse all sections</dd>
                 </dl>
             </div>
 
@@ -174,6 +185,12 @@
     after_content = layout.external_html.after_content,
     sidebar   = *sidebar,
     krate     = layout.krate,
+    themes = themes.iter()
+                   .filter_map(|t| t.file_stem())
+                   .filter_map(|t| t.to_str())
+                   .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}">"#,
+                                    page.root_path, t))
+                   .collect::<String>(),
     )
 }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index f7a67b1..dce0c4b 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -56,15 +56,16 @@
 /// A unit struct which has the `fmt::Display` trait implemented. When
 /// formatted, this struct will emit the HTML corresponding to the rendered
 /// version of the contained markdown string.
-// The second parameter is whether we need a shorter version or not.
-pub struct Markdown<'a>(pub &'a str, pub RenderType);
+/// The second parameter is a list of link replacements
+// The third parameter is whether we need a shorter version or not.
+pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)], pub RenderType);
 /// A unit struct like `Markdown`, that renders the markdown with a
 /// table of contents.
 pub struct MarkdownWithToc<'a>(pub &'a str, pub RenderType);
 /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
 pub struct MarkdownHtml<'a>(pub &'a str, pub RenderType);
 /// A unit struct like `Markdown`, that renders only the first paragraph.
-pub struct MarkdownSummaryLine<'a>(pub &'a str);
+pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
 
 /// Controls whether a line will be hidden or shown in HTML output.
 ///
@@ -196,7 +197,7 @@
                     .map(|l| map_line(l).for_code())
                     .collect::<Vec<&str>>().join("\n");
                 let krate = krate.as_ref().map(|s| &**s);
-                let test = test::make_test(&test, krate, false,
+                let (test, _) = test::make_test(&test, krate, false,
                                            &Default::default());
                 let channel = if test.contains("#![feature(") {
                     "&amp;version=nightly"
@@ -248,6 +249,39 @@
 }
 
 /// Make headings links with anchor ids and build up TOC.
+struct LinkReplacer<'a, 'b, I: Iterator<Item = Event<'a>>> {
+    inner: I,
+    links: &'b [(String, String)]
+}
+
+impl<'a, 'b, I: Iterator<Item = Event<'a>>> LinkReplacer<'a, 'b, I> {
+    fn new(iter: I, links: &'b [(String, String)]) -> Self {
+        LinkReplacer {
+            inner: iter,
+            links
+        }
+    }
+}
+
+impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, 'b, I> {
+    type Item = Event<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let event = self.inner.next();
+        if let Some(Event::Start(Tag::Link(dest, text))) = event {
+            if let Some(&(_, ref replace)) = self.links.into_iter().find(|link| &*link.0 == &*dest)
+            {
+                Some(Event::Start(Tag::Link(replace.to_owned().into(), text)))
+            } else {
+                Some(Event::Start(Tag::Link(dest, text)))
+            }
+        } else {
+            event
+        }
+    }
+}
+
+/// Make headings links with anchor ids and build up TOC.
 struct HeadingLinks<'a, 'b, I: Iterator<Item = Event<'a>>> {
     inner: I,
     toc: Option<&'b mut TocBuilder>,
@@ -527,6 +561,8 @@
                            *const hoedown_buffer, *const hoedown_renderer_data,
                            libc::size_t),
     toc_builder: Option<TocBuilder>,
+    links_out: Option<Vec<String>>,
+    links_replace: Vec<(String, String)>,
 }
 
 extern {
@@ -555,186 +591,293 @@
     }
 }
 
-pub fn render(w: &mut fmt::Formatter,
-              s: &str,
-              print_toc: bool,
-              html_flags: libc::c_uint) -> fmt::Result {
-    extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
-                    lang: *const hoedown_buffer, data: *const hoedown_renderer_data,
-                    line: libc::size_t) {
-        unsafe {
-            if orig_text.is_null() { return }
+extern fn hoedown_block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
+                        lang: *const hoedown_buffer, data: *const hoedown_renderer_data,
+                        line: libc::size_t) {
+    unsafe {
+        if orig_text.is_null() { return }
 
-            let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
-            let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque);
-            let text = (*orig_text).as_bytes();
-            let origtext = str::from_utf8(text).unwrap();
-            let origtext = origtext.trim_left();
-            debug!("docblock: ==============\n{:?}\n=======", text);
-            let mut compile_fail = false;
-            let mut ignore = false;
+        let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
+        let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque);
+        let text = (*orig_text).as_bytes();
+        let origtext = str::from_utf8(text).unwrap();
+        let origtext = origtext.trim_left();
+        debug!("docblock: ==============\n{:?}\n=======", text);
+        let mut compile_fail = false;
+        let mut ignore = false;
 
-            let rendered = if lang.is_null() || origtext.is_empty() {
-                false
-            } else {
-                let rlang = (*lang).as_bytes();
-                let rlang = str::from_utf8(rlang).unwrap();
-                let parse_result = LangString::parse(rlang);
-                compile_fail = parse_result.compile_fail;
-                ignore = parse_result.ignore;
-                if !parse_result.rust {
-                    (my_opaque.dfltblk)(ob, orig_text, lang,
-                                        opaque as *const hoedown_renderer_data,
-                                        line);
-                    true
-                } else {
-                    false
-                }
-            };
-
-            let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
-            let text = lines.collect::<Vec<&str>>().join("\n");
-            if rendered { return }
-            PLAYGROUND.with(|play| {
-                // insert newline to clearly separate it from the
-                // previous block so we can shorten the html output
-                let mut s = String::from("\n");
-                let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| {
-                    if url.is_empty() {
-                        return None;
-                    }
-                    let test = origtext.lines()
-                        .map(|l| map_line(l).for_code())
-                        .collect::<Vec<&str>>().join("\n");
-                    let krate = krate.as_ref().map(|s| &**s);
-                    let test = test::make_test(&test, krate, false,
-                                               &Default::default());
-                    let channel = if test.contains("#![feature(") {
-                        "&amp;version=nightly"
-                    } else {
-                        ""
-                    };
-                    // These characters don't need to be escaped in a URI.
-                    // FIXME: use a library function for percent encoding.
-                    fn dont_escape(c: u8) -> bool {
-                        (b'a' <= c && c <= b'z') ||
-                        (b'A' <= c && c <= b'Z') ||
-                        (b'0' <= c && c <= b'9') ||
-                        c == b'-' || c == b'_' || c == b'.' ||
-                        c == b'~' || c == b'!' || c == b'\'' ||
-                        c == b'(' || c == b')' || c == b'*'
-                    }
-                    let mut test_escaped = String::new();
-                    for b in test.bytes() {
-                        if dont_escape(b) {
-                            test_escaped.push(char::from(b));
-                        } else {
-                            write!(test_escaped, "%{:02X}", b).unwrap();
-                        }
-                    }
-                    Some(format!(
-                        r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
-                        url, test_escaped, channel
-                    ))
-                });
-                let tooltip = if ignore {
-                    Some(("This example is not tested", "ignore"))
-                } else if compile_fail {
-                    Some(("This example deliberately fails to compile", "compile_fail"))
-                } else {
-                    None
-                };
-                s.push_str(&highlight::render_with_highlighting(
-                               &text,
-                               Some(&format!("rust-example-rendered{}",
-                                             if ignore { " ignore" }
-                                             else if compile_fail { " compile_fail" }
-                                             else { "" })),
-                               None,
-                               playground_button.as_ref().map(String::as_str),
-                               tooltip));
-                hoedown_buffer_put(ob, s.as_ptr(), s.len());
-            })
-        }
-    }
-
-    extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
-                     level: libc::c_int, data: *const hoedown_renderer_data,
-                     _: libc::size_t) {
-        // hoedown does this, we may as well too
-        unsafe { hoedown_buffer_put(ob, "\n".as_ptr(), 1); }
-
-        // Extract the text provided
-        let s = if text.is_null() {
-            "".to_owned()
+        let rendered = if lang.is_null() || origtext.is_empty() {
+            false
         } else {
-            let s = unsafe { (*text).as_bytes() };
-            str::from_utf8(&s).unwrap().to_owned()
+            let rlang = (*lang).as_bytes();
+            let rlang = str::from_utf8(rlang).unwrap();
+            let parse_result = LangString::parse(rlang);
+            compile_fail = parse_result.compile_fail;
+            ignore = parse_result.ignore;
+            if !parse_result.rust {
+                (my_opaque.dfltblk)(ob, orig_text, lang,
+                                    opaque as *const hoedown_renderer_data,
+                                    line);
+                true
+            } else {
+                false
+            }
         };
 
-        // Discard '<em>', '<code>' tags and some escaped characters,
-        // transform the contents of the header into a hyphenated string
-        // without non-alphanumeric characters other than '-' and '_'.
-        //
-        // This is a terrible hack working around how hoedown gives us rendered
-        // html for text rather than the raw text.
-        let mut id = s.clone();
-        let repl_sub = vec!["<em>", "</em>", "<code>", "</code>",
-                            "<strong>", "</strong>",
-                            "&lt;", "&gt;", "&amp;", "&#39;", "&quot;"];
-        for sub in repl_sub {
-            id = id.replace(sub, "");
-        }
-        let id = id.chars().filter_map(|c| {
-            if c.is_alphanumeric() || c == '-' || c == '_' {
-                if c.is_ascii() {
-                    Some(c.to_ascii_lowercase())
-                } else {
-                    Some(c)
+        let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
+        let text = lines.collect::<Vec<&str>>().join("\n");
+        if rendered { return }
+        PLAYGROUND.with(|play| {
+            // insert newline to clearly separate it from the
+            // previous block so we can shorten the html output
+            let mut s = String::from("\n");
+            let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| {
+                if url.is_empty() {
+                    return None;
                 }
-            } else if c.is_whitespace() && c.is_ascii() {
-                Some('-')
+                let test = origtext.lines()
+                    .map(|l| map_line(l).for_code())
+                    .collect::<Vec<&str>>().join("\n");
+                let krate = krate.as_ref().map(|s| &**s);
+                let (test, _) = test::make_test(&test, krate, false,
+                                                &Default::default());
+                let channel = if test.contains("#![feature(") {
+                    "&amp;version=nightly"
+                } else {
+                    ""
+                };
+                // These characters don't need to be escaped in a URI.
+                // FIXME: use a library function for percent encoding.
+                fn dont_escape(c: u8) -> bool {
+                    (b'a' <= c && c <= b'z') ||
+                    (b'A' <= c && c <= b'Z') ||
+                    (b'0' <= c && c <= b'9') ||
+                    c == b'-' || c == b'_' || c == b'.' ||
+                    c == b'~' || c == b'!' || c == b'\'' ||
+                    c == b'(' || c == b')' || c == b'*'
+                }
+                let mut test_escaped = String::new();
+                for b in test.bytes() {
+                    if dont_escape(b) {
+                        test_escaped.push(char::from(b));
+                    } else {
+                        write!(test_escaped, "%{:02X}", b).unwrap();
+                    }
+                }
+                Some(format!(
+                    r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
+                    url, test_escaped, channel
+                ))
+            });
+            let tooltip = if ignore {
+                Some(("This example is not tested", "ignore"))
+            } else if compile_fail {
+                Some(("This example deliberately fails to compile", "compile_fail"))
             } else {
                 None
+            };
+            s.push_str(&highlight::render_with_highlighting(
+                           &text,
+                           Some(&format!("rust-example-rendered{}",
+                                         if ignore { " ignore" }
+                                         else if compile_fail { " compile_fail" }
+                                         else { "" })),
+                           None,
+                           playground_button.as_ref().map(String::as_str),
+                           tooltip));
+            hoedown_buffer_put(ob, s.as_ptr(), s.len());
+        })
+    }
+}
+
+extern fn hoedown_header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
+                         level: libc::c_int, data: *const hoedown_renderer_data,
+                         _: libc::size_t) {
+    // hoedown does this, we may as well too
+    unsafe { hoedown_buffer_put(ob, "\n".as_ptr(), 1); }
+
+    // Extract the text provided
+    let s = if text.is_null() {
+        "".to_owned()
+    } else {
+        let s = unsafe { (*text).as_bytes() };
+        str::from_utf8(&s).unwrap().to_owned()
+    };
+
+    // Discard '<em>', '<code>' tags and some escaped characters,
+    // transform the contents of the header into a hyphenated string
+    // without non-alphanumeric characters other than '-' and '_'.
+    //
+    // This is a terrible hack working around how hoedown gives us rendered
+    // html for text rather than the raw text.
+    let mut id = s.clone();
+    let repl_sub = vec!["<em>", "</em>", "<code>", "</code>",
+                        "<strong>", "</strong>",
+                        "&lt;", "&gt;", "&amp;", "&#39;", "&quot;"];
+    for sub in repl_sub {
+        id = id.replace(sub, "");
+    }
+    let id = id.chars().filter_map(|c| {
+        if c.is_alphanumeric() || c == '-' || c == '_' {
+            if c.is_ascii() {
+                Some(c.to_ascii_lowercase())
+            } else {
+                Some(c)
             }
-        }).collect::<String>();
+        } else if c.is_whitespace() && c.is_ascii() {
+            Some('-')
+        } else {
+            None
+        }
+    }).collect::<String>();
+
+    let opaque = unsafe { (*data).opaque as *mut hoedown_html_renderer_state };
+    let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
+
+    let id = derive_id(id);
+
+    let sec = opaque.toc_builder.as_mut().map_or("".to_owned(), |builder| {
+        format!("{} ", builder.push(level as u32, s.clone(), id.clone()))
+    });
+
+    // Render the HTML
+    let text = format!("<h{lvl} id='{id}' class='section-header'>\
+                       <a href='#{id}'>{sec}{}</a></h{lvl}>",
+                       s, lvl = level, id = id, sec = sec);
+
+    unsafe { hoedown_buffer_put(ob, text.as_ptr(), text.len()); }
+}
+
+extern fn hoedown_codespan(
+    ob: *mut hoedown_buffer,
+    text: *const hoedown_buffer,
+    _: *const hoedown_renderer_data,
+    _: libc::size_t
+) -> libc::c_int {
+    let content = if text.is_null() {
+        "".to_owned()
+    } else {
+        let bytes = unsafe { (*text).as_bytes() };
+        let s = str::from_utf8(bytes).unwrap();
+        collapse_whitespace(s)
+    };
+
+    let content = format!("<code>{}</code>", Escape(&content));
+    unsafe {
+        hoedown_buffer_put(ob, content.as_ptr(), content.len());
+    }
+    // Return anything except 0, which would mean "also print the code span verbatim".
+    1
+}
+
+pub fn render(w: &mut fmt::Formatter,
+              s: &str,
+              links: &[(String, String)],
+              print_toc: bool,
+              html_flags: libc::c_uint) -> fmt::Result {
+    // copied from pulldown-cmark (MIT license, Google)
+    // https://github.com/google/pulldown-cmark
+    // this is temporary till we remove the hoedown renderer
+    static HREF_SAFE: [u8; 128] = [
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
+            0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+        ];
+
+    static HEX_CHARS: &'static [u8] = b"0123456789ABCDEF";
+
+    fn escape_href(ob: &mut String, s: &str) {
+        let mut mark = 0;
+        for i in 0..s.len() {
+            let c = s.as_bytes()[i];
+            if c >= 0x80 || HREF_SAFE[c as usize] == 0 {
+                // character needing escape
+
+                // write partial substring up to mark
+                if mark < i {
+                    ob.push_str(&s[mark..i]);
+                }
+                match c {
+                    b'&' => {
+                        ob.push_str("&amp;");
+                    },
+                    b'\'' => {
+                        ob.push_str("&#x27;");
+                    },
+                    _ => {
+                        let mut buf = [0u8; 3];
+                        buf[0] = b'%';
+                        buf[1] = HEX_CHARS[((c as usize) >> 4) & 0xF];
+                        buf[2] = HEX_CHARS[(c as usize) & 0xF];
+                        ob.push_str(str::from_utf8(&buf).unwrap());
+                    }
+                }
+                mark = i + 1;  // all escaped characters are ASCII
+            }
+        }
+        ob.push_str(&s[mark..]);
+    }
+    // end code copied from pulldown-cmark
+
+    extern fn hoedown_link(
+        ob: *mut hoedown_buffer,
+        content: *const hoedown_buffer,
+        link: *const hoedown_buffer,
+        title: *const hoedown_buffer,
+        data: *const hoedown_renderer_data,
+        _line: libc::size_t
+    ) -> libc::c_int {
+        if link.is_null() {
+            return 0;
+        }
 
         let opaque = unsafe { (*data).opaque as *mut hoedown_html_renderer_state };
         let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
 
-        let id = derive_id(id);
-
-        let sec = opaque.toc_builder.as_mut().map_or("".to_owned(), |builder| {
-            format!("{} ", builder.push(level as u32, s.clone(), id.clone()))
-        });
-
-        // Render the HTML
-        let text = format!("<h{lvl} id='{id}' class='section-header'>\
-                           <a href='#{id}'>{sec}{}</a></h{lvl}>",
-                           s, lvl = level, id = id, sec = sec);
-
-        unsafe { hoedown_buffer_put(ob, text.as_ptr(), text.len()); }
-    }
-
-    extern fn codespan(
-        ob: *mut hoedown_buffer,
-        text: *const hoedown_buffer,
-        _: *const hoedown_renderer_data,
-        _: libc::size_t
-    ) -> libc::c_int {
-        let content = if text.is_null() {
-            "".to_owned()
-        } else {
-            let bytes = unsafe { (*text).as_bytes() };
-            let s = str::from_utf8(bytes).unwrap();
-            collapse_whitespace(s)
+        let link = {
+            let s = unsafe { (*link).as_bytes() };
+            str::from_utf8(s).unwrap().to_owned()
         };
 
-        let content = format!("<code>{}</code>", Escape(&content));
-        unsafe {
-            hoedown_buffer_put(ob, content.as_ptr(), content.len());
-        }
-        // Return anything except 0, which would mean "also print the code span verbatim".
+        let link = if let Some(&(_, ref new_target)) = opaque.links_replace
+                                                             .iter()
+                                                             .find(|t| &*t.0 == &*link) {
+            new_target.to_owned()
+        } else {
+            link
+        };
+
+        let content = unsafe {
+            content.as_ref().map(|c| {
+                let s = c.as_bytes();
+                str::from_utf8(s).unwrap().to_owned()
+            })
+        };
+
+        let mut link_buf = String::new();
+        escape_href(&mut link_buf, &link);
+
+        let title = unsafe {
+            title.as_ref().map(|t| {
+                let s = t.as_bytes();
+                str::from_utf8(s).unwrap().to_owned()
+            })
+        };
+
+        let link_out = format!("<a href=\"{link}\"{title}>{content}</a>",
+                               link = link_buf,
+                               title = title.map_or(String::new(),
+                                                    |t| format!(" title=\"{}\"", t)),
+                               content = content.unwrap_or(String::new()));
+
+        unsafe { hoedown_buffer_put(ob, link_out.as_ptr(), link_out.len()); }
+
+        //return "anything but 0" to show we've written the link in
         1
     }
 
@@ -743,13 +886,16 @@
         let renderer = hoedown_html_renderer_new(html_flags, 0);
         let mut opaque = MyOpaque {
             dfltblk: (*renderer).blockcode.unwrap(),
-            toc_builder: if print_toc {Some(TocBuilder::new())} else {None}
+            toc_builder: if print_toc {Some(TocBuilder::new())} else {None},
+            links_out: None,
+            links_replace: links.to_vec(),
         };
         (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
                 = &mut opaque as *mut _ as *mut libc::c_void;
-        (*renderer).blockcode = Some(block);
-        (*renderer).header = Some(header);
-        (*renderer).codespan = Some(codespan);
+        (*renderer).blockcode = Some(hoedown_block);
+        (*renderer).header = Some(hoedown_header);
+        (*renderer).codespan = Some(hoedown_codespan);
+        (*renderer).link = Some(hoedown_link);
 
         let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
         hoedown_document_render(document, ob, s.as_ptr(),
@@ -993,12 +1139,12 @@
 
 impl<'a> fmt::Display for Markdown<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let Markdown(md, render_type) = *self;
+        let Markdown(md, links, render_type) = *self;
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
         if render_type == RenderType::Hoedown {
-            render(fmt, md, false, 0)
+            render(fmt, md, links, false, 0)
         } else {
             let mut opts = Options::empty();
             opts.insert(OPTION_ENABLE_TABLES);
@@ -1009,7 +1155,11 @@
             let mut s = String::with_capacity(md.len() * 3 / 2);
 
             html::push_html(&mut s,
-                            Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None))));
+                            Footnotes::new(
+                                CodeBlocks::new(
+                                    LinkReplacer::new(
+                                        HeadingLinks::new(p, None),
+                                        links))));
 
             fmt.write_str(&s)
         }
@@ -1021,7 +1171,7 @@
         let MarkdownWithToc(md, render_type) = *self;
 
         if render_type == RenderType::Hoedown {
-            render(fmt, md, true, 0)
+            render(fmt, md, &[], true, 0)
         } else {
             let mut opts = Options::empty();
             opts.insert(OPTION_ENABLE_TABLES);
@@ -1050,7 +1200,7 @@
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
         if render_type == RenderType::Hoedown {
-            render(fmt, md, false, HOEDOWN_HTML_ESCAPE)
+            render(fmt, md, &[], false, HOEDOWN_HTML_ESCAPE)
         } else {
             let mut opts = Options::empty();
             opts.insert(OPTION_ENABLE_TABLES);
@@ -1076,7 +1226,7 @@
 
 impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownSummaryLine(md) = *self;
+        let MarkdownSummaryLine(md, links) = *self;
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
 
@@ -1084,7 +1234,7 @@
 
         let mut s = String::new();
 
-        html::push_html(&mut s, SummaryLine::new(p));
+        html::push_html(&mut s, LinkReplacer::new(SummaryLine::new(p), links));
 
         fmt.write_str(&s)
     }
@@ -1140,6 +1290,90 @@
     s
 }
 
+pub fn markdown_links(md: &str, render_type: RenderType) -> Vec<String> {
+    if md.is_empty() {
+        return vec![];
+    }
+
+    match render_type {
+        RenderType::Hoedown => {
+            extern fn hoedown_link(
+                _ob: *mut hoedown_buffer,
+                _content: *const hoedown_buffer,
+                link: *const hoedown_buffer,
+                _title: *const hoedown_buffer,
+                data: *const hoedown_renderer_data,
+                _line: libc::size_t
+            ) -> libc::c_int {
+                if link.is_null() {
+                    return 0;
+                }
+
+                let opaque = unsafe { (*data).opaque as *mut hoedown_html_renderer_state };
+                let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
+
+                if let Some(ref mut links) = opaque.links_out {
+                    let s = unsafe { (*link).as_bytes() };
+                    let s = str::from_utf8(&s).unwrap().to_owned();
+
+                    debug!("found link: {}", s);
+
+                    links.push(s);
+                }
+
+                //returning 0 here means "emit the span verbatim", but we're not using the output
+                //anyway so we don't really care
+                0
+            }
+
+            unsafe {
+                let ob = hoedown_buffer_new(DEF_OUNIT);
+                let renderer = hoedown_html_renderer_new(0, 0);
+                let mut opaque = MyOpaque {
+                    dfltblk: (*renderer).blockcode.unwrap(),
+                    toc_builder: None,
+                    links_out: Some(vec![]),
+                    links_replace: vec![],
+                };
+                (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
+                        = &mut opaque as *mut _ as *mut libc::c_void;
+                (*renderer).header = Some(hoedown_header);
+                (*renderer).codespan = Some(hoedown_codespan);
+                (*renderer).link = Some(hoedown_link);
+
+                let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
+                hoedown_document_render(document, ob, md.as_ptr(),
+                                        md.len() as libc::size_t);
+                hoedown_document_free(document);
+
+                hoedown_html_renderer_free(renderer);
+                hoedown_buffer_free(ob);
+
+                opaque.links_out.unwrap()
+            }
+        }
+        RenderType::Pulldown => {
+            let mut opts = Options::empty();
+            opts.insert(OPTION_ENABLE_TABLES);
+            opts.insert(OPTION_ENABLE_FOOTNOTES);
+
+            let p = Parser::new_ext(md, opts);
+
+            let iter = Footnotes::new(HeadingLinks::new(p, None));
+            let mut links = vec![];
+
+            for ev in iter {
+                if let Event::Start(Tag::Link(dest, _)) = ev {
+                    debug!("found link: {}", dest);
+                    links.push(dest.into_owned());
+                }
+            }
+
+            links
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::{LangString, Markdown, MarkdownHtml};
@@ -1191,14 +1425,14 @@
     #[test]
     fn issue_17736() {
         let markdown = "# title";
-        format!("{}", Markdown(markdown, RenderType::Pulldown));
+        format!("{}", Markdown(markdown, &[], RenderType::Pulldown));
         reset_ids(true);
     }
 
     #[test]
     fn test_header() {
         fn t(input: &str, expect: &str) {
-            let output = format!("{}", Markdown(input, RenderType::Pulldown));
+            let output = format!("{}", Markdown(input, &[], RenderType::Pulldown));
             assert_eq!(output, expect, "original: {}", input);
             reset_ids(true);
         }
@@ -1220,7 +1454,7 @@
     #[test]
     fn test_header_ids_multiple_blocks() {
         fn t(input: &str, expect: &str) {
-            let output = format!("{}", Markdown(input, RenderType::Pulldown));
+            let output = format!("{}", Markdown(input, &[], RenderType::Pulldown));
             assert_eq!(output, expect, "original: {}", input);
         }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 3be44f3..b0d535d 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -132,6 +132,8 @@
     /// This flag indicates whether listings of modules (in the side bar and documentation itself)
     /// should be ordered alphabetically or in order of appearance (in the source code).
     pub sort_modules_alphabetically: bool,
+    /// Additional themes to be added to the generated docs.
+    pub themes: Vec<PathBuf>,
 }
 
 impl SharedContext {
@@ -173,14 +175,7 @@
     Unknown,
 }
 
-/// Metadata about an implementor of a trait.
-pub struct Implementor {
-    pub def_id: DefId,
-    pub stability: Option<clean::Stability>,
-    pub impl_: clean::Impl,
-}
-
-/// Metadata about implementations for a type.
+/// Metadata about implementations for a type or trait.
 #[derive(Clone)]
 pub struct Impl {
     pub impl_item: clean::Item,
@@ -226,6 +221,17 @@
     }
 }
 
+macro_rules! try_none {
+    ($e:expr, $file:expr) => ({
+        use std::io;
+        match $e {
+            Some(e) => e,
+            None => return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"),
+                                          $file))
+        }
+    })
+}
+
 macro_rules! try_err {
     ($e:expr, $file:expr) => ({
         match $e {
@@ -279,7 +285,7 @@
     /// When rendering traits, it's often useful to be able to list all
     /// implementors of the trait, and this mapping is exactly, that: a mapping
     /// of trait ids to the list of known implementors of the trait
-    pub implementors: FxHashMap<DefId, Vec<Implementor>>,
+    pub implementors: FxHashMap<DefId, Vec<Impl>>,
 
     /// Cache of where external crate documentation can be found.
     pub extern_locations: FxHashMap<CrateNum, (String, PathBuf, ExternalLocation)>,
@@ -428,7 +434,7 @@
 thread_local!(pub static USED_ID_MAP: RefCell<FxHashMap<String, usize>> =
                     RefCell::new(init_ids()));
 
-pub fn render_text<F: FnMut(RenderType) -> String>(mut render: F) -> (String, String) {
+pub fn render_text<T, F: FnMut(RenderType) -> T>(mut render: F) -> (T, T) {
     // Save the state of USED_ID_MAP so it only gets updated once even
     // though we're rendering twice.
     let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone());
@@ -495,7 +501,9 @@
            css_file_extension: Option<PathBuf>,
            renderinfo: RenderInfo,
            render_type: RenderType,
-           sort_modules_alphabetically: bool) -> Result<(), Error> {
+           sort_modules_alphabetically: bool,
+           deny_render_differences: bool,
+           themes: Vec<PathBuf>) -> Result<(), Error> {
     let src_root = match krate.src {
         FileName::Real(ref p) => match p.parent() {
             Some(p) => p.to_path_buf(),
@@ -519,6 +527,7 @@
         markdown_warnings: RefCell::new(vec![]),
         created_dirs: RefCell::new(FxHashSet()),
         sort_modules_alphabetically,
+        themes,
     };
 
     // If user passed in `--playground-url` arg, we fill in crate name here
@@ -659,6 +668,11 @@
                 render_difference(d, &mut intro_msg, span, text);
             }
         }
+
+        if deny_render_differences {
+            println!("Aborting with {} rendering differences", markdown_warnings.len());
+            ::std::process::exit(1);
+        }
     }
 
     result
@@ -860,22 +874,68 @@
     // Add all the static files. These may already exist, but we just
     // overwrite them anyway to make sure that they're fresh and up-to-date.
 
-    write(cx.dst.join("main.js"),
-          include_bytes!("static/main.js"))?;
     write(cx.dst.join("rustdoc.css"),
           include_bytes!("static/rustdoc.css"))?;
-    write(cx.dst.join("main.css"),
-          include_bytes!("static/styles/main.css"))?;
-    if let Some(ref css) = cx.shared.css_file_extension {
-        let mut content = String::new();
-        let css = css.as_path();
-        let mut f = try_err!(File::open(css), css);
 
-        try_err!(f.read_to_string(&mut content), css);
-        let css = cx.dst.join("theme.css");
-        let css = css.as_path();
-        let mut f = try_err!(File::create(css), css);
-        try_err!(write!(f, "{}", &content), css);
+    // To avoid "main.css" to be overwritten, we'll first run over the received themes and only
+    // then we'll run over the "official" styles.
+    let mut themes: HashSet<String> = HashSet::new();
+
+    for entry in &cx.shared.themes {
+        let mut content = Vec::with_capacity(100000);
+
+        let mut f = try_err!(File::open(&entry), &entry);
+        try_err!(f.read_to_end(&mut content), &entry);
+        write(cx.dst.join(try_none!(entry.file_name(), &entry)), content.as_slice())?;
+        themes.insert(try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry).to_owned());
+    }
+
+    write(cx.dst.join("brush.svg"),
+          include_bytes!("static/brush.svg"))?;
+    write(cx.dst.join("main.css"),
+          include_bytes!("static/themes/main.css"))?;
+    themes.insert("main".to_owned());
+    write(cx.dst.join("dark.css"),
+          include_bytes!("static/themes/dark.css"))?;
+    themes.insert("dark".to_owned());
+
+    let mut themes: Vec<&String> = themes.iter().collect();
+    themes.sort();
+    // To avoid theme switch latencies as much as possible, we put everything theme related
+    // at the beginning of the html files into another js file.
+    write(cx.dst.join("theme.js"), format!(
+r#"var themes = document.getElementById("theme-choices");
+var themePicker = document.getElementById("theme-picker");
+themePicker.onclick = function() {{
+    if (themes.style.display === "block") {{
+        themes.style.display = "none";
+        themePicker.style.borderBottomRightRadius = "3px";
+        themePicker.style.borderBottomLeftRadius = "3px";
+    }} else {{
+        themes.style.display = "block";
+        themePicker.style.borderBottomRightRadius = "0";
+        themePicker.style.borderBottomLeftRadius = "0";
+    }}
+}};
+[{}].forEach(function(item) {{
+    var div = document.createElement('div');
+    div.innerHTML = item;
+    div.onclick = function(el) {{
+        switchTheme(currentTheme, mainTheme, item);
+    }};
+    themes.appendChild(div);
+}});
+"#, themes.iter()
+          .map(|s| format!("\"{}\"", s))
+          .collect::<Vec<String>>()
+          .join(",")).as_bytes())?;
+
+    write(cx.dst.join("main.js"), include_bytes!("static/main.js"))?;
+    write(cx.dst.join("storage.js"), include_bytes!("static/storage.js"))?;
+
+    if let Some(ref css) = cx.shared.css_file_extension {
+        let out = cx.dst.join("theme.css");
+        try_err!(fs::copy(css, out), css);
     }
     write(cx.dst.join("normalize.css"),
           include_bytes!("static/normalize.css"))?;
@@ -965,12 +1025,12 @@
             // there's no need to emit information about it (there's inlining
             // going on). If they're in different crates then the crate defining
             // the trait will be interested in our implementation.
-            if imp.def_id.krate == did.krate { continue }
+            if imp.impl_item.def_id.krate == did.krate { continue }
             // If the implementation is from another crate then that crate
             // should add it.
-            if !imp.def_id.is_local() { continue }
+            if !imp.impl_item.def_id.is_local() { continue }
             have_impls = true;
-            write!(implementors, "{},", as_json(&imp.impl_.to_string())).unwrap();
+            write!(implementors, "{},", as_json(&imp.inner_impl().to_string())).unwrap();
         }
         implementors.push_str("];");
 
@@ -1028,7 +1088,7 @@
 /// Writes the entire contents of a string to a destination, not attempting to
 /// catch any errors.
 fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> {
-    Ok(try_err!(try_err!(File::create(&dst), &dst).write_all(contents), &dst))
+    Ok(try_err!(fs::write(&dst, contents), &dst))
 }
 
 /// Takes a path to a source file and cleans the path to it. This canonicalizes
@@ -1125,16 +1185,13 @@
             return Ok(());
         }
 
-        let mut contents = Vec::new();
-        File::open(&p).and_then(|mut f| f.read_to_end(&mut contents))?;
-
-        let contents = str::from_utf8(&contents).unwrap();
+        let contents = fs::read_string(&p)?;
 
         // Remove the utf-8 BOM if any
         let contents = if contents.starts_with("\u{feff}") {
             &contents[3..]
         } else {
-            contents
+            &contents[..]
         };
 
         // Create the intermediate directories
@@ -1167,7 +1224,8 @@
         };
         layout::render(&mut w, &self.scx.layout,
                        &page, &(""), &Source(contents),
-                       self.scx.css_file_extension.is_some())?;
+                       self.scx.css_file_extension.is_some(),
+                       &self.scx.themes)?;
         w.flush()?;
         self.scx.local_sources.insert(p.clone(), href);
         Ok(())
@@ -1202,10 +1260,8 @@
             if !self.masked_crates.contains(&item.def_id.krate) {
                 if let Some(did) = i.trait_.def_id() {
                     if i.for_.def_id().map_or(true, |d| !self.masked_crates.contains(&d.krate)) {
-                        self.implementors.entry(did).or_insert(vec![]).push(Implementor {
-                            def_id: item.def_id,
-                            stability: item.stability.clone(),
-                            impl_: i.clone(),
+                        self.implementors.entry(did).or_insert(vec![]).push(Impl {
+                            impl_item: item.clone(),
                         });
                     }
                 }
@@ -1297,11 +1353,11 @@
             clean::FunctionItem(..) | clean::ModuleItem(..) |
             clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) |
             clean::ConstantItem(..) | clean::StaticItem(..) |
-            clean::UnionItem(..) | clean::ForeignTypeItem
+            clean::UnionItem(..) | clean::ForeignTypeItem | clean::MacroItem(..)
             if !self.stripped_mod => {
-                // Reexported items mean that the same id can show up twice
+                // Re-exported items mean that the same id can show up twice
                 // in the rustdoc ast that we're looking at. We know,
-                // however, that a reexported item doesn't show up in the
+                // however, that a re-exported item doesn't show up in the
                 // `public_items` map, so we can skip inserting into the
                 // paths map if there was already an entry present and we're
                 // not a public item.
@@ -1533,7 +1589,8 @@
             layout::render(writer, &self.shared.layout, &page,
                            &Sidebar{ cx: self, item: it },
                            &Item{ cx: self, item: it },
-                           self.shared.css_file_extension.is_some())?;
+                           self.shared.css_file_extension.is_some(),
+                           &self.shared.themes)?;
         } else {
             let mut url = self.root_path();
             if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
@@ -1558,7 +1615,7 @@
     {
         // Stripped modules survive the rustdoc passes (i.e. `strip-private`)
         // if they contain impls for public types. These modules can also
-        // contain items such as publicly reexported structures.
+        // contain items such as publicly re-exported structures.
         //
         // External crates will provide links to these structures, so
         // these modules are recursed into, but not rendered normally
@@ -1874,12 +1931,14 @@
 /// rendering between Pulldown and Hoedown.
 fn render_markdown(w: &mut fmt::Formatter,
                    md_text: &str,
+                   links: Vec<(String, String)>,
                    span: Span,
                    render_type: RenderType,
                    prefix: &str,
                    scx: &SharedContext)
                    -> fmt::Result {
-    let (hoedown_output, pulldown_output) = render_text(|ty| format!("{}", Markdown(md_text, ty)));
+    let (hoedown_output, pulldown_output) =
+        render_text(|ty| format!("{}", Markdown(md_text, &links, ty)));
     let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
     differences.retain(|s| {
         match *s {
@@ -1911,7 +1970,13 @@
         } else {
             format!("{}", &plain_summary_line(Some(s)))
         };
-        render_markdown(w, &markdown, item.source.clone(), cx.render_type, prefix, &cx.shared)?;
+        render_markdown(w,
+                        &markdown,
+                        item.links(),
+                        item.source.clone(),
+                        cx.render_type,
+                        prefix,
+                        &cx.shared)?;
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock'>{}</div>", prefix)?;
     }
@@ -1937,7 +2002,13 @@
                  cx: &Context, prefix: &str) -> fmt::Result {
     if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
         debug!("Doc block: =====\n{}\n=====", s);
-        render_markdown(w, &*s, item.source.clone(), cx.render_type, prefix, &cx.shared)?;
+        render_markdown(w,
+                        &*s,
+                        item.links(),
+                        item.source.clone(),
+                        cx.render_type,
+                        prefix,
+                        &cx.shared)?;
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock'>{}</div>", prefix)?;
     }
@@ -1977,12 +2048,8 @@
                item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
     document(w, cx, item)?;
 
-    let mut indices = (0..items.len()).filter(|i| {
-        if let clean::AutoImplItem(..) = items[*i].inner {
-            return false;
-        }
-        !items[*i].is_stripped()
-    }).collect::<Vec<usize>>();
+    let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped())
+                                      .collect::<Vec<usize>>();
 
     // the order of item types in the listing
     fn reorder(ty: ItemType) -> u8 {
@@ -2025,7 +2092,7 @@
     if cx.shared.sort_modules_alphabetically {
         indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
     }
-    // This call is to remove reexport duplicates in cases such as:
+    // This call is to remove re-export duplicates in cases such as:
     //
     // ```
     // pub mod foo {
@@ -2076,7 +2143,7 @@
             curty = myty;
             let (short, name) = match myty.unwrap() {
                 ItemType::ExternCrate |
-                ItemType::Import          => ("reexports", "Reexports"),
+                ItemType::Import          => ("reexports", "Re-exports"),
                 ItemType::Module          => ("modules", "Modules"),
                 ItemType::Struct          => ("structs", "Structs"),
                 ItemType::Union           => ("unions", "Unions"),
@@ -2163,10 +2230,10 @@
                        stab_docs = stab_docs,
                        docs = if cx.render_type == RenderType::Hoedown {
                            format!("{}",
-                                   shorter(Some(&Markdown(doc_value,
+                                   shorter(Some(&Markdown(doc_value, &myitem.links(),
                                                           RenderType::Hoedown).to_string())))
                        } else {
-                           format!("{}", MarkdownSummaryLine(doc_value))
+                           format!("{}", MarkdownSummaryLine(doc_value, &myitem.links()))
                        },
                        class = myitem.type_(),
                        stab = myitem.stability_class().unwrap_or("".to_string()),
@@ -2332,18 +2399,6 @@
     document(w, cx, it)
 }
 
-fn implementor2item<'a>(cache: &'a Cache, imp : &Implementor) -> Option<&'a clean::Item> {
-    if let Some(t_did) = imp.impl_.for_.def_id() {
-        if let Some(impl_item) = cache.impls.get(&t_did).and_then(|i| i.iter()
-            .find(|i| i.impl_item.def_id == imp.def_id))
-        {
-            let i = &impl_item.impl_item;
-            return Some(i);
-        }
-    }
-    None
-}
-
 fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
               t: &clean::Trait) -> fmt::Result {
     let mut bounds = String::new();
@@ -2368,9 +2423,10 @@
     // Output the trait definition
     write!(w, "<pre class='rust trait'>")?;
     render_attributes(w, it)?;
-    write!(w, "{}{}trait {}{}{}",
+    write!(w, "{}{}{}trait {}{}{}",
            VisSpace(&it.visibility),
            UnsafetySpace(t.unsafety),
+           if t.is_auto { "auto " } else { "" },
            it.name.as_ref().unwrap(),
            t.generics,
            bounds)?;
@@ -2527,7 +2583,7 @@
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap();
         for implementor in implementors {
-            match implementor.impl_.for_ {
+            match implementor.inner_impl().for_ {
                 clean::ResolvedPath { ref path, did, is_generic: false, .. } |
                 clean::BorrowedRef {
                     type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
@@ -2544,7 +2600,7 @@
         }
 
         let (local, foreign) = implementors.iter()
-            .partition::<Vec<_>, _>(|i| i.impl_.for_.def_id()
+            .partition::<Vec<_>, _>(|i| i.inner_impl().for_.def_id()
                                          .map_or(true, |d| cache.paths.contains_key(&d)));
 
         if !foreign.is_empty() {
@@ -2555,14 +2611,11 @@
             ")?;
 
             for implementor in foreign {
-                if let Some(i) = implementor2item(&cache, implementor) {
-                    let impl_ = Impl { impl_item: i.clone() };
-                    let assoc_link = AssocItemLink::GotoSource(
-                        i.def_id, &implementor.impl_.provided_trait_methods
-                    );
-                    render_impl(w, cx, &impl_, assoc_link,
-                                RenderMode::Normal, i.stable_since(), false)?;
-                }
+                let assoc_link = AssocItemLink::GotoSource(
+                    implementor.impl_item.def_id, &implementor.inner_impl().provided_trait_methods
+                );
+                render_impl(w, cx, &implementor, assoc_link,
+                            RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
             }
         }
 
@@ -2570,18 +2623,16 @@
 
         for implementor in local {
             write!(w, "<li>")?;
-            if let Some(item) = implementor2item(&cache, implementor) {
-                if let Some(l) = (Item { cx, item }).src_href() {
-                    write!(w, "<div class='out-of-band'>")?;
-                    write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
-                                l, "goto source code")?;
-                    write!(w, "</div>")?;
-                }
+            if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() {
+                write!(w, "<div class='out-of-band'>")?;
+                write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
+                            l, "goto source code")?;
+                write!(w, "</div>")?;
             }
             write!(w, "<code>")?;
             // If there's already another implementor that has the same abbridged name, use the
             // full path, for example in `std::iter::ExactSizeIterator`
-            let use_absolute = match implementor.impl_.for_ {
+            let use_absolute = match implementor.inner_impl().for_ {
                 clean::ResolvedPath { ref path, is_generic: false, .. } |
                 clean::BorrowedRef {
                     type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
@@ -2589,8 +2640,8 @@
                 } => implementor_dups[path.last_name()].1,
                 _ => false,
             };
-            fmt_impl_for_trait_page(&implementor.impl_, w, use_absolute)?;
-            for it in &implementor.impl_.items {
+            fmt_impl_for_trait_page(&implementor.inner_impl(), w, use_absolute)?;
+            for it in &implementor.inner_impl().items {
                 if let clean::TypedefItem(ref tydef, _) = it.inner {
                     write!(w, "<span class=\"where fmt-newline\">  ")?;
                     assoc_type(w, it, &vec![], Some(&tydef.type_), AssocItemLink::Anchor(None))?;
@@ -3311,8 +3362,7 @@
         if let Some(impls) = c.impls.get(&did) {
             for i in impls {
                 let impl_ = i.inner_impl();
-                if impl_.trait_.def_id().and_then(|d| c.traits.get(&d))
-                                        .map_or(false, |t| t.is_spotlight) {
+                if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
                     if out.is_empty() {
                         out.push_str(
                             &format!("<h3 class=\"important\">Important traits for {}</h3>\
@@ -3373,7 +3423,8 @@
         write!(w, "</span>")?;
         write!(w, "</h3>\n")?;
         if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
-            write!(w, "<div class='docblock'>{}</div>", Markdown(&*dox, cx.render_type))?;
+            write!(w, "<div class='docblock'>{}</div>",
+                   Markdown(&*dox, &i.impl_item.links(), cx.render_type))?;
         }
     }
 
@@ -3478,7 +3529,7 @@
     }
 
     let traits = &cache().traits;
-    let trait_ = i.trait_did().and_then(|did| traits.get(&did));
+    let trait_ = i.trait_did().map(|did| &traits[&did]);
 
     if !show_def_docs {
         write!(w, "<span class='docblock autohide'>")?;
@@ -3880,20 +3931,16 @@
 
     if let Some(implementors) = c.implementors.get(&it.def_id) {
         let res = implementors.iter()
-                              .filter(|i| i.impl_.for_.def_id()
-                                                      .map_or(false, |d| !c.paths.contains_key(&d)))
+                              .filter(|i| i.inner_impl().for_.def_id()
+                                           .map_or(false, |d| !c.paths.contains_key(&d)))
                               .filter_map(|i| {
-                                  if let Some(item) = implementor2item(&c, i) {
-                                      match extract_for_impl_name(&item) {
-                                          Some((ref name, ref url)) => {
-                                              Some(format!("<a href=\"#impl-{}\">{}</a>",
-                                                           small_url_encode(url),
-                                                           Escape(name)))
-                                          }
-                                          _ => None,
+                                  match extract_for_impl_name(&i.impl_item) {
+                                      Some((ref name, ref url)) => {
+                                          Some(format!("<a href=\"#impl-{}\">{}</a>",
+                                                      small_url_encode(url),
+                                                      Escape(name)))
                                       }
-                                  } else {
-                                      None
+                                      _ => None,
                                   }
                               })
                               .collect::<String>();
@@ -3997,7 +4044,7 @@
                              it.type_() == ItemType::Import) {
         sidebar.push_str(&format!("<li><a href=\"#{id}\">{name}</a></li>",
                                   id = "reexports",
-                                  name = "Reexports"));
+                                  name = "Re-exports"));
     }
 
     // ordering taken from item_module, reorder, where it prioritized elements in a certain order
@@ -4007,16 +4054,10 @@
                    ItemType::Function, ItemType::Typedef, ItemType::Union, ItemType::Impl,
                    ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
                    ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
-        if items.iter().any(|it| {
-            if let clean::AutoImplItem(..) = it.inner {
-                false
-            } else {
-                !it.is_stripped() && it.type_() == myty
-            }
-        }) {
+        if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) {
             let (short, name) = match myty {
                 ItemType::ExternCrate |
-                ItemType::Import          => ("reexports", "Reexports"),
+                ItemType::Import          => ("reexports", "Re-exports"),
                 ItemType::Module          => ("modules", "Modules"),
                 ItemType::Struct          => ("structs", "Structs"),
                 ItemType::Union           => ("unions", "Unions"),
@@ -4130,7 +4171,11 @@
     match *clean_type {
         clean::ResolvedPath { ref path, .. } => {
             let segments = &path.segments;
-            Some(segments[segments.len() - 1].name.clone())
+            let path_segment = segments.into_iter().last().unwrap_or_else(|| panic!(
+                "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path",
+                clean_type, accept_generic
+            ));
+            Some(path_segment.name.clone())
         }
         clean::Generic(ref s) if accept_generic => Some(s.clone()),
         clean::Primitive(ref p) => Some(format!("{:?}", p)),
diff --git a/src/librustdoc/html/static/brush.svg b/src/librustdoc/html/static/brush.svg
new file mode 100644
index 0000000..072264a
--- /dev/null
+++ b/src/librustdoc/html/static/brush.svg
@@ -0,0 +1 @@
+<?xml version="1.0" ?><svg height="1792" viewBox="0 0 1792 1792" width="1792" xmlns="http://www.w3.org/2000/svg"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 559f849..0f9e700 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -122,6 +122,10 @@
             }
         }
         document.getElementsByTagName("body")[0].style.marginTop = '45px';
+        var themePicker = document.getElementById("theme-picker");
+        if (themePicker) {
+            themePicker.style.position = "fixed";
+        }
     }
 
     function hideSidebar() {
@@ -136,6 +140,10 @@
             filler.remove();
         }
         document.getElementsByTagName("body")[0].style.marginTop = '';
+        var themePicker = document.getElementById("theme-picker");
+        if (themePicker) {
+            themePicker.style.position = "absolute";
+        }
     }
 
     // used for special search precedence
@@ -258,6 +266,7 @@
                 addClass(search, "hidden");
                 removeClass(document.getElementById("main"), "hidden");
             }
+            defocusSearchBar();
             break;
 
         case "s":
@@ -352,35 +361,33 @@
      * This code is an unmodified version of the code written by Marco de Wit
      * and was found at http://stackoverflow.com/a/18514751/745719
      */
-    var levenshtein = (function() {
-        var row2 = [];
-        return function(s1, s2) {
-            if (s1 === s2) {
-                return 0;
+    var levenshtein_row2 = [];
+    function levenshtein(s1, s2) {
+        if (s1 === s2) {
+            return 0;
+        }
+        var s1_len = s1.length, s2_len = s2.length;
+        if (s1_len && s2_len) {
+            var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
+            while (i1 < s1_len) {
+                row[i1] = ++i1;
             }
-            var s1_len = s1.length, s2_len = s2.length;
-            if (s1_len && s2_len) {
-                var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
-                while (i1 < s1_len) {
-                    row[i1] = ++i1;
+            while (i2 < s2_len) {
+                c2 = s2.charCodeAt(i2);
+                a = i2;
+                ++i2;
+                b = i2;
+                for (i1 = 0; i1 < s1_len; ++i1) {
+                    c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
+                    a = row[i1];
+                    b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
+                    row[i1] = b;
                 }
-                while (i2 < s2_len) {
-                    c2 = s2.charCodeAt(i2);
-                    a = i2;
-                    ++i2;
-                    b = i2;
-                    for (i1 = 0; i1 < s1_len; ++i1) {
-                        c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
-                        a = row[i1];
-                        b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
-                        row[i1] = b;
-                    }
-                }
-                return b;
             }
-            return s1_len + s2_len;
-        };
-    })();
+            return b;
+        }
+        return s1_len + s2_len;
+    }
 
     function initSearch(rawSearchIndex) {
         var currentResults, index, searchIndex;
@@ -399,12 +406,20 @@
         /**
          * Executes the query and builds an index of results
          * @param  {[Object]} query     [The user query]
-         * @param  {[type]} max         [The maximum results returned]
          * @param  {[type]} searchWords [The list of search words to query
          *                               against]
          * @return {[type]}             [A search index of results]
          */
-        function execQuery(query, max, searchWords) {
+        function execQuery(query, searchWords) {
+            function itemTypeFromName(typename) {
+                for (var i = 0; i < itemTypes.length; ++i) {
+                    if (itemTypes[i] === typename) {
+                        return i;
+                    }
+                }
+                return -1;
+            }
+
             var valLower = query.query.toLowerCase(),
                 val = valLower,
                 typeFilter = itemTypeFromName(query.type),
@@ -593,7 +608,7 @@
                 var lev_distance = MAX_LEV_DISTANCE + 1;
                 if (obj.name === val.name) {
                     if (literalSearch === true) {
-                        if (val.generics.length !== 0) {
+                        if (val.generics && val.generics.length !== 0) {
                             if (obj.generics && obj.length >= val.generics.length) {
                                 var elems = obj.generics.slice(0);
                                 var allFound = true;
@@ -630,7 +645,7 @@
                 }
                 // Names didn't match so let's check if one of the generic types could.
                 if (literalSearch === true) {
-                     if (obj.generics.length > 0) {
+                     if (obj.generics && obj.generics.length > 0) {
                         for (var x = 0; x < obj.generics.length; ++x) {
                             if (obj.generics[x] === val.name) {
                                 return true;
@@ -1020,9 +1035,8 @@
             return true;
         }
 
-        function getQuery() {
-            var matches, type, query, raw =
-                document.getElementsByClassName('search-input')[0].value;
+        function getQuery(raw) {
+            var matches, type, query;
             query = raw;
 
             matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
@@ -1131,6 +1145,10 @@
                     e.preventDefault();
                 } else if (e.which === 16) { // shift
                     // Does nothing, it's just to avoid losing "focus" on the highlighted element.
+                } else if (e.which === 27) { // escape
+                    removeClass(actives[currentTab][0], 'highlighted');
+                    document.getElementsByClassName('search-input')[0].value = '';
+                    defocusSearchBar();
                 } else if (actives[currentTab].length > 0) {
                     removeClass(actives[currentTab][0], 'highlighted');
                 }
@@ -1222,7 +1240,7 @@
         }
 
         function showResults(results) {
-            var output, query = getQuery();
+            var output, query = getQuery(document.getElementsByClassName('search-input')[0].value);
 
             currentResults = query.id;
             output = '<h1>Results for ' + escape(query.query) +
@@ -1266,7 +1284,7 @@
                 resultIndex;
             var params = getQueryStringParams();
 
-            query = getQuery();
+            query = getQuery(document.getElementsByClassName('search-input')[0].value);
             if (e) {
                 e.preventDefault();
             }
@@ -1288,19 +1306,10 @@
                 }
             }
 
-            results = execQuery(query, 20000, index);
+            results = execQuery(query, index);
             showResults(results);
         }
 
-        function itemTypeFromName(typename) {
-            for (var i = 0; i < itemTypes.length; ++i) {
-                if (itemTypes[i] === typename) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
         function buildIndex(rawSearchIndex) {
             searchIndex = [];
             var searchWords = [];
@@ -1531,7 +1540,9 @@
                 ul.appendChild(li);
             }
             div.appendChild(ul);
-            sidebar.appendChild(div);
+            if (sidebar) {
+                sidebar.appendChild(div);
+            }
         }
 
         block("primitive", "Primitive Types");
@@ -1884,3 +1895,8 @@
 function focusSearchBar() {
     document.getElementsByClassName('search-input')[0].focus();
 }
+
+// Removes the focus from the search bar
+function defocusSearchBar() {
+    document.getElementsByClassName('search-input')[0].blur();
+}
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index b41874a..c1ca86e 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -360,7 +360,8 @@
 }
 
 h4 > code, h3 > code, .invisible > code {
-	position: inherit;
+	max-width: calc(100% - 41px);
+	display: block;
 }
 
 .in-band, code {
@@ -376,6 +377,7 @@
 	margin: 0px;
 	padding: 0px;
 	display: inline-block;
+	max-width: calc(100% - 43px);
 }
 
 .in-band > code {
@@ -585,18 +587,13 @@
 	flex: 0 0 auto;
 	box-shadow: 0 0 6px rgba(0,0,0,.2);
 	width: 550px;
-	height: 354px;
+	height: auto;
 	border: 1px solid;
 }
 #help dt {
 	float: left;
-	border-radius: 4px;
-	border: 1px solid;
-	width: 23px;
-	text-align: center;
 	clear: left;
 	display: block;
-	margin-top: -1px;
 }
 #help dd { margin: 5px 35px; }
 #help .infos { padding-left: 0; }
@@ -1134,3 +1131,48 @@
 	left: -42px;
 	margin-top: 2px;
 }
+
+kbd {
+	display: inline-block;
+	padding: 3px 5px;
+	font: 15px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+	line-height: 10px;
+	vertical-align: middle;
+	border: solid 1px;
+	border-radius: 3px;
+	box-shadow: inset 0 -1px 0;
+}
+
+#theme-picker {
+	position: absolute;
+	left: 211px;
+	top: 17px;
+	padding: 4px;
+	border: 1px solid;
+	border-radius: 3px;
+	cursor: pointer;
+}
+
+#theme-choices {
+	display: none;
+	position: absolute;
+	left: -1px;
+	top: 30px;
+	border: 1px solid;
+	border-radius: 3px;
+	z-index: 1;
+}
+
+#theme-choices > div {
+	border-top: 1px solid;
+	padding: 4px;
+	text-align: center;
+}
+
+@media (max-width: 700px) {
+	#theme-picker {
+		left: 109px;
+		top: 7px;
+		z-index: 1;
+	}
+}
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
new file mode 100644
index 0000000..0aa1065
--- /dev/null
+++ b/src/librustdoc/html/static/storage.js
@@ -0,0 +1,36 @@
+/*!
+ * Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+ * file at the top-level directory of this distribution and at
+ * http://rust-lang.org/COPYRIGHT.
+ *
+ * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+ * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+ * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+ * option. This file may not be copied, modified, or distributed
+ * except according to those terms.
+ */
+
+var currentTheme = document.getElementById("themeStyle");
+var mainTheme = document.getElementById("mainThemeStyle");
+
+function updateLocalStorage(name, value) {
+    if (typeof(Storage) !== "undefined") {
+        localStorage[name] = value;
+    } else {
+        // No Web Storage support so we do nothing
+    }
+}
+
+function getCurrentValue(name) {
+    if (typeof(Storage) !== "undefined" && localStorage[name] !== undefined) {
+        return localStorage[name];
+    }
+    return null;
+}
+
+function switchTheme(styleElem, mainStyleElem, newTheme) {
+    styleElem.href = mainStyleElem.href.replace("rustdoc.css", newTheme + ".css");
+    updateLocalStorage('theme', newTheme);
+}
+
+switchTheme(currentTheme, mainTheme, getCurrentValue('theme') || 'main');
diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/themes/dark.css
similarity index 60%
copy from src/librustdoc/html/static/styles/main.css
copy to src/librustdoc/html/static/themes/dark.css
index c79413c..05ac066 100644
--- a/src/librustdoc/html/static/styles/main.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -10,25 +10,23 @@
  * except according to those terms.
  */
 
-/* General structure and fonts */
-
 body {
-	background-color: white;
-	color: black;
+	background-color: #353535;
+	color: #ddd;
 }
 
 h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
-	color: black;
+	color: #ddd;
 }
 h1.fqn {
-	border-bottom-color: #D5D5D5;
+	border-bottom-color: #d2d2d2;
 }
 h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
-	border-bottom-color: #DDDDDD;
+	border-bottom-color: #d2d2d2;
 }
 
 .in-band {
-	background-color: white;
+	background-color: #353535;
 }
 
 .invisible {
@@ -36,28 +34,28 @@
 }
 
 .docblock code, .docblock-short code {
-	background-color: #F5F5F5;
+	background-color: #2A2A2A;
 }
 pre {
-	background-color: #F5F5F5;
+	background-color: #2A2A2A;
 }
 
 .sidebar {
-	background-color: #F1F1F1;
+	background-color: #505050;
 }
 
 .sidebar .current {
-	background-color: #fff;
+	background-color: #333;
 }
 
 .source .sidebar {
-	background-color: #fff;
+	background-color: #353535;
 }
 
 .sidebar .location {
-	border-color: #000;
-	background-color: #fff;
-	color: #333;
+	border-color: #fff;
+	background: #575757;
+	color: #DDD;
 }
 
 .sidebar .version {
@@ -70,12 +68,12 @@
 }
 
 .block a:hover {
-	background: #F5F5F5;
+	background: #444;
 }
 
-.line-numbers span { color: #c67e2d; }
+.line-numbers span { color: #3B91E2; }
 .line-numbers .line-highlighted {
-	background-color: #f6fdb0 !important;
+	background-color: #0a042f !important;
 }
 
 .docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
@@ -96,79 +94,78 @@
 	border-bottom-color: #ddd;
 }
 
-:target { background: #FDFFD3; }
+:target { background: #494a3d; }
 
 :target > .in-band {
-	background: #FDFFD3;
+	background: #494a3d;
 }
 
 .content .method .where,
 .content .fn .where,
 .content .where.fmt-newline {
-	color: #4E4C4C;
+	color: #ddd;
 }
 
 .content .highlighted {
-	color: #000 !important;
-	background-color: #ccc;
+	color: #eee !important;
+	background-color: #333;
 }
-.content .highlighted a, .content .highlighted span { color: #000 !important; }
-.content .highlighted.trait { background-color: #c7b6ff; }
-.content .highlighted.mod,
-.content .highlighted.externcrate { background-color: #afc6e4; }
-.content .highlighted.enum { background-color: #b4d1b9; }
-.content .highlighted.struct { background-color: #e7b1a0; }
-.content .highlighted.union { background-color: #b7bd49; }
+.content .highlighted a, .content .highlighted span { color: #eee !important; }
+.content .highlighted.trait { background-color: #013191; }
+.content .highlighted.mod { background-color: #803a1b; }
+.content .highlighted.externcrate { background-color: #396bac; }
+.content .highlighted.enum { background-color: #5b4e68; }
+.content .highlighted.struct { background-color: #194e9f; }
 .content .highlighted.fn,
 .content .highlighted.method,
-.content .highlighted.tymethod { background-color: #c6afb3; }
-.content .highlighted.type { background-color: #ffc891; }
-.content .highlighted.foreigntype { background-color: #f5c4ff; }
-.content .highlighted.macro { background-color: #8ce488; }
+.content .highlighted.tymethod { background-color: #4950ed; }
+.content .highlighted.type { background-color: #38902c; }
+.content .highlighted.foreigntype { background-color: #b200d6; }
+.content .highlighted.macro { background-color: #217d1c; }
 .content .highlighted.constant,
-.content .highlighted.static { background-color: #c3e0ff; }
-.content .highlighted.primitive { background-color: #9aecff; }
+.content .highlighted.static { background-color: #0063cc; }
+.content .highlighted.primitive { background-color: #00708a; }
 
-.content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
-.content span.struct, .content a.struct, .block a.current.struct { color: #df3600; }
-.content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
-.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; }
-.content span.macro, .content a.macro, .block a.current.macro { color: #068000; }
-.content span.union, .content a.union, .block a.current.union { color: #767b27; }
+.content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
+.content span.struct, .content a.struct, .block a.current.struct { color: #ff794d; }
+.content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
+.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; }
+.content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; }
+.content span.union, .content a.union, .block a.current.union { color: #a6ae37; }
 .content span.constant, .content a.constant, .block a.current.constant,
-.content span.static, .content a.static, .block a.current.static { color: #546e8a; }
-.content span.primitive, .content a.primitive, .block a.current.primitive { color: #2c8093; }
+.content span.static, .content a.static, .block a.current.static { color: #82a5c9; }
+.content span.primitive, .content a.primitive, .block a.current.primitive { color: #43aec7; }
 .content span.externcrate,
-.content span.mod, .content a.mod, .block a.current.mod { color: #4d76ae; }
-.content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; }
+.content span.mod, .content a.mod, .block a.current.mod { color: #bda000; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #b78cf2; }
 .content span.fn, .content a.fn, .block a.current.fn,
 .content span.method, .content a.method, .block a.current.method,
 .content span.tymethod, .content a.tymethod, .block a.current.tymethod,
-.content .fnname { color: #9a6e31; }
+.content .fnname{ color: #2BAB63; }
 
-pre.rust .comment { color: #8E908C; }
-pre.rust .doccomment { color: #4D4D4C; }
+pre.rust .comment { color: #8d8d8b; }
+pre.rust .doccomment { color: #8ca375; }
 
 nav {
-	border-bottom-color: #e0e0e0;
+	border-bottom-color: #4e4e4e;
 }
 nav.main .current {
-	border-top-color: #000;
-	border-bottom-color: #000;
+	border-top-color: #eee;
+	border-bottom-color: #eee;
 }
 nav.main .separator {
-	border: 1px solid #000;
+	border-color: #eee;
 }
 a {
-	color: #000;
+	color: #ddd;
 }
 
 .docblock a, .docblock-short a, .stability a {
-	color: #3873AD;
+	color: #D2991D;
 }
 
 a.test-arrow {
-	color: #f5f5f5;
+	color: #dedede;
 }
 
 .collapse-toggle {
@@ -176,27 +173,32 @@
 }
 
 .search-input {
-	color: #555;
-	box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
-	background-color: white;
+	color: #111;
+	box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
+	background-color: #f0f0f0;
 }
 
 .search-input:focus {
-	border-color: #66afe9;
+	border-color: #008dfd;
 }
 
-.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
-.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
-.stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #404040; }
+.stab.deprecated { background: #F3DFFF; border-color: #7F0087;  color: #404040; }
+.stab.portability { background: #C4ECFF; border-color: #7BA5DB;  color: #404040; }
+
+.module-item .stab {
+	color: #ddd;
+}
 
 #help > div {
-	background: #e9e9e9;
+	background: #4d4d4d;
 	border-color: #bfbfbf;
 }
 
 #help dt {
 	border-color: #bfbfbf;
 	background: #fff;
+	color: black;
 }
 
 .since {
@@ -204,19 +206,19 @@
 }
 
 tr.result span.primitive::after {
-	color: black;
+	color: #ddd;
 }
 
 .line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
-pre.rust .kw { color: #8959A8; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
-pre.rust .number, pre.rust .string { color: #718C00; }
+pre.rust .kw { color: #ab8ac1; }
+pre.rust .kw-2, pre.rust .prelude-ty { color: #769acb; }
+pre.rust .number, pre.rust .string { color: #83a300; }
 pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
+pre.rust .attribute, pre.rust .attribute .ident { color: #ee6868; }
 pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #B76514; }
+pre.rust .lifetime { color: #d97f26; }
 pre.rust .question-mark {
 	color: #ff9011;
 }
@@ -238,7 +240,7 @@
 }
 
 pre.compile_fail {
-	border-left: 2px solid rgba(255,0,0,.4);
+	border-left: 2px solid rgba(255,0,0,.6);
 }
 
 pre.compile_fail:hover, .information:hover + pre.compile_fail {
@@ -246,7 +248,7 @@
 }
 
 pre.ignore {
-	border-left: 2px solid rgba(255,142,0,.4);
+	border-left: 2px solid rgba(255,142,0,.6);
 }
 
 pre.ignore:hover, .information:hover + pre.ignore {
@@ -254,7 +256,7 @@
 }
 
 .tooltip.compile_fail {
-	color: rgba(255,0,0,.3);
+	color: rgba(255,0,0,.6);
 }
 
 .information > .compile_fail:hover {
@@ -262,7 +264,7 @@
 }
 
 .tooltip.ignore {
-	color: rgba(255,142,0,.3);
+	color: rgba(255,142,0,.6);
 }
 
 .information > .ignore:hover {
@@ -309,12 +311,12 @@
 }
 
 .modal-content {
-	background-color: #eee;
+	background-color: #272727;
 	border-color: #999;
 }
 
 .modal-content > .close {
-	background-color: #eee;
+	background-color: #272727;
 	border-color: #999;
 }
 
@@ -324,7 +326,7 @@
 }
 
 .modal-content > .whiter {
-	background-color: #eee;
+	background-color: #272727;
 }
 
 .modal-content > .close:hover + .whiter {
@@ -333,18 +335,50 @@
 
 @media (max-width: 700px) {
 	.sidebar-menu {
-		background-color: #F1F1F1;
+		background-color: #505050;
 		border-bottom-color: #e0e0e0;
 		border-right-color: #e0e0e0;
 	}
 
 	.sidebar-elems {
-		background-color: #F1F1F1;
+		background-color: #505050;
 		border-right-color: #000;
 	}
 
 	#sidebar-filler {
-		background-color: #F1F1F1;
+		background-color: #505050;
 		border-bottom-color: #e0e0e0;
 	}
 }
+
+kbd {
+	color: #444d56;
+	background-color: #fafbfc;
+	border-color: #d1d5da;
+	border-bottom-color: #c6cbd1;
+	box-shadow-color: #c6cbd1;
+}
+
+#theme-picker {
+	border-color: #e0e0e0;
+	background: #f0f0f0;
+}
+
+#theme-choices {
+	border-color: #e0e0e0;
+	background-color: #353535;
+}
+
+#theme-choices > div {
+	border-top: #e0e0e0;
+}
+
+#theme-choices > div:hover {
+	background-color: #444;
+}
+
+@media (max-width: 700px) {
+	#theme-picker {
+		background: #353535;
+	}
+}
diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/themes/main.css
similarity index 94%
rename from src/librustdoc/html/static/styles/main.css
rename to src/librustdoc/html/static/themes/main.css
index c79413c..84b21e7 100644
--- a/src/librustdoc/html/static/styles/main.css
+++ b/src/librustdoc/html/static/themes/main.css
@@ -194,11 +194,6 @@
 	border-color: #bfbfbf;
 }
 
-#help dt {
-	border-color: #bfbfbf;
-	background: #fff;
-}
-
 .since {
 	color: grey;
 }
@@ -348,3 +343,34 @@
 		border-bottom-color: #e0e0e0;
 	}
 }
+
+kbd {
+	color: #444d56;
+	background-color: #fafbfc;
+	border-color: #d1d5da;
+	border-bottom-color: #c6cbd1;
+	box-shadow-color: #c6cbd1;
+}
+
+#theme-picker {
+	border-color: #e0e0e0;
+}
+
+#theme-choices {
+	border-color: #ccc;
+	background-color: #fff;
+}
+
+#theme-choices > div {
+	border-top: #e0e0e0;
+}
+
+#theme-choices > div:hover {
+	background-color: #eee;
+}
+
+@media (max-width: 700px) {
+	#theme-picker {
+		background: #fff;
+	}
+}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 7ebacde..ccd79e5 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -18,6 +18,7 @@
 #![feature(rustc_private)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(fs_read_write)]
 #![feature(libc)]
 #![feature(set_stdio)]
 #![feature(slice_patterns)]
@@ -33,7 +34,7 @@
 extern crate rustc;
 extern crate rustc_data_structures;
 extern crate rustc_const_math;
-extern crate rustc_trans;
+extern crate rustc_trans_utils;
 extern crate rustc_driver;
 extern crate rustc_resolve;
 extern crate rustc_lint;
@@ -62,6 +63,8 @@
 use std::process;
 use std::sync::mpsc::channel;
 
+use rustc_driver::rustc_trans;
+
 use externalfiles::ExternalHtml;
 use rustc::session::search_paths::SearchPaths;
 use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options,
@@ -241,8 +244,8 @@
                       or `#![doc(html_playground_url=...)]`",
                      "URL")
         }),
-        unstable("enable-commonmark", |o| {
-            o.optflag("", "enable-commonmark", "to enable commonmark doc rendering/testing")
+        unstable("disable-commonmark", |o| {
+            o.optflag("", "disable-commonmark", "to disable commonmark doc rendering/testing")
         }),
         unstable("display-warnings", |o| {
             o.optflag("", "display-warnings", "to print code warnings when testing doc")
@@ -257,6 +260,15 @@
             o.optflag("", "sort-modules-by-appearance", "sort modules by where they appear in the \
                                                          program, rather than alphabetically")
         }),
+        unstable("deny-render-differences", |o| {
+            o.optflag("", "deny-render-differences", "abort doc runs when markdown rendering \
+                                                      differences are found")
+        }),
+        unstable("themes", |o| {
+            o.optmulti("", "themes",
+                       "additional themes which will be added to the generated docs",
+                       "FILES")
+        }),
     ]
 }
 
@@ -342,10 +354,10 @@
     let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s));
     let cfgs = matches.opt_strs("cfg");
 
-    let render_type = if matches.opt_present("enable-commonmark") {
-        RenderType::Pulldown
-    } else {
+    let render_type = if matches.opt_present("disable-commonmark") {
         RenderType::Hoedown
+    } else {
+        RenderType::Pulldown
     };
 
     if let Some(ref p) = css_file_extension {
@@ -358,6 +370,15 @@
         }
     }
 
+    let mut themes = Vec::new();
+    for theme in matches.opt_strs("themes").iter().map(|s| PathBuf::from(&s)) {
+        if !theme.is_file() {
+            eprintln!("rustdoc: option --themes arguments must all be files");
+            return 1;
+        }
+        themes.push(theme);
+    }
+
     let external_html = match ExternalHtml::load(
             &matches.opt_strs("html-in-header"),
             &matches.opt_strs("html-before-content"),
@@ -393,6 +414,7 @@
     }
 
     let output_format = matches.opt_str("w");
+    let deny_render_differences = matches.opt_present("deny-render-differences");
     let res = acquire_input(PathBuf::from(input), externs, &matches, move |out| {
         let Output { krate, passes, renderinfo } = out;
         info!("going to format");
@@ -404,7 +426,9 @@
                                   css_file_extension,
                                   renderinfo,
                                   render_type,
-                                  sort_modules_alphabetically)
+                                  sort_modules_alphabetically,
+                                  deny_render_differences,
+                                  themes)
                     .expect("failed to generate documentation");
                 0
             }
@@ -494,6 +518,11 @@
     let crate_name = matches.opt_str("crate-name");
     let crate_version = matches.opt_str("crate-version");
     let plugin_path = matches.opt_str("plugin-path");
+    let render_type = if matches.opt_present("disable-commonmark") {
+        RenderType::Hoedown
+    } else {
+        RenderType::Pulldown
+    };
 
     info!("starting to run rustc");
     let display_warnings = matches.opt_present("display-warnings");
@@ -508,7 +537,7 @@
 
         let (mut krate, renderinfo) =
             core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
-                           display_warnings, force_unstable_if_unmarked);
+                           display_warnings, force_unstable_if_unmarked, render_type);
 
         info!("finished with rustc");
 
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index af93505..9af2ebf 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -104,7 +104,7 @@
     } else {
         // Save the state of USED_ID_MAP so it only gets updated once even
         // though we're rendering twice.
-        render_text(|ty| format!("{}", Markdown(text, ty)))
+        render_text(|ty| format!("{}", Markdown(text, &[], ty)))
     };
 
     let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 3e15d3d..32f0bca 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -116,7 +116,7 @@
             // handled in the `strip-priv-imports` pass
             clean::ExternCrateItem(..) | clean::ImportItem(..) => {}
 
-            clean::AutoImplItem(..) | clean::ImplItem(..) => {}
+            clean::ImplItem(..) => {}
 
             // tymethods/macros have no control over privacy
             clean::MacroItem(..) | clean::TyMethodItem(..) => {}
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 8e861f1..10850f8 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -34,7 +34,6 @@
 use rustc_metadata::cstore::CStore;
 use rustc_resolve::MakeGlobMap;
 use rustc_trans;
-use rustc_trans::back::link;
 use syntax::ast;
 use syntax::codemap::CodeMap;
 use syntax::feature_gate::UnstableFeatures;
@@ -82,11 +81,11 @@
                                           true, false,
                                           Some(codemap.clone()));
 
-    let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, Some(input_path.to_owned()), handler, codemap.clone(),
     );
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     sess.parse_sess.config =
         config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
@@ -108,7 +107,7 @@
     };
 
     let crate_name = crate_name.unwrap_or_else(|| {
-        link::find_crate_name(None, &hir_forest.krate().attrs, &input)
+        ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input)
     });
     let opts = scrape_test_config(hir_forest.krate());
     let mut collector = Collector::new(crate_name,
@@ -176,7 +175,8 @@
     opts
 }
 
-fn run_test(test: &str, cratename: &str, filename: &FileName, cfgs: Vec<String>, libs: SearchPaths,
+fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
+            cfgs: Vec<String>, libs: SearchPaths,
             externs: Externs,
             should_panic: bool, no_run: bool, as_test_harness: bool,
             compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
@@ -184,7 +184,7 @@
             linker: Option<PathBuf>) {
     // the test harness wants its own `main` & top level functions, so
     // never wrap the test in `fn main() { ... }`
-    let test = make_test(test, Some(cratename), as_test_harness, opts);
+    let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts);
     // FIXME(#44940): if doctests ever support path remapping, then this filename
     // needs to be the result of CodeMap::span_to_unmapped_path
     let input = config::Input::Str {
@@ -234,7 +234,9 @@
         }
     }
     let data = Arc::new(Mutex::new(Vec::new()));
-    let codemap = Rc::new(CodeMap::new(sessopts.file_path_mapping()));
+    let codemap = Rc::new(CodeMap::new_doctest(
+        sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize
+    ));
     let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
                                                       Some(codemap.clone()),
                                                       false);
@@ -244,11 +246,11 @@
     // Compile the code
     let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
 
-    let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, None, diagnostic_handler, codemap,
     );
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
@@ -263,7 +265,17 @@
     }
 
     let res = panic::catch_unwind(AssertUnwindSafe(|| {
-        driver::compile_input(&sess, &cstore, &None, &input, &out, &None, None, &control)
+        driver::compile_input(
+            trans,
+            &sess,
+            &cstore,
+            &None,
+            &input,
+            &out,
+            &None,
+            None,
+            &control
+        )
     }));
 
     let compile_result = match res {
@@ -326,13 +338,14 @@
     }
 }
 
+/// Makes the test file. Also returns the number of lines before the code begins
 pub fn make_test(s: &str,
                  cratename: Option<&str>,
                  dont_insert_main: bool,
                  opts: &TestOptions)
-                 -> String {
+                 -> (String, usize) {
     let (crate_attrs, everything_else) = partition_source(s);
-
+    let mut line_offset = 0;
     let mut prog = String::new();
 
     if opts.attrs.is_empty() {
@@ -341,11 +354,13 @@
         // commonly used to make tests fail in case they trigger warnings, so having this there in
         // that case may cause some tests to pass when they shouldn't have.
         prog.push_str("#![allow(unused)]\n");
+        line_offset += 1;
     }
 
     // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
     for attr in &opts.attrs {
         prog.push_str(&format!("#![{}]\n", attr));
+        line_offset += 1;
     }
 
     // Now push any outer attributes from the example, assuming they
@@ -358,6 +373,7 @@
         if let Some(cratename) = cratename {
             if s.contains(cratename) {
                 prog.push_str(&format!("extern crate {};\n", cratename));
+                line_offset += 1;
             }
         }
     }
@@ -379,6 +395,7 @@
         prog.push_str(&everything_else);
     } else {
         prog.push_str("fn main() {\n");
+        line_offset += 1;
         prog.push_str(&everything_else);
         prog = prog.trim().into();
         prog.push_str("\n}");
@@ -386,7 +403,7 @@
 
     info!("final test program: {}", prog);
 
-    prog
+    (prog, line_offset)
 }
 
 // FIXME(aburka): use a real parser to deal with multiline attributes
@@ -543,6 +560,7 @@
                         run_test(&test,
                                  &cratename,
                                  &filename,
+                                 line,
                                  cfgs,
                                  libs,
                                  externs,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index be78935..3b88282 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -23,6 +23,7 @@
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::cstore::{LoadedMacro, CrateStore};
 use rustc::middle::privacy::AccessLevel;
+use rustc::ty::Visibility;
 use rustc::util::nodemap::FxHashSet;
 
 use rustc::hir;
@@ -39,11 +40,11 @@
 // also, is there some reason that this doesn't use the 'visit'
 // framework from syntax?
 
-pub struct RustdocVisitor<'a, 'tcx: 'a> {
-    cstore: &'tcx CrateStore,
+pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
+    cstore: &'a CrateStore,
     pub module: Module,
     pub attrs: hir::HirVec<ast::Attribute>,
-    pub cx: &'a core::DocContext<'a, 'tcx>,
+    pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>,
     view_item_stack: FxHashSet<ast::NodeId>,
     inlining: bool,
     /// Is the current module and all of its parents public?
@@ -51,10 +52,10 @@
     reexported_macros: FxHashSet<DefId>,
 }
 
-impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
-    pub fn new(cstore: &'tcx CrateStore,
-               cx: &'a core::DocContext<'a, 'tcx>) -> RustdocVisitor<'a, 'tcx> {
-        // If the root is reexported, terminate all recursion.
+impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
+    pub fn new(cstore: &'a CrateStore,
+               cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> RustdocVisitor<'a, 'tcx, 'rcx> {
+        // If the root is re-exported, terminate all recursion.
         let mut stack = FxHashSet();
         stack.insert(ast::CRATE_NODE_ID);
         RustdocVisitor {
@@ -204,7 +205,7 @@
         self.inside_public_path = orig_inside_public_path;
         let def_id = self.cx.tcx.hir.local_def_id(id);
         if let Some(exports) = self.cx.tcx.module_exports(def_id) {
-            for export in exports.iter() {
+            for export in exports.iter().filter(|e| e.vis == Visibility::Public) {
                 if let Def::Macro(def_id, ..) = export.def {
                     if def_id.krate == LOCAL_CRATE || self.reexported_macros.contains(&def_id) {
                         continue // These are `krate.exported_macros`, handled in `self.visit()`.
@@ -213,7 +214,7 @@
                     let imported_from = self.cx.tcx.original_crate_name(def_id.krate);
                     let def = match self.cstore.load_macro_untracked(def_id, self.cx.sess()) {
                         LoadedMacro::MacroDef(macro_def) => macro_def,
-                        // FIXME(jseyfried): document proc macro reexports
+                        // FIXME(jseyfried): document proc macro re-exports
                         LoadedMacro::ProcMacro(..) => continue,
                     };
 
@@ -493,11 +494,12 @@
                 };
                 om.constants.push(s);
             },
-            hir::ItemTrait(_, unsafety, ref gen, ref b, ref item_ids) => {
+            hir::ItemTrait(is_auto, unsafety, ref gen, ref b, ref item_ids) => {
                 let items = item_ids.iter()
                                     .map(|ti| self.cx.tcx.hir.trait_item(ti.id).clone())
                                     .collect();
                 let t = Trait {
+                    is_auto,
                     unsafety,
                     name,
                     items,
@@ -547,19 +549,6 @@
                     om.impls.push(i);
                 }
             },
-            hir::ItemAutoImpl(unsafety, ref trait_ref) => {
-                // See comment above about ItemImpl.
-                if !self.inlining {
-                    let i = AutoImpl {
-                        unsafety,
-                        trait_: trait_ref.clone(),
-                        id: item.id,
-                        attrs: item.attrs.clone(),
-                        whence: item.span,
-                    };
-                    om.def_traits.push(i);
-                }
-            }
         }
     }
 
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 2fd47fa..15a8b58 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -22,8 +22,8 @@
 
 /// Similar to `librustc_privacy::EmbargoVisitor`, but also takes
 /// specific rustdoc annotations into account (i.e. `doc(hidden)`)
-pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    cx: &'a ::core::DocContext<'b, 'tcx>,
+pub struct LibEmbargoVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
+    cx: &'a ::core::DocContext<'a, 'tcx, 'rcx>,
     // Accessibility levels for reachable nodes
     access_levels: RefMut<'a, AccessLevels<DefId>>,
     // Previous accessibility level, None means unreachable
@@ -32,8 +32,8 @@
     visited_mods: FxHashSet<DefId>,
 }
 
-impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
-    pub fn new(cx: &'a ::core::DocContext<'b, 'tcx>) -> LibEmbargoVisitor<'a, 'b, 'tcx> {
+impl<'a, 'tcx, 'rcx> LibEmbargoVisitor<'a, 'tcx, 'rcx> {
+    pub fn new(cx: &'a ::core::DocContext<'a, 'tcx, 'rcx>) -> LibEmbargoVisitor<'a, 'tcx, 'rcx> {
         LibEmbargoVisitor {
             cx,
             access_levels: cx.access_levels.borrow_mut(),
diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs
index de7eebe..3a05cb7 100644
--- a/src/libserialize/collection_impls.rs
+++ b/src/libserialize/collection_impls.rs
@@ -241,4 +241,4 @@
             Ok(vec.into())
         })
     }
-}
\ No newline at end of file
+}
diff --git a/src/libserialize/leb128.rs b/src/libserialize/leb128.rs
index a963871..1786e29 100644
--- a/src/libserialize/leb128.rs
+++ b/src/libserialize/leb128.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #[inline]
-fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
+pub fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
     if position == vec.len() {
         vec.push(byte);
     } else {
@@ -17,57 +17,87 @@
     }
 }
 
-#[inline]
-/// encodes an integer using unsigned leb128 encoding and stores
-/// the result using a callback function.
-///
-/// The callback `write` is called once for each position
-/// that is to be written to with the byte to be encoded
-/// at that position.
-pub fn write_unsigned_leb128_to<W>(mut value: u128, mut write: W) -> usize
-    where W: FnMut(usize, u8)
-{
-    let mut position = 0;
-    loop {
-        let mut byte = (value & 0x7F) as u8;
-        value >>= 7;
-        if value != 0 {
-            byte |= 0x80;
-        }
+#[cfg(target_pointer_width = "32")]
+const USIZE_LEB128_SIZE: usize = 5;
+#[cfg(target_pointer_width = "64")]
+const USIZE_LEB128_SIZE: usize = 10;
 
-        write(position, byte);
-        position += 1;
-
-        if value == 0 {
-            break;
-        }
-    }
-
-    position
+macro_rules! leb128_size {
+    (u16) => (3);
+    (u32) => (5);
+    (u64) => (10);
+    (u128) => (19);
+    (usize) => (USIZE_LEB128_SIZE);
 }
 
-pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u128) -> usize {
-    write_unsigned_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
-}
+macro_rules! impl_write_unsigned_leb128 {
+    ($fn_name:ident, $int_ty:ident) => (
+        #[inline]
+        pub fn $fn_name(out: &mut Vec<u8>, start_position: usize, mut value: $int_ty) -> usize {
+            let mut position = start_position;
+            for _ in 0 .. leb128_size!($int_ty) {
+                let mut byte = (value & 0x7F) as u8;
+                value >>= 7;
+                if value != 0 {
+                    byte |= 0x80;
+                }
 
-#[inline]
-pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u128, usize) {
-    let mut result = 0;
-    let mut shift = 0;
-    let mut position = start_position;
-    loop {
-        let byte = data[position];
-        position += 1;
-        result |= ((byte & 0x7F) as u128) << shift;
-        if (byte & 0x80) == 0 {
-            break;
+                write_to_vec(out, position, byte);
+                position += 1;
+
+                if value == 0 {
+                    break;
+                }
+            }
+
+            position - start_position
         }
-        shift += 7;
-    }
-
-    (result, position - start_position)
+    )
 }
 
+impl_write_unsigned_leb128!(write_u16_leb128, u16);
+impl_write_unsigned_leb128!(write_u32_leb128, u32);
+impl_write_unsigned_leb128!(write_u64_leb128, u64);
+impl_write_unsigned_leb128!(write_u128_leb128, u128);
+impl_write_unsigned_leb128!(write_usize_leb128, usize);
+
+
+macro_rules! impl_read_unsigned_leb128 {
+    ($fn_name:ident, $int_ty:ident) => (
+        #[inline]
+        pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
+            let mut result: $int_ty = 0;
+            let mut shift = 0;
+            let mut position = 0;
+
+            for _ in 0 .. leb128_size!($int_ty) {
+                let byte = unsafe {
+                    *slice.get_unchecked(position)
+                };
+                position += 1;
+                result |= ((byte & 0x7F) as $int_ty) << shift;
+                if (byte & 0x80) == 0 {
+                    break;
+                }
+                shift += 7;
+            }
+
+            // Do a single bounds check at the end instead of for every byte.
+            assert!(position <= slice.len());
+
+            (result, position)
+        }
+    )
+}
+
+impl_read_unsigned_leb128!(read_u16_leb128, u16);
+impl_read_unsigned_leb128!(read_u32_leb128, u32);
+impl_read_unsigned_leb128!(read_u64_leb128, u64);
+impl_read_unsigned_leb128!(read_u128_leb128, u128);
+impl_read_unsigned_leb128!(read_usize_leb128, usize);
+
+
+
 #[inline]
 /// encodes an integer using signed leb128 encoding and stores
 /// the result using a callback function.
@@ -130,26 +160,36 @@
     (result, position - start_position)
 }
 
-#[test]
-fn test_unsigned_leb128() {
-    let mut stream = Vec::with_capacity(10000);
+macro_rules! impl_test_unsigned_leb128 {
+    ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => (
+        #[test]
+        fn $test_name() {
+            let mut stream = Vec::new();
 
-    for x in 0..62 {
-        let pos = stream.len();
-        let bytes_written = write_unsigned_leb128(&mut stream, pos, 3 << x);
-        assert_eq!(stream.len(), pos + bytes_written);
-    }
+            for x in 0..62 {
+                let pos = stream.len();
+                let bytes_written = $write_fn_name(&mut stream, pos, (3u64 << x) as $int_ty);
+                assert_eq!(stream.len(), pos + bytes_written);
+            }
 
-    let mut position = 0;
-    for x in 0..62 {
-        let expected = 3 << x;
-        let (actual, bytes_read) = read_unsigned_leb128(&stream, position);
-        assert_eq!(expected, actual);
-        position += bytes_read;
-    }
-    assert_eq!(stream.len(), position);
+            let mut position = 0;
+            for x in 0..62 {
+                let expected = (3u64 << x) as $int_ty;
+                let (actual, bytes_read) = $read_fn_name(&stream[position ..]);
+                assert_eq!(expected, actual);
+                position += bytes_read;
+            }
+            assert_eq!(stream.len(), position);
+        }
+    )
 }
 
+impl_test_unsigned_leb128!(test_u16_leb128, write_u16_leb128, read_u16_leb128, u16);
+impl_test_unsigned_leb128!(test_u32_leb128, write_u32_leb128, read_u32_leb128, u32);
+impl_test_unsigned_leb128!(test_u64_leb128, write_u64_leb128, read_u64_leb128, u64);
+impl_test_unsigned_leb128!(test_u128_leb128, write_u128_leb128, read_u128_leb128, u128);
+impl_test_unsigned_leb128!(test_usize_leb128, write_usize_leb128, read_usize_leb128, usize);
+
 #[test]
 fn test_signed_leb128() {
     let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs
index 9955765..077efad 100644
--- a/src/libserialize/opaque.rs
+++ b/src/libserialize/opaque.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128};
+use leb128::{self, read_signed_leb128, write_signed_leb128};
 use std::borrow::Cow;
 use std::io::{self, Write};
 use serialize;
@@ -27,13 +27,17 @@
     pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> {
         Encoder { cursor: cursor }
     }
+
+    pub fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
+        self.cursor.write_all(s)
+    }
 }
 
 
 macro_rules! write_uleb128 {
-    ($enc:expr, $value:expr) => {{
+    ($enc:expr, $value:expr, $fun:ident) => {{
         let pos = $enc.cursor.position() as usize;
-        let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u128);
+        let bytes_written = leb128::$fun($enc.cursor.get_mut(), pos, $value);
         $enc.cursor.set_position((pos + bytes_written) as u64);
         Ok(())
     }}
@@ -51,61 +55,76 @@
 impl<'a> serialize::Encoder for Encoder<'a> {
     type Error = io::Error;
 
+    #[inline]
     fn emit_nil(&mut self) -> EncodeResult {
         Ok(())
     }
 
+    #[inline]
     fn emit_usize(&mut self, v: usize) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_usize_leb128)
     }
 
+    #[inline]
     fn emit_u128(&mut self, v: u128) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u128_leb128)
     }
 
+    #[inline]
     fn emit_u64(&mut self, v: u64) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u64_leb128)
     }
 
+    #[inline]
     fn emit_u32(&mut self, v: u32) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u32_leb128)
     }
 
+    #[inline]
     fn emit_u16(&mut self, v: u16) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u16_leb128)
     }
 
+    #[inline]
     fn emit_u8(&mut self, v: u8) -> EncodeResult {
-        let _ = self.cursor.write_all(&[v]);
+        let pos = self.cursor.position() as usize;
+        leb128::write_to_vec(self.cursor.get_mut(), pos, v);
+        self.cursor.set_position((pos + 1) as u64);
         Ok(())
     }
 
+    #[inline]
     fn emit_isize(&mut self, v: isize) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i128(&mut self, v: i128) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i64(&mut self, v: i64) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i32(&mut self, v: i32) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i16(&mut self, v: i16) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i8(&mut self, v: i8) -> EncodeResult {
         let as_u8: u8 = unsafe { ::std::mem::transmute(v) };
-        let _ = self.cursor.write_all(&[as_u8]);
-        Ok(())
+        self.emit_u8(as_u8)
     }
 
+    #[inline]
     fn emit_bool(&mut self, v: bool) -> EncodeResult {
         self.emit_u8(if v {
             1
@@ -114,20 +133,24 @@
         })
     }
 
+    #[inline]
     fn emit_f64(&mut self, v: f64) -> EncodeResult {
         let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
         self.emit_u64(as_u64)
     }
 
+    #[inline]
     fn emit_f32(&mut self, v: f32) -> EncodeResult {
         let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
         self.emit_u32(as_u32)
     }
 
+    #[inline]
     fn emit_char(&mut self, v: char) -> EncodeResult {
         self.emit_u32(v as u32)
     }
 
+    #[inline]
     fn emit_str(&mut self, v: &str) -> EncodeResult {
         self.emit_usize(v.len())?;
         let _ = self.cursor.write_all(v.as_bytes());
@@ -136,6 +159,7 @@
 }
 
 impl<'a> Encoder<'a> {
+    #[inline]
     pub fn position(&self) -> usize {
         self.cursor.position() as usize
     }
@@ -158,24 +182,38 @@
         }
     }
 
+    #[inline]
     pub fn position(&self) -> usize {
         self.position
     }
 
+    #[inline]
     pub fn set_position(&mut self, pos: usize) {
         self.position = pos
     }
 
+    #[inline]
     pub fn advance(&mut self, bytes: usize) {
         self.position += bytes;
     }
+
+    pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
+        let start = self.position;
+        let end = start + s.len();
+
+        s.copy_from_slice(&self.data[start..end]);
+
+        self.position = end;
+
+        Ok(())
+    }
 }
 
 macro_rules! read_uleb128 {
-    ($dec:expr, $t:ty) => ({
-        let (value, bytes_read) = read_unsigned_leb128($dec.data, $dec.position);
+    ($dec:expr, $t:ty, $fun:ident) => ({
+        let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position ..]);
         $dec.position += bytes_read;
-        Ok(value as $t)
+        Ok(value)
     })
 }
 
@@ -198,22 +236,22 @@
 
     #[inline]
     fn read_u128(&mut self) -> Result<u128, Self::Error> {
-        read_uleb128!(self, u128)
+        read_uleb128!(self, u128, read_u128_leb128)
     }
 
     #[inline]
     fn read_u64(&mut self) -> Result<u64, Self::Error> {
-        read_uleb128!(self, u64)
+        read_uleb128!(self, u64, read_u64_leb128)
     }
 
     #[inline]
     fn read_u32(&mut self) -> Result<u32, Self::Error> {
-        read_uleb128!(self, u32)
+        read_uleb128!(self, u32, read_u32_leb128)
     }
 
     #[inline]
     fn read_u16(&mut self) -> Result<u16, Self::Error> {
-        read_uleb128!(self, u16)
+        read_uleb128!(self, u16, read_u16_leb128)
     }
 
     #[inline]
@@ -225,7 +263,7 @@
 
     #[inline]
     fn read_usize(&mut self) -> Result<usize, Self::Error> {
-        read_uleb128!(self, usize)
+        read_uleb128!(self, usize, read_usize_leb128)
     }
 
     #[inline]
diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs
index 6d67bbc..854ca4e 100644
--- a/src/libserialize/serialize.rs
+++ b/src/libserialize/serialize.rs
@@ -618,6 +618,54 @@
     }
 }
 
+impl<T1: Encodable, T2: Encodable> Encodable for Result<T1, T2> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_enum("Result", |s| {
+            match *self {
+                Ok(ref v) => {
+                    s.emit_enum_variant("Ok", 0, 1, |s| {
+                        s.emit_enum_variant_arg(0, |s| {
+                            v.encode(s)
+                        })
+                    })
+                }
+                Err(ref v) => {
+                    s.emit_enum_variant("Err", 1, 1, |s| {
+                        s.emit_enum_variant_arg(0, |s| {
+                            v.encode(s)
+                        })
+                    })
+                }
+            }
+        })
+    }
+}
+
+impl<T1:Decodable, T2:Decodable> Decodable for Result<T1, T2> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Result<T1, T2>, D::Error> {
+        d.read_enum("Result", |d| {
+            d.read_enum_variant(&["Ok", "Err"], |d, disr| {
+                match disr {
+                    0 => {
+                        Ok(Ok(d.read_enum_variant_arg(0, |d| {
+                            T1::decode(d)
+                        })?))
+                    }
+                    1 => {
+                        Ok(Err(d.read_enum_variant_arg(0, |d| {
+                            T2::decode(d)
+                        })?))
+                    }
+                    _ => {
+                        panic!("Encountered invalid discriminant while \
+                                decoding `Result`.");
+                    }
+                }
+            })
+        })
+    }
+}
+
 macro_rules! peel {
     ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })
 }
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 92507a7..82e1a34 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -247,7 +247,7 @@
     /// Checks if the value is an ASCII graphic character:
     /// U+0021 '@' ... U+007E '~'.
     /// For strings, true if all characters in the string are
-    /// ASCII punctuation.
+    /// ASCII graphic characters.
     ///
     /// # Note
     ///
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 06f11c8..a41c155 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -14,15 +14,16 @@
 
 use std::env;
 use std::process::Command;
-use build_helper::{run, native_lib_boilerplate, BuildExpectation};
+use build_helper::{run, native_lib_boilerplate};
 
 fn main() {
     let target = env::var("TARGET").expect("TARGET was not set");
     let host = env::var("HOST").expect("HOST was not set");
     if cfg!(feature = "backtrace") &&
-        !target.contains("msvc") &&
+        !target.contains("cloudabi") &&
         !target.contains("emscripten") &&
         !target.contains("fuchsia") &&
+        !target.contains("msvc") &&
         !target.contains("wasm32")
     {
         let _ = build_libbacktrace(&host, &target);
@@ -74,6 +75,12 @@
         println!("cargo:rustc-link-lib=zircon");
         println!("cargo:rustc-link-lib=fdio");
         println!("cargo:rustc-link-lib=launchpad"); // for std::process
+    } else if target.contains("cloudabi") {
+        if cfg!(feature = "backtrace") {
+            println!("cargo:rustc-link-lib=unwind");
+        }
+        println!("cargo:rustc-link-lib=c");
+        println!("cargo:rustc-link-lib=compiler_rt");
     }
 }
 
@@ -91,14 +98,11 @@
                 .arg("--disable-host-shared")
                 .arg(format!("--host={}", build_helper::gnu_target(target)))
                 .arg(format!("--build={}", build_helper::gnu_target(host)))
-                .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"),
-        BuildExpectation::None);
+                .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"));
 
     run(Command::new(build_helper::make(host))
                 .current_dir(&native.out_dir)
                 .arg(format!("INCDIR={}", native.src_dir.display()))
-                .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")),
-        BuildExpectation::None);
-
+                .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
     Ok(())
 }
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 7a79a47..4e5385c 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1241,6 +1241,46 @@
         self.search_mut(k).into_occupied_bucket().map(|bucket| pop_internal(bucket).1)
     }
 
+    /// Removes a key from the map, returning the stored key and value if the
+    /// key was previously in the map.
+    ///
+    /// The key may be any borrowed form of the map's key type, but
+    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+    /// the key type.
+    ///
+    /// [`Eq`]: ../../std/cmp/trait.Eq.html
+    /// [`Hash`]: ../../std/hash/trait.Hash.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(hash_map_remove_entry)]
+    /// use std::collections::HashMap;
+    ///
+    /// # fn main() {
+    /// let mut map = HashMap::new();
+    /// map.insert(1, "a");
+    /// assert_eq!(map.remove_entry(&1), Some((1, "a")));
+    /// assert_eq!(map.remove(&1), None);
+    /// # }
+    /// ```
+    #[unstable(feature = "hash_map_remove_entry", issue = "46344")]
+    pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
+        where K: Borrow<Q>,
+              Q: Hash + Eq
+    {
+        if self.table.size() == 0 {
+            return None;
+        }
+
+        self.search_mut(k)
+            .into_occupied_bucket()
+            .map(|bucket| {
+                let (k, v, _) = pop_internal(bucket);
+                (k, v)
+            })
+    }
+
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
@@ -3040,7 +3080,7 @@
     }
 
     #[test]
-    fn test_pop() {
+    fn test_remove() {
         let mut m = HashMap::new();
         m.insert(1, 2);
         assert_eq!(m.remove(&1), Some(2));
@@ -3048,6 +3088,14 @@
     }
 
     #[test]
+    fn test_remove_entry() {
+        let mut m = HashMap::new();
+        m.insert(1, 2);
+        assert_eq!(m.remove_entry(&1), Some((1, 2)));
+        assert_eq!(m.remove(&1), None);
+    }
+
+    #[test]
     fn test_iterate() {
         let mut m = HashMap::with_capacity(4);
         for i in 0..32 {
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 7f0e5a8..e9427fb 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -527,6 +527,16 @@
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the value type.
     ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+    /// assert_eq!(set.get(&2), Some(&2));
+    /// assert_eq!(set.get(&4), None);
+    /// ```
+    ///
     /// [`Eq`]: ../../std/cmp/trait.Eq.html
     /// [`Hash`]: ../../std/hash/trait.Hash.html
     #[stable(feature = "set_recovery", since = "1.9.0")]
@@ -631,6 +641,19 @@
 
     /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
     /// one. Returns the replaced value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set = HashSet::new();
+    /// set.insert(Vec::<i32>::new());
+    ///
+    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0);
+    /// set.replace(Vec::with_capacity(10));
+    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
+    /// ```
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn replace(&mut self, value: T) -> Option<T> {
         Recover::replace(&mut self.map, value)
@@ -671,6 +694,16 @@
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the value type.
     ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+    /// assert_eq!(set.take(&2), Some(2));
+    /// assert_eq!(set.take(&2), None);
+    /// ```
+    ///
     /// [`Eq`]: ../../std/cmp/trait.Eq.html
     /// [`Hash`]: ../../std/hash/trait.Hash.html
     #[stable(feature = "set_recovery", since = "1.9.0")]
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 96f98ef..73bd574 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -16,7 +16,7 @@
 use mem::{align_of, size_of, needs_drop};
 use mem;
 use ops::{Deref, DerefMut};
-use ptr::{self, Unique, Shared};
+use ptr::{self, Unique, NonNull};
 
 use self::BucketState::*;
 
@@ -873,7 +873,7 @@
                 elems_left,
                 marker: marker::PhantomData,
             },
-            table: Shared::from(self),
+            table: NonNull::from(self),
             marker: marker::PhantomData,
         }
     }
@@ -1020,7 +1020,7 @@
 
 /// Iterator over the entries in a table, clearing the table.
 pub struct Drain<'a, K: 'a, V: 'a> {
-    table: Shared<RawTable<K, V>>,
+    table: NonNull<RawTable<K, V>>,
     iter: RawBuckets<'static, K, V>,
     marker: marker::PhantomData<&'a RawTable<K, V>>,
 }
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index b8a6a66..e9a150f 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -64,11 +64,11 @@
 //! * You want a map, with no extra functionality.
 //!
 //! ### Use a `BTreeMap` when:
+//! * You want a map sorted by its keys.
+//! * You want to be able to get a range of entries on-demand.
 //! * You're interested in what the smallest or largest key-value pair is.
 //! * You want to find the largest or smallest key that is smaller or larger
 //!   than something.
-//! * You want to be able to get all of the entries in order on-demand.
-//! * You want a map sorted by its keys.
 //!
 //! ### Use the `Set` variant of any of these `Map`s when:
 //! * You just want to remember which keys you've seen.
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 457c6e1..27bf326 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -571,8 +571,11 @@
 
 /// Returns the full filesystem path of the current running executable.
 ///
-/// The path returned is not necessarily a "real path" of the executable as
-/// there may be intermediate symlinks.
+/// # Platform-specific behavior
+///
+/// If the executable was invoked through a symbolic link, some platforms will
+/// return the path of the symbolic link and other platforms will return the
+/// path of the symbolic link’s target.
 ///
 /// # Errors
 ///
@@ -599,14 +602,14 @@
 /// Ok("/home/alex/foo")
 /// ```
 ///
-/// And you make a symbolic link of the program:
+/// And you make a hard link of the program:
 ///
 /// ```bash
 /// $ ln foo bar
 /// ```
 ///
-/// When you run it, you won't get the original executable, you'll get the
-/// symlink:
+/// When you run it, you won’t get the path of the original executable, you’ll
+/// get the path of the hard link:
 ///
 /// ```bash
 /// $ ./bar
@@ -614,9 +617,9 @@
 /// ```
 ///
 /// This sort of behavior has been known to [lead to privilege escalation] when
-/// used incorrectly, for example.
+/// used incorrectly.
 ///
-/// [lead to privilege escalation]: http://securityvulns.com/Wdocument183.html
+/// [lead to privilege escalation]: https://securityvulns.com/Wdocument183.html
 ///
 /// # Examples
 ///
@@ -625,7 +628,7 @@
 ///
 /// match env::current_exe() {
 ///     Ok(exe_path) => println!("Path of this executable is: {}",
-///                               exe_path.display()),
+///                              exe_path.display()),
 ///     Err(e) => println!("failed to get current exe path: {}", e),
 /// };
 /// ```
@@ -953,8 +956,7 @@
 mod tests {
     use super::*;
 
-    use ffi::OsStr;
-    use path::{Path, PathBuf};
+    use path::Path;
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
@@ -977,6 +979,8 @@
     #[test]
     #[cfg(windows)]
     fn split_paths_windows() {
+        use path::PathBuf;
+
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
                 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
@@ -997,6 +1001,8 @@
     #[test]
     #[cfg(unix)]
     fn split_paths_unix() {
+        use path::PathBuf;
+
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
                 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
@@ -1012,6 +1018,8 @@
     #[test]
     #[cfg(unix)]
     fn join_paths_unix() {
+        use ffi::OsStr;
+
         fn test_eq(input: &[&str], output: &str) -> bool {
             &*join_paths(input.iter().cloned()).unwrap() ==
                 OsStr::new(output)
@@ -1028,6 +1036,8 @@
     #[test]
     #[cfg(windows)]
     fn join_paths_windows() {
+        use ffi::OsStr;
+
         fn test_eq(input: &[&str], output: &str) -> bool {
             &*join_paths(input.iter().cloned()).unwrap() ==
                 OsStr::new(output)
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 18eb2a2..9810ded 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -13,7 +13,7 @@
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
-//! *[See also the `f32` primitive type](../primitive.f32.html).*
+//! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
@@ -472,20 +472,19 @@
 
     /// Returns the logarithm of the number with respect to an arbitrary base.
     ///
+    /// The result may not be correctly rounded owing to implementation details;
+    /// `self.log2()` can produce more accurate results for base 2, and
+    /// `self.log10()` can produce more accurate results for base 10.
+    ///
     /// ```
     /// use std::f32;
     ///
-    /// let ten = 10.0f32;
-    /// let two = 2.0f32;
+    /// let five = 5.0f32;
     ///
-    /// // log10(10) - 1 == 0
-    /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
+    /// // log5(5) - 1 == 0
+    /// let abs_difference = (five.log(5.0) - 1.0).abs();
     ///
-    /// // log2(2) - 1 == 0
-    /// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
-    ///
-    /// assert!(abs_difference_10 <= f32::EPSILON);
-    /// assert!(abs_difference_2 <= f32::EPSILON);
+    /// assert!(abs_difference <= f32::EPSILON);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index cabb2c4..29ba7d0 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -13,7 +13,7 @@
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
-//! *[See also the `f64` primitive type](../primitive.f64.html).*
+//! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
@@ -432,18 +432,17 @@
 
     /// Returns the logarithm of the number with respect to an arbitrary base.
     ///
+    /// The result may not be correctly rounded owing to implementation details;
+    /// `self.log2()` can produce more accurate results for base 2, and
+    /// `self.log10()` can produce more accurate results for base 10.
+    ///
     /// ```
-    /// let ten = 10.0_f64;
-    /// let two = 2.0_f64;
+    /// let five = 5.0_f64;
     ///
-    /// // log10(10) - 1 == 0
-    /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
+    /// // log5(5) - 1 == 0
+    /// let abs_difference = (five.log(5.0) - 1.0).abs();
     ///
-    /// // log2(2) - 1 == 0
-    /// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
-    ///
-    /// assert!(abs_difference_10 < 1e-10);
-    /// assert!(abs_difference_2 < 1e-10);
+    /// assert!(abs_difference < 1e-10);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index a2022a2..a19fe82 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -706,7 +706,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Arc<CStr> {
     #[inline]
     fn from(s: CString) -> Arc<CStr> {
@@ -715,7 +715,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a CStr> for Arc<CStr> {
     #[inline]
     fn from(s: &CStr) -> Arc<CStr> {
@@ -724,7 +724,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
     #[inline]
     fn from(s: CString) -> Rc<CStr> {
@@ -733,7 +733,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a CStr> for Rc<CStr> {
     #[inline]
     fn from(s: &CStr) -> Rc<CStr> {
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index a755963..a37a5e8 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -53,7 +53,7 @@
 //! terminator, so the buffer length is really `len+1` characters.
 //! Rust strings don't have a nul terminator; their length is always
 //! stored and does not need to be calculated. While in Rust
-//! accessing a string's length is a O(1) operation (becasue the
+//! accessing a string's length is a O(1) operation (because the
 //! length is stored); in C it is an O(length) operation because the
 //! length needs to be computed by scanning the string for the nul
 //! terminator.
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index cb90246..3959e85 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -36,7 +36,7 @@
 /// and platform-native string values, and in particular allowing a Rust string
 /// to be converted into an "OS" string with no cost if possible.
 ///
-/// `OsString` is to [`OsStr`] as [`String`] is to [`&str`]: the former
+/// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
 /// in each pair are owned strings; the latter are borrowed
 /// references.
 ///
@@ -64,6 +64,7 @@
 /// the traits which `OsString` implements for conversions from/to native representations.
 ///
 /// [`OsStr`]: struct.OsStr.html
+/// [`&OsStr`]: struct.OsStr.html
 /// [`From`]: ../convert/trait.From.html
 /// [`String`]: ../string/struct.String.html
 /// [`&str`]: ../primitive.str.html
@@ -84,13 +85,15 @@
 /// This type represents a borrowed reference to a string in the operating system's preferred
 /// representation.
 ///
-/// `OsStr` is to [`OsString`] as [`String`] is to [`&str`]: the former in each pair are borrowed
+/// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed
 /// references; the latter are owned strings.
 ///
 /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
 /// the traits which `OsStr` implements for conversions from/to native representations.
 ///
 /// [`OsString`]: struct.OsString.html
+/// [`&str`]: ../primitive.str.html
+/// [`String`]: ../string/struct.String.html
 /// [conversions]: index.html#conversions
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OsStr {
@@ -594,7 +597,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Arc<OsStr> {
     #[inline]
     fn from(s: OsString) -> Arc<OsStr> {
@@ -603,7 +606,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a OsStr> for Arc<OsStr> {
     #[inline]
     fn from(s: &OsStr) -> Arc<OsStr> {
@@ -612,7 +615,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
     #[inline]
     fn from(s: OsString) -> Rc<OsStr> {
@@ -621,7 +624,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a OsStr> for Rc<OsStr> {
     #[inline]
     fn from(s: &OsStr) -> Rc<OsStr> {
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index f40aed2..d1f3ccb 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -211,6 +211,14 @@
     recursive: bool,
 }
 
+/// How large a buffer to pre-allocate before reading the entire file.
+fn initial_buffer_size(file: &File) -> usize {
+    // Allocate one extra byte so the buffer doesn't need to grow before the
+    // final `read` call at the end of the file.  Don't worry about `usize`
+    // overflow because reading will fail regardless in that case.
+    file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0)
+}
+
 /// Read the entire contents of a file into a bytes vector.
 ///
 /// This is a convenience function for using [`File::open`] and [`read_to_end`]
@@ -246,8 +254,9 @@
 /// ```
 #[unstable(feature = "fs_read_write", issue = "46588")]
 pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
-    let mut bytes = Vec::new();
-    File::open(path)?.read_to_end(&mut bytes)?;
+    let mut file = File::open(path)?;
+    let mut bytes = Vec::with_capacity(initial_buffer_size(&file));
+    file.read_to_end(&mut bytes)?;
     Ok(bytes)
 }
 
@@ -287,8 +296,9 @@
 /// ```
 #[unstable(feature = "fs_read_write", issue = "46588")]
 pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
-    let mut string = String::new();
-    File::open(path)?.read_to_string(&mut string)?;
+    let mut file = File::open(path)?;
+    let mut string = String::with_capacity(initial_buffer_size(&file));
+    file.read_to_string(&mut string)?;
     Ok(string)
 }
 
@@ -1981,7 +1991,7 @@
     }
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::prelude::*;
 
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 8308ab4..4e7db5f 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -194,6 +194,31 @@
     pub fn into_inner(self) -> R { self.inner }
 }
 
+impl<R: Seek> BufReader<R> {
+    /// Seeks relative to the current position. If the new position lies within the buffer,
+    /// the buffer will not be flushed, allowing for more efficient seeks.
+    /// This method does not return the location of the underlying reader, so the caller
+    /// must track this information themselves if it is required.
+    #[unstable(feature = "bufreader_seek_relative", issue = "31100")]
+    pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
+        let pos = self.pos as u64;
+        if offset < 0 {
+            if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
+                self.pos = new_pos as usize;
+                return Ok(())
+            }
+        } else {
+            if let Some(new_pos) = pos.checked_add(offset as u64) {
+                if new_pos <= self.cap as u64 {
+                    self.pos = new_pos as usize;
+                    return Ok(())
+                }
+            }
+        }
+        self.seek(SeekFrom::Current(offset)).map(|_|())
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<R: Read> Read for BufReader<R> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
@@ -260,6 +285,8 @@
     /// `.into_inner()` immediately after a seek yields the underlying reader
     /// at the same position.
     ///
+    /// To seek without discarding the internal buffer, use [`seek_relative`].
+    ///
     /// See `std::io::Seek` for more details.
     ///
     /// Note: In the edge case where you're seeking with `SeekFrom::Current(n)`
@@ -267,6 +294,8 @@
     /// seeks will be performed instead of one. If the second seek returns
     /// `Err`, the underlying reader will be left at the same position it would
     /// have if you seeked to `SeekFrom::Current(0)`.
+    ///
+    /// [`seek_relative`]: #method.seek_relative
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         let result: u64;
         if let SeekFrom::Current(n) = pos {
@@ -316,8 +345,8 @@
 ///
 /// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
 ///
-/// for i in 1..10 {
-///     stream.write(&[i]).unwrap();
+/// for i in 0..10 {
+///     stream.write(&[i+1]).unwrap();
 /// }
 /// ```
 ///
@@ -332,8 +361,8 @@
 ///
 /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
 ///
-/// for i in 1..10 {
-///     stream.write(&[i]).unwrap();
+/// for i in 0..10 {
+///     stream.write(&[i+1]).unwrap();
 /// }
 /// ```
 ///
@@ -486,6 +515,10 @@
     ///
     /// The buffer is written out before returning the writer.
     ///
+    /// # Errors
+    ///
+    /// An `Err` will be returned if an error occurs while flushing the buffer.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -650,6 +683,9 @@
 /// completed, rather than the entire buffer at once. Enter `LineWriter`. It
 /// does exactly that.
 ///
+/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the
+/// `LineWriter` goes out of scope or when its internal buffer is full.
+///
 /// [bufwriter]: struct.BufWriter.html
 ///
 /// If there's still a partial line in the buffer when the `LineWriter` is
@@ -785,6 +821,10 @@
     ///
     /// The internal buffer is written out before returning the writer.
     ///
+    // # Errors
+    ///
+    /// An `Err` will be returned if an error occurs while flushing the buffer.
+    ///
     /// # Examples
     ///
     /// ```
@@ -943,6 +983,23 @@
     }
 
     #[test]
+    fn test_buffered_reader_seek_relative() {
+        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+        let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner));
+
+        assert!(reader.seek_relative(3).is_ok());
+        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+        assert!(reader.seek_relative(0).is_ok());
+        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+        assert!(reader.seek_relative(1).is_ok());
+        assert_eq!(reader.fill_buf().ok(), Some(&[1][..]));
+        assert!(reader.seek_relative(-1).is_ok());
+        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+        assert!(reader.seek_relative(2).is_ok());
+        assert_eq!(reader.fill_buf().ok(), Some(&[2, 3][..]));
+    }
+
+    #[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 b5ea553..c844770 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -252,14 +252,54 @@
     fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
 }
 
+// Non-resizing write implementation
+fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
+    let pos = cmp::min(*pos_mut, slice.len() as u64);
+    let amt = (&mut slice[(pos as usize)..]).write(buf)?;
+    *pos_mut += amt as u64;
+    Ok(amt)
+}
+
+// Resizing write implementation
+fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
+    let pos: usize = (*pos_mut).try_into().map_err(|_| {
+        Error::new(ErrorKind::InvalidInput,
+                    "cursor position exceeds maximum possible vector length")
+    })?;
+    // Make sure the internal buffer is as least as big as where we
+    // currently are
+    let len = vec.len();
+    if len < pos {
+        // use `resize` so that the zero filling is as efficient as possible
+        vec.resize(pos, 0);
+    }
+    // Figure out what bytes will be used to overwrite what's currently
+    // there (left), and what will be appended on the end (right)
+    {
+        let space = vec.len() - pos;
+        let (left, right) = buf.split_at(cmp::min(space, buf.len()));
+        vec[pos..pos + left.len()].copy_from_slice(left);
+        vec.extend_from_slice(right);
+    }
+
+    // Bump us forward
+    *pos_mut = (pos + buf.len()) as u64;
+    Ok(buf.len())
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Write for Cursor<&'a mut [u8]> {
     #[inline]
-    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-        let pos = cmp::min(self.pos, self.inner.len() as u64);
-        let amt = (&mut self.inner[(pos as usize)..]).write(data)?;
-        self.pos += amt as u64;
-        Ok(amt)
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        slice_write(&mut self.pos, self.inner, buf)
+    }
+    fn flush(&mut self) -> io::Result<()> { Ok(()) }
+}
+
+#[unstable(feature = "cursor_mut_vec", issue = "30132")]
+impl<'a> Write for Cursor<&'a mut Vec<u8>> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        vec_write(&mut self.pos, self.inner, buf)
     }
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
@@ -267,29 +307,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Cursor<Vec<u8>> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let pos: usize = self.position().try_into().map_err(|_| {
-            Error::new(ErrorKind::InvalidInput,
-                       "cursor position exceeds maximum possible vector length")
-        })?;
-        // Make sure the internal buffer is as least as big as where we
-        // currently are
-        let len = self.inner.len();
-        if len < pos {
-            // use `resize` so that the zero filling is as efficient as possible
-            self.inner.resize(pos, 0);
-        }
-        // Figure out what bytes will be used to overwrite what's currently
-        // there (left), and what will be appended on the end (right)
-        {
-            let space = self.inner.len() - pos;
-            let (left, right) = buf.split_at(cmp::min(space, buf.len()));
-            self.inner[pos..pos + left.len()].copy_from_slice(left);
-            self.inner.extend_from_slice(right);
-        }
-
-        // Bump us forward
-        self.set_position((pos + buf.len()) as u64);
-        Ok(buf.len())
+        vec_write(&mut self.pos, &mut self.inner, buf)
     }
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
@@ -298,10 +316,7 @@
 impl Write for Cursor<Box<[u8]>> {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let pos = cmp::min(self.pos, self.inner.len() as u64);
-        let amt = (&mut self.inner[(pos as usize)..]).write(buf)?;
-        self.pos += amt as u64;
-        Ok(amt)
+        slice_write(&mut self.pos, &mut self.inner, buf)
     }
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
@@ -332,6 +347,17 @@
     }
 
     #[test]
+    fn test_mem_mut_writer() {
+        let mut vec = Vec::new();
+        let mut writer = Cursor::new(&mut vec);
+        assert_eq!(writer.write(&[0]).unwrap(), 1);
+        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
+        assert_eq!(&writer.get_ref()[..], b);
+    }
+
+    #[test]
     fn test_box_slice_writer() {
         let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
         assert_eq!(writer.position(), 0);
diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs
index bb9383d..f0b41f3 100644
--- a/src/libstd/io/error.rs
+++ b/src/libstd/io/error.rs
@@ -62,12 +62,18 @@
 /// [`Write`]: ../io/trait.Write.html
 /// [`Seek`]: ../io/trait.Seek.html
 /// [`ErrorKind`]: enum.ErrorKind.html
-#[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Error {
     repr: Repr,
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.repr, f)
+    }
+}
+
 enum Repr {
     Os(i32),
     Simple(ErrorKind),
@@ -511,10 +517,12 @@
 impl fmt::Debug for Repr {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Repr::Os(ref code) =>
-                fmt.debug_struct("Os").field("code", code)
-                   .field("message", &sys::os::error_string(*code)).finish(),
-            Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
+            Repr::Os(code) =>
+                fmt.debug_struct("Os")
+                    .field("code", &code)
+                    .field("kind", &sys::decode_error_kind(code))
+                    .field("message", &sys::os::error_string(code)).finish(),
+            Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
             Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
         }
     }
@@ -559,17 +567,36 @@
 
 #[cfg(test)]
 mod test {
-    use super::{Error, ErrorKind};
+    use super::{Error, ErrorKind, Repr, Custom};
     use error;
     use fmt;
     use sys::os::error_string;
+    use sys::decode_error_kind;
 
     #[test]
     fn test_debug_error() {
         let code = 6;
         let msg = error_string(code);
-        let err = Error { repr: super::Repr::Os(code) };
-        let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
+        let kind = decode_error_kind(code);
+        let err = Error {
+            repr: Repr::Custom(box Custom {
+                kind: ErrorKind::InvalidInput,
+                error: box Error {
+                    repr: super::Repr::Os(code)
+                },
+            })
+        };
+        let expected = format!(
+            "Custom {{ \
+                kind: InvalidInput, \
+                error: Os {{ \
+                    code: {:?}, \
+                    kind: {:?}, \
+                    message: {:?} \
+                }} \
+            }}",
+            code, kind, msg
+        );
         assert_eq!(format!("{:?}", err), expected);
     }
 
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index e9b707c..33d11eb 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -601,7 +601,7 @@
         read_to_end(self, buf)
     }
 
-    /// Read all bytes until EOF in this source, placing them into `buf`.
+    /// Read all bytes until EOF in this source, appending them to `buf`.
     ///
     /// If successful, this function returns the number of bytes which were read
     /// and appended to `buf`.
@@ -997,9 +997,9 @@
     ///
     /// Calls to `write` are not guaranteed to block waiting for data to be
     /// written, and a write which would otherwise block can be indicated through
-    /// an `Err` variant.
+    /// an [`Err`] variant.
     ///
-    /// If the return value is `Ok(n)` then it must be guaranteed that
+    /// If the return value is [`Ok(n)`] then it must be guaranteed that
     /// `0 <= n <= buf.len()`. A return value of `0` typically means that the
     /// underlying object is no longer able to accept bytes and will likely not
     /// be able to in the future as well, or that the buffer provided is empty.
@@ -1013,9 +1013,13 @@
     /// It is **not** considered an error if the entire buffer could not be
     /// written to this writer.
     ///
-    /// An error of the `ErrorKind::Interrupted` kind is non-fatal and the
+    /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the
     /// write operation should be retried if there is nothing else to do.
     ///
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Ok(n)`]:  ../../std/result/enum.Result.html#variant.Ok
+    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+    ///
     /// # Examples
     ///
     /// ```
@@ -1061,17 +1065,20 @@
 
     /// Attempts to write an entire buffer into this write.
     ///
-    /// This method will continuously call `write` until there is no more data
-    /// to be written or an error of non-`ErrorKind::Interrupted` kind is
+    /// This method will continuously call [`write`] until there is no more data
+    /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
     /// returned. This method will not return until the entire buffer has been
     /// successfully written or such an error occurs. The first error that is
-    /// not of `ErrorKind::Interrupted` kind generated from this method will be
+    /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
     /// returned.
     ///
     /// # Errors
     ///
     /// This function will return the first error of
-    /// non-`ErrorKind::Interrupted` kind that `write` returns.
+    /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns.
+    ///
+    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`write`]: #tymethod.write
     ///
     /// # Examples
     ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 12e62311..91cc6d2 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -229,7 +229,7 @@
 
 // Turn warnings into errors, but only after stage0, where it can be useful for
 // code to emit warnings during language transitions
-#![deny(warnings)]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 // std may use features in a platform-specific way
 #![allow(unused_features)]
@@ -293,28 +293,28 @@
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
 #![feature(prelude_import)]
+#![feature(ptr_internals)]
 #![feature(rand)]
 #![feature(raw)]
 #![feature(repr_align)]
-#![feature(repr_simd)]
 #![feature(rustc_attrs)]
-#![feature(shared)]
 #![feature(sip_hash_13)]
 #![feature(slice_bytes)]
 #![feature(slice_concat_ext)]
+#![feature(slice_internals)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(stmt_expr_attributes)]
 #![feature(str_char)]
 #![feature(str_internals)]
 #![feature(str_utf16)]
+#![feature(termination_trait)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
 #![feature(try_from)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unique)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
@@ -350,9 +350,9 @@
 #[cfg(test)] extern crate test;
 #[cfg(test)] extern crate rand;
 
-// We want to reexport a few macros from core but libcore has already been
+// We want to re-export a few macros from core but libcore has already been
 // imported by the compiler (via our #[no_std] attribute) In this case we just
-// add a new crate name so we can attach the reexports to it.
+// add a new crate name so we can attach the re-exports to it.
 #[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq,
                  debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
 extern crate core as __core;
@@ -389,7 +389,7 @@
 // The Rust prelude
 pub mod prelude;
 
-// Public module declarations and reexports
+// Public module declarations and re-exports
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::any;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -499,6 +499,11 @@
 // The runtime entry point and a few unstable public functions used by the
 // compiler
 pub mod rt;
+// The trait to support returning arbitrary types in the main function
+mod termination;
+
+#[unstable(feature = "termination_trait", issue = "43301")]
+pub use self::termination::Termination;
 
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index de46fed..f058b1c 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -283,7 +283,7 @@
     /// Unconditionally causes compilation to fail with the given error message when encountered.
     ///
     /// This macro should be used when a crate uses a conditional compilation strategy to provide
-    /// better error messages for errornous conditions.
+    /// better error messages for erroneous conditions.
     ///
     /// # Examples
     ///
@@ -460,9 +460,12 @@
     /// With [`column!`] and [`file!`], these macros provide debugging information for
     /// developers about the location within the source.
     ///
-    /// The expanded expression has type `u32`, and the returned line is not
-    /// the invocation of the `line!()` macro itself, but rather the first macro
-    /// invocation leading up to the invocation of the `line!()` macro.
+    /// The expanded expression has type `u32` and is 1-based, so the first line
+    /// in each file evaluates to 1, the second to 2, etc. This is consistent
+    /// with error messages by common compilers or popular editors.
+    /// The returned line is not the invocation of the `line!` macro itself,
+    /// but rather the first macro invocation leading up to the invocation
+    /// of the `line!` macro.
     ///
     /// [`column!`]: macro.column.html
     /// [`file!`]: macro.file.html
@@ -482,9 +485,12 @@
     /// With [`line!`] and [`file!`], these macros provide debugging information for
     /// developers about the location within the source.
     ///
-    /// The expanded expression has type `u32`, and the returned column is not
-    /// the invocation of the `column!` macro itself, but rather the first macro
-    /// invocation leading up to the invocation of the `column!` macro.
+    /// The expanded expression has type `u32` and is 1-based, so the first column
+    /// in each line evaluates to 1, the second to 2, etc. This is consistent
+    /// with error messages by common compilers or popular editors.
+    /// The returned column is not the invocation of the `column!` macro itself,
+    /// but rather the first macro invocation leading up to the invocation
+    /// of the `column!` macro.
     ///
     /// [`line!`]: macro.line.html
     /// [`file!`]: macro.file.html
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index 1ca7e66..fa43093 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -12,7 +12,9 @@
 use hash;
 use io;
 use mem;
-use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+#[allow(deprecated)]
+use net::lookup_host;
 use option;
 use sys::net::netc as c;
 use sys_common::{FromInner, AsInner, IntoInner};
@@ -845,6 +847,7 @@
     }
 }
 
+#[allow(deprecated)]
 fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
     let ips = lookup_host(s)?;
     let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect();
diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs
index 9fcb93e..eb0e2e1 100644
--- a/src/libstd/net/mod.rs
+++ b/src/libstd/net/mod.rs
@@ -134,12 +134,15 @@
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
 pub struct LookupHost(net_imp::LookupHost);
 
 #[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
@@ -149,6 +152,8 @@
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
 impl fmt::Debug for LookupHost {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("LookupHost { .. }")
@@ -181,6 +186,8 @@
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
 pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     net_imp::lookup_host(host).map(LookupHost)
 }
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 539ff1d..78235ea 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -885,7 +885,7 @@
     }
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::ErrorKind;
     use io::prelude::*;
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index 84ceaa6..fc7f920 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -786,7 +786,7 @@
     }
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::ErrorKind;
     use net::*;
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 219e55d..5608760 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -17,7 +17,7 @@
 use fmt;
 use ops::{Deref, DerefMut};
 use panicking;
-use ptr::{Unique, Shared};
+use ptr::{Unique, NonNull};
 use rc::Rc;
 use sync::{Arc, Mutex, RwLock, atomic};
 use thread::Result;
@@ -101,7 +101,7 @@
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
                             across an unwind boundary"]
-pub trait UnwindSafe {}
+pub auto trait UnwindSafe {}
 
 /// A marker trait representing types where a shared reference is considered
 /// unwind safe.
@@ -115,7 +115,7 @@
 #[rustc_on_unimplemented = "the type {Self} may contain interior mutability \
                             and a reference may not be safely transferrable \
                             across a catch_unwind boundary"]
-pub trait RefUnwindSafe {}
+pub auto trait RefUnwindSafe {}
 
 /// A simple wrapper around a type to assert that it is unwind safe.
 ///
@@ -187,10 +187,7 @@
 // * Unique, an owning pointer, lifts an implementation
 // * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
 // * Our custom AssertUnwindSafe wrapper is indeed unwind safe
-#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl UnwindSafe for .. {}
+
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
@@ -199,10 +196,10 @@
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> UnwindSafe for Mutex<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
@@ -219,14 +216,10 @@
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
 
 // Pretty simple implementations for the `RefUnwindSafe` marker trait,
-// basically just saying that this is a marker trait and `UnsafeCell` is the
+// basically just saying that `UnsafeCell` is the
 // only thing which doesn't implement it (which then transitively applies to
 // everything else).
 #[stable(feature = "catch_unwind", since = "1.9.0")]
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl RefUnwindSafe for .. {}
-#[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T> RefUnwindSafe for AssertUnwindSafe<T> {}
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 80ce159..f91eaf43 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -316,7 +316,6 @@
     /// # Examples
     ///
     /// ```should_panic
-    /// #![feature(panic_col)]
     /// use std::panic;
     ///
     /// panic::set_hook(Box::new(|panic_info| {
@@ -329,7 +328,7 @@
     ///
     /// panic!("Normal panic");
     /// ```
-    #[unstable(feature = "panic_col", reason = "recently added", issue = "42939")]
+    #[stable(feature = "panic_col", since = "1.25")]
     pub fn column(&self) -> u32 {
         self.col
     }
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index eb125a4..ed102c2 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -576,6 +576,13 @@
     }
 }
 
+#[stable(feature = "path_component_asref", since = "1.24.0")]
+impl<'a> AsRef<Path> for Component<'a> {
+    fn as_ref(&self) -> &Path {
+        self.as_os_str().as_ref()
+    }
+}
+
 /// An iterator over the [`Component`]s of a [`Path`].
 ///
 /// This `struct` is created by the [`components`] method on [`Path`].
@@ -1454,7 +1461,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Arc<Path> {
     #[inline]
     fn from(s: PathBuf) -> Arc<Path> {
@@ -1463,7 +1470,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a Path> for Arc<Path> {
     #[inline]
     fn from(s: &Path) -> Arc<Path> {
@@ -1472,7 +1479,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Rc<Path> {
     #[inline]
     fn from(s: PathBuf) -> Rc<Path> {
@@ -1481,7 +1488,7 @@
     }
 }
 
-#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl<'a> From<&'a Path> for Rc<Path> {
     #[inline]
     fn from(s: &Path) -> Rc<Path> {
@@ -1702,6 +1709,7 @@
     /// let path_buf = Path::new("foo.txt").to_path_buf();
     /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
     /// ```
+    #[rustc_conversion_suggestion]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_path_buf(&self) -> PathBuf {
         PathBuf::from(self.inner.to_os_string())
@@ -1861,7 +1869,11 @@
     ///
     /// let path = Path::new("/test/haha/foo.txt");
     ///
+    /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
     /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
     /// assert_eq!(path.strip_prefix("test").is_ok(), false);
     /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
     /// ```
@@ -1892,6 +1904,9 @@
     /// let path = Path::new("/etc/passwd");
     ///
     /// assert!(path.starts_with("/etc"));
+    /// assert!(path.starts_with("/etc/"));
+    /// assert!(path.starts_with("/etc/passwd"));
+    /// assert!(path.starts_with("/etc/passwd/"));
     ///
     /// assert!(!path.starts_with("/e"));
     /// ```
diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs
index 538753d..919e033 100644
--- a/src/libstd/prelude/mod.rs
+++ b/src/libstd/prelude/mod.rs
@@ -52,7 +52,7 @@
 //! # Prelude contents
 //!
 //! The current version of the prelude (version 1) lives in
-//! [`std::prelude::v1`], and reexports the following.
+//! [`std::prelude::v1`], and re-exports the following.
 //!
 //! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
 //!   traits indicate fundamental properties of types.
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index 9ca5b44..feedd4e 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -14,17 +14,17 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-// Reexported core operators
+// Re-exported core operators
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
 
-// Reexported functions
+// Re-exported functions
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use mem::drop;
 
-// Reexported types and traits
+// Re-exported types and traits
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use boxed::Box;
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 2335695..5c66ac6 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -68,8 +68,8 @@
 //! assert_eq!(b"Oh no, a typo!\n", output.stdout.as_slice());
 //! ```
 //!
-//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Write`] and
-//! [`ChildStdin`] implements [`Read`]:
+//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Read`] and
+//! [`ChildStdin`] implements [`Write`]:
 //!
 //! ```no_run
 //! use std::process::{Command, Stdio};
@@ -513,7 +513,7 @@
     pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
         where K: AsRef<OsStr>, V: AsRef<OsStr>
     {
-        self.inner.env(key.as_ref(), val.as_ref());
+        self.inner.env_mut().set(key.as_ref(), val.as_ref());
         self
     }
 
@@ -546,7 +546,7 @@
         where I: IntoIterator<Item=(K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>
     {
         for (ref key, ref val) in vars {
-            self.inner.env(key.as_ref(), val.as_ref());
+            self.inner.env_mut().set(key.as_ref(), val.as_ref());
         }
         self
     }
@@ -567,7 +567,7 @@
     /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
-        self.inner.env_remove(key.as_ref());
+        self.inner.env_mut().remove(key.as_ref());
         self
     }
 
@@ -587,7 +587,7 @@
     /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn env_clear(&mut self) -> &mut Command {
-        self.inner.env_clear();
+        self.inner.env_mut().clear();
         self
     }
 
@@ -1392,7 +1392,7 @@
     ::sys::os::getpid()
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::prelude::*;
 
@@ -1584,7 +1584,7 @@
              = if cfg!(target_os = "windows") {
                  Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
              } else {
-                 Command::new("mkdir").arg(".").output().unwrap()
+                 Command::new("mkdir").arg("./").output().unwrap()
              };
 
         assert!(status.code() == Some(1));
@@ -1715,6 +1715,27 @@
                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
     }
 
+    #[test]
+    fn test_capture_env_at_spawn() {
+        use env;
+
+        let mut cmd = env_cmd();
+        cmd.env("RUN_TEST_NEW_ENV1", "123");
+
+        // This variable will not be present if the environment has already
+        // been captured above.
+        env::set_var("RUN_TEST_NEW_ENV2", "456");
+        let result = cmd.output().unwrap();
+        env::remove_var("RUN_TEST_NEW_ENV2");
+
+        let output = String::from_utf8_lossy(&result.stdout).to_string();
+
+        assert!(output.contains("RUN_TEST_NEW_ENV1=123"),
+                "didn't find RUN_TEST_NEW_ENV1 inside of:\n\n{}", output);
+        assert!(output.contains("RUN_TEST_NEW_ENV2=456"),
+                "didn't find RUN_TEST_NEW_ENV2 inside of:\n\n{}", output);
+    }
+
     // Regression tests for #30858.
     #[test]
     fn test_interior_nul_in_progname_is_error() {
diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs
deleted file mode 100644
index 08bc809..0000000
--- a/src/libstd/rand/reader.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A wrapper around any Read to treat it as an RNG.
-
-#![allow(dead_code)]
-
-use io::prelude::*;
-use rand::Rng;
-
-/// An RNG that reads random bytes straight from a `Read`. This will
-/// work best with an infinite reader, but this is not required.
-///
-/// # Panics
-///
-/// It will panic if it there is insufficient data to fulfill a request.
-pub struct ReaderRng<R> {
-    reader: R
-}
-
-impl<R: Read> ReaderRng<R> {
-    /// Create a new `ReaderRng` from a `Read`.
-    pub fn new(r: R) -> ReaderRng<R> {
-        ReaderRng {
-            reader: r
-        }
-    }
-}
-
-impl<R: Read> Rng for ReaderRng<R> {
-    fn next_u32(&mut self) -> u32 {
-        // This is designed for speed: reading a LE integer on a LE
-        // platform just involves blitting the bytes into the memory
-        // of the u32, similarly for BE on BE; avoiding byteswapping.
-        let mut bytes = [0; 4];
-        self.fill_bytes(&mut bytes);
-        unsafe { *(bytes.as_ptr() as *const u32) }
-    }
-    fn next_u64(&mut self) -> u64 {
-        // see above for explanation.
-        let mut bytes = [0; 8];
-        self.fill_bytes(&mut bytes);
-        unsafe { *(bytes.as_ptr() as *const u64) }
-    }
-    fn fill_bytes(&mut self, mut v: &mut [u8]) {
-        while !v.is_empty() {
-            let t = v;
-            match self.reader.read(t) {
-                Ok(0) => panic!("ReaderRng.fill_bytes: EOF reached"),
-                Ok(n) => v = t.split_at_mut(n).1,
-                Err(e) => panic!("ReaderRng.fill_bytes: {}", e),
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::ReaderRng;
-    use rand::Rng;
-
-    #[test]
-    fn test_reader_rng_u64() {
-        // transmute from the target to avoid endianness concerns.
-        let v = &[0, 0, 0, 0, 0, 0, 0, 1,
-                  0, 0, 0, 0, 0, 0, 0, 2,
-                  0, 0, 0, 0, 0, 0, 0, 3][..];
-        let mut rng = ReaderRng::new(v);
-
-        assert_eq!(rng.next_u64(), 1u64.to_be());
-        assert_eq!(rng.next_u64(), 2u64.to_be());
-        assert_eq!(rng.next_u64(), 3u64.to_be());
-    }
-    #[test]
-    fn test_reader_rng_u32() {
-        let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..];
-        let mut rng = ReaderRng::new(v);
-
-        assert_eq!(rng.next_u32(), 1u32.to_be());
-        assert_eq!(rng.next_u32(), 2u32.to_be());
-        assert_eq!(rng.next_u32(), 3u32.to_be());
-    }
-    #[test]
-    fn test_reader_rng_fill_bytes() {
-        let v = [1, 2, 3, 4, 5, 6, 7, 8];
-        let mut w = [0; 8];
-
-        let mut rng = ReaderRng::new(&v[..]);
-        rng.fill_bytes(&mut w);
-
-        assert!(v == w);
-    }
-
-    #[test]
-    #[should_panic]
-    fn test_reader_rng_insufficient_bytes() {
-        let mut rng = ReaderRng::new(&[][..]);
-        let mut v = [0; 3];
-        rng.fill_bytes(&mut v);
-    }
-}
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 40b24ce..9dbaf78 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -23,23 +23,23 @@
 #![doc(hidden)]
 
 
-// Reexport some of our utilities which are expected by other crates.
+// Re-export some of our utilities which are expected by other crates.
 pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 
+// To reduce the generated code of the new `lang_start`, this function is doing
+// the real work.
 #[cfg(not(test))]
-#[lang = "start"]
-fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
+fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
+                       argc: isize, argv: *const *const u8) -> isize {
     use panic;
     use sys;
     use sys_common;
     use sys_common::thread_info;
     use thread::Thread;
-    #[cfg(not(feature = "backtrace"))]
-    use mem;
 
     sys::init();
 
-    let failed = unsafe {
+    unsafe {
         let main_guard = sys::thread::guard::init();
         sys::stack_overflow::init();
 
@@ -55,18 +55,21 @@
 
         // Let's run some code!
         #[cfg(feature = "backtrace")]
-        let res = panic::catch_unwind(|| {
-            ::sys_common::backtrace::__rust_begin_short_backtrace(main)
+        let exit_code = panic::catch_unwind(|| {
+            ::sys_common::backtrace::__rust_begin_short_backtrace(move || main())
         });
         #[cfg(not(feature = "backtrace"))]
-        let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
-        sys_common::cleanup();
-        res.is_err()
-    };
+        let exit_code = panic::catch_unwind(move || main());
 
-    if failed {
-        101
-    } else {
-        0
+        sys_common::cleanup();
+        exit_code.unwrap_or(101) as isize
     }
 }
+
+#[cfg(not(test))]
+#[lang = "start"]
+fn lang_start<T: ::termination::Termination + 'static>
+    (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
+{
+    lang_start_internal(&move || main().report(), argc, argv)
+}
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 81f5594..3b4904c 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -382,7 +382,7 @@
     }
 }
 
-#[stable(feature = "mutex_from", since = "1.22.0")]
+#[stable(feature = "mutex_from", since = "1.24.0")]
 impl<T> From<T> for Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     /// This is equivalent to [`Mutex::new`].
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index fd6cff6..2edf02e 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -36,7 +36,7 @@
 /// required that `T` satisfies [`Send`] to be shared across threads and
 /// [`Sync`] to allow concurrent access through readers. The RAII guards
 /// returned from the locking methods implement [`Deref`][] (and [`DerefMut`]
-/// for the `write` methods) to allow access to the contained of the lock.
+/// for the `write` methods) to allow access to the content of the lock.
 ///
 /// # Poisoning
 ///
@@ -457,7 +457,7 @@
     }
 }
 
-#[stable(feature = "rw_lock_from", since = "1.22.0")]
+#[stable(feature = "rw_lock_from", since = "1.24.0")]
 impl<T> From<T> for RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
     /// This is equivalent to [`RwLock::new`].
diff --git a/src/libstd/sys/cloudabi/abi/bitflags.rs b/src/libstd/sys/cloudabi/abi/bitflags.rs
new file mode 100644
index 0000000..f764cc1
--- /dev/null
+++ b/src/libstd/sys/cloudabi/abi/bitflags.rs
@@ -0,0 +1,51 @@
+// Copyright (c) 2018 Nuxi (https://nuxi.nl/) and contributors.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+
+// Appease Rust's tidy.
+// ignore-license
+
+#[cfg(feature = "bitflags")]
+#[macro_use]
+extern crate bitflags;
+
+// Minimal implementation of bitflags! in case we can't depend on the bitflags
+// crate. Only implements `bits()` and a `from_bits_truncate()` that doesn't
+// actually truncate.
+#[cfg(not(feature = "bitflags"))]
+macro_rules! bitflags {
+  (
+    $(#[$attr:meta])*
+    pub struct $name:ident: $type:ty {
+      $($(#[$const_attr:meta])* const $const:ident = $val:expr;)*
+    }
+  ) => {
+    $(#[$attr])*
+    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+    pub struct $name { bits: $type }
+    impl $name {
+      $($(#[$const_attr])* pub const $const: $name = $name{ bits: $val };)*
+      pub fn bits(&self) -> $type { self.bits }
+      pub fn from_bits_truncate(bits: $type) -> Self { $name{ bits } }
+    }
+  }
+}
diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs
new file mode 100644
index 0000000..2909db5
--- /dev/null
+++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs
@@ -0,0 +1,2847 @@
+// Copyright (c) 2016-2017 Nuxi (https://nuxi.nl/) and contributors.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// This file is automatically generated. Do not edit.
+//
+// Source: https://github.com/NuxiNL/cloudabi
+
+// Appease Rust's tidy.
+// ignore-license
+// ignore-tidy-linelength
+
+//! **PLEASE NOTE: This entire crate including this
+//! documentation is automatically generated from
+//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt)**
+//!
+//! # Nuxi CloudABI
+//!
+//! CloudABI is what you get if you take POSIX, add capability-based
+//! security, and remove everything that's incompatible with that. The
+//! result is a minimal ABI consisting of only 49 syscalls.
+//!
+//! CloudABI doesn't have its own kernel, but instead is implemented in existing
+//! kernels: FreeBSD has CloudABI support for x86-64 and arm64, and [a patch-set
+//! for NetBSD](https://github.com/NuxiNL/netbsd) and [a patch-set for
+//! Linux](https://github.com/NuxiNL/linux) are available as well. This means that
+//! CloudABI binaries can be executed on different operating systems, without any
+//! modification.
+//!
+//! ## Capability-Based Security
+//!
+//! Capability-based security means that processes can only perform
+//! actions that have no global impact. Processes cannot open files by
+//! their absolute path, cannot open network connections, and cannot
+//! observe global system state such as the process table.
+//!
+//! The capabilities of a process are fully determined by its set of open
+//! file descriptors (fds). For example, files can only be opened if the
+//! process already has a file descriptor to a directory the file is in.
+//!
+//! Unlike in POSIX, where processes are normally started with file
+//! descriptors 0, 1, and 2 reserved for standard input, output, and
+//! error, CloudABI does not reserve any file descriptor numbers for
+//! specific purposes.
+//!
+//! In CloudABI, a process depends on its parent process to launch it with
+//! the right set of resources, since the process will not be able to open
+//! any new resources. For example, a simple static web server would need
+//! to be started with a file descriptor to a [TCP
+//! listener](https://github.com/NuxiNL/flower), and a file descriptor to
+//! the directory for which to serve files. The web server will then be
+//! unable to do anything other than reading files in that directory, and
+//! process incoming network connections.
+//!
+//! So, unknown CloudABI binaries can safely be executed without the need
+//! for containers, virtual machines, or other sandboxing technologies.
+//!
+//! Watch [Ed Schouten's Talk at
+//! 32C3](https://www.youtube.com/watch?v=3N29vrPoDv8) for more
+//! information about what capability-based security for UNIX means.
+//!
+//! ## Cloudlibc
+//!
+//! [Cloudlibc](https://github.com/NuxiNL/cloudlibc) is an implementation
+//! of the C standard library, without all CloudABI-incompatible
+//! functions. For example, Cloudlibc does not have `printf`, but does
+//! have `fprintf`. It does not have `open`, but does have `openat`.
+//!
+//! ## CloudABI-Ports
+//!
+//! [CloudABI-Ports](https://github.com/NuxiNL/cloudabi-ports) is a
+//! collection of ports of commonly used libraries and applications to
+//! CloudABI. It contains software such as `zlib`, `libpng`, `boost`,
+//! `memcached`, and much more. The software is patched to not depend on
+//! any global state, such as files in `/etc` or `/dev`, using `open()`,
+//! etc.
+//!
+//! ## Using CloudABI
+//!
+//! Instructions for using CloudABI (including kernel modules/patches,
+//! toolchain, and ports) are available for several operating systems:
+//!
+//! - [Arch Linux](https://nuxi.nl/cloudabi/archlinux/)
+//! - [Debian, Ubuntu, and other Debian derivatives](https://nuxi.nl/cloudabi/debian/)
+//! - [FreeBSD, PC-BSD and DragonFly BSD](https://nuxi.nl/cloudabi/freebsd/)
+//! - [Mac OS X](https://nuxi.nl/cloudabi/mac/)
+//! - [NetBSD](https://nuxi.nl/cloudabi/netbsd/)
+//!
+//! ## Specification of the ABI
+//!
+//! The entire ABI is specified in a a file called
+//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt),
+//! from which all
+//! [headers](https://github.com/NuxiNL/cloudabi/tree/master/headers)
+//! and documentation (including the one you're reading now) is generated.
+
+#![no_std]
+#![allow(non_camel_case_types)]
+
+include!("bitflags.rs");
+
+/// File or memory access pattern advisory information.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum advice {
+  /// The application expects that it will not access the
+  /// specified data in the near future.
+  DONTNEED   = 1,
+  /// The application expects to access the specified data
+  /// once and then not reuse it thereafter.
+  NOREUSE    = 2,
+  /// The application has no advice to give on its behavior
+  /// with respect to the specified data.
+  NORMAL     = 3,
+  /// The application expects to access the specified data
+  /// in a random order.
+  RANDOM     = 4,
+  /// The application expects to access the specified data
+  /// sequentially from lower offsets to higher offsets.
+  SEQUENTIAL = 5,
+  /// The application expects to access the specified data
+  /// in the near future.
+  WILLNEED   = 6,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum auxtype {
+  /// Base address of the binary argument data provided to
+  /// [`proc_exec()`](fn.proc_exec.html).
+  ARGDATA      = 256,
+  /// Length of the binary argument data provided to
+  /// [`proc_exec()`](fn.proc_exec.html).
+  ARGDATALEN   = 257,
+  /// Base address at which the executable is placed in
+  /// memory.
+  BASE         =   7,
+  /// Base address of a buffer of random data that may be
+  /// used for non-cryptographic purposes, for example as a
+  /// canary for stack smashing protection.
+  CANARY       = 258,
+  /// Length of a buffer of random data that may be used
+  /// for non-cryptographic purposes, for example as a
+  /// canary for stack smashing protection.
+  CANARYLEN    = 259,
+  /// Number of CPUs that the system this process is running
+  /// on has.
+  NCPUS        = 260,
+  /// Terminator of the auxiliary vector.
+  NULL         =   0,
+  /// Smallest memory object size for which individual
+  /// memory protection controls can be configured.
+  PAGESZ       =   6,
+  /// Address of the first ELF program header of the
+  /// executable.
+  PHDR         =   3,
+  /// Number of ELF program headers of the executable.
+  PHNUM        =   4,
+  /// Identifier of the process.
+  ///
+  /// This environment does not provide any simple numerical
+  /// process identifiers, for the reason that these are not
+  /// useful in distributed contexts. Instead, processes are
+  /// identified by a UUID.
+  ///
+  /// This record should point to sixteen bytes of binary
+  /// data, containing a version 4 UUID (fully random).
+  PID          = 263,
+  /// Address of the ELF header of the vDSO.
+  ///
+  /// The vDSO is a shared library that is mapped in the
+  /// address space of the process. It provides entry points
+  /// for every system call supported by the environment,
+  /// all having a corresponding symbol that is prefixed
+  /// with `cloudabi_sys_`. System calls should be invoked
+  /// through these entry points.
+  ///
+  /// The first advantage of letting processes call into a
+  /// vDSO to perform system calls instead of raising
+  /// hardware traps is that it allows for easy emulation of
+  /// executables on top of existing operating systems. The
+  /// second advantage is that in cases where an operating
+  /// system provides native support for CloudABI executables,
+  /// it may still implement partial userspace
+  /// implementations of these system calls to improve
+  /// performance (e.g., [`clock_time_get()`](fn.clock_time_get.html)). It also provides
+  /// a more dynamic way of adding, removing or replacing
+  /// system calls.
+  SYSINFO_EHDR = 262,
+  /// Thread ID of the initial thread of the process.
+  TID          = 261,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// Identifiers for clocks.
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum clockid {
+  /// The system-wide monotonic clock, which is defined as a
+  /// clock measuring real time, whose value cannot be
+  /// adjusted and which cannot have negative clock jumps.
+  ///
+  /// The epoch of this clock is undefined. The absolute
+  /// time value of this clock therefore has no meaning.
+  MONOTONIC          = 1,
+  /// The CPU-time clock associated with the current
+  /// process.
+  PROCESS_CPUTIME_ID = 2,
+  /// The system-wide clock measuring real time. Time value
+  /// zero corresponds with 1970-01-01T00:00:00Z.
+  REALTIME           = 3,
+  /// The CPU-time clock associated with the current thread.
+  THREAD_CPUTIME_ID  = 4,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// A userspace condition variable.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct condvar(pub u32);
+/// The condition variable is in its initial state. There
+/// are no threads waiting to be woken up. If the
+/// condition variable has any other value, the kernel
+/// must be called to wake up any sleeping threads.
+pub const CONDVAR_HAS_NO_WAITERS: condvar = condvar(0);
+
+/// Identifier for a device containing a file system. Can be used
+/// in combination with [`inode`](struct.inode.html) to uniquely identify a file on the
+/// local system.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct device(pub u64);
+
+/// A reference to the offset of a directory entry.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct dircookie(pub u64);
+/// Permanent reference to the first directory entry
+/// within a directory.
+pub const DIRCOOKIE_START: dircookie = dircookie(0);
+
+/// Error codes returned by system calls.
+///
+/// Not all of these error codes are returned by the system calls
+/// provided by this environment, but are either used in userspace
+/// exclusively or merely provided for alignment with POSIX.
+#[repr(u16)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum errno {
+  /// No error occurred. System call completed successfully.
+  SUCCESS        =  0,
+  /// Argument list too long.
+  TOOBIG         =  1,
+  /// Permission denied.
+  ACCES          =  2,
+  /// Address in use.
+  ADDRINUSE      =  3,
+  /// Address not available.
+  ADDRNOTAVAIL   =  4,
+  /// Address family not supported.
+  AFNOSUPPORT    =  5,
+  /// Resource unavailable, or operation would block.
+  AGAIN          =  6,
+  /// Connection already in progress.
+  ALREADY        =  7,
+  /// Bad file descriptor.
+  BADF           =  8,
+  /// Bad message.
+  BADMSG         =  9,
+  /// Device or resource busy.
+  BUSY           = 10,
+  /// Operation canceled.
+  CANCELED       = 11,
+  /// No child processes.
+  CHILD          = 12,
+  /// Connection aborted.
+  CONNABORTED    = 13,
+  /// Connection refused.
+  CONNREFUSED    = 14,
+  /// Connection reset.
+  CONNRESET      = 15,
+  /// Resource deadlock would occur.
+  DEADLK         = 16,
+  /// Destination address required.
+  DESTADDRREQ    = 17,
+  /// Mathematics argument out of domain of function.
+  DOM            = 18,
+  /// Reserved.
+  DQUOT          = 19,
+  /// File exists.
+  EXIST          = 20,
+  /// Bad address.
+  FAULT          = 21,
+  /// File too large.
+  FBIG           = 22,
+  /// Host is unreachable.
+  HOSTUNREACH    = 23,
+  /// Identifier removed.
+  IDRM           = 24,
+  /// Illegal byte sequence.
+  ILSEQ          = 25,
+  /// Operation in progress.
+  INPROGRESS     = 26,
+  /// Interrupted function.
+  INTR           = 27,
+  /// Invalid argument.
+  INVAL          = 28,
+  /// I/O error.
+  IO             = 29,
+  /// Socket is connected.
+  ISCONN         = 30,
+  /// Is a directory.
+  ISDIR          = 31,
+  /// Too many levels of symbolic links.
+  LOOP           = 32,
+  /// File descriptor value too large.
+  MFILE          = 33,
+  /// Too many links.
+  MLINK          = 34,
+  /// Message too large.
+  MSGSIZE        = 35,
+  /// Reserved.
+  MULTIHOP       = 36,
+  /// Filename too long.
+  NAMETOOLONG    = 37,
+  /// Network is down.
+  NETDOWN        = 38,
+  /// Connection aborted by network.
+  NETRESET       = 39,
+  /// Network unreachable.
+  NETUNREACH     = 40,
+  /// Too many files open in system.
+  NFILE          = 41,
+  /// No buffer space available.
+  NOBUFS         = 42,
+  /// No such device.
+  NODEV          = 43,
+  /// No such file or directory.
+  NOENT          = 44,
+  /// Executable file format error.
+  NOEXEC         = 45,
+  /// No locks available.
+  NOLCK          = 46,
+  /// Reserved.
+  NOLINK         = 47,
+  /// Not enough space.
+  NOMEM          = 48,
+  /// No message of the desired type.
+  NOMSG          = 49,
+  /// Protocol not available.
+  NOPROTOOPT     = 50,
+  /// No space left on device.
+  NOSPC          = 51,
+  /// Function not supported.
+  NOSYS          = 52,
+  /// The socket is not connected.
+  NOTCONN        = 53,
+  /// Not a directory or a symbolic link to a directory.
+  NOTDIR         = 54,
+  /// Directory not empty.
+  NOTEMPTY       = 55,
+  /// State not recoverable.
+  NOTRECOVERABLE = 56,
+  /// Not a socket.
+  NOTSOCK        = 57,
+  /// Not supported, or operation not supported on socket.
+  NOTSUP         = 58,
+  /// Inappropriate I/O control operation.
+  NOTTY          = 59,
+  /// No such device or address.
+  NXIO           = 60,
+  /// Value too large to be stored in data type.
+  OVERFLOW       = 61,
+  /// Previous owner died.
+  OWNERDEAD      = 62,
+  /// Operation not permitted.
+  PERM           = 63,
+  /// Broken pipe.
+  PIPE           = 64,
+  /// Protocol error.
+  PROTO          = 65,
+  /// Protocol not supported.
+  PROTONOSUPPORT = 66,
+  /// Protocol wrong type for socket.
+  PROTOTYPE      = 67,
+  /// Result too large.
+  RANGE          = 68,
+  /// Read-only file system.
+  ROFS           = 69,
+  /// Invalid seek.
+  SPIPE          = 70,
+  /// No such process.
+  SRCH           = 71,
+  /// Reserved.
+  STALE          = 72,
+  /// Connection timed out.
+  TIMEDOUT       = 73,
+  /// Text file busy.
+  TXTBSY         = 74,
+  /// Cross-device link.
+  XDEV           = 75,
+  /// Extension: Capabilities insufficient.
+  NOTCAPABLE     = 76,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u16,
+}
+
+bitflags! {
+  /// The state of the file descriptor subscribed to with
+  /// [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+  #[repr(C)]
+  pub struct eventrwflags: u16 {
+    /// The peer of this socket has closed or disconnected.
+    const HANGUP = 0x0001;
+  }
+}
+
+/// Type of a subscription to an event or its occurrence.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum eventtype {
+  /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
+  /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
+  CLOCK          = 1,
+  /// Condition variable [`subscription.union.condvar.condvar`](struct.subscription_condvar.html#structfield.condvar) has
+  /// been woken up and [`subscription.union.condvar.lock`](struct.subscription_condvar.html#structfield.lock) has been
+  /// acquired for writing.
+  CONDVAR        = 2,
+  /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
+  /// data available for reading. This event always triggers
+  /// for regular files.
+  FD_READ        = 3,
+  /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
+  /// capacity available for writing. This event always
+  /// triggers for regular files.
+  FD_WRITE       = 4,
+  /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
+  /// reading.
+  LOCK_RDLOCK    = 5,
+  /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
+  /// writing.
+  LOCK_WRLOCK    = 6,
+  /// The process associated with process descriptor
+  /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
+  PROC_TERMINATE = 7,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Exit code generated by a process when exiting.
+pub type exitcode = u32;
+
+/// A file descriptor number.
+///
+/// Unlike on POSIX-compliant systems, none of the file descriptor
+/// numbers are reserved for a purpose (e.g., stdin, stdout,
+/// stderr). Operating systems are not required to allocate new
+/// file descriptors in ascending order.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct fd(pub u32);
+/// Returned to the child process by [`proc_fork()`](fn.proc_fork.html).
+pub const PROCESS_CHILD: fd = fd(0xffffffff);
+/// Passed to [`mem_map()`](fn.mem_map.html) when creating a mapping to
+/// anonymous memory.
+pub const MAP_ANON_FD  : fd = fd(0xffffffff);
+
+bitflags! {
+  /// File descriptor flags.
+  #[repr(C)]
+  pub struct fdflags: u16 {
+    /// Append mode: Data written to the file is always
+    /// appended to the file's end.
+    const APPEND   = 0x0001;
+    /// Write according to synchronized I/O data integrity
+    /// completion. Only the data stored in the file is
+    /// synchronized.
+    const DSYNC    = 0x0002;
+    /// Non-blocking mode.
+    const NONBLOCK = 0x0004;
+    /// Synchronized read I/O operations.
+    const RSYNC    = 0x0008;
+    /// Write according to synchronized I/O file integrity
+    /// completion. In addition to synchronizing the data
+    /// stored in the file, the system may also synchronously
+    /// update the file's metadata.
+    const SYNC     = 0x0010;
+  }
+}
+
+bitflags! {
+  /// Which file descriptor attributes to adjust.
+  #[repr(C)]
+  pub struct fdsflags: u16 {
+    /// Adjust the file descriptor flags stored in
+    /// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags).
+    const FLAGS  = 0x0001;
+    /// Restrict the rights of the file descriptor to the
+    /// rights stored in [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
+    /// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting).
+    const RIGHTS = 0x0002;
+  }
+}
+
+/// Relative offset within a file.
+pub type filedelta = i64;
+
+/// Non-negative file size or length of a region within a file.
+pub type filesize = u64;
+
+/// The type of a file descriptor or file.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum filetype {
+  /// The type of the file descriptor or file is unknown or
+  /// is different from any of the other types specified.
+  UNKNOWN          =   0,
+  /// The file descriptor or file refers to a block device
+  /// inode.
+  BLOCK_DEVICE     =  16,
+  /// The file descriptor or file refers to a character
+  /// device inode.
+  CHARACTER_DEVICE =  17,
+  /// The file descriptor or file refers to a directory
+  /// inode.
+  DIRECTORY        =  32,
+  /// The file descriptor refers to a process handle.
+  PROCESS          =  80,
+  /// The file descriptor or file refers to a regular file
+  /// inode.
+  REGULAR_FILE     =  96,
+  /// The file descriptor refers to a shared memory object.
+  SHARED_MEMORY    = 112,
+  /// The file descriptor or file refers to a datagram
+  /// socket.
+  SOCKET_DGRAM     = 128,
+  /// The file descriptor or file refers to a byte-stream
+  /// socket.
+  SOCKET_STREAM    = 130,
+  /// The file refers to a symbolic link inode.
+  SYMBOLIC_LINK    = 144,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+  /// Which file attributes to adjust.
+  #[repr(C)]
+  pub struct fsflags: u16 {
+    /// Adjust the last data access timestamp to the value
+    /// stored in [`filestat.st_atim`](struct.filestat.html#structfield.st_atim).
+    const ATIM     = 0x0001;
+    /// Adjust the last data access timestamp to the time
+    /// of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
+    const ATIM_NOW = 0x0002;
+    /// Adjust the last data modification timestamp to the
+    /// value stored in [`filestat.st_mtim`](struct.filestat.html#structfield.st_mtim).
+    const MTIM     = 0x0004;
+    /// Adjust the last data modification timestamp to the
+    /// time of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
+    const MTIM_NOW = 0x0008;
+    /// Truncate or extend the file to the size stored in
+    /// [`filestat.st_size`](struct.filestat.html#structfield.st_size).
+    const SIZE     = 0x0010;
+  }
+}
+
+/// File serial number that is unique within its file system.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct inode(pub u64);
+
+/// Number of hard links to an inode.
+pub type linkcount = u32;
+
+/// A userspace read-recursive readers-writer lock, similar to a
+/// Linux futex or a FreeBSD umtx.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct lock(pub u32);
+/// Value indicating that the lock is in its initial
+/// unlocked state.
+pub const LOCK_UNLOCKED      : lock = lock(0x00000000);
+/// Bitmask indicating that the lock is write-locked. If
+/// set, the lower 30 bits of the lock contain the
+/// identifier of the thread that owns the write lock.
+/// Otherwise, the lower 30 bits of the lock contain the
+/// number of acquired read locks.
+pub const LOCK_WRLOCKED      : lock = lock(0x40000000);
+/// Bitmask indicating that the lock is either read locked
+/// or write locked, and that one or more threads have
+/// their execution suspended, waiting to acquire the
+/// lock. The last owner of the lock must call the
+/// kernel to unlock.
+///
+/// When the lock is acquired for reading and this bit is
+/// set, it means that one or more threads are attempting
+/// to acquire this lock for writing. In that case, other
+/// threads should only acquire additional read locks if
+/// suspending execution would cause a deadlock. It is
+/// preferred to suspend execution, as this prevents
+/// starvation of writers.
+pub const LOCK_KERNEL_MANAGED: lock = lock(0x80000000);
+/// Value indicating that the lock is in an incorrect
+/// state. A lock cannot be in its initial unlocked state,
+/// while also managed by the kernel.
+pub const LOCK_BOGUS         : lock = lock(0x80000000);
+
+bitflags! {
+  /// Flags determining the method of how paths are resolved.
+  #[repr(C)]
+  pub struct lookupflags: u32 {
+    /// As long as the resolved path corresponds to a symbolic
+    /// link, it is expanded.
+    const SYMLINK_FOLLOW = 0x00000001;
+  }
+}
+
+bitflags! {
+  /// Memory mapping flags.
+  #[repr(C)]
+  pub struct mflags: u8 {
+    /// Instead of mapping the contents of the file provided,
+    /// create a mapping to anonymous memory. The file
+    /// descriptor argument must be set to [`MAP_ANON_FD`](constant.MAP_ANON_FD.html),
+    /// and the offset must be set to zero.
+    const ANON    = 0x01;
+    /// Require that the mapping is performed at the base
+    /// address provided.
+    const FIXED   = 0x02;
+    /// Changes are private.
+    const PRIVATE = 0x04;
+    /// Changes are shared.
+    const SHARED  = 0x08;
+  }
+}
+
+bitflags! {
+  /// Memory page protection options.
+  ///
+  /// This implementation enforces the `W^X` property: Pages cannot be
+  /// mapped for execution while also mapped for writing.
+  #[repr(C)]
+  pub struct mprot: u8 {
+    /// Page can be executed.
+    const EXEC  = 0x01;
+    /// Page can be written.
+    const WRITE = 0x02;
+    /// Page can be read.
+    const READ  = 0x04;
+  }
+}
+
+bitflags! {
+  /// Methods of synchronizing memory with physical storage.
+  #[repr(C)]
+  pub struct msflags: u8 {
+    /// Perform asynchronous writes.
+    const ASYNC      = 0x01;
+    /// Invalidate cached data.
+    const INVALIDATE = 0x02;
+    /// Perform synchronous writes.
+    const SYNC       = 0x04;
+  }
+}
+
+/// Specifies the number of threads sleeping on a condition
+/// variable that should be woken up.
+pub type nthreads = u32;
+
+bitflags! {
+  /// Open flags used by [`file_open()`](fn.file_open.html).
+  #[repr(C)]
+  pub struct oflags: u16 {
+    /// Create file if it does not exist.
+    const CREAT     = 0x0001;
+    /// Fail if not a directory.
+    const DIRECTORY = 0x0002;
+    /// Fail if file already exists.
+    const EXCL      = 0x0004;
+    /// Truncate file to size 0.
+    const TRUNC     = 0x0008;
+  }
+}
+
+bitflags! {
+  /// Flags provided to [`sock_recv()`](fn.sock_recv.html).
+  #[repr(C)]
+  pub struct riflags: u16 {
+    /// Returns the message without removing it from the
+    /// socket's receive queue.
+    const PEEK    = 0x0004;
+    /// On byte-stream sockets, block until the full amount
+    /// of data can be returned.
+    const WAITALL = 0x0010;
+  }
+}
+
+bitflags! {
+  /// File descriptor rights, determining which actions may be
+  /// performed.
+  #[repr(C)]
+  pub struct rights: u64 {
+    /// The right to invoke [`fd_datasync()`](fn.fd_datasync.html).
+    ///
+    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+    /// invoke [`file_open()`](fn.file_open.html) with [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
+    const FD_DATASYNC           = 0x0000000000000001;
+    /// The right to invoke [`fd_read()`](fn.fd_read.html) and [`sock_recv()`](fn.sock_recv.html).
+    ///
+    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
+    /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
+    /// [`READ`](struct.mprot.html#associatedconstant.READ).
+    ///
+    /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to invoke
+    /// [`fd_pread()`](fn.fd_pread.html).
+    const FD_READ               = 0x0000000000000002;
+    /// The right to invoke [`fd_seek()`](fn.fd_seek.html). This flag implies
+    /// [`FD_TELL`](struct.rights.html#associatedconstant.FD_TELL).
+    const FD_SEEK               = 0x0000000000000004;
+    /// The right to invoke [`fd_stat_put()`](fn.fd_stat_put.html) with
+    /// [`FLAGS`](struct.fdsflags.html#associatedconstant.FLAGS).
+    const FD_STAT_PUT_FLAGS     = 0x0000000000000008;
+    /// The right to invoke [`fd_sync()`](fn.fd_sync.html).
+    ///
+    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+    /// invoke [`file_open()`](fn.file_open.html) with [`RSYNC`](struct.fdflags.html#associatedconstant.RSYNC) and
+    /// [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
+    const FD_SYNC               = 0x0000000000000010;
+    /// The right to invoke [`fd_seek()`](fn.fd_seek.html) in such a way that the
+    /// file offset remains unaltered (i.e., [`CUR`](enum.whence.html#variant.CUR) with
+    /// offset zero).
+    const FD_TELL               = 0x0000000000000020;
+    /// The right to invoke [`fd_write()`](fn.fd_write.html) and [`sock_send()`](fn.sock_send.html).
+    ///
+    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
+    /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
+    /// [`WRITE`](struct.mprot.html#associatedconstant.WRITE).
+    ///
+    /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to
+    /// invoke [`fd_pwrite()`](fn.fd_pwrite.html).
+    const FD_WRITE              = 0x0000000000000040;
+    /// The right to invoke [`file_advise()`](fn.file_advise.html).
+    const FILE_ADVISE           = 0x0000000000000080;
+    /// The right to invoke [`file_allocate()`](fn.file_allocate.html).
+    const FILE_ALLOCATE         = 0x0000000000000100;
+    /// The right to invoke [`file_create()`](fn.file_create.html) with
+    /// [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY).
+    const FILE_CREATE_DIRECTORY = 0x0000000000000200;
+    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, the right to invoke
+    /// [`file_open()`](fn.file_open.html) with [`CREAT`](struct.oflags.html#associatedconstant.CREAT).
+    const FILE_CREATE_FILE      = 0x0000000000000400;
+    /// The right to invoke [`file_link()`](fn.file_link.html) with the file
+    /// descriptor as the source directory.
+    const FILE_LINK_SOURCE      = 0x0000000000001000;
+    /// The right to invoke [`file_link()`](fn.file_link.html) with the file
+    /// descriptor as the target directory.
+    const FILE_LINK_TARGET      = 0x0000000000002000;
+    /// The right to invoke [`file_open()`](fn.file_open.html).
+    const FILE_OPEN             = 0x0000000000004000;
+    /// The right to invoke [`file_readdir()`](fn.file_readdir.html).
+    const FILE_READDIR          = 0x0000000000008000;
+    /// The right to invoke [`file_readlink()`](fn.file_readlink.html).
+    const FILE_READLINK         = 0x0000000000010000;
+    /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
+    /// descriptor as the source directory.
+    const FILE_RENAME_SOURCE    = 0x0000000000020000;
+    /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
+    /// descriptor as the target directory.
+    const FILE_RENAME_TARGET    = 0x0000000000040000;
+    /// The right to invoke [`file_stat_fget()`](fn.file_stat_fget.html).
+    const FILE_STAT_FGET        = 0x0000000000080000;
+    /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
+    /// [`SIZE`](struct.fsflags.html#associatedconstant.SIZE).
+    ///
+    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
+    /// invoke [`file_open()`](fn.file_open.html) with [`TRUNC`](struct.oflags.html#associatedconstant.TRUNC).
+    const FILE_STAT_FPUT_SIZE   = 0x0000000000100000;
+    /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
+    /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
+    /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
+    const FILE_STAT_FPUT_TIMES  = 0x0000000000200000;
+    /// The right to invoke [`file_stat_get()`](fn.file_stat_get.html).
+    const FILE_STAT_GET         = 0x0000000000400000;
+    /// The right to invoke [`file_stat_put()`](fn.file_stat_put.html) with
+    /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
+    /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
+    const FILE_STAT_PUT_TIMES   = 0x0000000000800000;
+    /// The right to invoke [`file_symlink()`](fn.file_symlink.html).
+    const FILE_SYMLINK          = 0x0000000001000000;
+    /// The right to invoke [`file_unlink()`](fn.file_unlink.html).
+    const FILE_UNLINK           = 0x0000000002000000;
+    /// The right to invoke [`mem_map()`](fn.mem_map.html) with [`mprot`](struct.mprot.html) set to
+    /// zero.
+    const MEM_MAP               = 0x0000000004000000;
+    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, the right to invoke
+    /// [`mem_map()`](fn.mem_map.html) with [`EXEC`](struct.mprot.html#associatedconstant.EXEC).
+    const MEM_MAP_EXEC          = 0x0000000008000000;
+    /// If [`FD_READ`](struct.rights.html#associatedconstant.FD_READ) is set, includes the right to
+    /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_READ`](enum.eventtype.html#variant.FD_READ).
+    ///
+    /// If [`FD_WRITE`](struct.rights.html#associatedconstant.FD_WRITE) is set, includes the right to
+    /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+    const POLL_FD_READWRITE     = 0x0000000010000000;
+    /// The right to invoke [`poll()`](fn.poll.html) to subscribe to
+    /// [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+    const POLL_PROC_TERMINATE   = 0x0000000040000000;
+    /// The right to invoke [`proc_exec()`](fn.proc_exec.html).
+    const PROC_EXEC             = 0x0000000100000000;
+    /// The right to invoke [`sock_shutdown()`](fn.sock_shutdown.html).
+    const SOCK_SHUTDOWN         = 0x0000008000000000;
+  }
+}
+
+bitflags! {
+  /// Flags returned by [`sock_recv()`](fn.sock_recv.html).
+  #[repr(C)]
+  pub struct roflags: u16 {
+    /// Returned by [`sock_recv()`](fn.sock_recv.html): List of file descriptors
+    /// has been truncated.
+    const FDS_TRUNCATED  = 0x0001;
+    /// Returned by [`sock_recv()`](fn.sock_recv.html): Message data has been
+    /// truncated.
+    const DATA_TRUNCATED = 0x0008;
+  }
+}
+
+/// Indicates whether an object is stored in private or shared
+/// memory.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum scope {
+  /// The object is stored in private memory.
+  PRIVATE = 4,
+  /// The object is stored in shared memory.
+  SHARED  = 8,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+  /// Which channels on a socket need to be shut down.
+  #[repr(C)]
+  pub struct sdflags: u8 {
+    /// Disables further receive operations.
+    const RD = 0x01;
+    /// Disables further send operations.
+    const WR = 0x02;
+  }
+}
+
+bitflags! {
+  /// Flags provided to [`sock_send()`](fn.sock_send.html). As there are currently no flags
+  /// defined, it must be set to zero.
+  #[repr(C)]
+  pub struct siflags: u16 {
+    const DEFAULT = 0;
+  }
+}
+
+/// Signal condition.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum signal {
+  /// Process abort signal.
+  ///
+  /// Action: Terminates the process.
+  ABRT   =  1,
+  /// Alarm clock.
+  ///
+  /// Action: Terminates the process.
+  ALRM   =  2,
+  /// Access to an undefined portion of a memory object.
+  ///
+  /// Action: Terminates the process.
+  BUS    =  3,
+  /// Child process terminated, stopped, or continued.
+  ///
+  /// Action: Ignored.
+  CHLD   =  4,
+  /// Continue executing, if stopped.
+  ///
+  /// Action: Continues executing, if stopped.
+  CONT   =  5,
+  /// Erroneous arithmetic operation.
+  ///
+  /// Action: Terminates the process.
+  FPE    =  6,
+  /// Hangup.
+  ///
+  /// Action: Terminates the process.
+  HUP    =  7,
+  /// Illegal instruction.
+  ///
+  /// Action: Terminates the process.
+  ILL    =  8,
+  /// Terminate interrupt signal.
+  ///
+  /// Action: Terminates the process.
+  INT    =  9,
+  /// Kill.
+  ///
+  /// Action: Terminates the process.
+  KILL   = 10,
+  /// Write on a pipe with no one to read it.
+  ///
+  /// Action: Ignored.
+  PIPE   = 11,
+  /// Terminal quit signal.
+  ///
+  /// Action: Terminates the process.
+  QUIT   = 12,
+  /// Invalid memory reference.
+  ///
+  /// Action: Terminates the process.
+  SEGV   = 13,
+  /// Stop executing.
+  ///
+  /// Action: Stops executing.
+  STOP   = 14,
+  /// Bad system call.
+  ///
+  /// Action: Terminates the process.
+  SYS    = 15,
+  /// Termination signal.
+  ///
+  /// Action: Terminates the process.
+  TERM   = 16,
+  /// Trace/breakpoint trap.
+  ///
+  /// Action: Terminates the process.
+  TRAP   = 17,
+  /// Terminal stop signal.
+  ///
+  /// Action: Stops executing.
+  TSTP   = 18,
+  /// Background process attempting read.
+  ///
+  /// Action: Stops executing.
+  TTIN   = 19,
+  /// Background process attempting write.
+  ///
+  /// Action: Stops executing.
+  TTOU   = 20,
+  /// High bandwidth data is available at a socket.
+  ///
+  /// Action: Ignored.
+  URG    = 21,
+  /// User-defined signal 1.
+  ///
+  /// Action: Terminates the process.
+  USR1   = 22,
+  /// User-defined signal 2.
+  ///
+  /// Action: Terminates the process.
+  USR2   = 23,
+  /// Virtual timer expired.
+  ///
+  /// Action: Terminates the process.
+  VTALRM = 24,
+  /// CPU time limit exceeded.
+  ///
+  /// Action: Terminates the process.
+  XCPU   = 25,
+  /// File size limit exceeded.
+  ///
+  /// Action: Terminates the process.
+  XFSZ   = 26,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+bitflags! {
+  /// Flags determining how the timestamp provided in
+  /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) should be interpreted.
+  #[repr(C)]
+  pub struct subclockflags: u16 {
+    /// If set, treat the timestamp provided in
+    /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) as an absolute timestamp
+    /// of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
+    ///
+    /// If clear, treat the timestamp provided in
+    /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) relative to the current
+    /// time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
+    const ABSTIME = 0x0001;
+  }
+}
+
+bitflags! {
+  /// Flags influencing the method of polling for read or writing on
+  /// a file descriptor.
+  #[repr(C)]
+  pub struct subrwflags: u16 {
+    /// Deprecated. Must be set by callers and ignored by
+    /// implementations.
+    const POLL = 0x0001;
+  }
+}
+
+/// Unique system-local identifier of a thread. This identifier is
+/// only valid during the lifetime of the thread.
+///
+/// Threads must be aware of their thread identifier, as it is
+/// written it into locks when acquiring them for writing. It is
+/// not advised to use these identifiers for any other purpose.
+///
+/// As the thread identifier is also stored in [`lock`](struct.lock.html) when
+/// [`LOCK_WRLOCKED`](constant.LOCK_WRLOCKED.html) is set, the top two bits of the thread
+/// must always be set to zero.
+#[repr(C)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub struct tid(pub u32);
+
+/// Timestamp in nanoseconds.
+pub type timestamp = u64;
+
+bitflags! {
+  /// Specifies whether files are unlinked or directories are
+  /// removed.
+  #[repr(C)]
+  pub struct ulflags: u8 {
+    /// If set, removes a directory. Otherwise, unlinks any
+    /// non-directory file.
+    const REMOVEDIR = 0x01;
+  }
+}
+
+/// User-provided value that can be attached to objects that is
+/// retained when extracted from the kernel.
+pub type userdata = u64;
+
+/// Relative to which position the offset of the file descriptor
+/// should be set.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum whence {
+  /// Seek relative to current position.
+  CUR = 1,
+  /// Seek relative to end-of-file.
+  END = 2,
+  /// Seek relative to start-of-file.
+  SET = 3,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Auxiliary vector entry.
+///
+/// The auxiliary vector is a list of key-value pairs that is
+/// provided to the process on startup. Unlike structures, it is
+/// extensible, as it is possible to add new records later on.
+/// The auxiliary vector is always terminated by an entry having
+/// type [`NULL`](enum.auxtype.html#variant.NULL).
+///
+/// The auxiliary vector is part of the x86-64 ABI, but is used by
+/// this environment on all architectures.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct auxv {
+  /// The type of the auxiliary vector entry.
+  pub a_type: auxtype,
+  pub union: auxv_union
+}
+/// A union inside `auxv`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union auxv_union {
+  /// Used when `a_type` is [`ARGDATALEN`](enum.auxtype.html#variant.ARGDATALEN), [`CANARYLEN`](enum.auxtype.html#variant.CANARYLEN), [`NCPUS`](enum.auxtype.html#variant.NCPUS), [`PAGESZ`](enum.auxtype.html#variant.PAGESZ), [`PHNUM`](enum.auxtype.html#variant.PHNUM), or [`TID`](enum.auxtype.html#variant.TID).
+/// A numerical value.
+  pub a_val: usize,
+  /// Used when `a_type` is [`ARGDATA`](enum.auxtype.html#variant.ARGDATA), [`BASE`](enum.auxtype.html#variant.BASE), [`CANARY`](enum.auxtype.html#variant.CANARY), [`PHDR`](enum.auxtype.html#variant.PHDR), [`PID`](enum.auxtype.html#variant.PID), or [`SYSINFO_EHDR`](enum.auxtype.html#variant.SYSINFO_EHDR).
+/// A pointer value.
+  pub a_ptr: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn auxv_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<auxv>(), 8);
+  assert_eq!(::core::mem::align_of::<auxv>(), 4);
+  unsafe {
+    let obj: auxv = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.a_type as *const _ as usize - base, 0);
+    assert_eq!(&obj.union.a_val as *const _ as usize - base, 4);
+    assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 4);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn auxv_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<auxv>(), 16);
+  assert_eq!(::core::mem::align_of::<auxv>(), 8);
+  unsafe {
+    let obj: auxv = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.a_type as *const _ as usize - base, 0);
+    assert_eq!(&obj.union.a_val as *const _ as usize - base, 8);
+    assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 8);
+  }
+}
+
+/// A region of memory for scatter/gather writes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct ciovec {
+  /// The address and length of the buffer to be written.
+  pub buf: (*const (), usize),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn ciovec_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<ciovec>(), 8);
+  assert_eq!(::core::mem::align_of::<ciovec>(), 4);
+  unsafe {
+    let obj: ciovec = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn ciovec_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<ciovec>(), 16);
+  assert_eq!(::core::mem::align_of::<ciovec>(), 8);
+  unsafe {
+    let obj: ciovec = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
+  }
+}
+
+/// A directory entry.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct dirent {
+  /// The offset of the next directory entry stored in this
+  /// directory.
+  pub d_next: dircookie,
+  /// The serial number of the file referred to by this
+  /// directory entry.
+  pub d_ino: inode,
+  /// The length of the name of the directory entry.
+  pub d_namlen: u32,
+  /// The type of the file referred to by this directory
+  /// entry.
+  pub d_type: filetype,
+}
+#[test]
+fn dirent_layout_test() {
+  assert_eq!(::core::mem::size_of::<dirent>(), 24);
+  assert_eq!(::core::mem::align_of::<dirent>(), 8);
+  unsafe {
+    let obj: dirent = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.d_next as *const _ as usize - base, 0);
+    assert_eq!(&obj.d_ino as *const _ as usize - base, 8);
+    assert_eq!(&obj.d_namlen as *const _ as usize - base, 16);
+    assert_eq!(&obj.d_type as *const _ as usize - base, 20);
+  }
+}
+
+/// An event that occurred.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event {
+  /// User-provided value that got attached to
+  /// [`subscription.userdata`](struct.subscription.html#structfield.userdata).
+  pub userdata: userdata,
+  /// If non-zero, an error that occurred while processing
+  /// the subscription request.
+  pub error: errno,
+  /// The type of the event that occurred.
+  pub type_: eventtype,
+  pub union: event_union
+}
+/// A union inside `event`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union event_union {
+  /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+  pub fd_readwrite: event_fd_readwrite,
+  /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+  pub proc_terminate: event_proc_terminate,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event_fd_readwrite {
+  /// The number of bytes available
+  /// for reading or writing.
+  pub nbytes: filesize,
+  /// Obsolete.
+  pub unused: [u8; 4],
+  /// The state of the file
+  /// descriptor.
+  pub flags: eventrwflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct event_proc_terminate {
+  /// Obsolete.
+  pub unused: [u8; 4],
+  /// If zero, the process has
+  /// exited.
+  /// Otherwise, the signal
+  /// condition causing it to
+  /// terminated.
+  pub signal: signal,
+  /// If exited, the exit code of
+  /// the process.
+  pub exitcode: exitcode,
+}
+#[test]
+fn event_layout_test() {
+  assert_eq!(::core::mem::size_of::<event>(), 32);
+  assert_eq!(::core::mem::align_of::<event>(), 8);
+  unsafe {
+    let obj: event = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+    assert_eq!(&obj.error as *const _ as usize - base, 8);
+    assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+    assert_eq!(&obj.union.fd_readwrite.nbytes as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.fd_readwrite.unused as *const _ as usize - base, 24);
+    assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 28);
+    assert_eq!(&obj.union.proc_terminate.unused as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.proc_terminate.signal as *const _ as usize - base, 20);
+    assert_eq!(&obj.union.proc_terminate.exitcode as *const _ as usize - base, 24);
+  }
+}
+
+/// File descriptor attributes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct fdstat {
+  /// File type.
+  pub fs_filetype: filetype,
+  /// File descriptor flags.
+  pub fs_flags: fdflags,
+  /// Rights that apply to this file descriptor.
+  pub fs_rights_base: rights,
+  /// Maximum set of rights that can be installed on new
+  /// file descriptors that are created through this file
+  /// descriptor, e.g., through [`file_open()`](fn.file_open.html).
+  pub fs_rights_inheriting: rights,
+}
+#[test]
+fn fdstat_layout_test() {
+  assert_eq!(::core::mem::size_of::<fdstat>(), 24);
+  assert_eq!(::core::mem::align_of::<fdstat>(), 8);
+  unsafe {
+    let obj: fdstat = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.fs_filetype as *const _ as usize - base, 0);
+    assert_eq!(&obj.fs_flags as *const _ as usize - base, 2);
+    assert_eq!(&obj.fs_rights_base as *const _ as usize - base, 8);
+    assert_eq!(&obj.fs_rights_inheriting as *const _ as usize - base, 16);
+  }
+}
+
+/// File attributes.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct filestat {
+  /// Device ID of device containing the file.
+  pub st_dev: device,
+  /// File serial number.
+  pub st_ino: inode,
+  /// File type.
+  pub st_filetype: filetype,
+  /// Number of hard links to the file.
+  pub st_nlink: linkcount,
+  /// For regular files, the file size in bytes. For
+  /// symbolic links, the length in bytes of the pathname
+  /// contained in the symbolic link.
+  pub st_size: filesize,
+  /// Last data access timestamp.
+  pub st_atim: timestamp,
+  /// Last data modification timestamp.
+  pub st_mtim: timestamp,
+  /// Last file status change timestamp.
+  pub st_ctim: timestamp,
+}
+#[test]
+fn filestat_layout_test() {
+  assert_eq!(::core::mem::size_of::<filestat>(), 56);
+  assert_eq!(::core::mem::align_of::<filestat>(), 8);
+  unsafe {
+    let obj: filestat = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.st_dev as *const _ as usize - base, 0);
+    assert_eq!(&obj.st_ino as *const _ as usize - base, 8);
+    assert_eq!(&obj.st_filetype as *const _ as usize - base, 16);
+    assert_eq!(&obj.st_nlink as *const _ as usize - base, 20);
+    assert_eq!(&obj.st_size as *const _ as usize - base, 24);
+    assert_eq!(&obj.st_atim as *const _ as usize - base, 32);
+    assert_eq!(&obj.st_mtim as *const _ as usize - base, 40);
+    assert_eq!(&obj.st_ctim as *const _ as usize - base, 48);
+  }
+}
+
+/// A region of memory for scatter/gather reads.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct iovec {
+  /// The address and length of the buffer to be filled.
+  pub buf: (*mut (), usize),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn iovec_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<iovec>(), 8);
+  assert_eq!(::core::mem::align_of::<iovec>(), 4);
+  unsafe {
+    let obj: iovec = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn iovec_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<iovec>(), 16);
+  assert_eq!(::core::mem::align_of::<iovec>(), 8);
+  unsafe {
+    let obj: iovec = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
+  }
+}
+
+/// Path lookup properties.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct lookup {
+  /// The working directory at which the resolution of the
+  /// path starts.
+  pub fd: fd,
+  /// Flags determining the method of how the path is
+  /// resolved.
+  pub flags: lookupflags,
+}
+#[test]
+fn lookup_layout_test() {
+  assert_eq!(::core::mem::size_of::<lookup>(), 8);
+  assert_eq!(::core::mem::align_of::<lookup>(), 4);
+  unsafe {
+    let obj: lookup = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.fd as *const _ as usize - base, 0);
+    assert_eq!(&obj.flags as *const _ as usize - base, 4);
+  }
+}
+
+/// Entry point for a process (`_start`).
+///
+/// **auxv**:
+/// The auxiliary vector. See [`auxv`](struct.auxv.html).
+pub type processentry = unsafe extern "C" fn(
+  auxv: *const auxv,
+) -> ();
+
+/// Arguments of [`sock_recv()`](fn.sock_recv.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct recv_in {
+  /// List of scatter/gather vectors where message data
+  /// should be stored.
+  pub ri_data: (*const iovec, usize),
+  /// Buffer where numbers of incoming file descriptors
+  /// should be stored.
+  pub ri_fds: (*mut fd, usize),
+  /// Message flags.
+  pub ri_flags: riflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn recv_in_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<recv_in>(), 20);
+  assert_eq!(::core::mem::align_of::<recv_in>(), 4);
+  unsafe {
+    let obj: recv_in = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 4);
+    assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 8);
+    assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 12);
+    assert_eq!(&obj.ri_flags as *const _ as usize - base, 16);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn recv_in_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<recv_in>(), 40);
+  assert_eq!(::core::mem::align_of::<recv_in>(), 8);
+  unsafe {
+    let obj: recv_in = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 8);
+    assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 16);
+    assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 24);
+    assert_eq!(&obj.ri_flags as *const _ as usize - base, 32);
+  }
+}
+
+/// Results of [`sock_recv()`](fn.sock_recv.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct recv_out {
+  /// Number of bytes stored in [`recv_in.ri_data`](struct.recv_in.html#structfield.ri_data).
+  pub ro_datalen: usize,
+  /// Number of file descriptors stored in [`recv_in.ri_fds`](struct.recv_in.html#structfield.ri_fds).
+  pub ro_fdslen: usize,
+  /// Fields that were used by previous implementations.
+  pub ro_unused: [u8; 40],
+  /// Message flags.
+  pub ro_flags: roflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn recv_out_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<recv_out>(), 52);
+  assert_eq!(::core::mem::align_of::<recv_out>(), 4);
+  unsafe {
+    let obj: recv_out = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
+    assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 4);
+    assert_eq!(&obj.ro_unused as *const _ as usize - base, 8);
+    assert_eq!(&obj.ro_flags as *const _ as usize - base, 48);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn recv_out_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<recv_out>(), 64);
+  assert_eq!(::core::mem::align_of::<recv_out>(), 8);
+  unsafe {
+    let obj: recv_out = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
+    assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 8);
+    assert_eq!(&obj.ro_unused as *const _ as usize - base, 16);
+    assert_eq!(&obj.ro_flags as *const _ as usize - base, 56);
+  }
+}
+
+/// Arguments of [`sock_send()`](fn.sock_send.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct send_in {
+  /// List of scatter/gather vectors where message data
+  /// should be retrieved.
+  pub si_data: (*const ciovec, usize),
+  /// File descriptors that need to be attached to the
+  /// message.
+  pub si_fds: (*const fd, usize),
+  /// Message flags.
+  pub si_flags: siflags,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn send_in_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<send_in>(), 20);
+  assert_eq!(::core::mem::align_of::<send_in>(), 4);
+  unsafe {
+    let obj: send_in = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.si_data.1 as *const _ as usize - base, 4);
+    assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 8);
+    assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 12);
+    assert_eq!(&obj.si_flags as *const _ as usize - base, 16);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn send_in_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<send_in>(), 40);
+  assert_eq!(::core::mem::align_of::<send_in>(), 8);
+  unsafe {
+    let obj: send_in = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
+    assert_eq!(&obj.si_data.1 as *const _ as usize - base, 8);
+    assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 16);
+    assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 24);
+    assert_eq!(&obj.si_flags as *const _ as usize - base, 32);
+  }
+}
+
+/// Results of [`sock_send()`](fn.sock_send.html).
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct send_out {
+  /// Number of bytes transmitted.
+  pub so_datalen: usize,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn send_out_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<send_out>(), 4);
+  assert_eq!(::core::mem::align_of::<send_out>(), 4);
+  unsafe {
+    let obj: send_out = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn send_out_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<send_out>(), 8);
+  assert_eq!(::core::mem::align_of::<send_out>(), 8);
+  unsafe {
+    let obj: send_out = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
+  }
+}
+
+/// Subscription to an event.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription {
+  /// User-provided value that is attached to the
+  /// subscription in the kernel and returned through
+  /// [`event.userdata`](struct.event.html#structfield.userdata).
+  pub userdata: userdata,
+  /// Used by previous implementations. Ignored.
+  pub unused: u16,
+  /// The type of the event to which to subscribe.
+  ///
+  /// Currently, [`CONDVAR`](enum.eventtype.html#variant.CONDVAR),
+  /// [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK), and [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK)
+  /// must be provided as the first subscription and may
+  /// only be followed by up to one other subscription,
+  /// having type [`CLOCK`](enum.eventtype.html#variant.CLOCK).
+  pub type_: eventtype,
+  pub union: subscription_union
+}
+/// A union inside `subscription`.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union subscription_union {
+  /// Used when `type_` is [`CLOCK`](enum.eventtype.html#variant.CLOCK).
+  pub clock: subscription_clock,
+  /// Used when `type_` is [`CONDVAR`](enum.eventtype.html#variant.CONDVAR).
+  pub condvar: subscription_condvar,
+  /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
+  pub fd_readwrite: subscription_fd_readwrite,
+  /// Used when `type_` is [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK) or [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK).
+  pub lock: subscription_lock,
+  /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
+  pub proc_terminate: subscription_proc_terminate,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_clock {
+  /// The user-defined unique
+  /// identifier of the clock.
+  pub identifier: userdata,
+  /// The clock against which the
+  /// timestamp should be compared.
+  pub clock_id: clockid,
+  /// The absolute or relative
+  /// timestamp.
+  pub timeout: timestamp,
+  /// The amount of time that the
+  /// kernel may wait additionally
+  /// to coalesce with other events.
+  pub precision: timestamp,
+  /// Flags specifying whether the
+  /// timeout is absolute or
+  /// relative.
+  pub flags: subclockflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_condvar {
+  /// The condition variable on
+  /// which to wait to be woken up.
+  pub condvar: *mut condvar,
+  /// The lock that will be
+  /// released while waiting.
+  ///
+  /// The lock will be reacquired
+  /// for writing when the condition
+  /// variable triggers.
+  pub lock: *mut lock,
+  /// Whether the condition variable
+  /// is stored in private or shared
+  /// memory.
+  pub condvar_scope: scope,
+  /// Whether the lock is stored in
+  /// private or shared memory.
+  pub lock_scope: scope,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_fd_readwrite {
+  /// The file descriptor on which
+  /// to wait for it to become ready
+  /// for reading or writing.
+  pub fd: fd,
+  /// Under which conditions to
+  /// trigger.
+  pub flags: subrwflags,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_lock {
+  /// The lock that will be acquired
+  /// for reading or writing.
+  pub lock: *mut lock,
+  /// Whether the lock is stored in
+  /// private or shared memory.
+  pub lock_scope: scope,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct subscription_proc_terminate {
+  /// The process descriptor on
+  /// which to wait for process
+  /// termination.
+  pub fd: fd,
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn subscription_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<subscription>(), 56);
+  assert_eq!(::core::mem::align_of::<subscription>(), 8);
+  unsafe {
+    let obj: subscription = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+    assert_eq!(&obj.unused as *const _ as usize - base, 8);
+    assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+    assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
+    assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
+    assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
+    assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
+    assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 20);
+    assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 24);
+    assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 25);
+    assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
+    assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 20);
+    assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn subscription_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<subscription>(), 56);
+  assert_eq!(::core::mem::align_of::<subscription>(), 8);
+  unsafe {
+    let obj: subscription = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.userdata as *const _ as usize - base, 0);
+    assert_eq!(&obj.unused as *const _ as usize - base, 8);
+    assert_eq!(&obj.type_ as *const _ as usize - base, 10);
+    assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
+    assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
+    assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
+    assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
+    assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 24);
+    assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 32);
+    assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 33);
+    assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
+    assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
+    assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 24);
+    assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
+  }
+}
+
+/// The Thread Control Block (TCB).
+///
+/// After a thread begins execution (at program startup or when
+/// created through [`thread_create()`](fn.thread_create.html)), the CPU's registers
+/// controlling Thread-Local Storage (TLS) will already be
+/// initialized. They will point to an area only containing the
+/// TCB.
+///
+/// If the thread needs space for storing thread-specific
+/// variables, the thread may allocate a larger area and adjust
+/// the CPU's registers to point to that area instead. However, it
+/// does need to make sure that the TCB is copied over to the new
+/// TLS area.
+///
+/// The purpose of the TCB is that it allows light-weight
+/// emulators to store information related to individual threads.
+/// For example, it may be used to store a copy of the CPU
+/// registers prior emulation, so that TLS for the host system
+/// can be restored if needed.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct tcb {
+  /// Pointer that may be freely assigned by the system. Its
+  /// value cannot be interpreted by the application.
+  pub parent: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn tcb_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<tcb>(), 4);
+  assert_eq!(::core::mem::align_of::<tcb>(), 4);
+  unsafe {
+    let obj: tcb = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.parent as *const _ as usize - base, 0);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn tcb_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<tcb>(), 8);
+  assert_eq!(::core::mem::align_of::<tcb>(), 8);
+  unsafe {
+    let obj: tcb = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.parent as *const _ as usize - base, 0);
+  }
+}
+
+/// Entry point for additionally created threads.
+///
+/// **tid**:
+/// Thread ID of the current thread.
+///
+/// **aux**:
+/// Copy of the value stored in
+/// [`threadattr.argument`](struct.threadattr.html#structfield.argument).
+pub type threadentry = unsafe extern "C" fn(
+  tid: tid,
+  aux: *mut (),
+) -> ();
+
+/// Attributes for thread creation.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct threadattr {
+  /// Initial program counter value.
+  pub entry_point: threadentry,
+  /// Region allocated to serve as stack space.
+  pub stack: (*mut (), usize),
+  /// Argument to be forwarded to the entry point function.
+  pub argument: *mut (),
+}
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn threadattr_layout_test_32() {
+  assert_eq!(::core::mem::size_of::<threadattr>(), 16);
+  assert_eq!(::core::mem::align_of::<threadattr>(), 4);
+  unsafe {
+    let obj: threadattr = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
+    assert_eq!(&obj.stack.0 as *const _ as usize - base, 4);
+    assert_eq!(&obj.stack.1 as *const _ as usize - base, 8);
+    assert_eq!(&obj.argument as *const _ as usize - base, 12);
+  }
+}
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn threadattr_layout_test_64() {
+  assert_eq!(::core::mem::size_of::<threadattr>(), 32);
+  assert_eq!(::core::mem::align_of::<threadattr>(), 8);
+  unsafe {
+    let obj: threadattr = ::core::mem::uninitialized();
+    let base = &obj as *const _ as usize;
+    assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
+    assert_eq!(&obj.stack.0 as *const _ as usize - base, 8);
+    assert_eq!(&obj.stack.1 as *const _ as usize - base, 16);
+    assert_eq!(&obj.argument as *const _ as usize - base, 24);
+  }
+}
+
+/// The table with pointers to all syscall implementations.
+#[allow(improper_ctypes)]
+extern "C" {
+  fn cloudabi_sys_clock_res_get(_: clockid, _: *mut timestamp) -> errno;
+  fn cloudabi_sys_clock_time_get(_: clockid, _: timestamp, _: *mut timestamp) -> errno;
+  fn cloudabi_sys_condvar_signal(_: *mut condvar, _: scope, _: nthreads) -> errno;
+  fn cloudabi_sys_fd_close(_: fd) -> errno;
+  fn cloudabi_sys_fd_create1(_: filetype, _: *mut fd) -> errno;
+  fn cloudabi_sys_fd_create2(_: filetype, _: *mut fd, _: *mut fd) -> errno;
+  fn cloudabi_sys_fd_datasync(_: fd) -> errno;
+  fn cloudabi_sys_fd_dup(_: fd, _: *mut fd) -> errno;
+  fn cloudabi_sys_fd_pread(_: fd, _: *const iovec, _: usize, _: filesize, _: *mut usize) -> errno;
+  fn cloudabi_sys_fd_pwrite(_: fd, _: *const ciovec, _: usize, _: filesize, _: *mut usize) -> errno;
+  fn cloudabi_sys_fd_read(_: fd, _: *const iovec, _: usize, _: *mut usize) -> errno;
+  fn cloudabi_sys_fd_replace(_: fd, _: fd) -> errno;
+  fn cloudabi_sys_fd_seek(_: fd, _: filedelta, _: whence, _: *mut filesize) -> errno;
+  fn cloudabi_sys_fd_stat_get(_: fd, _: *mut fdstat) -> errno;
+  fn cloudabi_sys_fd_stat_put(_: fd, _: *const fdstat, _: fdsflags) -> errno;
+  fn cloudabi_sys_fd_sync(_: fd) -> errno;
+  fn cloudabi_sys_fd_write(_: fd, _: *const ciovec, _: usize, _: *mut usize) -> errno;
+  fn cloudabi_sys_file_advise(_: fd, _: filesize, _: filesize, _: advice) -> errno;
+  fn cloudabi_sys_file_allocate(_: fd, _: filesize, _: filesize) -> errno;
+  fn cloudabi_sys_file_create(_: fd, _: *const u8, _: usize, _: filetype) -> errno;
+  fn cloudabi_sys_file_link(_: lookup, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+  fn cloudabi_sys_file_open(_: lookup, _: *const u8, _: usize, _: oflags, _: *const fdstat, _: *mut fd) -> errno;
+  fn cloudabi_sys_file_readdir(_: fd, _: *mut (), _: usize, _: dircookie, _: *mut usize) -> errno;
+  fn cloudabi_sys_file_readlink(_: fd, _: *const u8, _: usize, _: *mut u8, _: usize, _: *mut usize) -> errno;
+  fn cloudabi_sys_file_rename(_: fd, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+  fn cloudabi_sys_file_stat_fget(_: fd, _: *mut filestat) -> errno;
+  fn cloudabi_sys_file_stat_fput(_: fd, _: *const filestat, _: fsflags) -> errno;
+  fn cloudabi_sys_file_stat_get(_: lookup, _: *const u8, _: usize, _: *mut filestat) -> errno;
+  fn cloudabi_sys_file_stat_put(_: lookup, _: *const u8, _: usize, _: *const filestat, _: fsflags) -> errno;
+  fn cloudabi_sys_file_symlink(_: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
+  fn cloudabi_sys_file_unlink(_: fd, _: *const u8, _: usize, _: ulflags) -> errno;
+  fn cloudabi_sys_lock_unlock(_: *mut lock, _: scope) -> errno;
+  fn cloudabi_sys_mem_advise(_: *mut (), _: usize, _: advice) -> errno;
+  fn cloudabi_sys_mem_map(_: *mut (), _: usize, _: mprot, _: mflags, _: fd, _: filesize, _: *mut *mut ()) -> errno;
+  fn cloudabi_sys_mem_protect(_: *mut (), _: usize, _: mprot) -> errno;
+  fn cloudabi_sys_mem_sync(_: *mut (), _: usize, _: msflags) -> errno;
+  fn cloudabi_sys_mem_unmap(_: *mut (), _: usize) -> errno;
+  fn cloudabi_sys_poll(_: *const subscription, _: *mut event, _: usize, _: *mut usize) -> errno;
+  fn cloudabi_sys_proc_exec(_: fd, _: *const (), _: usize, _: *const fd, _: usize) -> errno;
+  fn cloudabi_sys_proc_exit(_: exitcode) -> !;
+  fn cloudabi_sys_proc_fork(_: *mut fd, _: *mut tid) -> errno;
+  fn cloudabi_sys_proc_raise(_: signal) -> errno;
+  fn cloudabi_sys_random_get(_: *mut (), _: usize) -> errno;
+  fn cloudabi_sys_sock_recv(_: fd, _: *const recv_in, _: *mut recv_out) -> errno;
+  fn cloudabi_sys_sock_send(_: fd, _: *const send_in, _: *mut send_out) -> errno;
+  fn cloudabi_sys_sock_shutdown(_: fd, _: sdflags) -> errno;
+  fn cloudabi_sys_thread_create(_: *mut threadattr, _: *mut tid) -> errno;
+  fn cloudabi_sys_thread_exit(_: *mut lock, _: scope) -> !;
+  fn cloudabi_sys_thread_yield() -> errno;
+}
+
+/// Obtains the resolution of a clock.
+///
+/// ## Parameters
+///
+/// **clock_id**:
+/// The clock for which the resolution needs to be
+/// returned.
+///
+/// **resolution**:
+/// The resolution of the clock.
+#[inline]
+pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) -> errno {
+  cloudabi_sys_clock_res_get(clock_id_, resolution_)
+}
+
+/// Obtains the time value of a clock.
+///
+/// ## Parameters
+///
+/// **clock_id**:
+/// The clock for which the time needs to be
+/// returned.
+///
+/// **precision**:
+/// The maximum lag (exclusive) that the returned
+/// time value may have, compared to its actual
+/// value.
+///
+/// **time**:
+/// The time value of the clock.
+#[inline]
+pub unsafe fn clock_time_get(clock_id_: clockid, precision_: timestamp, time_: &mut timestamp) -> errno {
+  cloudabi_sys_clock_time_get(clock_id_, precision_, time_)
+}
+
+/// Wakes up threads waiting on a userspace condition variable.
+///
+/// If an invocation of this system call causes all waiting
+/// threads to be woken up, the value of the condition variable
+/// is set to [`CONDVAR_HAS_NO_WAITERS`](constant.CONDVAR_HAS_NO_WAITERS.html). As long as the condition
+/// variable is set to this value, it is not needed to invoke this
+/// system call.
+///
+/// ## Parameters
+///
+/// **condvar**:
+/// The userspace condition variable that has
+/// waiting threads.
+///
+/// **scope**:
+/// Whether the condition variable is stored in
+/// private or shared memory.
+///
+/// **nwaiters**:
+/// The number of threads that need to be woken
+/// up. If it exceeds the number of waiting
+/// threads, all threads are woken up.
+#[inline]
+pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: nthreads) -> errno {
+  cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_)
+}
+
+/// Closes a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor that needs to be closed.
+#[inline]
+pub unsafe fn fd_close(fd_: fd) -> errno {
+  cloudabi_sys_fd_close(fd_)
+}
+
+/// Creates a file descriptor.
+///
+/// ## Parameters
+///
+/// **type**:
+/// Possible values:
+///
+///   - [`SHARED_MEMORY`](enum.filetype.html#variant.SHARED_MEMORY):
+///     Creates an anonymous shared memory
+///     object.
+///
+/// **fd**:
+/// The file descriptor that has been created.
+#[inline]
+pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno {
+  cloudabi_sys_fd_create1(type_, fd_)
+}
+
+/// Creates a pair of file descriptors.
+///
+/// ## Parameters
+///
+/// **type**:
+/// Possible values:
+///
+///   - [`SOCKET_DGRAM`](enum.filetype.html#variant.SOCKET_DGRAM):
+///     Creates a UNIX datagram socket pair.
+///   - [`SOCKET_STREAM`](enum.filetype.html#variant.SOCKET_STREAM):
+///     Creates a UNIX byte-stream socket
+///     pair.
+///
+/// **fd1**:
+/// The first file descriptor of the pair.
+///
+/// **fd2**:
+/// The second file descriptor of the pair.
+#[inline]
+pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno {
+  cloudabi_sys_fd_create2(type_, fd1_, fd2_)
+}
+
+/// Synchronizes the data of a file to disk.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor of the file whose data
+/// needs to be synchronized to disk.
+#[inline]
+pub unsafe fn fd_datasync(fd_: fd) -> errno {
+  cloudabi_sys_fd_datasync(fd_)
+}
+
+/// Duplicates a file descriptor.
+///
+/// ## Parameters
+///
+/// **from**:
+/// The file descriptor that needs to be
+/// duplicated.
+///
+/// **fd**:
+/// The new file descriptor.
+#[inline]
+pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno {
+  cloudabi_sys_fd_dup(from_, fd_)
+}
+
+/// Reads from a file descriptor, without using and updating the
+/// file descriptor's offset.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor from which data should be
+/// read.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be stored.
+///
+/// **offset**:
+/// The offset within the file at which reading
+/// should start.
+///
+/// **nread**:
+/// The number of bytes read.
+#[inline]
+pub unsafe fn fd_pread(fd_: fd, iovs_: &[iovec], offset_: filesize, nread_: &mut usize) -> errno {
+  cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_)
+}
+
+/// Writes to a file descriptor, without using and updating the
+/// file descriptor's offset.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor to which data should be
+/// written.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be retrieved.
+///
+/// **offset**:
+/// The offset within the file at which writing
+/// should start.
+///
+/// **nwritten**:
+/// The number of bytes written.
+#[inline]
+pub unsafe fn fd_pwrite(fd_: fd, iovs_: &[ciovec], offset_: filesize, nwritten_: &mut usize) -> errno {
+  cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_)
+}
+
+/// Reads from a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor from which data should be
+/// read.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be stored.
+///
+/// **nread**:
+/// The number of bytes read.
+#[inline]
+pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno {
+  cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_)
+}
+
+/// Atomically replaces a file descriptor by a copy of another
+/// file descriptor.
+///
+/// Due to the strong focus on thread safety, this environment
+/// does not provide a mechanism to duplicate a file descriptor to
+/// an arbitrary number, like dup2(). This would be prone to race
+/// conditions, as an actual file descriptor with the same number
+/// could be allocated by a different thread at the same time.
+///
+/// This system call provides a way to atomically replace file
+/// descriptors, which would disappear if dup2() were to be
+/// removed entirely.
+///
+/// ## Parameters
+///
+/// **from**:
+/// The file descriptor that needs to be copied.
+///
+/// **to**:
+/// The file descriptor that needs to be
+/// overwritten.
+#[inline]
+pub unsafe fn fd_replace(from_: fd, to_: fd) -> errno {
+  cloudabi_sys_fd_replace(from_, to_)
+}
+
+/// Moves the offset of the file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose offset has to be
+/// moved.
+///
+/// **offset**:
+/// The number of bytes to move.
+///
+/// **whence**:
+/// Relative to which position the move should
+/// take place.
+///
+/// **newoffset**:
+/// The new offset of the file descriptor,
+/// relative to the start of the file.
+#[inline]
+pub unsafe fn fd_seek(fd_: fd, offset_: filedelta, whence_: whence, newoffset_: &mut filesize) -> errno {
+  cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_)
+}
+
+/// Gets attributes of a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file descriptor's
+/// attributes are stored.
+#[inline]
+pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno {
+  cloudabi_sys_fd_stat_get(fd_, buf_)
+}
+
+/// Adjusts attributes of a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file descriptor
+/// attributes that are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> errno {
+  cloudabi_sys_fd_stat_put(fd_, buf_, flags_)
+}
+
+/// Synchronizes the data and metadata of a file to disk.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor of the file whose data
+/// and metadata needs to be synchronized to disk.
+#[inline]
+pub unsafe fn fd_sync(fd_: fd) -> errno {
+  cloudabi_sys_fd_sync(fd_)
+}
+
+/// Writes to a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor to which data should be
+/// written.
+///
+/// **iovs**:
+/// List of scatter/gather vectors where data
+/// should be retrieved.
+///
+/// **nwritten**:
+/// The number of bytes written.
+#[inline]
+pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errno {
+  cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_)
+}
+
+/// Provides file advisory information on a file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor for which to provide file
+/// advisory information.
+///
+/// **offset**:
+/// The offset within the file to which the
+/// advisory applies.
+///
+/// **len**:
+/// The length of the region to which the advisory
+/// applies.
+///
+/// **advice**:
+/// The advice.
+#[inline]
+pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: advice) -> errno {
+  cloudabi_sys_file_advise(fd_, offset_, len_, advice_)
+}
+
+/// Forces the allocation of space in a file.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file in which the space should be
+/// allocated.
+///
+/// **offset**:
+/// The offset at which the allocation should
+/// start.
+///
+/// **len**:
+/// The length of the area that is allocated.
+#[inline]
+pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno {
+  cloudabi_sys_file_allocate(fd_, offset_, len_)
+}
+
+/// Creates a file of a specified type.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the file to be created starts.
+///
+/// **path**:
+/// The path at which the file should be created.
+///
+/// **type**:
+/// Possible values:
+///
+///   - [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY):
+///     Creates a directory.
+#[inline]
+pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno {
+  cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_)
+}
+
+/// Creates a hard link.
+///
+/// ## Parameters
+///
+/// **fd1**:
+/// The working directory at which the resolution
+/// of the source path starts.
+///
+/// **path1**:
+/// The source path of the file that should be
+/// hard linked.
+///
+/// **fd2**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path at which the hard link
+/// should be created.
+#[inline]
+pub unsafe fn file_link(fd1_: lookup, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
+  cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len())
+}
+
+/// Opens a file.
+///
+/// ## Parameters
+///
+/// **dirfd**:
+/// The working directory at which the resolution
+/// of the file to be opened starts.
+///
+/// **path**:
+/// The path of the file that should be opened.
+///
+/// **oflags**:
+/// The method at which the file should be opened.
+///
+/// **fds**:
+/// [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
+/// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting) specify the
+/// initial rights of the newly created file
+/// descriptor. The operating system is allowed to
+/// return a file descriptor with fewer rights
+/// than specified, if and only if those rights do
+/// not apply to the type of file being opened.
+///
+/// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags) specifies the initial flags
+/// of the file descriptor.
+///
+/// [`fdstat.fs_filetype`](struct.fdstat.html#structfield.fs_filetype) is ignored.
+///
+/// **fd**:
+/// The file descriptor of the file that has been
+/// opened.
+#[inline]
+pub unsafe fn file_open(dirfd_: lookup, path_: &[u8], oflags_: oflags, fds_: *const fdstat, fd_: &mut fd) -> errno {
+  cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_)
+}
+
+/// Reads directory entries from a directory.
+///
+/// When successful, the contents of the output buffer consist of
+/// a sequence of directory entries. Each directory entry consists
+/// of a [`dirent`](struct.dirent.html) object, followed by [`dirent.d_namlen`](struct.dirent.html#structfield.d_namlen) bytes
+/// holding the name of the directory entry.
+///
+/// This system call fills the output buffer as much as possible,
+/// potentially truncating the last directory entry. This allows
+/// the caller to grow its read buffer size in case it's too small
+/// to fit a single large directory entry, or skip the oversized
+/// directory entry.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The directory from which to read the directory
+/// entries.
+///
+/// **buf**:
+/// The buffer where directory entries are stored.
+///
+/// **cookie**:
+/// The location within the directory to start
+/// reading.
+///
+/// **bufused**:
+/// The number of bytes stored in the read buffer.
+/// If less than the size of the read buffer, the
+/// end of the directory has been reached.
+#[inline]
+pub unsafe fn file_readdir(fd_: fd, buf_: &mut [u8], cookie_: dircookie, bufused_: &mut usize) -> errno {
+  cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_)
+}
+
+/// Reads the contents of a symbolic link.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path of the symbolic starts.
+///
+/// **path**:
+/// The path of the symbolic link whose contents
+/// should be read.
+///
+/// **buf**:
+/// The buffer where the contents of the symbolic
+/// link should be stored.
+///
+/// **bufused**:
+/// The number of bytes placed in the buffer.
+#[inline]
+pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &mut usize) -> errno {
+  cloudabi_sys_file_readlink(fd_, path_.as_ptr(), path_.len(), buf_.as_mut_ptr(), buf_.len(), bufused_)
+}
+
+/// Renames a file.
+///
+/// ## Parameters
+///
+/// **fd1**:
+/// The working directory at which the resolution
+/// of the source path starts.
+///
+/// **path1**:
+/// The source path of the file that should be
+/// renamed.
+///
+/// **fd2**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path to which the file should
+/// be renamed.
+#[inline]
+pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
+  cloudabi_sys_file_rename(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len())
+}
+
+/// Gets attributes of a file by file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file's attributes are
+/// stored.
+#[inline]
+pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno {
+  cloudabi_sys_file_stat_fget(fd_, buf_)
+}
+
+/// Adjusts attributes of a file by file descriptor.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The file descriptor whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file attributes that
+/// are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) -> errno {
+  cloudabi_sys_file_stat_fput(fd_, buf_, flags_)
+}
+
+/// Gets attributes of a file by path.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path whose attributes have to be
+/// obtained starts.
+///
+/// **path**:
+/// The path of the file whose attributes have to
+/// be obtained.
+///
+/// **buf**:
+/// The buffer where the file's attributes are
+/// stored.
+#[inline]
+pub unsafe fn file_stat_get(fd_: lookup, path_: &[u8], buf_: *mut filestat) -> errno {
+  cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_)
+}
+
+/// Adjusts attributes of a file by path.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path whose attributes have to be
+/// adjusted starts.
+///
+/// **path**:
+/// The path of the file whose attributes have to
+/// be adjusted.
+///
+/// **buf**:
+/// The desired values of the file attributes that
+/// are adjusted.
+///
+/// **flags**:
+/// A bitmask indicating which attributes have to
+/// be adjusted.
+#[inline]
+pub unsafe fn file_stat_put(fd_: lookup, path_: &[u8], buf_: *const filestat, flags_: fsflags) -> errno {
+  cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_)
+}
+
+/// Creates a symbolic link.
+///
+/// ## Parameters
+///
+/// **path1**:
+/// The contents of the symbolic link.
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the destination path starts.
+///
+/// **path2**:
+/// The destination path at which the symbolic
+/// link should be created.
+#[inline]
+pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno {
+  cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len())
+}
+
+/// Unlinks a file, or removes a directory.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// The working directory at which the resolution
+/// of the path starts.
+///
+/// **path**:
+/// The path that needs to be unlinked or removed.
+///
+/// **flags**:
+/// Possible values:
+///
+///   - [`REMOVEDIR`](struct.ulflags.html#associatedconstant.REMOVEDIR):
+///     If set, attempt to remove a directory.
+///     Otherwise, unlink a file.
+#[inline]
+pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno {
+  cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_)
+}
+
+/// Unlocks a write-locked userspace lock.
+///
+/// If a userspace lock is unlocked while having its
+/// [`LOCK_KERNEL_MANAGED`](constant.LOCK_KERNEL_MANAGED.html) flag set, the lock cannot be unlocked in
+/// userspace directly. This system call needs to be performed
+/// instead, so that any waiting threads can be woken up.
+///
+/// To prevent spurious invocations of this system call, the lock
+/// must be locked for writing. This prevents other threads from
+/// acquiring additional read locks while the system call is in
+/// progress. If the lock is acquired for reading, it must first
+/// be upgraded to a write lock.
+///
+/// ## Parameters
+///
+/// **lock**:
+/// The userspace lock that is locked for writing
+/// by the calling thread.
+///
+/// **scope**:
+/// Whether the lock is stored in private or
+/// shared memory.
+#[inline]
+pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno {
+  cloudabi_sys_lock_unlock(lock_, scope_)
+}
+
+/// Provides memory advisory information on a region of memory.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages for which to provide memory advisory
+/// information.
+///
+/// **advice**:
+/// The advice.
+#[inline]
+pub unsafe fn mem_advise(mapping_: &mut [u8], advice_: advice) -> errno {
+  cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_)
+}
+
+/// Creates a memory mapping, making the contents of a file
+/// accessible through memory.
+///
+/// ## Parameters
+///
+/// **addr**:
+/// If [`FIXED`](struct.mflags.html#associatedconstant.FIXED) is set, specifies to which
+/// address the file region is mapped. Otherwise,
+/// the mapping is performed at an unused
+/// location.
+///
+/// **len**:
+/// The length of the memory mapping to be
+/// created.
+///
+/// **prot**:
+/// Initial memory protection options for the
+/// memory mapping.
+///
+/// **flags**:
+/// Memory mapping flags.
+///
+/// **fd**:
+/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
+/// [`MAP_ANON_FD`](constant.MAP_ANON_FD.html). Otherwise, this argument
+/// specifies the file whose contents need to be
+/// mapped.
+///
+/// **off**:
+/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
+/// zero. Otherwise, this argument specifies the
+/// offset within the file at which the mapping
+/// starts.
+///
+/// **mem**:
+/// The starting address of the memory mapping.
+#[inline]
+pub unsafe fn mem_map(addr_: *mut (), len_: usize, prot_: mprot, flags_: mflags, fd_: fd, off_: filesize, mem_: &mut *mut ()) -> errno {
+  cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_)
+}
+
+/// Change the protection of a memory mapping.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that need their protection changed.
+///
+/// **prot**:
+/// New protection options.
+#[inline]
+pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno {
+  cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_)
+}
+
+/// Synchronize a region of memory with its physical storage.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that need to be synchronized.
+///
+/// **flags**:
+/// The method of synchronization.
+#[inline]
+pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno {
+  cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_)
+}
+
+/// Unmaps a region of memory.
+///
+/// ## Parameters
+///
+/// **mapping**:
+/// The pages that needs to be unmapped.
+#[inline]
+pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno {
+  cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len())
+}
+
+/// Concurrently polls for the occurrence of a set of events.
+///
+/// ## Parameters
+///
+/// **in**:
+/// The events to which to subscribe.
+///
+/// **out**:
+/// The events that have occurred.
+///
+/// **nsubscriptions**:
+/// Both the number of subscriptions and events.
+///
+/// **nevents**:
+/// The number of events stored.
+#[inline]
+pub unsafe fn poll(in_: *const subscription, out_: *mut event, nsubscriptions_: usize, nevents_: &mut usize) -> errno {
+  cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_)
+}
+
+/// Replaces the process by a new executable.
+///
+/// Process execution in CloudABI differs from POSIX in two ways:
+/// handling of arguments and inheritance of file descriptors.
+///
+/// CloudABI does not use string command line arguments. Instead,
+/// a buffer with binary data is copied into the address space of
+/// the new executable. The kernel does not enforce any specific
+/// structure to this data, although CloudABI's C library uses it
+/// to store a tree structure that is semantically identical to
+/// YAML.
+///
+/// Due to the strong focus on thread safety, file descriptors
+/// aren't inherited through close-on-exec flags. An explicit
+/// list of file descriptors that need to be retained needs to be
+/// provided. After execution, file descriptors are placed in the
+/// order in which they are stored in the array. This not only
+/// makes the execution process deterministic. It also prevents
+/// potential information disclosures about the layout of the
+/// original process.
+///
+/// ## Parameters
+///
+/// **fd**:
+/// A file descriptor of the new executable.
+///
+/// **data**:
+/// Binary argument data that is passed on to the
+/// new executable.
+///
+/// **fds**:
+/// The layout of the file descriptor table after
+/// execution.
+#[inline]
+pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno {
+  cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len())
+}
+
+/// Terminates the process normally.
+///
+/// ## Parameters
+///
+/// **rval**:
+/// The exit code returned by the process. The
+/// exit code can be obtained by other processes
+/// through [`event.union.proc_terminate.exitcode`](struct.event_proc_terminate.html#structfield.exitcode).
+#[inline]
+pub unsafe fn proc_exit(rval_: exitcode) -> ! {
+  cloudabi_sys_proc_exit(rval_)
+}
+
+/// Forks the process of the calling thread.
+///
+/// After forking, a new process shall be created, having only a
+/// copy of the calling thread. The parent process will obtain a
+/// process descriptor. When closed, the child process is
+/// automatically signaled with [`KILL`](enum.signal.html#variant.KILL).
+///
+/// ## Parameters
+///
+/// **fd**:
+/// In the parent process: the file descriptor
+/// number of the process descriptor.
+///
+/// In the child process: [`PROCESS_CHILD`](constant.PROCESS_CHILD.html).
+///
+/// **tid**:
+/// In the parent process: undefined.
+///
+/// In the child process: the thread ID of the
+/// initial thread of the child process.
+#[inline]
+pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno {
+  cloudabi_sys_proc_fork(fd_, tid_)
+}
+
+/// Sends a signal to the process of the calling thread.
+///
+/// ## Parameters
+///
+/// **sig**:
+/// The signal condition that should be triggered.
+/// If the signal causes the process to terminate,
+/// its condition can be obtained by other
+/// processes through
+/// [`event.union.proc_terminate.signal`](struct.event_proc_terminate.html#structfield.signal).
+#[inline]
+pub unsafe fn proc_raise(sig_: signal) -> errno {
+  cloudabi_sys_proc_raise(sig_)
+}
+
+/// Obtains random data from the kernel random number generator.
+///
+/// As this interface is not guaranteed to be fast, it is advised
+/// that the random data obtained through this system call is used
+/// as the seed for a userspace pseudo-random number generator.
+///
+/// ## Parameters
+///
+/// **buf**:
+/// The buffer that needs to be filled with random
+/// data.
+#[inline]
+pub unsafe fn random_get(buf_: &mut [u8]) -> errno {
+  cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len())
+}
+
+/// Receives a message on a socket.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket on which a message should be
+/// received.
+///
+/// **in**:
+/// Input parameters.
+///
+/// **out**:
+/// Output parameters.
+#[inline]
+pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) -> errno {
+  cloudabi_sys_sock_recv(sock_, in_, out_)
+}
+
+/// Sends a message on a socket.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket on which a message should be sent.
+///
+/// **in**:
+/// Input parameters.
+///
+/// **out**:
+/// Output parameters.
+#[inline]
+pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) -> errno {
+  cloudabi_sys_sock_send(sock_, in_, out_)
+}
+
+/// Shuts down socket send and receive channels.
+///
+/// ## Parameters
+///
+/// **sock**:
+/// The socket that needs its channels shut down.
+///
+/// **how**:
+/// Which channels on the socket need to be shut
+/// down.
+#[inline]
+pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno {
+  cloudabi_sys_sock_shutdown(sock_, how_)
+}
+
+/// Creates a new thread within the current process.
+///
+/// ## Parameters
+///
+/// **attr**:
+/// The desired attributes of the new thread.
+///
+/// **tid**:
+/// The thread ID of the new thread.
+#[inline]
+pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno {
+  cloudabi_sys_thread_create(attr_, tid_)
+}
+
+/// Terminates the calling thread.
+///
+/// This system call can also unlock a single userspace lock
+/// after termination, which can be used to implement thread
+/// joining.
+///
+/// ## Parameters
+///
+/// **lock**:
+/// Userspace lock that is locked for writing by
+/// the calling thread.
+///
+/// **scope**:
+/// Whether the lock is stored in private or
+/// shared memory.
+#[inline]
+pub unsafe fn thread_exit(lock_: *mut lock, scope_: scope) -> ! {
+  cloudabi_sys_thread_exit(lock_, scope_)
+}
+
+/// Temporarily yields execution of the calling thread.
+#[inline]
+pub unsafe fn thread_yield() -> errno {
+  cloudabi_sys_thread_yield()
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/libstd/sys/cloudabi/abi/mod.rs
similarity index 75%
copy from src/test/compile-fail/E0580.rs
copy to src/libstd/sys/cloudabi/abi/mod.rs
index a2ef7da..81a4d29 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/libstd/sys/cloudabi/abi/mod.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#[allow(warnings)]
+mod cloudabi;
+pub use self::cloudabi::*;
diff --git a/src/test/compile-fail/E0580.rs b/src/libstd/sys/cloudabi/args.rs
similarity index 65%
copy from src/test/compile-fail/E0580.rs
copy to src/libstd/sys/cloudabi/args.rs
index a2ef7da..7b62cc6 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/libstd/sys/cloudabi/args.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+pub use sys::cloudabi::shims::args::*;
+
+#[allow(dead_code)]
+pub fn init(_: isize, _: *const *const u8) {}
+
+#[allow(dead_code)]
+pub fn cleanup() {}
diff --git a/src/libstd/sys/cloudabi/backtrace.rs b/src/libstd/sys/cloudabi/backtrace.rs
new file mode 100644
index 0000000..33d9317
--- /dev/null
+++ b/src/libstd/sys/cloudabi/backtrace.rs
@@ -0,0 +1,121 @@
+// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use error::Error;
+use ffi::CStr;
+use intrinsics;
+use io;
+use libc;
+use sys_common::backtrace::Frame;
+use unwind as uw;
+
+pub struct BacktraceContext;
+
+struct Context<'a> {
+    idx: usize,
+    frames: &'a mut [Frame],
+}
+
+#[derive(Debug)]
+struct UnwindError(uw::_Unwind_Reason_Code);
+
+impl Error for UnwindError {
+    fn description(&self) -> &'static str {
+        "unexpected return value while unwinding"
+    }
+}
+
+impl ::fmt::Display for UnwindError {
+    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+        write!(f, "{}: {:?}", self.description(), self.0)
+    }
+}
+
+#[inline(never)] // if we know this is a function call, we can skip it when
+                 // tracing
+pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
+    let mut cx = Context { idx: 0, frames };
+    let result_unwind =
+        unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) };
+    // See libunwind:src/unwind/Backtrace.c for the return values.
+    // No, there is no doc.
+    match result_unwind {
+        // These return codes seem to be benign and need to be ignored for backtraces
+        // to show up properly on all tested platforms.
+        uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
+            Ok((cx.idx, BacktraceContext))
+        }
+        _ => Err(io::Error::new(
+            io::ErrorKind::Other,
+            UnwindError(result_unwind),
+        )),
+    }
+}
+
+extern "C" fn trace_fn(
+    ctx: *mut uw::_Unwind_Context,
+    arg: *mut libc::c_void,
+) -> uw::_Unwind_Reason_Code {
+    let cx = unsafe { &mut *(arg as *mut Context) };
+    let mut ip_before_insn = 0;
+    let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
+    if !ip.is_null() && ip_before_insn == 0 {
+        // this is a non-signaling frame, so `ip` refers to the address
+        // after the calling instruction. account for that.
+        ip = (ip as usize - 1) as *mut _;
+    }
+
+    let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
+    if cx.idx < cx.frames.len() {
+        cx.frames[cx.idx] = Frame {
+            symbol_addr: symaddr as *mut u8,
+            exact_position: ip as *mut u8,
+        };
+        cx.idx += 1;
+    }
+
+    uw::_URC_NO_REASON
+}
+
+pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
+where
+    F: FnMut(&[u8], u32) -> io::Result<()>,
+{
+    // No way to obtain this information on CloudABI.
+    Ok(false)
+}
+
+pub fn resolve_symname<F>(frame: Frame, callback: F, _: &BacktraceContext) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
+{
+    unsafe {
+        let mut info: Dl_info = intrinsics::init();
+        let symname =
+            if dladdr(frame.exact_position as *mut _, &mut info) == 0 || info.dli_sname.is_null() {
+                None
+            } else {
+                CStr::from_ptr(info.dli_sname).to_str().ok()
+            };
+        callback(symname)
+    }
+}
+
+#[repr(C)]
+struct Dl_info {
+    dli_fname: *const libc::c_char,
+    dli_fbase: *mut libc::c_void,
+    dli_sname: *const libc::c_char,
+    dli_saddr: *mut libc::c_void,
+}
+
+extern "C" {
+    fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
+}
diff --git a/src/libstd/sys/cloudabi/condvar.rs b/src/libstd/sys/cloudabi/condvar.rs
new file mode 100644
index 0000000..c05c837
--- /dev/null
+++ b/src/libstd/sys/cloudabi/condvar.rs
@@ -0,0 +1,169 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use sys::mutex::{self, Mutex};
+use sys::time::dur2intervals;
+use time::Duration;
+
+extern "C" {
+    #[thread_local]
+    static __pthread_thread_id: abi::tid;
+}
+
+pub struct Condvar {
+    condvar: UnsafeCell<AtomicU32>,
+}
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar {
+            condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
+        }
+    }
+
+    pub unsafe fn init(&mut self) {}
+
+    pub unsafe fn notify_one(&self) {
+        let condvar = self.condvar.get();
+        if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+            let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
+            assert_eq!(
+                ret,
+                abi::errno::SUCCESS,
+                "Failed to signal on condition variable"
+            );
+        }
+    }
+
+    pub unsafe fn notify_all(&self) {
+        let condvar = self.condvar.get();
+        if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+            let ret = abi::condvar_signal(
+                condvar as *mut abi::condvar,
+                abi::scope::PRIVATE,
+                abi::nthreads::max_value(),
+            );
+            assert_eq!(
+                ret,
+                abi::errno::SUCCESS,
+                "Failed to broadcast on condition variable"
+            );
+        }
+    }
+
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        let mutex = mutex::raw(mutex);
+        assert_eq!(
+            (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+            "This lock is not write-locked by this thread"
+        );
+
+        // Call into the kernel to wait on the condition variable.
+        let condvar = self.condvar.get();
+        let subscription = abi::subscription {
+            type_: abi::eventtype::CONDVAR,
+            union: abi::subscription_union {
+                condvar: abi::subscription_condvar {
+                    condvar: condvar as *mut abi::condvar,
+                    condvar_scope: abi::scope::PRIVATE,
+                    lock: mutex as *mut abi::lock,
+                    lock_scope: abi::scope::PRIVATE,
+                },
+            },
+            ..mem::zeroed()
+        };
+        let mut event: abi::event = mem::uninitialized();
+        let mut nevents: usize = mem::uninitialized();
+        let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+        assert_eq!(
+            ret,
+            abi::errno::SUCCESS,
+            "Failed to wait on condition variable"
+        );
+        assert_eq!(
+            event.error,
+            abi::errno::SUCCESS,
+            "Failed to wait on condition variable"
+        );
+    }
+
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        let mutex = mutex::raw(mutex);
+        assert_eq!(
+            (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+            "This lock is not write-locked by this thread"
+        );
+
+        // Call into the kernel to wait on the condition variable.
+        let condvar = self.condvar.get();
+        let subscriptions = [
+            abi::subscription {
+                type_: abi::eventtype::CONDVAR,
+                union: abi::subscription_union {
+                    condvar: abi::subscription_condvar {
+                        condvar: condvar as *mut abi::condvar,
+                        condvar_scope: abi::scope::PRIVATE,
+                        lock: mutex as *mut abi::lock,
+                        lock_scope: abi::scope::PRIVATE,
+                    },
+                },
+                ..mem::zeroed()
+            },
+            abi::subscription {
+                type_: abi::eventtype::CLOCK,
+                union: abi::subscription_union {
+                    clock: abi::subscription_clock {
+                        clock_id: abi::clockid::MONOTONIC,
+                        timeout: dur2intervals(&dur),
+                        ..mem::zeroed()
+                    },
+                },
+                ..mem::zeroed()
+            },
+        ];
+        let mut events: [abi::event; 2] = mem::uninitialized();
+        let mut nevents: usize = mem::uninitialized();
+        let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
+        assert_eq!(
+            ret,
+            abi::errno::SUCCESS,
+            "Failed to wait on condition variable"
+        );
+        for i in 0..nevents {
+            assert_eq!(
+                events[i].error,
+                abi::errno::SUCCESS,
+                "Failed to wait on condition variable"
+            );
+            if events[i].type_ == abi::eventtype::CONDVAR {
+                return true;
+            }
+        }
+        false
+    }
+
+    pub unsafe fn destroy(&self) {
+        let condvar = self.condvar.get();
+        assert_eq!(
+            (*condvar).load(Ordering::Relaxed),
+            abi::CONDVAR_HAS_NO_WAITERS.0,
+            "Attempted to destroy a condition variable with blocked threads"
+        );
+    }
+}
diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs
new file mode 100644
index 0000000..9e943c1
--- /dev/null
+++ b/src/libstd/sys/cloudabi/mod.rs
@@ -0,0 +1,76 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+use libc;
+use mem;
+
+pub mod args;
+#[cfg(feature = "backtrace")]
+pub mod backtrace;
+#[path = "../unix/cmath.rs"]
+pub mod cmath;
+pub mod condvar;
+#[path = "../unix/memchr.rs"]
+pub mod memchr;
+pub mod mutex;
+pub mod os;
+#[path = "../unix/os_str.rs"]
+pub mod os_str;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod stdio;
+pub mod thread;
+#[path = "../unix/thread_local.rs"]
+pub mod thread_local;
+pub mod time;
+
+mod abi;
+
+mod shims;
+pub use self::shims::*;
+
+#[allow(dead_code)]
+pub fn init() {}
+
+pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
+    match errno {
+        x if x == abi::errno::ACCES as i32 => io::ErrorKind::PermissionDenied,
+        x if x == abi::errno::ADDRINUSE as i32 => io::ErrorKind::AddrInUse,
+        x if x == abi::errno::ADDRNOTAVAIL as i32 => io::ErrorKind::AddrNotAvailable,
+        x if x == abi::errno::AGAIN as i32 => io::ErrorKind::WouldBlock,
+        x if x == abi::errno::CONNABORTED as i32 => io::ErrorKind::ConnectionAborted,
+        x if x == abi::errno::CONNREFUSED as i32 => io::ErrorKind::ConnectionRefused,
+        x if x == abi::errno::CONNRESET as i32 => io::ErrorKind::ConnectionReset,
+        x if x == abi::errno::EXIST as i32 => io::ErrorKind::AlreadyExists,
+        x if x == abi::errno::INTR as i32 => io::ErrorKind::Interrupted,
+        x if x == abi::errno::INVAL as i32 => io::ErrorKind::InvalidInput,
+        x if x == abi::errno::NOENT as i32 => io::ErrorKind::NotFound,
+        x if x == abi::errno::NOTCONN as i32 => io::ErrorKind::NotConnected,
+        x if x == abi::errno::PERM as i32 => io::ErrorKind::PermissionDenied,
+        x if x == abi::errno::PIPE as i32 => io::ErrorKind::BrokenPipe,
+        x if x == abi::errno::TIMEDOUT as i32 => io::ErrorKind::TimedOut,
+        _ => io::ErrorKind::Other,
+    }
+}
+
+pub unsafe fn abort_internal() -> ! {
+    ::core::intrinsics::abort();
+}
+
+pub use libc::strlen;
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+    unsafe {
+        let mut v = mem::uninitialized();
+        libc::arc4random_buf(&mut v as *mut _ as *mut libc::c_void, mem::size_of_val(&v));
+        v
+    }
+}
diff --git a/src/libstd/sys/cloudabi/mutex.rs b/src/libstd/sys/cloudabi/mutex.rs
new file mode 100644
index 0000000..d4ba6bc
--- /dev/null
+++ b/src/libstd/sys/cloudabi/mutex.rs
@@ -0,0 +1,158 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use sys::rwlock::{self, RWLock};
+
+extern "C" {
+    #[thread_local]
+    static __pthread_thread_id: abi::tid;
+}
+
+// Implement Mutex using an RWLock. This doesn't introduce any
+// performance overhead in this environment, as the operations would be
+// implemented identically.
+pub struct Mutex(RWLock);
+
+pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
+    rwlock::raw(&m.0)
+}
+
+impl Mutex {
+    pub const fn new() -> Mutex {
+        Mutex(RWLock::new())
+    }
+
+    pub unsafe fn init(&mut self) {
+        // This function should normally reinitialize the mutex after
+        // moving it to a different memory address. This implementation
+        // does not require adjustments after moving.
+    }
+
+    pub unsafe fn try_lock(&self) -> bool {
+        self.0.try_write()
+    }
+
+    pub unsafe fn lock(&self) {
+        self.0.write()
+    }
+
+    pub unsafe fn unlock(&self) {
+        self.0.write_unlock()
+    }
+
+    pub unsafe fn destroy(&self) {
+        self.0.destroy()
+    }
+}
+
+pub struct ReentrantMutex {
+    lock: UnsafeCell<AtomicU32>,
+    recursion: UnsafeCell<u32>,
+}
+
+impl ReentrantMutex {
+    pub unsafe fn uninitialized() -> ReentrantMutex {
+        mem::uninitialized()
+    }
+
+    pub unsafe fn init(&mut self) {
+        self.lock = UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
+        self.recursion = UnsafeCell::new(0);
+    }
+
+    pub unsafe fn try_lock(&self) -> bool {
+        // Attempt to acquire the lock.
+        let lock = self.lock.get();
+        let recursion = self.recursion.get();
+        if let Err(old) = (*lock).compare_exchange(
+            abi::LOCK_UNLOCKED.0,
+            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+            Ordering::Acquire,
+            Ordering::Relaxed,
+        ) {
+            // If we fail to acquire the lock, it may be the case
+            // that we've already acquired it and may need to recurse.
+            if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
+                *recursion += 1;
+                true
+            } else {
+                false
+            }
+        } else {
+            // Success.
+            assert_eq!(*recursion, 0, "Mutex has invalid recursion count");
+            true
+        }
+    }
+
+    pub unsafe fn lock(&self) {
+        if !self.try_lock() {
+            // Call into the kernel to acquire a write lock.
+            let lock = self.lock.get();
+            let subscription = abi::subscription {
+                type_: abi::eventtype::LOCK_WRLOCK,
+                union: abi::subscription_union {
+                    lock: abi::subscription_lock {
+                        lock: lock as *mut abi::lock,
+                        lock_scope: abi::scope::PRIVATE,
+                    },
+                },
+                ..mem::zeroed()
+            };
+            let mut event: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
+            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
+        }
+    }
+
+    pub unsafe fn unlock(&self) {
+        let lock = self.lock.get();
+        let recursion = self.recursion.get();
+        assert_eq!(
+            (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+            "This mutex is locked by a different thread"
+        );
+
+        if *recursion > 0 {
+            *recursion -= 1;
+        } else if !(*lock)
+            .compare_exchange(
+                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+                abi::LOCK_UNLOCKED.0,
+                Ordering::Release,
+                Ordering::Relaxed,
+            )
+            .is_ok()
+        {
+            // Lock is managed by kernelspace. Call into the kernel
+            // to unblock waiting threads.
+            let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
+        }
+    }
+
+    pub unsafe fn destroy(&self) {
+        let lock = self.lock.get();
+        let recursion = self.recursion.get();
+        assert_eq!(
+            (*lock).load(Ordering::Relaxed),
+            abi::LOCK_UNLOCKED.0,
+            "Attempted to destroy locked mutex"
+        );
+        assert_eq!(*recursion, 0, "Recursion counter invalid");
+    }
+}
diff --git a/src/libstd/sys/cloudabi/os.rs b/src/libstd/sys/cloudabi/os.rs
new file mode 100644
index 0000000..7e506b8
--- /dev/null
+++ b/src/libstd/sys/cloudabi/os.rs
@@ -0,0 +1,37 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::CStr;
+use libc::{self, c_int};
+use str;
+
+pub use sys::cloudabi::shims::os::*;
+
+pub fn errno() -> i32 {
+    extern "C" {
+        #[thread_local]
+        static errno: c_int;
+    }
+
+    unsafe { errno as i32 }
+}
+
+/// Gets a detailed string description for the given error number.
+pub fn error_string(errno: i32) -> String {
+    // cloudlibc's strerror() is guaranteed to be thread-safe. There is
+    // thus no need to use strerror_r().
+    str::from_utf8(unsafe { CStr::from_ptr(libc::strerror(errno)) }.to_bytes())
+        .unwrap()
+        .to_owned()
+}
+
+pub fn exit(code: i32) -> ! {
+    unsafe { libc::exit(code as c_int) }
+}
diff --git a/src/libstd/sys/cloudabi/rwlock.rs b/src/libstd/sys/cloudabi/rwlock.rs
new file mode 100644
index 0000000..8539aec
--- /dev/null
+++ b/src/libstd/sys/cloudabi/rwlock.rs
@@ -0,0 +1,237 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+
+extern "C" {
+    #[thread_local]
+    static __pthread_thread_id: abi::tid;
+}
+
+#[thread_local]
+static mut RDLOCKS_ACQUIRED: u32 = 0;
+
+pub struct RWLock {
+    lock: UnsafeCell<AtomicU32>,
+}
+
+pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
+    r.lock.get()
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
+impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock {
+            lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
+        }
+    }
+
+    pub unsafe fn try_read(&self) -> bool {
+        let lock = self.lock.get();
+        let mut old = abi::LOCK_UNLOCKED.0;
+        while let Err(cur) =
+            (*lock).compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
+        {
+            if (cur & abi::LOCK_WRLOCKED.0) != 0 {
+                // Another thread already has a write lock.
+                assert_ne!(
+                    old & !abi::LOCK_KERNEL_MANAGED.0,
+                    __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+                    "Attempted to acquire a read lock while holding a write lock"
+                );
+                return false;
+            } else if (old & abi::LOCK_KERNEL_MANAGED.0) != 0 && RDLOCKS_ACQUIRED == 0 {
+                // Lock has threads waiting for the lock. Only acquire
+                // the lock if we have already acquired read locks. In
+                // that case, it is justified to acquire this lock to
+                // prevent a deadlock.
+                return false;
+            }
+            old = cur;
+        }
+
+        RDLOCKS_ACQUIRED += 1;
+        true
+    }
+
+    pub unsafe fn read(&self) {
+        if !self.try_read() {
+            // Call into the kernel to acquire a read lock.
+            let lock = self.lock.get();
+            let subscription = abi::subscription {
+                type_: abi::eventtype::LOCK_RDLOCK,
+                union: abi::subscription_union {
+                    lock: abi::subscription_lock {
+                        lock: lock as *mut abi::lock,
+                        lock_scope: abi::scope::PRIVATE,
+                    },
+                },
+                ..mem::zeroed()
+            };
+            let mut event: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock");
+            assert_eq!(
+                event.error,
+                abi::errno::SUCCESS,
+                "Failed to acquire read lock"
+            );
+
+            RDLOCKS_ACQUIRED += 1;
+        }
+    }
+
+    pub unsafe fn read_unlock(&self) {
+        // Perform a read unlock. We can do this in userspace, except when
+        // other threads are blocked and we are performing the last unlock.
+        // In that case, call into the kernel.
+        //
+        // Other threads may attempt to increment the read lock count,
+        // meaning that the call into the kernel could be spurious. To
+        // prevent this from happening, upgrade to a write lock first. This
+        // allows us to call into the kernel, having the guarantee that the
+        // lock value will not change in the meantime.
+        assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
+        let mut old = 1;
+        loop {
+            let lock = self.lock.get();
+            if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
+                // Last read lock while threads are waiting. Attempt to upgrade
+                // to a write lock before calling into the kernel to unlock.
+                if let Err(cur) = (*lock).compare_exchange_weak(
+                    old,
+                    __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
+                    Ordering::Acquire,
+                    Ordering::Relaxed,
+                ) {
+                    old = cur;
+                } else {
+                    // Call into the kernel to unlock.
+                    let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+                    assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
+                    break;
+                }
+            } else {
+                // No threads waiting or not the last read lock. Just decrement
+                // the read lock count.
+                assert_ne!(
+                    old & !abi::LOCK_KERNEL_MANAGED.0,
+                    0,
+                    "This rwlock is not locked"
+                );
+                assert_eq!(
+                    old & abi::LOCK_WRLOCKED.0,
+                    0,
+                    "Attempted to read-unlock a write-locked rwlock"
+                );
+                if let Err(cur) = (*lock).compare_exchange_weak(
+                    old,
+                    old - 1,
+                    Ordering::Acquire,
+                    Ordering::Relaxed,
+                ) {
+                    old = cur;
+                } else {
+                    break;
+                }
+            }
+        }
+
+        RDLOCKS_ACQUIRED -= 1;
+    }
+
+    pub unsafe fn try_write(&self) -> bool {
+        // Attempt to acquire the lock.
+        let lock = self.lock.get();
+        if let Err(old) = (*lock).compare_exchange(
+            abi::LOCK_UNLOCKED.0,
+            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+            Ordering::Acquire,
+            Ordering::Relaxed,
+        ) {
+            // Failure. Crash upon recursive acquisition.
+            assert_ne!(
+                old & !abi::LOCK_KERNEL_MANAGED.0,
+                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+                "Attempted to recursive write-lock a rwlock",
+            );
+            false
+        } else {
+            // Success.
+            true
+        }
+    }
+
+    pub unsafe fn write(&self) {
+        if !self.try_write() {
+            // Call into the kernel to acquire a write lock.
+            let lock = self.lock.get();
+            let subscription = abi::subscription {
+                type_: abi::eventtype::LOCK_WRLOCK,
+                union: abi::subscription_union {
+                    lock: abi::subscription_lock {
+                        lock: lock as *mut abi::lock,
+                        lock_scope: abi::scope::PRIVATE,
+                    },
+                },
+                ..mem::zeroed()
+            };
+            let mut event: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock");
+            assert_eq!(
+                event.error,
+                abi::errno::SUCCESS,
+                "Failed to acquire write lock"
+            );
+        }
+    }
+
+    pub unsafe fn write_unlock(&self) {
+        let lock = self.lock.get();
+        assert_eq!(
+            (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+            "This rwlock is not write-locked by this thread"
+        );
+
+        if !(*lock)
+            .compare_exchange(
+                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
+                abi::LOCK_UNLOCKED.0,
+                Ordering::Release,
+                Ordering::Relaxed,
+            )
+            .is_ok()
+        {
+            // Lock is managed by kernelspace. Call into the kernel
+            // to unblock waiting threads.
+            let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
+        }
+    }
+
+    pub unsafe fn destroy(&self) {
+        let lock = self.lock.get();
+        assert_eq!(
+            (*lock).load(Ordering::Relaxed),
+            abi::LOCK_UNLOCKED.0,
+            "Attempted to destroy locked rwlock"
+        );
+    }
+}
diff --git a/src/libstd/sys/cloudabi/shims/args.rs b/src/libstd/sys/cloudabi/shims/args.rs
new file mode 100644
index 0000000..1b5785a
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/args.rs
@@ -0,0 +1,45 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::OsString;
+
+pub struct Args(());
+
+impl Args {
+    pub fn inner_debug(&self) -> &[OsString] {
+        &[]
+    }
+}
+
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> {
+        None
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(0))
+    }
+}
+
+impl ExactSizeIterator for Args {
+    fn len(&self) -> usize {
+        0
+    }
+}
+
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> {
+        None
+    }
+}
+
+pub fn args() -> Args {
+    Args(())
+}
diff --git a/src/libstd/sys/cloudabi/shims/env.rs b/src/libstd/sys/cloudabi/shims/env.rs
new file mode 100644
index 0000000..31777aa
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/env.rs
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod os {
+    pub const FAMILY: &'static str = "cloudabi";
+    pub const OS: &'static str = "cloudabi";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
diff --git a/src/libstd/sys/cloudabi/shims/fs.rs b/src/libstd/sys/cloudabi/shims/fs.rs
new file mode 100644
index 0000000..d3da0fb
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/fs.rs
@@ -0,0 +1,302 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::OsString;
+use fmt;
+use hash::{Hash, Hasher};
+use io::{self, SeekFrom};
+use path::{Path, PathBuf};
+use sys::time::SystemTime;
+use sys::{unsupported, Void};
+
+pub struct File(Void);
+
+pub struct FileAttr(Void);
+
+pub struct ReadDir(Void);
+
+pub struct DirEntry(Void);
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions {}
+
+pub struct FilePermissions(Void);
+
+pub struct FileType(Void);
+
+#[derive(Debug)]
+pub struct DirBuilder {}
+
+impl FileAttr {
+    pub fn size(&self) -> u64 {
+        match self.0 {}
+    }
+
+    pub fn perm(&self) -> FilePermissions {
+        match self.0 {}
+    }
+
+    pub fn file_type(&self) -> FileType {
+        match self.0 {}
+    }
+
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        match self.0 {}
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        match self.0 {}
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        match self.0 {}
+    }
+}
+
+impl Clone for FileAttr {
+    fn clone(&self) -> FileAttr {
+        match self.0 {}
+    }
+}
+
+impl FilePermissions {
+    pub fn readonly(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn set_readonly(&mut self, _readonly: bool) {
+        match self.0 {}
+    }
+}
+
+impl Clone for FilePermissions {
+    fn clone(&self) -> FilePermissions {
+        match self.0 {}
+    }
+}
+
+impl PartialEq for FilePermissions {
+    fn eq(&self, _other: &FilePermissions) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Eq for FilePermissions {}
+
+impl fmt::Debug for FilePermissions {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl FileType {
+    pub fn is_dir(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn is_file(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn is_symlink(&self) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Clone for FileType {
+    fn clone(&self) -> FileType {
+        match self.0 {}
+    }
+}
+
+impl Copy for FileType {}
+
+impl PartialEq for FileType {
+    fn eq(&self, _other: &FileType) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Eq for FileType {}
+
+impl Hash for FileType {
+    fn hash<H: Hasher>(&self, _h: &mut H) {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for FileType {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        match self.0 {}
+    }
+}
+
+impl DirEntry {
+    pub fn path(&self) -> PathBuf {
+        match self.0 {}
+    }
+
+    pub fn file_name(&self) -> OsString {
+        match self.0 {}
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        match self.0 {}
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        match self.0 {}
+    }
+}
+
+impl OpenOptions {
+    pub fn new() -> OpenOptions {
+        OpenOptions {}
+    }
+
+    pub fn read(&mut self, _read: bool) {}
+    pub fn write(&mut self, _write: bool) {}
+    pub fn append(&mut self, _append: bool) {}
+    pub fn truncate(&mut self, _truncate: bool) {}
+    pub fn create(&mut self, _create: bool) {}
+    pub fn create_new(&mut self, _create_new: bool) {}
+}
+
+impl File {
+    pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
+        unsupported()
+    }
+
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        match self.0 {}
+    }
+
+    pub fn fsync(&self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn truncate(&self, _size: u64) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<File> {
+        match self.0 {}
+    }
+
+    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn diverge(&self) -> ! {
+        match self.0 {}
+    }
+}
+
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder {}
+    }
+
+    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
+        unsupported()
+    }
+}
+
+impl fmt::Debug for File {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
+    unsupported()
+}
+
+pub fn unlink(_p: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
+    match perm.0 {}
+}
+
+pub fn rmdir(_p: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn stat(_p: &Path) -> io::Result<FileAttr> {
+    unsupported()
+}
+
+pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
+    unsupported()
+}
+
+pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
+    unsupported()
+}
diff --git a/src/libstd/sys/cloudabi/shims/mod.rs b/src/libstd/sys/cloudabi/shims/mod.rs
new file mode 100644
index 0000000..407c2b9
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/mod.rs
@@ -0,0 +1,32 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+
+pub mod args;
+pub mod env;
+pub mod fs;
+pub mod net;
+#[path = "../../unix/path.rs"]
+pub mod path;
+pub mod pipe;
+pub mod process;
+pub mod os;
+
+// This enum is used as the storage for a bunch of types which can't actually exist.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub enum Void {}
+
+pub fn unsupported<T>() -> io::Result<T> {
+    Err(io::Error::new(
+        io::ErrorKind::Other,
+        "This function is not available on CloudABI.",
+    ))
+}
diff --git a/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs
new file mode 100644
index 0000000..93eaf6a
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/net.rs
@@ -0,0 +1,296 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use fmt;
+use io;
+use net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use time::Duration;
+use sys::{unsupported, Void};
+
+pub extern crate libc as netc;
+
+pub struct TcpStream(Void);
+
+impl TcpStream {
+    pub fn connect(_: &SocketAddr) -> io::Result<TcpStream> {
+        unsupported()
+    }
+
+    pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+        unsupported()
+    }
+
+    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpStream> {
+        match self.0 {}
+    }
+
+    pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn nodelay(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        match self.0 {}
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for TcpStream {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct TcpListener(Void);
+
+impl TcpListener {
+    pub fn bind(_: &SocketAddr) -> io::Result<TcpListener> {
+        unsupported()
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpListener> {
+        match self.0 {}
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn only_v6(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        match self.0 {}
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for TcpListener {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct UdpSocket(Void);
+
+impl UdpSocket {
+    pub fn bind(_: &SocketAddr) -> io::Result<UdpSocket> {
+        unsupported()
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        match self.0 {}
+    }
+
+    pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        match self.0 {}
+    }
+
+    pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<UdpSocket> {
+        match self.0 {}
+    }
+
+    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn broadcast(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        match self.0 {}
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn send(&self, _: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn connect(&self, _: &SocketAddr) -> io::Result<()> {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for UdpSocket {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct LookupHost(Void);
+
+impl Iterator for LookupHost {
+    type Item = SocketAddr;
+    fn next(&mut self) -> Option<SocketAddr> {
+        match self.0 {}
+    }
+}
+
+pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
+    unsupported()
+}
diff --git a/src/libstd/sys/cloudabi/shims/os.rs b/src/libstd/sys/cloudabi/shims/os.rs
new file mode 100644
index 0000000..1e355d9
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/os.rs
@@ -0,0 +1,95 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use error::Error as StdError;
+use ffi::{OsStr, OsString};
+use fmt;
+use io;
+use iter;
+use path::{self, PathBuf};
+use sys::{unsupported, Void};
+
+pub fn getcwd() -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn chdir(_: &path::Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub type Env = iter::Empty<(OsString, OsString)>;
+
+pub fn env() -> Env {
+    iter::empty()
+}
+
+pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
+    Ok(None)
+}
+
+pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn unsetenv(_: &OsStr) -> io::Result<()> {
+    unsupported()
+}
+
+pub struct SplitPaths<'a>(&'a Void);
+
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
+    panic!("unsupported")
+}
+
+impl<'a> Iterator for SplitPaths<'a> {
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> {
+        match *self.0 {}
+    }
+}
+
+#[derive(Debug)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
+where
+    I: Iterator<Item = T>,
+    T: AsRef<OsStr>,
+{
+    Err(JoinPathsError)
+}
+
+impl fmt::Display for JoinPathsError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "not supported on CloudABI yet".fmt(f)
+    }
+}
+
+impl StdError for JoinPathsError {
+    fn description(&self) -> &str {
+        "not supported on CloudABI yet"
+    }
+}
+
+pub fn home_dir() -> Option<PathBuf> {
+    None
+}
+
+pub fn temp_dir() -> PathBuf {
+    PathBuf::from("/tmp")
+}
+
+pub fn current_exe() -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn getpid() -> u32 {
+    1
+}
diff --git a/src/libstd/sys/cloudabi/shims/pipe.rs b/src/libstd/sys/cloudabi/shims/pipe.rs
new file mode 100644
index 0000000..77a9cd6
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/pipe.rs
@@ -0,0 +1,32 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+use sys::Void;
+
+pub struct AnonPipe(Void);
+
+impl AnonPipe {
+    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn diverge(&self) -> ! {
+        match self.0 {}
+    }
+}
+
+pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
+    match p1.0 {}
+}
diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs
new file mode 100644
index 0000000..52e8c82
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/process.rs
@@ -0,0 +1,147 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::OsStr;
+use fmt;
+use io;
+use sys::fs::File;
+use sys::pipe::AnonPipe;
+use sys::{unsupported, Void};
+use sys_common::process::{CommandEnv, DefaultEnvKey};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+    env: CommandEnv<DefaultEnvKey>,
+}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+    pub stdin: Option<AnonPipe>,
+    pub stdout: Option<AnonPipe>,
+    pub stderr: Option<AnonPipe>,
+}
+
+pub enum Stdio {
+    Inherit,
+    Null,
+    MakePipe,
+}
+
+impl Command {
+    pub fn new(_program: &OsStr) -> Command {
+        Command {
+            env: Default::default(),
+        }
+    }
+
+    pub fn arg(&mut self, _arg: &OsStr) {}
+
+    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+        &mut self.env
+    }
+
+    pub fn cwd(&mut self, _dir: &OsStr) {}
+
+    pub fn stdin(&mut self, _stdin: Stdio) {}
+
+    pub fn stdout(&mut self, _stdout: Stdio) {}
+
+    pub fn stderr(&mut self, _stderr: Stdio) {}
+
+    pub fn spawn(
+        &mut self,
+        _default: Stdio,
+        _needs_stdin: bool,
+    ) -> io::Result<(Process, StdioPipes)> {
+        unsupported()
+    }
+}
+
+impl From<AnonPipe> for Stdio {
+    fn from(pipe: AnonPipe) -> Stdio {
+        pipe.diverge()
+    }
+}
+
+impl From<File> for Stdio {
+    fn from(file: File) -> Stdio {
+        file.diverge()
+    }
+}
+
+impl fmt::Debug for Command {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        Ok(())
+    }
+}
+
+pub struct ExitStatus(Void);
+
+impl ExitStatus {
+    pub fn success(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        match self.0 {}
+    }
+}
+
+impl Clone for ExitStatus {
+    fn clone(&self) -> ExitStatus {
+        match self.0 {}
+    }
+}
+
+impl Copy for ExitStatus {}
+
+impl PartialEq for ExitStatus {
+    fn eq(&self, _other: &ExitStatus) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Eq for ExitStatus {}
+
+impl fmt::Debug for ExitStatus {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct Process(Void);
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        match self.0 {}
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        match self.0 {}
+    }
+
+    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+        match self.0 {}
+    }
+}
diff --git a/src/test/ui-fulldeps/issue-44953/issue-44953.rs b/src/libstd/sys/cloudabi/stack_overflow.rs
similarity index 71%
rename from src/test/ui-fulldeps/issue-44953/issue-44953.rs
rename to src/libstd/sys/cloudabi/stack_overflow.rs
index de798e2..5c0b1e5 100644
--- a/src/test/ui-fulldeps/issue-44953/issue-44953.rs
+++ b/src/libstd/sys/cloudabi/stack_overflow.rs
@@ -7,14 +7,17 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-//
 
+#![cfg_attr(test, allow(dead_code))]
 
-#![feature(proc_macro)]
-#![allow(unused_macros)]
+pub struct Handler;
 
-#[macro_use] extern crate log; //~ ERROR use of unstable library feature
-
-pub fn main() {
-    info!("This is a log message.");
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        Handler
+    }
 }
+
+pub unsafe fn init() {}
+
+pub unsafe fn cleanup() {}
diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs
new file mode 100644
index 0000000..9519a92
--- /dev/null
+++ b/src/libstd/sys/cloudabi/stdio.rs
@@ -0,0 +1,79 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+use sys::cloudabi::abi;
+
+pub struct Stdin(());
+pub struct Stdout(());
+pub struct Stderr(());
+
+impl Stdin {
+    pub fn new() -> io::Result<Stdin> {
+        Ok(Stdin(()))
+    }
+
+    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+        Ok(0)
+    }
+}
+
+impl Stdout {
+    pub fn new() -> io::Result<Stdout> {
+        Ok(Stdout(()))
+    }
+
+    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+        Err(io::Error::new(
+            io::ErrorKind::BrokenPipe,
+            "Stdout is not connected to any output in this environment",
+        ))
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub fn new() -> io::Result<Stderr> {
+        Ok(Stderr(()))
+    }
+
+    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+        Err(io::Error::new(
+            io::ErrorKind::BrokenPipe,
+            "Stderr is not connected to any output in this environment",
+        ))
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+// FIXME: right now this raw stderr handle is used in a few places because
+//        std::io::stderr_raw isn't exposed, but once that's exposed this impl
+//        should go away
+impl io::Write for Stderr {
+    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+        Stderr::write(self, data)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Stderr::flush(self)
+    }
+}
+
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(abi::errno::BADF as i32)
+}
+
+pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
new file mode 100644
index 0000000..c980ae7
--- /dev/null
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -0,0 +1,124 @@
+// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use alloc::boxed::FnBox;
+use cmp;
+use ffi::CStr;
+use io;
+use libc;
+use mem;
+use ptr;
+use sys::cloudabi::abi;
+use sys::time::dur2intervals;
+use sys_common::thread::*;
+use time::Duration;
+
+pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
+
+pub struct Thread {
+    id: libc::pthread_t,
+}
+
+// CloudABI has pthread_t as a pointer in which case we still want
+// a thread to be Send/Sync
+unsafe impl Send for Thread {}
+unsafe impl Sync for Thread {}
+
+impl Thread {
+    pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
+        let p = box p;
+        let mut native: libc::pthread_t = mem::zeroed();
+        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+
+        let stack_size = cmp::max(stack, min_stack_size(&attr));
+        assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
+
+        let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
+        assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+
+        return if ret != 0 {
+            Err(io::Error::from_raw_os_error(ret))
+        } else {
+            mem::forget(p); // ownership passed to pthread_create
+            Ok(Thread { id: native })
+        };
+
+        extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
+            unsafe {
+                start_thread(main as *mut u8);
+            }
+            ptr::null_mut()
+        }
+    }
+
+    pub fn yield_now() {
+        let ret = unsafe { abi::thread_yield() };
+        debug_assert_eq!(ret, abi::errno::SUCCESS);
+    }
+
+    pub fn set_name(_name: &CStr) {
+        // CloudABI has no way to set a thread name.
+    }
+
+    pub fn sleep(dur: Duration) {
+        unsafe {
+            let subscription = abi::subscription {
+                type_: abi::eventtype::CLOCK,
+                union: abi::subscription_union {
+                    clock: abi::subscription_clock {
+                        clock_id: abi::clockid::MONOTONIC,
+                        timeout: dur2intervals(&dur),
+                        ..mem::zeroed()
+                    },
+                },
+                ..mem::zeroed()
+            };
+            let mut event: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS);
+            assert_eq!(event.error, abi::errno::SUCCESS);
+        }
+    }
+
+    pub fn join(self) {
+        unsafe {
+            let ret = libc::pthread_join(self.id, ptr::null_mut());
+            mem::forget(self);
+            assert!(
+                ret == 0,
+                "failed to join thread: {}",
+                io::Error::from_raw_os_error(ret)
+            );
+        }
+    }
+}
+
+impl Drop for Thread {
+    fn drop(&mut self) {
+        let ret = unsafe { libc::pthread_detach(self.id) };
+        debug_assert_eq!(ret, 0);
+    }
+}
+
+#[cfg_attr(test, allow(dead_code))]
+pub mod guard {
+    pub unsafe fn current() -> Option<usize> {
+        None
+    }
+    pub unsafe fn init() -> Option<usize> {
+        None
+    }
+}
+
+fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
+    libc::PTHREAD_STACK_MIN
+}
diff --git a/src/libstd/sys/cloudabi/time.rs b/src/libstd/sys/cloudabi/time.rs
new file mode 100644
index 0000000..ee12731
--- /dev/null
+++ b/src/libstd/sys/cloudabi/time.rs
@@ -0,0 +1,111 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use mem;
+use sys::cloudabi::abi;
+use time::Duration;
+
+const NSEC_PER_SEC: abi::timestamp = 1_000_000_000;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct Instant {
+    t: abi::timestamp,
+}
+
+pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
+    dur.as_secs()
+        .checked_mul(NSEC_PER_SEC)
+        .and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
+        .expect("overflow converting duration to nanoseconds")
+}
+
+impl Instant {
+    pub fn now() -> Instant {
+        unsafe {
+            let mut t = mem::uninitialized();
+            let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, &mut t);
+            assert_eq!(ret, abi::errno::SUCCESS);
+            Instant { t: t }
+        }
+    }
+
+    pub fn sub_instant(&self, other: &Instant) -> Duration {
+        let diff = self.t
+            .checked_sub(other.t)
+            .expect("second instant is later than self");
+        Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
+    }
+
+    pub fn add_duration(&self, other: &Duration) -> Instant {
+        Instant {
+            t: self.t
+                .checked_add(dur2intervals(other))
+                .expect("overflow when adding duration to instant"),
+        }
+    }
+
+    pub fn sub_duration(&self, other: &Duration) -> Instant {
+        Instant {
+            t: self.t
+                .checked_sub(dur2intervals(other))
+                .expect("overflow when subtracting duration from instant"),
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct SystemTime {
+    t: abi::timestamp,
+}
+
+impl SystemTime {
+    pub fn now() -> SystemTime {
+        unsafe {
+            let mut t = mem::uninitialized();
+            let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, &mut t);
+            assert_eq!(ret, abi::errno::SUCCESS);
+            SystemTime { t: t }
+        }
+    }
+
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+        if self.t >= other.t {
+            let diff = self.t - other.t;
+            Ok(Duration::new(
+                diff / NSEC_PER_SEC,
+                (diff % NSEC_PER_SEC) as u32,
+            ))
+        } else {
+            let diff = other.t - self.t;
+            Err(Duration::new(
+                diff / NSEC_PER_SEC,
+                (diff % NSEC_PER_SEC) as u32,
+            ))
+        }
+    }
+
+    pub fn add_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime {
+            t: self.t
+                .checked_add(dur2intervals(other))
+                .expect("overflow when adding duration to instant"),
+        }
+    }
+
+    pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime {
+            t: self.t
+                .checked_sub(dur2intervals(other))
+                .expect("overflow when subtracting duration from instant"),
+        }
+    }
+}
+
+pub const UNIX_EPOCH: SystemTime = SystemTime { t: 0 };
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index be8cb88..1231898 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -39,6 +39,9 @@
     } else if #[cfg(windows)] {
         mod windows;
         pub use self::windows::*;
+    } else if #[cfg(target_os = "cloudabi")] {
+        mod cloudabi;
+        pub use self::cloudabi::*;
     } else if #[cfg(target_os = "redox")] {
         mod redox;
         pub use self::redox::*;
@@ -59,9 +62,10 @@
     if #[cfg(any(unix, target_os = "redox"))] {
         // On unix we'll document what's already available
         pub use self::ext as unix_ext;
-    } else if #[cfg(target_arch = "wasm32")] {
-        // On wasm right now the module below doesn't compile (missing things
-        // in `libc` which is empty) so just omit everything with an empty module
+    } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+        // On CloudABI and wasm right now the module below doesn't compile
+        // (missing things in `libc` which is empty) so just omit everything
+        // with an empty module
         #[unstable(issue = "0", feature = "std_internals")]
         pub mod unix_ext {}
     } else {
@@ -77,8 +81,9 @@
     if #[cfg(windows)] {
         // On windows we'll just be documenting what's already available
         pub use self::ext as windows_ext;
-    } else if #[cfg(target_arch = "wasm32")] {
-        // On wasm right now the shim below doesn't compile, so just omit it
+    } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+        // On CloudABI and wasm right now the shim below doesn't compile, so
+        // just omit it
         #[unstable(issue = "0", feature = "std_internals")]
         pub mod windows_ext {}
     } else {
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
index 3483477..2e22161 100644
--- a/src/libstd/sys/redox/fs.rs
+++ b/src/libstd/sys/redox/fs.rs
@@ -384,8 +384,11 @@
 }
 
 pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
-    copy(old, new)?;
-    unlink(old)?;
+    let fd = cvt(syscall::open(old.to_str().unwrap(),
+                               syscall::O_CLOEXEC | syscall::O_STAT | syscall::O_NOFOLLOW))?;
+    let res = cvt(syscall::frename(fd, new.to_str().unwrap()));
+    cvt(syscall::close(fd))?;
+    res?;
     Ok(())
 }
 
@@ -421,18 +424,22 @@
 }
 
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_RDONLY))?;
+    let fd = cvt(syscall::open(p.to_str().unwrap(),
+                               syscall::O_CLOEXEC | syscall::O_SYMLINK | syscall::O_RDONLY))?;
     let mut buf: [u8; 4096] = [0; 4096];
-    let count = cvt(syscall::read(fd, &mut buf))?;
+    let res = cvt(syscall::read(fd, &mut buf));
     cvt(syscall::close(fd))?;
+    let count = res?;
     Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) }))
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
     let fd = cvt(syscall::open(dst.to_str().unwrap(),
-                               syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?;
-    cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()))?;
+                               syscall::O_CLOEXEC | syscall::O_SYMLINK |
+                               syscall::O_CREAT | syscall::O_WRONLY | 0o777))?;
+    let res = cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()));
     cvt(syscall::close(fd))?;
+    res?;
     Ok(())
 }
 
diff --git a/src/libstd/sys/redox/memchr.rs b/src/libstd/sys/redox/memchr.rs
index 4c314b7..873b335 100644
--- a/src/libstd/sys/redox/memchr.rs
+++ b/src/libstd/sys/redox/memchr.rs
@@ -11,4 +11,4 @@
 // Original implementation taken from rust-memchr
 // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
 
-pub use sys_common::memchr::fallback::{memchr, memrchr};
+pub use core::slice::memchr::{memchr, memrchr};
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
index d87364b..3fd5497 100644
--- a/src/libstd/sys/redox/process.rs
+++ b/src/libstd/sys/redox/process.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use collections::hash_map::HashMap;
-use env::{self, split_paths};
+use env::{split_paths};
 use ffi::OsStr;
 use os::unix::ffi::OsStrExt;
 use fmt;
@@ -19,6 +18,7 @@
 use sys::fs::{File, OpenOptions};
 use sys::pipe::{self, AnonPipe};
 use sys::{cvt, syscall};
+use sys_common::process::{CommandEnv, DefaultEnvKey};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
@@ -44,7 +44,7 @@
     // other keys.
     program: String,
     args: Vec<String>,
-    env: HashMap<String, String>,
+    env: CommandEnv<DefaultEnvKey>,
 
     cwd: Option<String>,
     uid: Option<u32>,
@@ -90,7 +90,7 @@
         Command {
             program: program.to_str().unwrap().to_owned(),
             args: Vec::new(),
-            env: HashMap::new(),
+            env: Default::default(),
             cwd: None,
             uid: None,
             gid: None,
@@ -106,16 +106,8 @@
         self.args.push(arg.to_str().unwrap().to_owned());
     }
 
-    pub fn env(&mut self, key: &OsStr, val: &OsStr) {
-        self.env.insert(key.to_str().unwrap().to_owned(), val.to_str().unwrap().to_owned());
-    }
-
-    pub fn env_remove(&mut self, key: &OsStr) {
-        self.env.remove(key.to_str().unwrap());
-    }
-
-    pub fn env_clear(&mut self) {
-        self.env.clear();
+    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+        &mut self.env
     }
 
     pub fn cwd(&mut self, dir: &OsStr) {
@@ -309,9 +301,7 @@
             args.push([arg.as_ptr() as usize, arg.len()]);
         }
 
-        for (key, val) in self.env.iter() {
-            env::set_var(key, val);
-        }
+        self.env.apply();
 
         let program = if self.program.contains(':') || self.program.contains('/') {
             Some(PathBuf::from(&self.program))
diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs
index 7770a2f..f9a8bd6 100644
--- a/src/libstd/sys/redox/syscall/call.rs
+++ b/src/libstd/sys/redox/syscall/call.rs
@@ -93,7 +93,19 @@
     unsafe { syscall1(SYS_EXIT, status) }
 }
 
-/// Register a file for event-based I/O
+/// Change file permissions
+pub fn fchmod(fd: usize, mode: u16) -> Result<usize> {
+    unsafe { syscall2(SYS_FCHMOD, fd, mode as usize) }
+
+}
+
+/// Change file ownership
+pub fn fchown(fd: usize, uid: u32, gid: u32) -> Result<usize> {
+    unsafe { syscall3(SYS_FCHOWN, fd, uid as usize, gid as usize) }
+
+}
+
+/// Change file descriptor flags
 pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
     unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
 }
@@ -118,6 +130,11 @@
     unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
 }
 
+/// Rename a file
+pub fn frename<T: AsRef<[u8]>>(fd: usize, path: T) -> Result<usize> {
+    unsafe { syscall3(SYS_FRENAME, fd, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
+}
+
 /// Get metadata about a file
 pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
     unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::<Stat>()) }
diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs
index 07db916..45cb40e 100644
--- a/src/libstd/sys/redox/syscall/number.rs
+++ b/src/libstd/sys/redox/syscall/number.rs
@@ -32,11 +32,14 @@
 pub const SYS_READ: usize =     SYS_CLASS_FILE | SYS_ARG_MSLICE | 3;
 pub const SYS_WRITE: usize =    SYS_CLASS_FILE | SYS_ARG_SLICE | 4;
 pub const SYS_LSEEK: usize =    SYS_CLASS_FILE | 19;
+pub const SYS_FCHMOD: usize =   SYS_CLASS_FILE | 94;
+pub const SYS_FCHOWN: usize =   SYS_CLASS_FILE | 207;
 pub const SYS_FCNTL: usize =    SYS_CLASS_FILE | 55;
 pub const SYS_FEVENT: usize =   SYS_CLASS_FILE | 927;
 pub const SYS_FMAP: usize =     SYS_CLASS_FILE | 90;
 pub const SYS_FUNMAP: usize =   SYS_CLASS_FILE | 91;
 pub const SYS_FPATH: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
+pub const SYS_FRENAME: usize =  SYS_CLASS_FILE | SYS_ARG_PATH | 38;
 pub const SYS_FSTAT: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 28;
 pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100;
 pub const SYS_FSYNC: usize =    SYS_CLASS_FILE | 118;
diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs
index 7216977..e1c7ffc 100644
--- a/src/libstd/sys/unix/args.rs
+++ b/src/libstd/sys/unix/args.rs
@@ -69,7 +69,7 @@
           target_os = "fuchsia"))]
 mod imp {
     use os::unix::prelude::*;
-    use mem;
+    use ptr;
     use ffi::{CStr, OsString};
     use marker::PhantomData;
     use libc;
@@ -77,49 +77,42 @@
 
     use sys_common::mutex::Mutex;
 
-    static mut GLOBAL_ARGS_PTR: usize = 0;
+    static mut ARGC: isize = 0;
+    static mut ARGV: *const *const u8 = ptr::null();
     static LOCK: Mutex = Mutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
-        let args = (0..argc).map(|i| {
-            CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
-        }).collect();
-
         LOCK.lock();
-        let ptr = get_global_ptr();
-        assert!((*ptr).is_none());
-        (*ptr) = Some(box args);
+        ARGC = argc;
+        ARGV = argv;
         LOCK.unlock();
     }
 
     pub unsafe fn cleanup() {
         LOCK.lock();
-        *get_global_ptr() = None;
+        ARGC = 0;
+        ARGV = ptr::null();
         LOCK.unlock();
     }
 
     pub fn args() -> Args {
-        let bytes = clone().unwrap_or(Vec::new());
-        let v: Vec<OsString> = bytes.into_iter().map(|v| {
-            OsStringExt::from_vec(v)
-        }).collect();
-        Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
+        Args {
+            iter: clone().into_iter(),
+            _dont_send_or_sync_me: PhantomData
+        }
     }
 
-    fn clone() -> Option<Vec<Vec<u8>>> {
+    fn clone() -> Vec<OsString> {
         unsafe {
             LOCK.lock();
-            let ptr = get_global_ptr();
-            let ret = (*ptr).as_ref().map(|s| (**s).clone());
+            let ret = (0..ARGC).map(|i| {
+                let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
+                OsStringExt::from_vec(cstr.to_bytes().to_vec())
+            }).collect();
             LOCK.unlock();
             return ret
         }
     }
-
-    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
-        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
-    }
-
 }
 
 #[cfg(any(target_os = "macos",
diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs
index c3e8d0b..2121848 100644
--- a/src/libstd/sys/unix/l4re.rs
+++ b/src/libstd/sys/unix/l4re.rs
@@ -437,9 +437,5 @@
     pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
         unimpl!();
     }
-
-    pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
-        unimpl!();
-    }
 }
 
diff --git a/src/libstd/sys/unix/memchr.rs b/src/libstd/sys/unix/memchr.rs
index aed0470..f49adc2 100644
--- a/src/libstd/sys/unix/memchr.rs
+++ b/src/libstd/sys/unix/memchr.rs
@@ -50,7 +50,7 @@
 
     #[cfg(not(target_os = "linux"))]
     fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        ::sys_common::memchr::fallback::memrchr(needle, haystack)
+        ::core::slice::memchr::memrchr(needle, haystack)
     }
 
     memrchr_specific(needle, haystack)
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index e775f85..3f65975 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -51,6 +51,10 @@
     if err == 0 {
         return Ok(())
     }
+
+    // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
+    on_resolver_failure();
+
     if err == EAI_SYSTEM {
         return Err(io::Error::last_os_error())
     }
@@ -377,21 +381,22 @@
 // res_init unconditionally, we call it only when we detect we're linking
 // against glibc version < 2.26. (That is, when we both know its needed and
 // believe it's thread-safe).
-pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
+#[cfg(target_env = "gnu")]
+fn on_resolver_failure() {
     // If the version fails to parse, we treat it the same as "not glibc".
     if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
         if let Some(version) = parse_glibc_version(version_str) {
             if version < (2, 26) {
-                let ret = unsafe { libc::res_init() };
-                if ret != 0 {
-                    return Err(io::Error::last_os_error());
-                }
+                unsafe { libc::res_init() };
             }
         }
     }
-    Ok(())
 }
 
+#[cfg(not(target_env = "gnu"))]
+fn on_resolver_failure() {}
+
+#[cfg(target_env = "gnu")]
 fn glibc_version_cstr() -> Option<&'static CStr> {
     weak! {
         fn gnu_get_libc_version() -> *const libc::c_char
@@ -405,6 +410,7 @@
 
 // Returns Some((major, minor)) if the string is a valid "x.y" version,
 // ignoring any extra dot-separated parts. Otherwise return None.
+#[cfg(target_env = "gnu")]
 fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
     match (parsed_ints.next(), parsed_ints.next()) {
@@ -413,7 +419,7 @@
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, taget_env = "gnu"))]
 mod test {
     use super::*;
 
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 4f33a2b..a46e855 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -453,7 +453,7 @@
     let k = CString::new(k.as_bytes())?;
     unsafe {
         ENV_LOCK.lock();
-        let s = libc::getenv(k.as_ptr()) as *const _;
+        let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
         let ret = if s.is_null() {
             None
         } else {
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index 383434b..c53bcdb 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -10,8 +10,6 @@
 
 use os::unix::prelude::*;
 
-use collections::hash_map::{HashMap, Entry};
-use env;
 use ffi::{OsString, OsStr, CString, CStr};
 use fmt;
 use io;
@@ -20,6 +18,8 @@
 use sys::fd::FileDesc;
 use sys::fs::{File, OpenOptions};
 use sys::pipe::{self, AnonPipe};
+use sys_common::process::{CommandEnv, DefaultEnvKey};
+use collections::BTreeMap;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
@@ -45,9 +45,8 @@
     // other keys.
     program: CString,
     args: Vec<CString>,
-    env: Option<HashMap<OsString, (usize, CString)>>,
     argv: Vec<*const c_char>,
-    envp: Option<Vec<*const c_char>>,
+    env: CommandEnv<DefaultEnvKey>,
 
     cwd: Option<CString>,
     uid: Option<uid_t>,
@@ -96,8 +95,7 @@
             argv: vec![program.as_ptr(), ptr::null()],
             program,
             args: Vec::new(),
-            env: None,
-            envp: None,
+            env: Default::default(),
             cwd: None,
             uid: None,
             gid: None,
@@ -121,68 +119,6 @@
         self.args.push(arg);
     }
 
-    fn init_env_map(&mut self) -> (&mut HashMap<OsString, (usize, CString)>,
-                                   &mut Vec<*const c_char>) {
-        if self.env.is_none() {
-            let mut map = HashMap::new();
-            let mut envp = Vec::new();
-            for (k, v) in env::vars_os() {
-                let s = pair_to_key(&k, &v, &mut self.saw_nul);
-                envp.push(s.as_ptr());
-                map.insert(k, (envp.len() - 1, s));
-            }
-            envp.push(ptr::null());
-            self.env = Some(map);
-            self.envp = Some(envp);
-        }
-        (self.env.as_mut().unwrap(), self.envp.as_mut().unwrap())
-    }
-
-    pub fn env(&mut self, key: &OsStr, val: &OsStr) {
-        let new_key = pair_to_key(key, val, &mut self.saw_nul);
-        let (map, envp) = self.init_env_map();
-
-        // If `key` is already present then we just update `envp` in place
-        // (and store the owned value), but if it's not there we override the
-        // trailing NULL pointer, add a new NULL pointer, and store where we
-        // were located.
-        match map.entry(key.to_owned()) {
-            Entry::Occupied(mut e) => {
-                let (i, ref mut s) = *e.get_mut();
-                envp[i] = new_key.as_ptr();
-                *s = new_key;
-            }
-            Entry::Vacant(e) => {
-                let len = envp.len();
-                envp[len - 1] = new_key.as_ptr();
-                envp.push(ptr::null());
-                e.insert((len - 1, new_key));
-            }
-        }
-    }
-
-    pub fn env_remove(&mut self, key: &OsStr) {
-        let (map, envp) = self.init_env_map();
-
-        // If we actually ended up removing a key, then we need to update the
-        // position of all keys that come after us in `envp` because they're all
-        // one element sooner now.
-        if let Some((i, _)) = map.remove(key) {
-            envp.remove(i);
-
-            for (_, &mut (ref mut j, _)) in map.iter_mut() {
-                if *j >= i {
-                    *j -= 1;
-                }
-            }
-        }
-    }
-
-    pub fn env_clear(&mut self) {
-        self.env = Some(HashMap::new());
-        self.envp = Some(vec![ptr::null()]);
-    }
-
     pub fn cwd(&mut self, dir: &OsStr) {
         self.cwd = Some(os2c(dir, &mut self.saw_nul));
     }
@@ -196,9 +132,6 @@
     pub fn saw_nul(&self) -> bool {
         self.saw_nul
     }
-    pub fn get_envp(&self) -> &Option<Vec<*const c_char>> {
-        &self.envp
-    }
     pub fn get_argv(&self) -> &Vec<*const c_char> {
         &self.argv
     }
@@ -237,6 +170,15 @@
         self.stderr = Some(stderr);
     }
 
+    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+        &mut self.env
+    }
+
+    pub fn capture_env(&mut self) -> Option<CStringArray> {
+        let maybe_env = self.env.capture_if_changed();
+        maybe_env.map(|env| construct_envp(env, &mut self.saw_nul))
+    }
+
     pub fn setup_io(&self, default: Stdio, needs_stdin: bool)
                 -> io::Result<(StdioPipes, ChildPipes)> {
         let null = Stdio::Null;
@@ -268,6 +210,53 @@
     })
 }
 
+// Helper type to manage ownership of the strings within a C-style array.
+pub struct CStringArray {
+    items: Vec<CString>,
+    ptrs: Vec<*const c_char>
+}
+
+impl CStringArray {
+    pub fn with_capacity(capacity: usize) -> Self {
+        let mut result = CStringArray {
+            items: Vec::with_capacity(capacity),
+            ptrs: Vec::with_capacity(capacity+1)
+        };
+        result.ptrs.push(ptr::null());
+        result
+    }
+    pub fn push(&mut self, item: CString) {
+        let l = self.ptrs.len();
+        self.ptrs[l-1] = item.as_ptr();
+        self.ptrs.push(ptr::null());
+        self.items.push(item);
+    }
+    pub fn as_ptr(&self) -> *const *const c_char {
+        self.ptrs.as_ptr()
+    }
+}
+
+fn construct_envp(env: BTreeMap<DefaultEnvKey, OsString>, saw_nul: &mut bool) -> CStringArray {
+    let mut result = CStringArray::with_capacity(env.len());
+    for (k, v) in env {
+        let mut k: OsString = k.into();
+
+        // Reserve additional space for '=' and null terminator
+        k.reserve_exact(v.len() + 2);
+        k.push("=");
+        k.push(&v);
+
+        // Add the new entry into the array
+        if let Ok(item) = CString::new(k.into_vec()) {
+            result.push(item);
+        } else {
+            *saw_nul = true;
+        }
+    }
+
+    result
+}
+
 impl Stdio {
     pub fn to_child_stdio(&self, readable: bool)
                       -> io::Result<(ChildStdio, Option<AnonPipe>)> {
@@ -337,18 +326,6 @@
     }
 }
 
-fn pair_to_key(key: &OsStr, value: &OsStr, saw_nul: &mut bool) -> CString {
-    let (key, value) = (key.as_bytes(), value.as_bytes());
-    let mut v = Vec::with_capacity(key.len() + value.len() + 1);
-    v.extend(key);
-    v.push(b'=');
-    v.extend(value);
-    CString::new(v).unwrap_or_else(|_e| {
-        *saw_nul = true;
-        CString::new("foo=bar").unwrap()
-    })
-}
-
 impl fmt::Debug for Command {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{:?}", self.program)?;
diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs
index a7a67ed..06c0540 100644
--- a/src/libstd/sys/unix/process/process_fuchsia.rs
+++ b/src/libstd/sys/unix/process/process_fuchsia.rs
@@ -23,6 +23,8 @@
 impl Command {
     pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
                  -> io::Result<(Process, StdioPipes)> {
+        let envp = self.capture_env();
+
         if self.saw_nul() {
             return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                       "nul byte found in provided data"));
@@ -30,7 +32,7 @@
 
         let (ours, theirs) = self.setup_io(default, needs_stdin)?;
 
-        let process_handle = unsafe { self.do_exec(theirs)? };
+        let process_handle = unsafe { self.do_exec(theirs, envp.as_ref())? };
 
         Ok((Process { handle: Handle::new(process_handle) }, ours))
     }
@@ -50,13 +52,13 @@
         }
     }
 
-    unsafe fn do_exec(&mut self, stdio: ChildPipes)
+    unsafe fn do_exec(&mut self, stdio: ChildPipes, maybe_envp: Option<&CStringArray>)
                       -> io::Result<zx_handle_t> {
         use sys::process::zircon::*;
 
         let job_handle = zx_job_default();
-        let envp = match *self.get_envp() {
-            Some(ref envp) => envp.as_ptr(),
+        let envp = match maybe_envp {
+            Some(envp) => envp.as_ptr(),
             None => ptr::null(),
         };
 
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 743c458..189280a 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -26,6 +26,8 @@
 
         const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
 
+        let envp = self.capture_env();
+
         if self.saw_nul() {
             return Err(io::Error::new(ErrorKind::InvalidInput,
                                       "nul byte found in provided data"));
@@ -38,7 +40,7 @@
             match cvt(libc::fork())? {
                 0 => {
                     drop(input);
-                    let err = self.do_exec(theirs);
+                    let err = self.do_exec(theirs, envp.as_ref());
                     let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
                     let bytes = [
                         (errno >> 24) as u8,
@@ -99,13 +101,15 @@
     }
 
     pub fn exec(&mut self, default: Stdio) -> io::Error {
+        let envp = self.capture_env();
+
         if self.saw_nul() {
             return io::Error::new(ErrorKind::InvalidInput,
                                   "nul byte found in provided data")
         }
 
         match self.setup_io(default, true) {
-            Ok((_, theirs)) => unsafe { self.do_exec(theirs) },
+            Ok((_, theirs)) => unsafe { self.do_exec(theirs, envp.as_ref()) },
             Err(e) => e,
         }
     }
@@ -140,7 +144,11 @@
     // allocation). Instead we just close it manually. This will never
     // have the drop glue anyway because this code never returns (the
     // child will either exec() or invoke libc::exit)
-    unsafe fn do_exec(&mut self, stdio: ChildPipes) -> io::Error {
+    unsafe fn do_exec(
+        &mut self,
+        stdio: ChildPipes,
+        maybe_envp: Option<&CStringArray>
+    ) -> io::Error {
         use sys::{self, cvt_r};
 
         macro_rules! t {
@@ -180,7 +188,7 @@
         if let Some(ref cwd) = *self.get_cwd() {
             t!(cvt(libc::chdir(cwd.as_ptr())));
         }
-        if let Some(ref envp) = *self.get_envp() {
+        if let Some(envp) = maybe_envp {
             *sys::os::environ() = envp.as_ptr();
         }
 
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index cb249af..525882c 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -311,8 +311,8 @@
 
     #[cfg(target_os = "macos")]
     pub unsafe fn current() -> Option<usize> {
-        Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
-              libc::pthread_get_stacksize_np(libc::pthread_self())))
+        Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
+             libc::pthread_get_stacksize_np(libc::pthread_self()))
     }
 
     #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
diff --git a/src/libstd/sys/wasm/memchr.rs b/src/libstd/sys/wasm/memchr.rs
index e611d94..964e359 100644
--- a/src/libstd/sys/wasm/memchr.rs
+++ b/src/libstd/sys/wasm/memchr.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use sys_common::memchr::fallback::{memchr, memrchr};
+pub use core::slice::memchr::{memchr, memrchr};
diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs
index b838dba..ba3d6a2 100644
--- a/src/libstd/sys/wasm/mod.rs
+++ b/src/libstd/sys/wasm/mod.rs
@@ -39,6 +39,7 @@
 const DEBUG: bool = false;
 
 pub mod args;
+#[cfg(feature = "backtrace")]
 pub mod backtrace;
 pub mod cmath;
 pub mod condvar;
diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs
index 4febe8a..f3f5de3 100644
--- a/src/libstd/sys/wasm/process.rs
+++ b/src/libstd/sys/wasm/process.rs
@@ -14,12 +14,14 @@
 use sys::fs::File;
 use sys::pipe::AnonPipe;
 use sys::{unsupported, Void};
+use sys_common::process::{CommandEnv, DefaultEnvKey};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Command {
+    env: CommandEnv<DefaultEnvKey>
 }
 
 // passed back to std::process with the pipes connected to the child, if any
@@ -38,19 +40,16 @@
 
 impl Command {
     pub fn new(_program: &OsStr) -> Command {
-        Command {}
+        Command {
+            env: Default::default()
+        }
     }
 
     pub fn arg(&mut self, _arg: &OsStr) {
     }
 
-    pub fn env(&mut self, _key: &OsStr, _val: &OsStr) {
-    }
-
-    pub fn env_remove(&mut self, _key: &OsStr) {
-    }
-
-    pub fn env_clear(&mut self) {
+    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+        &mut self.env
     }
 
     pub fn cwd(&mut self, _dir: &OsStr) {
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 6e0cccf..66b44f1 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -20,11 +20,6 @@
 use libc::{wchar_t, size_t, c_void};
 use ptr;
 
-#[repr(simd)]
-#[repr(C)]
-#[cfg(target_arch = "x86_64")]
-struct u64x2(u64, u64);
-
 pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
 pub use self::EXCEPTION_DISPOSITION::*;
 
@@ -700,9 +695,8 @@
 }
 
 #[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
 pub struct CONTEXT {
-    _align_hack: [u64x2; 0], // FIXME align on 16-byte
     pub P1Home: DWORDLONG,
     pub P2Home: DWORDLONG,
     pub P3Home: DWORDLONG,
@@ -760,17 +754,15 @@
 }
 
 #[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
 pub struct M128A {
-    _align_hack: [u64x2; 0], // FIXME align on 16-byte
     pub Low:  c_ulonglong,
     pub High: c_longlong
 }
 
 #[cfg(target_arch = "x86_64")]
-#[repr(C)]
+#[repr(C, align(16))]
 pub struct FLOATING_SAVE_AREA {
-    _align_hack: [u64x2; 0], // FIXME align on 16-byte
     _Dummy: [u8; 512] // FIXME: Fill this out
 }
 
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index ae95351..165e1b0 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -770,7 +770,7 @@
         let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
         let db = data.as_mut_ptr()
                     as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
-        let buf = &mut (*db).ReparseTarget as *mut _;
+        let buf = &mut (*db).ReparseTarget as *mut c::WCHAR;
         let mut i = 0;
         // FIXME: this conversion is very hacky
         let v = br"\??\";
diff --git a/src/libstd/sys/windows/memchr.rs b/src/libstd/sys/windows/memchr.rs
index 5a5386a..fa7c816 100644
--- a/src/libstd/sys/windows/memchr.rs
+++ b/src/libstd/sys/windows/memchr.rs
@@ -12,4 +12,4 @@
 // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
 
 // Fallback memchr is fastest on windows
-pub use sys_common::memchr::fallback::{memchr, memrchr};
+pub use core::slice::memchr::{memchr, memrchr};
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index b8d2f7b..414c9c5 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -17,7 +17,7 @@
 use mem;
 use rc::Rc;
 use sync::Arc;
-use sys_common::{AsInner, IntoInner};
+use sys_common::{AsInner, IntoInner, FromInner};
 
 #[derive(Clone, Hash)]
 pub struct Buf {
@@ -30,6 +30,12 @@
     }
 }
 
+impl FromInner<Wtf8Buf> for Buf {
+    fn from_inner(inner: Wtf8Buf) -> Self {
+        Buf { inner }
+    }
+}
+
 impl AsInner<Wtf8> for Buf {
     fn as_inner(&self) -> &Wtf8 {
         &self.inner
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 631d69b..c931798 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![unstable(feature = "process_internals", issue = "0")]
+
 use ascii::AsciiExt;
-use collections::HashMap;
-use collections;
+use collections::BTreeMap;
 use env::split_paths;
 use env;
 use ffi::{OsString, OsStr};
@@ -28,19 +29,42 @@
 use sys::handle::Handle;
 use sys::pipe::{self, AnonPipe};
 use sys::stdio;
-use sys::{self, cvt};
-use sys_common::{AsInner, FromInner};
+use sys::cvt;
+use sys_common::{AsInner, FromInner, IntoInner};
+use sys_common::process::{CommandEnv, EnvKey};
+use alloc::borrow::Borrow;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
 
-fn mk_key(s: &OsStr) -> OsString {
-    FromInner::from_inner(sys::os_str::Buf {
-        inner: s.as_inner().inner.to_ascii_uppercase()
-    })
+#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+#[doc(hidden)]
+pub struct WindowsEnvKey(OsString);
+
+impl From<OsString> for WindowsEnvKey {
+    fn from(k: OsString) -> Self {
+        let mut buf = k.into_inner().into_inner();
+        buf.make_ascii_uppercase();
+        WindowsEnvKey(FromInner::from_inner(FromInner::from_inner(buf)))
+    }
 }
 
+impl From<WindowsEnvKey> for OsString {
+    fn from(k: WindowsEnvKey) -> Self { k.0 }
+}
+
+impl Borrow<OsStr> for WindowsEnvKey {
+    fn borrow(&self) -> &OsStr { &self.0 }
+}
+
+impl AsRef<OsStr> for WindowsEnvKey {
+    fn as_ref(&self) -> &OsStr { &self.0 }
+}
+
+impl EnvKey for WindowsEnvKey {}
+
+
 fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> {
     if str.as_ref().encode_wide().any(|b| b == 0) {
         Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data"))
@@ -52,7 +76,7 @@
 pub struct Command {
     program: OsString,
     args: Vec<OsString>,
-    env: Option<HashMap<OsString, OsString>>,
+    env: CommandEnv<WindowsEnvKey>,
     cwd: Option<OsString>,
     flags: u32,
     detach: bool, // not currently exposed in std::process
@@ -83,7 +107,7 @@
         Command {
             program: program.to_os_string(),
             args: Vec::new(),
-            env: None,
+            env: Default::default(),
             cwd: None,
             flags: 0,
             detach: false,
@@ -96,23 +120,8 @@
     pub fn arg(&mut self, arg: &OsStr) {
         self.args.push(arg.to_os_string())
     }
-    fn init_env_map(&mut self){
-        if self.env.is_none() {
-            self.env = Some(env::vars_os().map(|(key, val)| {
-                (mk_key(&key), val)
-            }).collect());
-        }
-    }
-    pub fn env(&mut self, key: &OsStr, val: &OsStr) {
-        self.init_env_map();
-        self.env.as_mut().unwrap().insert(mk_key(key), val.to_os_string());
-    }
-    pub fn env_remove(&mut self, key: &OsStr) {
-        self.init_env_map();
-        self.env.as_mut().unwrap().remove(&mk_key(key));
-    }
-    pub fn env_clear(&mut self) {
-        self.env = Some(HashMap::new())
+    pub fn env_mut(&mut self) -> &mut CommandEnv<WindowsEnvKey> {
+        &mut self.env
     }
     pub fn cwd(&mut self, dir: &OsStr) {
         self.cwd = Some(dir.to_os_string())
@@ -132,13 +141,12 @@
 
     pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
                  -> io::Result<(Process, StdioPipes)> {
+        let maybe_env = self.env.capture_if_changed();
         // To have the spawning semantics of unix/windows stay the same, we need
         // to read the *child's* PATH if one is provided. See #15149 for more
         // details.
-        let program = self.env.as_ref().and_then(|env| {
-            for (key, v) in env {
-                if OsStr::new("PATH") != &**key { continue }
-
+        let program = maybe_env.as_ref().and_then(|env| {
+            if let Some(v) = env.get(OsStr::new("PATH")) {
                 // Split the value and test each path to see if the
                 // program exists.
                 for path in split_paths(&v) {
@@ -148,7 +156,6 @@
                         return Some(path.into_os_string())
                     }
                 }
-                break
             }
             None
         });
@@ -167,7 +174,7 @@
             flags |= c::DETACHED_PROCESS | c::CREATE_NEW_PROCESS_GROUP;
         }
 
-        let (envp, _data) = make_envp(self.env.as_ref())?;
+        let (envp, _data) = make_envp(maybe_env)?;
         let (dirp, _data) = make_dirp(self.cwd.as_ref())?;
         let mut pi = zeroed_process_information();
 
@@ -488,25 +495,24 @@
     }
 }
 
-fn make_envp(env: Option<&collections::HashMap<OsString, OsString>>)
+fn make_envp(maybe_env: Option<BTreeMap<WindowsEnvKey, OsString>>)
              -> io::Result<(*mut c_void, Vec<u16>)> {
     // On Windows we pass an "environment block" which is not a char**, but
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
     // \0 to terminate.
-    match env {
-        Some(env) => {
-            let mut blk = Vec::new();
+    if let Some(env) = maybe_env {
+        let mut blk = Vec::new();
 
-            for pair in env {
-                blk.extend(ensure_no_nuls(pair.0)?.encode_wide());
-                blk.push('=' as u16);
-                blk.extend(ensure_no_nuls(pair.1)?.encode_wide());
-                blk.push(0);
-            }
+        for (k, v) in env {
+            blk.extend(ensure_no_nuls(k.0)?.encode_wide());
+            blk.push('=' as u16);
+            blk.extend(ensure_no_nuls(v)?.encode_wide());
             blk.push(0);
-            Ok((blk.as_mut_ptr() as *mut c_void, blk))
         }
-        _ => Ok((ptr::null_mut(), Vec::new()))
+        blk.push(0);
+        Ok((blk.as_mut_ptr() as *mut c_void, blk))
+    } else {
+        Ok((ptr::null_mut(), Vec::new()))
     }
 }
 
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index b5cf6d7..36cbce2 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -128,7 +128,7 @@
 /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
 #[inline(never)]
 pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
-    where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
+    where F: FnOnce() -> T, F: Send, T: Send
 {
     f()
 }
diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs
index 75c6bd5..6ad3af6 100644
--- a/src/libstd/sys_common/gnu/libbacktrace.rs
+++ b/src/libstd/sys_common/gnu/libbacktrace.rs
@@ -73,7 +73,7 @@
                 "failed to allocate libbacktrace state")
             )
         }
-        let mut data = ptr::null();
+        let mut data: *const libc::c_char = ptr::null();
         let data_addr = &mut data as *mut *const libc::c_char;
         let ret = unsafe {
             backtrace_syminfo(state,
diff --git a/src/libstd/sys_common/memchr.rs b/src/libstd/sys_common/memchr.rs
deleted file mode 100644
index 50f998e..0000000
--- a/src/libstd/sys_common/memchr.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-// Original implementation taken from rust-memchr
-// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
-
-#[allow(dead_code)]
-pub mod fallback {
-    use cmp;
-    use mem;
-
-    const LO_U64: u64 = 0x0101010101010101;
-    const HI_U64: u64 = 0x8080808080808080;
-
-    // use truncation
-    const LO_USIZE: usize = LO_U64 as usize;
-    const HI_USIZE: usize = HI_U64 as usize;
-
-    /// Return `true` if `x` contains any zero byte.
-    ///
-    /// From *Matters Computational*, J. Arndt
-    ///
-    /// "The idea is to subtract one from each of the bytes and then look for
-    /// bytes where the borrow propagated all the way to the most significant
-    /// bit."
-    #[inline]
-    fn contains_zero_byte(x: usize) -> bool {
-        x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
-    }
-
-    #[cfg(target_pointer_width = "32")]
-    #[inline]
-    fn repeat_byte(b: u8) -> usize {
-        let mut rep = (b as usize) << 8 | b as usize;
-        rep = rep << 16 | rep;
-        rep
-    }
-
-    #[cfg(target_pointer_width = "64")]
-    #[inline]
-    fn repeat_byte(b: u8) -> usize {
-        let mut rep = (b as usize) << 8 | b as usize;
-        rep = rep << 16 | rep;
-        rep = rep << 32 | rep;
-        rep
-    }
-
-    /// Return the first index matching the byte `a` in `text`.
-    pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
-        // Scan for a single byte value by reading two `usize` words at a time.
-        //
-        // Split `text` in three parts
-        // - unaligned initial part, before the first word aligned address in text
-        // - body, scan by 2 words at a time
-        // - the last remaining part, < 2 word size
-        let len = text.len();
-        let ptr = text.as_ptr();
-        let usize_bytes = mem::size_of::<usize>();
-
-        // search up to an aligned boundary
-        let mut offset = ptr.align_offset(usize_bytes);
-        if offset > 0 {
-            offset = cmp::min(offset, len);
-            if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
-                return Some(index);
-            }
-        }
-
-        // search the body of the text
-        let repeated_x = repeat_byte(x);
-
-        if len >= 2 * usize_bytes {
-            while offset <= len - 2 * usize_bytes {
-                unsafe {
-                    let u = *(ptr.offset(offset as isize) as *const usize);
-                    let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
-
-                    // break if there is a matching byte
-                    let zu = contains_zero_byte(u ^ repeated_x);
-                    let zv = contains_zero_byte(v ^ repeated_x);
-                    if zu || zv {
-                        break;
-                    }
-                }
-                offset += usize_bytes * 2;
-            }
-        }
-
-        // find the byte after the point the body loop stopped
-        text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
-    }
-
-    /// Return the last index matching the byte `a` in `text`.
-    pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
-        // Scan for a single byte value by reading two `usize` words at a time.
-        //
-        // Split `text` in three parts
-        // - unaligned tail, after the last word aligned address in text
-        // - body, scan by 2 words at a time
-        // - the first remaining bytes, < 2 word size
-        let len = text.len();
-        let ptr = text.as_ptr();
-        let usize_bytes = mem::size_of::<usize>();
-
-        // search to an aligned boundary
-        let end_align = (ptr as usize + len) & (usize_bytes - 1);
-        let mut offset;
-        if end_align > 0 {
-            offset = if end_align >= len { 0 } else { len - end_align };
-            if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
-                return Some(offset + index);
-            }
-        } else {
-            offset = len;
-        }
-
-        // search the body of the text
-        let repeated_x = repeat_byte(x);
-
-        while offset >= 2 * usize_bytes {
-            unsafe {
-                let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
-                let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
-
-                // break if there is a matching byte
-                let zu = contains_zero_byte(u ^ repeated_x);
-                let zv = contains_zero_byte(v ^ repeated_x);
-                if zu || zv {
-                    break;
-                }
-            }
-            offset -= 2 * usize_bytes;
-        }
-
-        // find the byte before the point the body loop stopped
-        text[..offset].iter().rposition(|elt| *elt == x)
-    }
-
-    // test fallback implementations on all platforms
-    #[test]
-    fn matches_one() {
-        assert_eq!(Some(0), memchr(b'a', b"a"));
-    }
-
-    #[test]
-    fn matches_begin() {
-        assert_eq!(Some(0), memchr(b'a', b"aaaa"));
-    }
-
-    #[test]
-    fn matches_end() {
-        assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
-    }
-
-    #[test]
-    fn matches_nul() {
-        assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
-    }
-
-    #[test]
-    fn matches_past_nul() {
-        assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
-    }
-
-    #[test]
-    fn no_match_empty() {
-        assert_eq!(None, memchr(b'a', b""));
-    }
-
-    #[test]
-    fn no_match() {
-        assert_eq!(None, memchr(b'a', b"xyz"));
-    }
-
-    #[test]
-    fn matches_one_reversed() {
-        assert_eq!(Some(0), memrchr(b'a', b"a"));
-    }
-
-    #[test]
-    fn matches_begin_reversed() {
-        assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
-    }
-
-    #[test]
-    fn matches_end_reversed() {
-        assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
-    }
-
-    #[test]
-    fn matches_nul_reversed() {
-        assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
-    }
-
-    #[test]
-    fn matches_past_nul_reversed() {
-        assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
-    }
-
-    #[test]
-    fn no_match_empty_reversed() {
-        assert_eq!(None, memrchr(b'a', b""));
-    }
-
-    #[test]
-    fn no_match_reversed() {
-        assert_eq!(None, memrchr(b'a', b"xyz"));
-    }
-
-    #[test]
-    fn each_alignment_reversed() {
-        let mut data = [1u8; 64];
-        let needle = 2;
-        let pos = 40;
-        data[pos] = needle;
-        for start in 0..16 {
-            assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
-        }
-    }
-}
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 5c4d7b5..27504d3 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -33,7 +33,6 @@
 pub mod backtrace;
 pub mod condvar;
 pub mod io;
-pub mod memchr;
 pub mod mutex;
 pub mod poison;
 pub mod remutex;
@@ -44,9 +43,10 @@
 pub mod util;
 pub mod wtf8;
 pub mod bytestring;
+pub mod process;
 
 cfg_if! {
-    if #[cfg(any(target_os = "redox", target_os = "l4re"))] {
+    if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] {
         pub use sys::net;
     } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
         pub use sys::net;
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index c70b399..b841afe 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -166,27 +166,9 @@
     hints.ai_socktype = c::SOCK_STREAM;
     let mut res = ptr::null_mut();
     unsafe {
-        match cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)) {
-            Ok(_) => {
-                Ok(LookupHost { original: res, cur: res })
-            },
-            #[cfg(unix)]
-            Err(e) => {
-                // If we're running glibc prior to version 2.26, the lookup
-                // failure could be caused by caching a stale /etc/resolv.conf.
-                // We need to call libc::res_init() to clear the cache. But we
-                // shouldn't call it in on any other platform, because other
-                // res_init implementations aren't thread-safe. See
-                // https://github.com/rust-lang/rust/issues/41570 and
-                // https://github.com/rust-lang/rust/issues/43592.
-                use sys::net::res_init_if_glibc_before_2_26;
-                let _ = res_init_if_glibc_before_2_26();
-                Err(e)
-            },
-            // the cfg is needed here to avoid an "unreachable pattern" warning
-            #[cfg(not(unix))]
-            Err(e) => Err(e),
-        }
+        cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| {
+            LookupHost { original: res, cur: res }
+        })
     }
 }
 
diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs
new file mode 100644
index 0000000..fd1a5fd
--- /dev/null
+++ b/src/libstd/sys_common/process.rs
@@ -0,0 +1,124 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+#![unstable(feature = "process_internals", issue = "0")]
+
+use ffi::{OsStr, OsString};
+use env;
+use collections::BTreeMap;
+use alloc::borrow::Borrow;
+
+pub trait EnvKey:
+    From<OsString> + Into<OsString> +
+    Borrow<OsStr> + Borrow<Self> + AsRef<OsStr> +
+    Ord + Clone {}
+
+// Implement a case-sensitive environment variable key
+#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct DefaultEnvKey(OsString);
+
+impl From<OsString> for DefaultEnvKey {
+    fn from(k: OsString) -> Self { DefaultEnvKey(k) }
+}
+
+impl From<DefaultEnvKey> for OsString {
+    fn from(k: DefaultEnvKey) -> Self { k.0 }
+}
+
+impl Borrow<OsStr> for DefaultEnvKey {
+    fn borrow(&self) -> &OsStr { &self.0 }
+}
+
+impl AsRef<OsStr> for DefaultEnvKey {
+    fn as_ref(&self) -> &OsStr { &self.0 }
+}
+
+impl EnvKey for DefaultEnvKey {}
+
+// Stores a set of changes to an environment
+#[derive(Clone, Debug)]
+pub struct CommandEnv<K> {
+    clear: bool,
+    vars: BTreeMap<K, Option<OsString>>
+}
+
+impl<K: EnvKey> Default for CommandEnv<K> {
+    fn default() -> Self {
+        CommandEnv {
+            clear: false,
+            vars: Default::default()
+        }
+    }
+}
+
+impl<K: EnvKey> CommandEnv<K> {
+    // Capture the current environment with these changes applied
+    pub fn capture(&self) -> BTreeMap<K, OsString> {
+        let mut result = BTreeMap::<K, OsString>::new();
+        if !self.clear {
+            for (k, v) in env::vars_os() {
+                result.insert(k.into(), v);
+            }
+        }
+        for (k, maybe_v) in &self.vars {
+            if let &Some(ref v) = maybe_v {
+                result.insert(k.clone(), v.clone());
+            } else {
+                result.remove(k);
+            }
+        }
+        result
+    }
+
+    // Apply these changes directly to the current environment
+    pub fn apply(&self) {
+        if self.clear {
+            for (k, _) in env::vars_os() {
+                env::remove_var(k);
+            }
+        }
+        for (key, maybe_val) in self.vars.iter() {
+            if let &Some(ref val) = maybe_val {
+                env::set_var(key, val);
+            } else {
+                env::remove_var(key);
+            }
+        }
+    }
+
+    pub fn is_unchanged(&self) -> bool {
+        !self.clear && self.vars.is_empty()
+    }
+
+    pub fn capture_if_changed(&self) -> Option<BTreeMap<K, OsString>> {
+        if self.is_unchanged() {
+            None
+        } else {
+            Some(self.capture())
+        }
+    }
+
+    // The following functions build up changes
+    pub fn set(&mut self, key: &OsStr, value: &OsStr) {
+        self.vars.insert(key.to_owned().into(), Some(value.to_owned()));
+    }
+    pub fn remove(&mut self, key: &OsStr) {
+        if self.clear {
+            self.vars.remove(key);
+        } else {
+            self.vars.insert(key.to_owned().into(), None);
+        }
+    }
+    pub fn clear(&mut self) {
+        self.clear = true;
+        self.vars.clear();
+    }
+}
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index b2fc559..46d554d 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -134,6 +134,12 @@
     }
 }
 
+impl ops::DerefMut for Wtf8Buf {
+    fn deref_mut(&mut self) -> &mut Wtf8 {
+        self.as_mut_slice()
+    }
+}
+
 /// Format the string with double quotes,
 /// and surrogates as `\u` followed by four hexadecimal digits.
 /// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
@@ -221,6 +227,11 @@
         unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
     }
 
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut Wtf8 {
+        unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) }
+    }
+
     /// Reserves capacity for at least `additional` more bytes to be inserted
     /// in the given `Wtf8Buf`.
     /// The collection may reserve more space to avoid frequent reallocations.
@@ -486,6 +497,15 @@
         mem::transmute(value)
     }
 
+    /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice.
+    ///
+    /// Since the byte slice is not checked for valid WTF-8, this functions is
+    /// marked unsafe.
+    #[inline]
+    unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 {
+        mem::transmute(value)
+    }
+
     /// Returns the length, in WTF-8 bytes.
     #[inline]
     pub fn len(&self) -> usize {
diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
new file mode 100644
index 0000000..93a913b
--- /dev/null
+++ b/src/libstd/termination.rs
@@ -0,0 +1,86 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use error::Error;
+#[cfg(target_arch = "wasm32")]
+mod exit {
+    pub const SUCCESS: i32 = 0;
+    pub const FAILURE: i32 = 1;
+}
+#[cfg(not(target_arch = "wasm32"))]
+mod exit {
+    use libc;
+    pub const SUCCESS: i32 = libc::EXIT_SUCCESS;
+    pub const FAILURE: i32 = libc::EXIT_FAILURE;
+}
+
+/// A trait for implementing arbitrary return types in the `main` function.
+///
+/// The c-main function only supports to return integers as return type.
+/// So, every type implementing the `Termination` trait has to be converted
+/// to an integer.
+///
+/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
+/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
+#[cfg_attr(not(test), lang = "termination")]
+#[unstable(feature = "termination_trait", issue = "43301")]
+#[rustc_on_unimplemented =
+  "`main` can only return types that implement {Termination}, not `{Self}`"]
+pub trait Termination {
+    /// Is called to get the representation of the value as status code.
+    /// This status code is returned to the operating system.
+    fn report(self) -> i32;
+}
+
+#[unstable(feature = "termination_trait", issue = "43301")]
+impl Termination for () {
+    fn report(self) -> i32 { exit::SUCCESS }
+}
+
+#[unstable(feature = "termination_trait", issue = "43301")]
+impl<T: Termination, E: Error> Termination for Result<T, E> {
+    fn report(self) -> i32 {
+        match self {
+            Ok(val) => val.report(),
+            Err(err) => {
+                print_error(err);
+                exit::FAILURE
+            }
+        }
+    }
+}
+
+#[unstable(feature = "termination_trait", issue = "43301")]
+fn print_error<E: Error>(err: E) {
+    eprintln!("Error: {}", err.description());
+
+    if let Some(ref err) = err.cause() {
+        eprintln!("Caused by: {}", err.description());
+    }
+}
+
+#[unstable(feature = "termination_trait", issue = "43301")]
+impl Termination for ! {
+    fn report(self) -> i32 { unreachable!(); }
+}
+
+#[unstable(feature = "termination_trait", issue = "43301")]
+impl Termination for bool {
+    fn report(self) -> i32 {
+        if self { exit::SUCCESS } else { exit::FAILURE }
+    }
+}
+
+#[unstable(feature = "termination_trait", issue = "43301")]
+impl Termination for i32 {
+    fn report(self) -> i32 {
+        self
+    }
+}
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index 15ddb62..cb5bfb9 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -206,7 +206,7 @@
     ///
     /// let duration = Duration::from_millis(5432);
     /// assert_eq!(duration.as_secs(), 5);
-    /// assert_eq!(duration.subsec_nanos(), 432_000_000);
+    /// assert_eq!(duration.subsec_millis(), 432);
     /// ```
     #[unstable(feature = "duration_extras", issue = "46507")]
     #[inline]
@@ -226,7 +226,7 @@
     ///
     /// let duration = Duration::from_micros(1_234_567);
     /// assert_eq!(duration.as_secs(), 1);
-    /// assert_eq!(duration.subsec_nanos(), 234_567_000);
+    /// assert_eq!(duration.subsec_micros(), 234_567);
     /// ```
     #[unstable(feature = "duration_extras", issue = "46507")]
     #[inline]
diff --git a/src/libstd_unicode/bool_trie.rs b/src/libstd_unicode/bool_trie.rs
new file mode 100644
index 0000000..3e45b08
--- /dev/null
+++ b/src/libstd_unicode/bool_trie.rs
@@ -0,0 +1,76 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// BoolTrie is a trie for representing a set of Unicode codepoints. It is
+/// implemented with postfix compression (sharing of identical child nodes),
+/// which gives both compact size and fast lookup.
+///
+/// The space of Unicode codepoints is divided into 3 subareas, each
+/// represented by a trie with different depth. In the first (0..0x800), there
+/// is no trie structure at all; each u64 entry corresponds to a bitvector
+/// effectively holding 64 bool values.
+///
+/// In the second (0x800..0x10000), each child of the root node represents a
+/// 64-wide subrange, but instead of storing the full 64-bit value of the leaf,
+/// the trie stores an 8-bit index into a shared table of leaf values. This
+/// exploits the fact that in reasonable sets, many such leaves can be shared.
+///
+/// In the third (0x10000..0x110000), each child of the root node represents a
+/// 4096-wide subrange, and the trie stores an 8-bit index into a 64-byte slice
+/// of a child tree. Each of these 64 bytes represents an index into the table
+/// of shared 64-bit leaf values. This exploits the sparse structure in the
+/// non-BMP range of most Unicode sets.
+pub struct BoolTrie {
+    // 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences)
+    pub r1: [u64; 32],   // leaves
+
+    // 0x800..0x10000 (corresponding to 3 byte utf-8 sequences)
+    pub r2: [u8; 992],      // first level
+    pub r3: &'static [u64],  // leaves
+
+    // 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences)
+    pub r4: [u8; 256],       // first level
+    pub r5: &'static [u8],   // second level
+    pub r6: &'static [u64],  // leaves
+}
+impl BoolTrie {
+    pub fn lookup(&self, c: char) -> bool {
+        let c = c as usize;
+        if c < 0x800 {
+            trie_range_leaf(c, self.r1[c >> 6])
+        } else if c < 0x10000 {
+            let child = self.r2[(c >> 6) - 0x20];
+            trie_range_leaf(c, self.r3[child as usize])
+        } else {
+            let child = self.r4[(c >> 12) - 0x10];
+            let leaf = self.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)];
+            trie_range_leaf(c, self.r6[leaf as usize])
+        }
+    }
+}
+
+pub struct SmallBoolTrie {
+    pub(crate) r1: &'static [u8],  // first level
+    pub(crate) r2: &'static [u64],  // leaves
+}
+
+impl SmallBoolTrie {
+    pub fn lookup(&self, c: char) -> bool {
+        let c = c as usize;
+        match self.r1.get(c >> 6) {
+            Some(&child) => trie_range_leaf(c, self.r2[child as usize]),
+            None => false,
+        }
+    }
+}
+
+fn trie_range_leaf(c: usize, bitmap_chunk: u64) -> bool {
+    ((bitmap_chunk >> (c & 63)) & 1) != 0
+}
diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs
index f9ad6f9..b4be4a9 100644
--- a/src/libstd_unicode/char.rs
+++ b/src/libstd_unicode/char.rs
@@ -33,7 +33,7 @@
 use core::fmt::{self, Write};
 use tables::{conversions, derived_property, general_category, property};
 
-// stable reexports
+// stable re-exports
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -41,13 +41,15 @@
 #[stable(feature = "char_from_str", since = "1.20.0")]
 pub use core::char::ParseCharError;
 
-// unstable reexports
+// unstable re-exports
 #[unstable(feature = "try_from", issue = "33417")]
 pub use core::char::CharTryFromError;
 #[unstable(feature = "decode_utf8", issue = "33906")]
 pub use core::char::{DecodeUtf8, decode_utf8};
 #[unstable(feature = "unicode", issue = "27783")]
-pub use tables::{UnicodeVersion, UNICODE_VERSION};
+pub use tables::{UNICODE_VERSION};
+#[unstable(feature = "unicode", issue = "27783")]
+pub use version::UnicodeVersion;
 
 /// Returns an iterator that yields the lowercase equivalent of a `char`.
 ///
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
index 22f8bda..dcae7d0 100644
--- a/src/libstd_unicode/lib.rs
+++ b/src/libstd_unicode/lib.rs
@@ -35,15 +35,18 @@
 #![feature(core_char_ext)]
 #![feature(str_internals)]
 #![feature(decode_utf8)]
-#![feature(fused)]
 #![feature(fn_traits)]
+#![feature(fused)]
 #![feature(lang_items)]
+#![feature(non_exhaustive)]
 #![feature(staged_api)]
 #![feature(try_from)]
 #![feature(unboxed_closures)]
 
+mod bool_trie;
 mod tables;
 mod u_str;
+mod version;
 pub mod char;
 pub mod lossy;
 
diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs
index 1e8a0be..b53953b 100644
--- a/src/libstd_unicode/tables.rs
+++ b/src/libstd_unicode/tables.rs
@@ -12,23 +12,8 @@
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
-/// Represents a Unicode Version.
-///
-/// See also: <http://www.unicode.org/versions/>
-#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
-pub struct UnicodeVersion {
-    /// Major version.
-    pub major: u32,
-
-    /// Minor version.
-    pub minor: u32,
-
-    /// Micro (or Update) version.
-    pub micro: u32,
-
-    // Private field to keep struct expandable.
-    _priv: (),
-}
+use version::UnicodeVersion;
+use bool_trie::{BoolTrie, SmallBoolTrie};
 
 /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
 /// `CharExt` and `UnicodeStrPrelude` traits are based on.
@@ -38,76 +23,8 @@
     micro: 0,
     _priv: (),
 };
-
-
-// BoolTrie is a trie for representing a set of Unicode codepoints. It is
-// implemented with postfix compression (sharing of identical child nodes),
-// which gives both compact size and fast lookup.
-//
-// The space of Unicode codepoints is divided into 3 subareas, each
-// represented by a trie with different depth. In the first (0..0x800), there
-// is no trie structure at all; each u64 entry corresponds to a bitvector
-// effectively holding 64 bool values.
-//
-// In the second (0x800..0x10000), each child of the root node represents a
-// 64-wide subrange, but instead of storing the full 64-bit value of the leaf,
-// the trie stores an 8-bit index into a shared table of leaf values. This
-// exploits the fact that in reasonable sets, many such leaves can be shared.
-//
-// In the third (0x10000..0x110000), each child of the root node represents a
-// 4096-wide subrange, and the trie stores an 8-bit index into a 64-byte slice
-// of a child tree. Each of these 64 bytes represents an index into the table
-// of shared 64-bit leaf values. This exploits the sparse structure in the
-// non-BMP range of most Unicode sets.
-pub struct BoolTrie {
-    // 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences)
-    r1: [u64; 32],   // leaves
-
-    // 0x800..0x10000 (corresponding to 3 byte utf-8 sequences)
-    r2: [u8; 992],      // first level
-    r3: &'static [u64],  // leaves
-
-    // 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences)
-    r4: [u8; 256],       // first level
-    r5: &'static [u8],   // second level
-    r6: &'static [u64],  // leaves
-}
-
-fn trie_range_leaf(c: usize, bitmap_chunk: u64) -> bool {
-    ((bitmap_chunk >> (c & 63)) & 1) != 0
-}
-
-fn trie_lookup_range_table(c: char, r: &'static BoolTrie) -> bool {
-    let c = c as usize;
-    if c < 0x800 {
-        trie_range_leaf(c, r.r1[c >> 6])
-    } else if c < 0x10000 {
-        let child = r.r2[(c >> 6) - 0x20];
-        trie_range_leaf(c, r.r3[child as usize])
-    } else {
-        let child = r.r4[(c >> 12) - 0x10];
-        let leaf = r.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)];
-        trie_range_leaf(c, r.r6[leaf as usize])
-    }
-}
-
-pub struct SmallBoolTrie {
-    r1: &'static [u8],  // first level
-    r2: &'static [u64],  // leaves
-}
-
-impl SmallBoolTrie {
-    fn lookup(&self, c: char) -> bool {
-        let c = c as usize;
-        match self.r1.get(c >> 6) {
-            Some(&child) => trie_range_leaf(c, self.r2[child as usize]),
-            None => false,
-        }
-    }
-}
-
 pub mod general_category {
-    pub const Cc_table: &'static super::SmallBoolTrie = &super::SmallBoolTrie {
+    pub const Cc_table: &super::SmallBoolTrie = &super::SmallBoolTrie {
         r1: &[
             0, 1, 0
         ],
@@ -120,7 +37,7 @@
         Cc_table.lookup(c)
     }
 
-    pub const N_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const N_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x03ff000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
@@ -212,13 +129,13 @@
     };
 
     pub fn N(c: char) -> bool {
-        super::trie_lookup_range_table(c, N_table)
+        N_table.lookup(c)
     }
 
 }
 
 pub mod derived_property {
-    pub const Alphabetic_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const Alphabetic_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff,
             0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
@@ -397,10 +314,10 @@
     };
 
     pub fn Alphabetic(c: char) -> bool {
-        super::trie_lookup_range_table(c, Alphabetic_table)
+        Alphabetic_table.lookup(c)
     }
 
-    pub const Case_Ignorable_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const Case_Ignorable_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x0400408000000000, 0x0000000140000000, 0x0190a10000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
@@ -529,10 +446,10 @@
     };
 
     pub fn Case_Ignorable(c: char) -> bool {
-        super::trie_lookup_range_table(c, Case_Ignorable_table)
+        Case_Ignorable_table.lookup(c)
     }
 
-    pub const Cased_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const Cased_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff,
             0xffffffffffffffff, 0xffffffffffffffff, 0xf7ffffffffffffff, 0xfffffffffffffff0,
@@ -628,10 +545,10 @@
     };
 
     pub fn Cased(c: char) -> bool {
-        super::trie_lookup_range_table(c, Cased_table)
+        Cased_table.lookup(c)
     }
 
-    pub const Lowercase_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const Lowercase_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x0000000000000000, 0x07fffffe00000000, 0x0420040000000000, 0xff7fffff80000000,
             0x55aaaaaaaaaaaaaa, 0xd4aaaaaaaaaaab55, 0xe6512d2a4e243129, 0xaa29aaaab5555240,
@@ -725,10 +642,10 @@
     };
 
     pub fn Lowercase(c: char) -> bool {
-        super::trie_lookup_range_table(c, Lowercase_table)
+        Lowercase_table.lookup(c)
     }
 
-    pub const Uppercase_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const Uppercase_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x0000000000000000, 0x0000000007fffffe, 0x0000000000000000, 0x000000007f7fffff,
             0xaa55555555555555, 0x2b555555555554aa, 0x11aed2d5b1dbced6, 0x55d255554aaaa490,
@@ -823,10 +740,10 @@
     };
 
     pub fn Uppercase(c: char) -> bool {
-        super::trie_lookup_range_table(c, Uppercase_table)
+        Uppercase_table.lookup(c)
     }
 
-    pub const XID_Continue_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const XID_Continue_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x03ff000000000000, 0x07fffffe87fffffe, 0x04a0040000000000, 0xff7fffffff7fffff,
             0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
@@ -998,10 +915,10 @@
     };
 
     pub fn XID_Continue(c: char) -> bool {
-        super::trie_lookup_range_table(c, XID_Continue_table)
+        XID_Continue_table.lookup(c)
     }
 
-    pub const XID_Start_table: &'static super::BoolTrie = &super::BoolTrie {
+    pub const XID_Start_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
             0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff,
             0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
@@ -1175,13 +1092,13 @@
     };
 
     pub fn XID_Start(c: char) -> bool {
-        super::trie_lookup_range_table(c, XID_Start_table)
+        XID_Start_table.lookup(c)
     }
 
 }
 
 pub mod property {
-    pub const Pattern_White_Space_table: &'static super::SmallBoolTrie = &super::SmallBoolTrie {
+    pub const Pattern_White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie {
         r1: &[
             0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -1198,7 +1115,7 @@
         Pattern_White_Space_table.lookup(c)
     }
 
-    pub const White_Space_table: &'static super::SmallBoolTrie = &super::SmallBoolTrie {
+    pub const White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie {
         r1: &[
             0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -1238,11 +1155,11 @@
         }
     }
 
-    fn bsearch_case_table(c: char, table: &'static [(char, [char; 3])]) -> Option<usize> {
+    fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
         table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
     }
 
-    const to_lowercase_table: &'static [(char, [char; 3])] = &[
+    const to_lowercase_table: &[(char, [char; 3])] = &[
         ('\u{41}', ['\u{61}', '\0', '\0']), ('\u{42}', ['\u{62}', '\0', '\0']), ('\u{43}',
         ['\u{63}', '\0', '\0']), ('\u{44}', ['\u{64}', '\0', '\0']), ('\u{45}', ['\u{65}', '\0',
         '\0']), ('\u{46}', ['\u{66}', '\0', '\0']), ('\u{47}', ['\u{67}', '\0', '\0']), ('\u{48}',
@@ -1826,7 +1743,7 @@
         ('\u{1e920}', ['\u{1e942}', '\0', '\0']), ('\u{1e921}', ['\u{1e943}', '\0', '\0'])
     ];
 
-    const to_uppercase_table: &'static [(char, [char; 3])] = &[
+    const to_uppercase_table: &[(char, [char; 3])] = &[
         ('\u{61}', ['\u{41}', '\0', '\0']), ('\u{62}', ['\u{42}', '\0', '\0']), ('\u{63}',
         ['\u{43}', '\0', '\0']), ('\u{64}', ['\u{44}', '\0', '\0']), ('\u{65}', ['\u{45}', '\0',
         '\0']), ('\u{66}', ['\u{46}', '\0', '\0']), ('\u{67}', ['\u{47}', '\0', '\0']), ('\u{68}',
diff --git a/src/libstd_unicode/unicode.py b/src/libstd_unicode/unicode.py
index df79760..a862949 100755
--- a/src/libstd_unicode/unicode.py
+++ b/src/libstd_unicode/unicode.py
@@ -38,6 +38,9 @@
 // NOTE: The following code was generated by "./unicode.py", do not edit directly
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
+
+use version::UnicodeVersion;
+use bool_trie::{BoolTrie, SmallBoolTrie};
 '''
 
 # Mapping taken from Table 12 from:
@@ -274,24 +277,7 @@
 def escape_char(c):
     return "'\\u{%x}'" % c if c != 0 else "'\\0'"
 
-def emit_bsearch_range_table(f):
-    f.write("""
-fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
-    use core::cmp::Ordering::{Equal, Less, Greater};
-    r.binary_search_by(|&(lo, hi)| {
-         if c < lo {
-             Greater
-         } else if hi < c {
-             Less
-         } else {
-             Equal
-         }
-     })
-     .is_ok()
-}\n
-""")
-
-def emit_table(f, name, t_data, t_type = "&'static [(char, char)]", is_pub=True,
+def emit_table(f, name, t_data, t_type = "&[(char, char)]", is_pub=True,
         pfun=lambda x: "(%s,%s)" % (escape_char(x[0]), escape_char(x[1]))):
     pub_string = ""
     if is_pub:
@@ -307,77 +293,6 @@
     format_table_content(f, data, 8)
     f.write("\n    ];\n\n")
 
-def emit_trie_lookup_range_table(f):
-    f.write("""
-
-// BoolTrie is a trie for representing a set of Unicode codepoints. It is
-// implemented with postfix compression (sharing of identical child nodes),
-// which gives both compact size and fast lookup.
-//
-// The space of Unicode codepoints is divided into 3 subareas, each
-// represented by a trie with different depth. In the first (0..0x800), there
-// is no trie structure at all; each u64 entry corresponds to a bitvector
-// effectively holding 64 bool values.
-//
-// In the second (0x800..0x10000), each child of the root node represents a
-// 64-wide subrange, but instead of storing the full 64-bit value of the leaf,
-// the trie stores an 8-bit index into a shared table of leaf values. This
-// exploits the fact that in reasonable sets, many such leaves can be shared.
-//
-// In the third (0x10000..0x110000), each child of the root node represents a
-// 4096-wide subrange, and the trie stores an 8-bit index into a 64-byte slice
-// of a child tree. Each of these 64 bytes represents an index into the table
-// of shared 64-bit leaf values. This exploits the sparse structure in the
-// non-BMP range of most Unicode sets.
-pub struct BoolTrie {
-    // 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences)
-    r1: [u64; 32],   // leaves
-
-    // 0x800..0x10000 (corresponding to 3 byte utf-8 sequences)
-    r2: [u8; 992],      // first level
-    r3: &'static [u64],  // leaves
-
-    // 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences)
-    r4: [u8; 256],       // first level
-    r5: &'static [u8],   // second level
-    r6: &'static [u64],  // leaves
-}
-
-fn trie_range_leaf(c: usize, bitmap_chunk: u64) -> bool {
-    ((bitmap_chunk >> (c & 63)) & 1) != 0
-}
-
-fn trie_lookup_range_table(c: char, r: &'static BoolTrie) -> bool {
-    let c = c as usize;
-    if c < 0x800 {
-        trie_range_leaf(c, r.r1[c >> 6])
-    } else if c < 0x10000 {
-        let child = r.r2[(c >> 6) - 0x20];
-        trie_range_leaf(c, r.r3[child as usize])
-    } else {
-        let child = r.r4[(c >> 12) - 0x10];
-        let leaf = r.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)];
-        trie_range_leaf(c, r.r6[leaf as usize])
-    }
-}
-
-pub struct SmallBoolTrie {
-    r1: &'static [u8],  // first level
-    r2: &'static [u64],  // leaves
-}
-
-impl SmallBoolTrie {
-    fn lookup(&self, c: char) -> bool {
-        let c = c as usize;
-        match self.r1.get(c >> 6) {
-            Some(&child) => trie_range_leaf(c, self.r2[child as usize]),
-            None => false,
-        }
-    }
-}
-
-""")
-
 def compute_trie(rawdata, chunksize):
     root = []
     childmap = {}
@@ -410,7 +325,7 @@
     pub_string = ""
     if is_pub:
         pub_string = "pub "
-    f.write("    %sconst %s: &'static super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name))
+    f.write("    %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name))
     f.write("        r1: [\n")
     data = ','.join('0x%016x' % chunk for chunk in chunks[0:0x800 // CHUNK])
     format_table_content(f, data, 12)
@@ -458,7 +373,7 @@
     pub_string = ""
     if is_pub:
         pub_string = "pub "
-    f.write("    %sconst %s: &'static super::SmallBoolTrie = &super::SmallBoolTrie {\n"
+    f.write("    %sconst %s: &super::SmallBoolTrie = &super::SmallBoolTrie {\n"
             % (pub_string, name))
 
     (r1, r2) = compute_trie(chunks, 1)
@@ -486,7 +401,7 @@
         else:
             emit_bool_trie(f, "%s_table" % cat, tbl[cat])
             f.write("    pub fn %s(c: char) -> bool {\n" % cat)
-            f.write("        super::trie_lookup_range_table(c, %s_table)\n" % cat)
+            f.write("        %s_table.lookup(c)\n" % cat)
             f.write("    }\n\n")
     f.write("}\n\n")
 
@@ -510,12 +425,12 @@
         }
     }
 
-    fn bsearch_case_table(c: char, table: &'static [(char, [char; 3])]) -> Option<usize> {
+    fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
         table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
     }
 
 """)
-    t_type = "&'static [(char, [char; 3])]"
+    t_type = "&[(char, [char; 3])]"
     pfun = lambda x: "(%s,[%s,%s,%s])" % (
         escape_char(x[0]), escape_char(x[1][0]), escape_char(x[1][1]), escape_char(x[1][2]))
     emit_table(f, "to_lowercase_table",
@@ -557,24 +472,6 @@
             pattern = "for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
             unicode_version = re.search(pattern, readme.read()).groups()
         rf.write("""
-/// Represents a Unicode Version.
-///
-/// See also: <http://www.unicode.org/versions/>
-#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
-pub struct UnicodeVersion {
-    /// Major version.
-    pub major: u32,
-
-    /// Minor version.
-    pub minor: u32,
-
-    /// Micro (or Update) version.
-    pub micro: u32,
-
-    // Private field to keep struct expandable.
-    _priv: (),
-}
-
 /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
 /// `CharExt` and `UnicodeStrPrelude` traits are based on.
 pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {
@@ -596,10 +493,6 @@
         norm_props = load_properties("DerivedNormalizationProps.txt",
                      ["Full_Composition_Exclusion"])
 
-        # trie_lookup_table is used in all the property modules below
-        emit_trie_lookup_range_table(rf)
-        # emit_bsearch_range_table(rf)
-
         # category tables
         for (name, cat, pfuns) in ("general_category", gencats, ["N", "Cc"]), \
                                   ("derived_property", derived, want_derived), \
diff --git a/src/libstd_unicode/version.rs b/src/libstd_unicode/version.rs
new file mode 100644
index 0000000..d82a749
--- /dev/null
+++ b/src/libstd_unicode/version.rs
@@ -0,0 +1,27 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Represents a Unicode Version.
+///
+/// See also: <http://www.unicode.org/versions/>
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub struct UnicodeVersion {
+    /// Major version.
+    pub major: u32,
+
+    /// Minor version.
+    pub minor: u32,
+
+    /// Micro (or Update) version.
+    pub micro: u32,
+
+    // Private field to keep struct expandable.
+    pub(crate) _priv: (),
+}
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index fb1f300..07631e0 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -11,7 +11,7 @@
 [dependencies]
 bitflags = "1.0"
 serialize = { path = "../libserialize" }
-log = "0.3"
+log = "0.4"
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e0f14c0..d6e2605 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -15,6 +15,7 @@
 pub use self::PathParameters::*;
 pub use symbol::{Ident, Symbol as Name};
 pub use util::ThinVec;
+pub use util::parser::ExprPrecedence;
 
 use syntax_pos::{Span, DUMMY_SP};
 use codemap::{respan, Spanned};
@@ -730,6 +731,7 @@
             _ => false
         }
     }
+
     pub fn is_comparison(&self) -> bool {
         use self::BinOpKind::*;
         match *self {
@@ -740,6 +742,7 @@
             false,
         }
     }
+
     /// Returns `true` if the binary operator takes its arguments by value
     pub fn is_by_value(&self) -> bool {
         !self.is_comparison()
@@ -966,6 +969,49 @@
 
         Some(P(Ty { node, id: self.id, span: self.span }))
     }
+
+    pub fn precedence(&self) -> ExprPrecedence {
+        match self.node {
+            ExprKind::Box(_) => ExprPrecedence::Box,
+            ExprKind::InPlace(..) => ExprPrecedence::InPlace,
+            ExprKind::Array(_) => ExprPrecedence::Array,
+            ExprKind::Call(..) => ExprPrecedence::Call,
+            ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
+            ExprKind::Tup(_) => ExprPrecedence::Tup,
+            ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node),
+            ExprKind::Unary(..) => ExprPrecedence::Unary,
+            ExprKind::Lit(_) => ExprPrecedence::Lit,
+            ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
+            ExprKind::If(..) => ExprPrecedence::If,
+            ExprKind::IfLet(..) => ExprPrecedence::IfLet,
+            ExprKind::While(..) => ExprPrecedence::While,
+            ExprKind::WhileLet(..) => ExprPrecedence::WhileLet,
+            ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
+            ExprKind::Loop(..) => ExprPrecedence::Loop,
+            ExprKind::Match(..) => ExprPrecedence::Match,
+            ExprKind::Closure(..) => ExprPrecedence::Closure,
+            ExprKind::Block(..) => ExprPrecedence::Block,
+            ExprKind::Catch(..) => ExprPrecedence::Catch,
+            ExprKind::Assign(..) => ExprPrecedence::Assign,
+            ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
+            ExprKind::Field(..) => ExprPrecedence::Field,
+            ExprKind::TupField(..) => ExprPrecedence::TupField,
+            ExprKind::Index(..) => ExprPrecedence::Index,
+            ExprKind::Range(..) => ExprPrecedence::Range,
+            ExprKind::Path(..) => ExprPrecedence::Path,
+            ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
+            ExprKind::Break(..) => ExprPrecedence::Break,
+            ExprKind::Continue(..) => ExprPrecedence::Continue,
+            ExprKind::Ret(..) => ExprPrecedence::Ret,
+            ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprKind::Mac(..) => ExprPrecedence::Mac,
+            ExprKind::Struct(..) => ExprPrecedence::Struct,
+            ExprKind::Repeat(..) => ExprPrecedence::Repeat,
+            ExprKind::Paren(..) => ExprPrecedence::Paren,
+            ExprKind::Try(..) => ExprPrecedence::Try,
+            ExprKind::Yield(..) => ExprPrecedence::Yield,
+        }
+    }
 }
 
 impl fmt::Debug for Expr {
@@ -1054,7 +1100,7 @@
     /// A closure (for example, `move |a, b, c| a + b + c`)
     ///
     /// The final span is the span of the argument block `|...|`
-    Closure(CaptureBy, P<FnDecl>, P<Expr>, Span),
+    Closure(CaptureBy, Movability, P<FnDecl>, P<Expr>, Span),
     /// A block (`{ ... }`)
     Block(P<Block>),
     /// A catch block (`catch { ... }`)
@@ -1148,6 +1194,13 @@
     Ref,
 }
 
+/// The movability of a generator / closure literal
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum Movability {
+    Static,
+    Movable,
+}
+
 pub type Mac = Spanned<Mac_>;
 
 /// Represents a macro invocation. The Path indicates which macro
@@ -1324,7 +1377,7 @@
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy,
          PartialOrd, Ord)]
 pub enum IntTy {
-    Is,
+    Isize,
     I8,
     I16,
     I32,
@@ -1347,7 +1400,7 @@
 impl IntTy {
     pub fn ty_to_string(&self) -> &'static str {
         match *self {
-            IntTy::Is => "isize",
+            IntTy::Isize => "isize",
             IntTy::I8 => "i8",
             IntTy::I16 => "i16",
             IntTy::I32 => "i32",
@@ -1365,7 +1418,7 @@
 
     pub fn bit_width(&self) -> Option<usize> {
         Some(match *self {
-            IntTy::Is => return None,
+            IntTy::Isize => return None,
             IntTy::I8 => 8,
             IntTy::I16 => 16,
             IntTy::I32 => 32,
@@ -1378,7 +1431,7 @@
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy,
          PartialOrd, Ord)]
 pub enum UintTy {
-    Us,
+    Usize,
     U8,
     U16,
     U32,
@@ -1389,7 +1442,7 @@
 impl UintTy {
     pub fn ty_to_string(&self) -> &'static str {
         match *self {
-            UintTy::Us => "usize",
+            UintTy::Usize => "usize",
             UintTy::U8 => "u8",
             UintTy::U16 => "u16",
             UintTy::U32 => "u32",
@@ -1404,7 +1457,7 @@
 
     pub fn bit_width(&self) -> Option<usize> {
         Some(match *self {
-            UintTy::Us => return None,
+            UintTy::Usize => return None,
             UintTy::U8 => 8,
             UintTy::U16 => 16,
             UintTy::U32 => 32,
@@ -1543,7 +1596,7 @@
 
 /// Inline assembly dialect.
 ///
-/// E.g. `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")``
+/// E.g. `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum AsmDialect {
     Att,
@@ -1552,7 +1605,7 @@
 
 /// Inline assembly.
 ///
-/// E.g. `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")``
+/// E.g. `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct InlineAsmOutput {
     pub constraint: Symbol,
@@ -2022,10 +2075,6 @@
     ///
     /// E.g. `trait Foo = Bar + Quux;`
     TraitAlias(Generics, TyParamBounds),
-    /// Auto trait implementation.
-    ///
-    /// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
-    AutoImpl(Unsafety, TraitRef),
     /// An implementation.
     ///
     /// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
@@ -2064,8 +2113,7 @@
             ItemKind::TraitAlias(..) => "trait alias",
             ItemKind::Mac(..) |
             ItemKind::MacroDef(..) |
-            ItemKind::Impl(..) |
-            ItemKind::AutoImpl(..) => "item"
+            ItemKind::Impl(..) => "item"
         }
     }
 }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index cc72ff7..d18d6f5 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -992,7 +992,8 @@
 /// Valid repr contents: any of the primitive integral type names (see
 /// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
 /// the same discriminant size that the corresponding C enum would or C
-/// structure layout, and `packed` to remove padding.
+/// structure layout, `packed` to remove padding, and `transparent` to elegate representation
+/// concerns to the only non-ZST field.
 pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> {
     let mut acc = Vec::new();
     if attr.path == "repr" {
@@ -1008,10 +1009,10 @@
                 if let Some(mi) = item.word() {
                     let word = &*mi.name().as_str();
                     let hint = match word {
-                        // Can't use "extern" because it's not a lexical identifier.
-                        "C" => Some(ReprExtern),
+                        "C" => Some(ReprC),
                         "packed" => Some(ReprPacked),
                         "simd" => Some(ReprSimd),
+                        "transparent" => Some(ReprTransparent),
                         _ => match int_type_of_word(word) {
                             Some(ity) => Some(ReprInt(ity)),
                             None => {
@@ -1071,8 +1072,8 @@
         "u64" => Some(UnsignedInt(ast::UintTy::U64)),
         "i128" => Some(SignedInt(ast::IntTy::I128)),
         "u128" => Some(UnsignedInt(ast::UintTy::U128)),
-        "isize" => Some(SignedInt(ast::IntTy::Is)),
-        "usize" => Some(UnsignedInt(ast::UintTy::Us)),
+        "isize" => Some(SignedInt(ast::IntTy::Isize)),
+        "usize" => Some(UnsignedInt(ast::UintTy::Usize)),
         _ => None
     }
 }
@@ -1080,9 +1081,10 @@
 #[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
 pub enum ReprAttr {
     ReprInt(IntType),
-    ReprExtern,
+    ReprC,
     ReprPacked,
     ReprSimd,
+    ReprTransparent,
     ReprAlign(u32),
 }
 
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index e49a711..a58a61c3 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -131,6 +131,9 @@
     // -Zremap-path-prefix to all FileMaps allocated within this CodeMap.
     path_mapping: FilePathMapping,
     stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Rc<FileMap>>>,
+    /// In case we are in a doctest, replace all file names with the PathBuf,
+    /// and add the given offsets to the line info
+    doctest_offset: Option<(FileName, isize)>,
 }
 
 impl CodeMap {
@@ -140,9 +143,19 @@
             file_loader: Box::new(RealFileLoader),
             path_mapping,
             stable_id_to_filemap: RefCell::new(FxHashMap()),
+            doctest_offset: None,
         }
     }
 
+    pub fn new_doctest(path_mapping: FilePathMapping,
+                       file: FileName, line: isize) -> CodeMap {
+        CodeMap {
+            doctest_offset: Some((file, line)),
+            ..CodeMap::new(path_mapping)
+        }
+
+    }
+
     pub fn with_file_loader(file_loader: Box<FileLoader>,
                             path_mapping: FilePathMapping)
                             -> CodeMap {
@@ -151,6 +164,7 @@
             file_loader,
             path_mapping,
             stable_id_to_filemap: RefCell::new(FxHashMap()),
+            doctest_offset: None,
         }
     }
 
@@ -164,7 +178,12 @@
 
     pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
         let src = self.file_loader.read_file(path)?;
-        Ok(self.new_filemap(path.to_owned().into(), src))
+        let filename = if let Some((ref name, _)) = self.doctest_offset {
+            name.clone()
+        } else {
+            path.to_owned().into()
+        };
+        Ok(self.new_filemap(filename, src))
     }
 
     pub fn files(&self) -> Ref<Vec<Rc<FileMap>>> {
@@ -303,6 +322,18 @@
                  pos.col.to_usize() + 1)).to_string()
     }
 
+    // If there is a doctest_offset, apply it to the line
+    pub fn doctest_offset_line(&self, mut orig: usize) -> usize {
+        if let Some((_, line)) = self.doctest_offset {
+            if line >= 0 {
+                orig = orig + line as usize;
+            } else {
+                orig = orig - (-line) as usize;
+            }
+        }
+        orig
+    }
+
     /// Lookup source information about a BytePos
     pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
         let chpos = self.bytepos_to_file_charpos(pos);
@@ -391,6 +422,7 @@
     /// Returns `Some(span)`, a union of the lhs and rhs span.  The lhs must precede the rhs. If
     /// there are gaps between lhs and rhs, the resulting union will cross these gaps.
     /// For this to work, the spans have to be:
+    ///
     ///    * the ctxt of both spans much match
     ///    * the lhs span needs to end on the same line the rhs span begins
     ///    * the lhs span must start at or before the rhs span
@@ -446,6 +478,12 @@
             .expect("CodeMap::span_to_unmapped_path called for imported FileMap?")
     }
 
+    pub fn is_multiline(&self, sp: Span) -> bool {
+        let lo = self.lookup_char_pos(sp.lo());
+        let hi = self.lookup_char_pos(sp.hi());
+        lo.line != hi.line
+    }
+
     pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
         debug!("span_to_lines(sp={:?})", sp);
 
@@ -674,6 +712,9 @@
             }
         )
     }
+    fn doctest_offset_line(&self, line: usize) -> usize {
+        self.doctest_offset_line(line)
+    }
 }
 
 #[derive(Clone)]
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index c3cf474..d841281 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -317,6 +317,31 @@
 ```
 "##,
 
+E0658: r##"
+An unstable feature was used.
+
+Erroneous code example:
+
+```compile_fail,E658
+let x = ::std::u128::MAX; // error: use of unstable library feature 'i128'
+```
+
+If you're using a stable or a beta version of rustc, you won't be able to use
+any unstable features. In order to do so, please switch to a nightly version of
+rustc (by using rustup).
+
+If you're using a nightly version of rustc, just add the corresponding feature
+to be able to use it:
+
+```
+#![feature(i128)]
+
+fn main() {
+    let x = ::std::u128::MAX; // ok!
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
index c01836b..61f3e70 100644
--- a/src/libsyntax/diagnostics/macros.rs
+++ b/src/libsyntax/diagnostics/macros.rs
@@ -106,6 +106,14 @@
 }
 
 #[macro_export]
+macro_rules! stringify_error_code {
+    ($code:ident) => ({
+        __diagnostic_used!($code);
+        $crate::errors::DiagnosticId::Error(stringify!($code).to_owned())
+    })
+}
+
+#[macro_export]
 macro_rules! type_error_struct {
     ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
         if $typ.references_error() {
diff --git a/src/libsyntax/diagnostics/metadata.rs b/src/libsyntax/diagnostics/metadata.rs
index 5f06475..dc01a79 100644
--- a/src/libsyntax/diagnostics/metadata.rs
+++ b/src/libsyntax/diagnostics/metadata.rs
@@ -14,9 +14,10 @@
 //! currently always a crate name.
 
 use std::collections::BTreeMap;
-use std::path::PathBuf;
+use std::env;
 use std::fs::{remove_file, create_dir_all, File};
 use std::io::Write;
+use std::path::PathBuf;
 use std::error::Error;
 use rustc_serialize::json::as_json;
 
@@ -24,9 +25,6 @@
 use ext::base::ExtCtxt;
 use diagnostics::plugin::{ErrorMap, ErrorInfo};
 
-// Default metadata directory to use for extended error JSON.
-const ERROR_METADATA_PREFIX: &'static str = "tmp/extended-errors";
-
 /// JSON encodable/decodable version of `ErrorInfo`.
 #[derive(PartialEq, RustcDecodable, RustcEncodable)]
 pub struct ErrorMetadata {
@@ -59,7 +57,10 @@
 ///
 /// See `output_metadata`.
 pub fn get_metadata_dir(prefix: &str) -> PathBuf {
-    PathBuf::from(ERROR_METADATA_PREFIX).join(prefix)
+    env::var_os("RUSTC_ERROR_METADATA_DST")
+        .map(PathBuf::from)
+        .expect("env var `RUSTC_ERROR_METADATA_DST` isn't set")
+        .join(prefix)
 }
 
 /// Map `name` to a path in the given directory: <directory>/<name>.json
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index d53335f..612d850 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -13,7 +13,7 @@
 use ast::{self, Attribute, Name, PatKind, MetaItem};
 use attr::HasAttrs;
 use codemap::{self, CodeMap, Spanned, respan};
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{Span, MultiSpan, DUMMY_SP};
 use errors::DiagnosticBuilder;
 use ext::expand::{self, Expansion, Invocation};
 use ext::hygiene::{Mark, SyntaxContext};
@@ -96,6 +96,18 @@
             _ => panic!("expected Item")
         }
     }
+
+    pub fn derive_allowed(&self) -> bool {
+        match *self {
+            Annotatable::Item(ref item) => match item.node {
+                ast::ItemKind::Struct(..) |
+                ast::ItemKind::Enum(..) |
+                ast::ItemKind::Union(..) => true,
+                _ => false,
+            },
+            _ => false,
+        }
+    }
 }
 
 // A more flexible ItemDecorator.
@@ -742,29 +754,30 @@
         last_macro
     }
 
-    pub fn struct_span_warn(&self,
-                            sp: Span,
-                            msg: &str)
-                            -> DiagnosticBuilder<'a> {
+    pub fn struct_span_warn<S: Into<MultiSpan>>(&self,
+                                                sp: S,
+                                                msg: &str)
+                                                -> DiagnosticBuilder<'a> {
         self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
     }
-    pub fn struct_span_err(&self,
-                           sp: Span,
-                           msg: &str)
-                           -> DiagnosticBuilder<'a> {
+    pub fn struct_span_err<S: Into<MultiSpan>>(&self,
+                                               sp: S,
+                                               msg: &str)
+                                               -> DiagnosticBuilder<'a> {
         self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
     }
-    pub fn struct_span_fatal(&self,
-                             sp: Span,
-                             msg: &str)
-                             -> DiagnosticBuilder<'a> {
+    pub fn struct_span_fatal<S: Into<MultiSpan>>(&self,
+                                                 sp: S,
+                                                 msg: &str)
+                                                 -> DiagnosticBuilder<'a> {
         self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
     }
 
     /// Emit `msg` attached to `sp`, and stop compilation immediately.
     ///
     /// `span_err` should be strongly preferred where-ever possible:
-    /// this should *only* be used when
+    /// this should *only* be used when:
+    ///
     /// - continuing has a high risk of flow-on errors (e.g. errors in
     ///   declaring a macro would cause all uses of that macro to
     ///   complain about "undefined macro"), or
@@ -772,7 +785,7 @@
     ///   in most cases one can construct a dummy expression/item to
     ///   substitute; we never hit resolve/type-checking so the dummy
     ///   value doesn't have to match anything)
-    pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
+    pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         panic!(self.parse_sess.span_diagnostic.span_fatal(sp, msg));
     }
 
@@ -781,20 +794,20 @@
     ///
     /// Compilation will be stopped in the near future (at the end of
     /// the macro expansion phase).
-    pub fn span_err(&self, sp: Span, msg: &str) {
+    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.parse_sess.span_diagnostic.span_err(sp, msg);
     }
-    pub fn mut_span_err(&self, sp: Span, msg: &str)
+    pub fn mut_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str)
                         -> DiagnosticBuilder<'a> {
         self.parse_sess.span_diagnostic.mut_span_err(sp, msg)
     }
-    pub fn span_warn(&self, sp: Span, msg: &str) {
+    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
-    pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
+    pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
     }
-    pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
+    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         self.parse_sess.span_diagnostic.span_bug(sp, msg);
     }
     pub fn trace_macros_diag(&mut self) {
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 34e5610..cf63592 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -17,7 +17,7 @@
 use ptr::P;
 use symbol::{Symbol, keywords};
 
-// Transitional reexports so qquote can find the paths it is looking for
+// Transitional re-exports so qquote can find the paths it is looking for
 mod syntax {
     pub use ext;
     pub use parse;
@@ -694,17 +694,17 @@
     }
     fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
         self.expr_lit(span, ast::LitKind::Int(i as u128,
-                                              ast::LitIntType::Unsigned(ast::UintTy::Us)))
+                                              ast::LitIntType::Unsigned(ast::UintTy::Usize)))
     }
     fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr> {
         if i < 0 {
             let i = (-i) as u128;
-            let lit_ty = ast::LitIntType::Signed(ast::IntTy::Is);
+            let lit_ty = ast::LitIntType::Signed(ast::IntTy::Isize);
             let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty));
             self.expr_unary(sp, ast::UnOp::Neg, lit)
         } else {
             self.expr_lit(sp, ast::LitKind::Int(i as u128,
-                                                ast::LitIntType::Signed(ast::IntTy::Is)))
+                                                ast::LitIntType::Signed(ast::IntTy::Isize)))
         }
     }
     fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
@@ -912,6 +912,7 @@
                       fn_decl_span: Span) // span of the `|...|` part
                       -> P<ast::Expr> {
         self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
+                                               ast::Movability::Movable,
                                                fn_decl,
                                                body,
                                                fn_decl_span))
@@ -930,7 +931,11 @@
         // part of the lambda, but it probably (maybe?) corresponds to
         // the entire lambda body. Probably we should extend the API
         // here, but that's not entirely clear.
-        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, body, span))
+        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
+                                               ast::Movability::Movable,
+                                               fn_decl,
+                                               body,
+                                               span))
     }
 
     fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 81baa0c..11988a8 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -136,8 +136,8 @@
 }
 
 impl ExpansionKind {
-    fn dummy(self, span: Span) -> Expansion {
-        self.make_from(DummyResult::any(span)).unwrap()
+    fn dummy(self, span: Span) -> Option<Expansion> {
+        self.make_from(DummyResult::any(span))
     }
 
     fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
@@ -304,21 +304,12 @@
             // FIXME(jseyfried): Refactor out the following logic
             let (expansion, new_invocations) = if let Some(ext) = ext {
                 if let Some(ext) = ext {
-                    let expansion = self.expand_invoc(invoc, ext);
+                    let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap();
+                    let expansion = self.expand_invoc(invoc, ext).unwrap_or(dummy);
                     self.collect_invocations(expansion, &[])
                 } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
-                    let derive_allowed = match item {
-                        Annotatable::Item(ref item) => match item.node {
-                            ast::ItemKind::Struct(..) |
-                            ast::ItemKind::Enum(..) |
-                            ast::ItemKind::Union(..) => true,
-                            _ => false,
-                        },
-                        _ => false,
-                    };
-                    if !derive_allowed {
-                        let attr = item.attrs().iter()
-                            .find(|attr| attr.check_name("derive"))
+                    if !item.derive_allowed() {
+                        let attr = attr::find_by_name(item.attrs(), "derive")
                             .expect("`derive` attribute should exist");
                         let span = attr.span;
                         let mut err = self.cx.mut_span_err(span,
@@ -366,7 +357,7 @@
                     unreachable!()
                 }
             } else {
-                self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()), &[])
+                self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()).unwrap(), &[])
             };
 
             if expansions.len() < depth {
@@ -446,11 +437,11 @@
         }
     }
 
-    fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
+    fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Option<Expansion> {
         let result = match invoc.kind {
-            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
-            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext),
-            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext),
+            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
+            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
+            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?,
         };
 
         if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
@@ -467,13 +458,16 @@
             panic!(FatalError);
         }
 
-        result
+        Some(result)
     }
 
-    fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
+    fn expand_attr_invoc(&mut self,
+                         invoc: Invocation,
+                         ext: Rc<SyntaxExtension>)
+                         -> Option<Expansion> {
         let Invocation { expansion_kind: kind, .. } = invoc;
         let (attr, item) = match invoc.kind {
-            InvocationKind::Attr { attr, item, .. } => (attr.unwrap(), item),
+            InvocationKind::Attr { attr, item, .. } => (attr?, item),
             _ => unreachable!(),
         };
 
@@ -490,16 +484,16 @@
 
         match *ext {
             MultiModifier(ref mac) => {
-                let meta = panictry!(attr.parse_meta(self.cx.parse_sess));
+                let meta = attr.parse_meta(self.cx.parse_sess).ok()?;
                 let item = mac.expand(self.cx, attr.span, &meta, item);
-                kind.expect_from_annotatables(item)
+                Some(kind.expect_from_annotatables(item))
             }
             MultiDecorator(ref mac) => {
                 let mut items = Vec::new();
-                let meta = panictry!(attr.parse_meta(self.cx.parse_sess));
+                let meta = attr.parse_meta(self.cx.parse_sess).ok()?;
                 mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
                 items.push(item);
-                kind.expect_from_annotatables(items)
+                Some(kind.expect_from_annotatables(items))
             }
             AttrProcMacro(ref mac) => {
                 let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
@@ -525,7 +519,10 @@
     }
 
     /// Expand a macro invocation. Returns the result of expansion.
-    fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
+    fn expand_bang_invoc(&mut self,
+                         invoc: Invocation,
+                         ext: Rc<SyntaxExtension>)
+                         -> Option<Expansion> {
         let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
         let (mac, ident, span) = match invoc.kind {
             InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
@@ -558,9 +555,10 @@
                                                              false, false) {
                     self.cx.span_err(path.span, &msg);
                     self.cx.trace_macros_diag();
-                    return kind.dummy(span);
+                    kind.dummy(span)
+                } else {
+                    kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
                 }
-                kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
             }
 
             NormalTT {
@@ -574,9 +572,10 @@
                                                              allow_internal_unsafe) {
                     self.cx.span_err(path.span, &msg);
                     self.cx.trace_macros_diag();
-                    return kind.dummy(span);
+                    kind.dummy(span)
+                } else {
+                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
                 }
-                kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
             }
 
             IdentTT(ref expander, tt_span, allow_internal_unstable) => {
@@ -584,34 +583,34 @@
                     self.cx.span_err(path.span,
                                     &format!("macro {}! expects an ident argument", path));
                     self.cx.trace_macros_diag();
-                    return kind.dummy(span);
-                };
+                    kind.dummy(span)
+                } else {
+                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
+                        call_site: span,
+                        callee: NameAndSpan {
+                            format: macro_bang_format(path),
+                            span: tt_span,
+                            allow_internal_unstable,
+                            allow_internal_unsafe: false,
+                        }
+                    });
 
-                invoc.expansion_data.mark.set_expn_info(ExpnInfo {
-                    call_site: span,
-                    callee: NameAndSpan {
-                        format: macro_bang_format(path),
-                        span: tt_span,
-                        allow_internal_unstable,
-                        allow_internal_unsafe: false,
-                    }
-                });
-
-                let input: Vec<_> = mac.node.stream().into_trees().collect();
-                kind.make_from(expander.expand(self.cx, span, ident, input))
+                    let input: Vec<_> = mac.node.stream().into_trees().collect();
+                    kind.make_from(expander.expand(self.cx, span, ident, input))
+                }
             }
 
             MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
                 self.cx.span_err(path.span,
                                  &format!("`{}` can only be used in attributes", path));
                 self.cx.trace_macros_diag();
-                return kind.dummy(span);
+                kind.dummy(span)
             }
 
             ProcMacroDerive(..) | BuiltinDerive(..) => {
                 self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
                 self.cx.trace_macros_diag();
-                return kind.dummy(span);
+                kind.dummy(span)
             }
 
             ProcMacro(ref expandfun) => {
@@ -620,43 +619,51 @@
                         format!("macro {}! expects no ident argument, given '{}'", path, ident);
                     self.cx.span_err(path.span, &msg);
                     self.cx.trace_macros_diag();
-                    return kind.dummy(span);
+                    kind.dummy(span)
+                } else {
+                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
+                        call_site: span,
+                        callee: NameAndSpan {
+                            format: macro_bang_format(path),
+                            // FIXME procedural macros do not have proper span info
+                            // yet, when they do, we should use it here.
+                            span: None,
+                            // FIXME probably want to follow macro_rules macros here.
+                            allow_internal_unstable: false,
+                            allow_internal_unsafe: false,
+                        },
+                    });
+
+                    let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
+                    self.parse_expansion(tok_result, kind, path, span)
                 }
-
-                invoc.expansion_data.mark.set_expn_info(ExpnInfo {
-                    call_site: span,
-                    callee: NameAndSpan {
-                        format: macro_bang_format(path),
-                        // FIXME procedural macros do not have proper span info
-                        // yet, when they do, we should use it here.
-                        span: None,
-                        // FIXME probably want to follow macro_rules macros here.
-                        allow_internal_unstable: false,
-                        allow_internal_unsafe: false,
-                    },
-                });
-
-                let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
-                Some(self.parse_expansion(tok_result, kind, path, span))
             }
         };
 
-        unwrap_or!(opt_expanded, {
+        if opt_expanded.is_some() {
+            opt_expanded
+        } else {
             let msg = format!("non-{kind} macro in {kind} position: {name}",
                               name = path.segments[0].identifier.name, kind = kind.name());
             self.cx.span_err(path.span, &msg);
             self.cx.trace_macros_diag();
             kind.dummy(span)
-        })
+        }
     }
 
     /// Expand a derive invocation. Returns the result of expansion.
-    fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
+    fn expand_derive_invoc(&mut self,
+                           invoc: Invocation,
+                           ext: Rc<SyntaxExtension>)
+                           -> Option<Expansion> {
         let Invocation { expansion_kind: kind, .. } = invoc;
         let (path, item) = match invoc.kind {
             InvocationKind::Derive { path, item } => (path, item),
             _ => unreachable!(),
         };
+        if !item.derive_allowed() {
+            return None;
+        }
 
         let pretty_name = Symbol::intern(&format!("derive({})", path));
         let span = path.span;
@@ -686,15 +693,15 @@
                     span: DUMMY_SP,
                     node: ast::MetaItemKind::Word,
                 };
-                kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item))
+                Some(kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item)))
             }
             BuiltinDerive(func) => {
                 expn_info.callee.allow_internal_unstable = true;
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = span.with_ctxt(self.cx.backtrace());
                 let mut items = Vec::new();
-                func(self.cx, span, &attr.meta().unwrap(), &item, &mut |a| items.push(a));
-                kind.expect_from_annotatables(items)
+                func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
+                Some(kind.expect_from_annotatables(items))
             }
             _ => {
                 let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
@@ -705,19 +712,24 @@
         }
     }
 
-    fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, path: &Path, span: Span)
-                       -> Expansion {
+    fn parse_expansion(&mut self,
+                       toks: TokenStream,
+                       kind: ExpansionKind,
+                       path: &Path,
+                       span: Span)
+                       -> Option<Expansion> {
         let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
-        let expansion = match parser.parse_expansion(kind, false) {
-            Ok(expansion) => expansion,
+        match parser.parse_expansion(kind, false) {
+            Ok(expansion) => {
+                parser.ensure_complete_parse(path, kind.name(), span);
+                Some(expansion)
+            }
             Err(mut err) => {
                 err.emit();
                 self.cx.trace_macros_diag();
-                return kind.dummy(span);
+                kind.dummy(span)
             }
-        };
-        parser.ensure_complete_parse(path, kind.name(), span);
-        expansion
+        }
     }
 }
 
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 426dde4..7fcd88c 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -190,6 +190,12 @@
         }
     }
 
+    impl ToTokens for ast::Lifetime {
+        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
+            vec![TokenTree::Token(DUMMY_SP, token::Lifetime(self.ident))]
+        }
+    }
+
     macro_rules! impl_to_tokens_slice {
         ($t: ty, $sep: expr) => {
             impl ToTokens for [$t] {
@@ -320,13 +326,13 @@
         );
     }
 
-    impl_to_tokens_int! { signed, isize, ast::IntTy::Is }
+    impl_to_tokens_int! { signed, isize, ast::IntTy::Isize }
     impl_to_tokens_int! { signed, i8,  ast::IntTy::I8 }
     impl_to_tokens_int! { signed, i16, ast::IntTy::I16 }
     impl_to_tokens_int! { signed, i32, ast::IntTy::I32 }
     impl_to_tokens_int! { signed, i64, ast::IntTy::I64 }
 
-    impl_to_tokens_int! { unsigned, usize, ast::UintTy::Us }
+    impl_to_tokens_int! { unsigned, usize, ast::UintTy::Usize }
     impl_to_tokens_int! { unsigned, u8,   ast::UintTy::U8 }
     impl_to_tokens_int! { unsigned, u16,  ast::UintTy::U16 }
     impl_to_tokens_int! { unsigned, u32,  ast::UintTy::U32 }
@@ -669,7 +675,11 @@
                                 vec![mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident))]);
         }
 
-        token::Interpolated(_) => panic!("quote! with interpolated token"),
+        token::Interpolated(_) => {
+            cx.span_err(sp, "quote! with interpolated token");
+            // Use dummy name.
+            "Interpolated"
+        }
 
         token::Eq           => "Eq",
         token::Lt           => "Lt",
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 4da485f..6b08448 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -49,7 +49,7 @@
     let topmost = cx.expansion_cause().unwrap_or(sp);
     let loc = cx.codemap().lookup_char_pos(topmost.lo());
 
-    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32))
+    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))
 }
 
 /* __rust_unstable_column!(): expands to the current column number */
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 2167b64..1244776 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -603,6 +603,7 @@
         "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
+        "lifetime" => token::NtLifetime(p.expect_lifetime()),
         // this is not supposed to happen, since it has been checked
         // when compiling the macro.
         _ => p.span_bug(sp, "invalid fragment specifier")
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 5e58f00..d86603e 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -768,10 +768,11 @@
 /// ANYTHING without fear of future compatibility hazards).
 fn frag_can_be_followed_by_any(frag: &str) -> bool {
     match frag {
-        "item"  | // always terminated by `}` or `;`
-        "block" | // exactly one token tree
-        "ident" | // exactly one token tree
-        "meta"  | // exactly one token tree
+        "item"     | // always terminated by `}` or `;`
+        "block"    | // exactly one token tree
+        "ident"    | // exactly one token tree
+        "meta"     | // exactly one token tree
+        "lifetime" | // exactly one token tree
         "tt" =>   // exactly one token tree
             true,
 
@@ -832,8 +833,8 @@
                 TokenTree::MetaVarDecl(_, _, frag) if frag.name == "block" => Ok(true),
                 _ => Ok(false),
             },
-            "ident" => {
-                // being a single token, idents are harmless
+            "ident" | "lifetime" => {
+                // being a single token, idents and lifetimes are harmless
                 Ok(true)
             },
             "meta" | "tt" => {
@@ -887,9 +888,21 @@
     match frag_name {
         "item" | "block" | "stmt" | "expr" | "pat" |
         "path" | "ty" | "ident" | "meta" | "tt" | "" => true,
+        "lifetime" => {
+            if !features.borrow().macro_lifetime_matcher &&
+               !attr::contains_name(attrs, "allow_internal_unstable") {
+                let explain = feature_gate::EXPLAIN_LIFETIME_MATCHER;
+                emit_feature_err(sess,
+                                 "macro_lifetime_matcher",
+                                 frag_span,
+                                 GateIssue::Language,
+                                 explain);
+            }
+            true
+        },
         "vis" => {
-            if     !features.borrow().macro_vis_matcher
-                && !attr::contains_name(attrs, "allow_internal_unstable") {
+            if !features.borrow().macro_vis_matcher &&
+               !attr::contains_name(attrs, "allow_internal_unstable") {
                 let explain = feature_gate::EXPLAIN_VIS_MATCHER;
                 emit_feature_err(sess,
                                  "macro_vis_matcher",
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 2d47382..ac5a10e 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -63,9 +63,9 @@
 
         /// A set of features to be used by later passes.
         pub struct Features {
-            /// #![feature] attrs for stable language features, for error reporting
+            /// `#![feature]` attrs for stable language features, for error reporting
             pub declared_stable_lang_features: Vec<(Symbol, Span)>,
-            /// #![feature] attrs for non-language (library) features
+            /// `#![feature]` attrs for non-language (library) features
             pub declared_lib_features: Vec<(Symbol, Span)>,
             $(pub $feature: bool),+
         }
@@ -131,7 +131,6 @@
     (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
     (active, linkage, "1.0.0", Some(29603)),
     (active, quote, "1.0.0", Some(29601)),
-    (active, simd, "1.0.0", Some(27731)),
 
 
     // rustc internal
@@ -156,7 +155,7 @@
     // OIBIT specific features
     (active, optin_builtin_traits, "1.0.0", Some(13231)),
 
-    // macro reexport needs more discussion and stabilization
+    // macro re-export needs more discussion and stabilization
     (active, macro_reexport, "1.0.0", Some(29638)),
 
     // Allows use of #[staged_api]
@@ -441,6 +440,21 @@
 
     // `foo.rs` as an alternative to `foo/mod.rs`
     (active, non_modrs_mods, "1.24.0", Some(44660)),
+
+    // Nested `impl Trait`
+    (active, nested_impl_trait, "1.24.0", Some(34511)),
+
+    // Termination trait in main (RFC 1937)
+    (active, termination_trait, "1.24.0", Some(43301)),
+
+    // Allows use of the :lifetime macro fragment specifier
+    (active, macro_lifetime_matcher, "1.24.0", Some(46895)),
+
+    // `extern` in paths
+    (active, extern_in_paths, "1.23.0", Some(44660)),
+
+    // Allows `#[repr(transparent)]` attribute on newtype structs
+    (active, repr_transparent, "1.25.0", Some(43036)),
 );
 
 declare_features! (
@@ -461,6 +475,8 @@
     (removed, unmarked_api, "1.0.0", None),
     (removed, pushpop_unsafe, "1.2.0", None),
     (removed, allocator, "1.0.0", None),
+    // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]`
+    (removed, simd, "1.0.0", Some(27731)),
 );
 
 declare_features! (
@@ -624,7 +640,6 @@
     ("start", Normal, Ungated),
     ("test", Normal, Ungated),
     ("bench", Normal, Ungated),
-    ("simd", Normal, Ungated),
     ("repr", Normal, Ungated),
     ("path", Normal, Ungated),
     ("abi", Normal, Ungated),
@@ -957,6 +972,13 @@
                                       never be stable",
                                      cfg_fn!(rustc_attrs))),
 
+    // whitelists "identity-like" conversion methods to suggest on type mismatch
+    ("rustc_conversion_suggestion", Whitelisted, Gated(Stability::Unstable,
+                                                       "rustc_attrs",
+                                                       "this is an internal attribute that will \
+                                                        never be stable",
+                                                       cfg_fn!(rustc_attrs))),
+
     ("wasm_import_memory", Whitelisted, Gated(Stability::Unstable,
                                  "wasm_import_memory",
                                  "wasm_import_memory attribute is currently unstable",
@@ -1160,7 +1182,9 @@
     };
 
     let mut err = match level {
-        GateStrength::Hard => diag.struct_span_err(span, &explanation),
+        GateStrength::Hard => {
+            diag.struct_span_err_with_code(span, &explanation, stringify_error_code!(E0658))
+        }
         GateStrength::Soft => diag.struct_span_warn(span, &explanation),
     };
 
@@ -1220,6 +1244,9 @@
 pub const EXPLAIN_VIS_MATCHER: &'static str =
     ":vis fragment specifier is experimental and subject to change";
 
+pub const EXPLAIN_LIFETIME_MATCHER: &'static str =
+    ":lifetime fragment specifier is experimental and subject to change";
+
 pub const EXPLAIN_PLACEMENT_IN: &'static str =
     "placement-in expression syntax is experimental and subject to change.";
 
@@ -1314,8 +1341,73 @@
     }
 }
 
+// Bans nested `impl Trait`, e.g. `impl Into<impl Debug>`.
+// Nested `impl Trait` _is_ allowed in associated type position,
+// e.g `impl Iterator<Item=impl Debug>`
+struct NestedImplTraitVisitor<'a> {
+    context: &'a Context<'a>,
+    is_in_impl_trait: bool,
+}
+
+impl<'a> NestedImplTraitVisitor<'a> {
+    fn with_impl_trait<F>(&mut self, is_in_impl_trait: bool, f: F)
+        where F: FnOnce(&mut NestedImplTraitVisitor<'a>)
+    {
+        let old_is_in_impl_trait = self.is_in_impl_trait;
+        self.is_in_impl_trait = is_in_impl_trait;
+        f(self);
+        self.is_in_impl_trait = old_is_in_impl_trait;
+    }
+}
+
+
+impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
+    fn visit_ty(&mut self, t: &'a ast::Ty) {
+        if let ast::TyKind::ImplTrait(_) = t.node {
+            if self.is_in_impl_trait {
+                gate_feature_post!(&self, nested_impl_trait, t.span,
+                    "nested `impl Trait` is experimental"
+                );
+            }
+            self.with_impl_trait(true, |this| visit::walk_ty(this, t));
+        } else {
+            visit::walk_ty(self, t);
+        }
+    }
+    fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a ast::PathParameters) {
+        match *path_parameters {
+            ast::PathParameters::AngleBracketed(ref params) => {
+                for type_ in &params.types {
+                    self.visit_ty(type_);
+                }
+                for type_binding in &params.bindings {
+                    // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
+                    // are allowed to contain nested `impl Trait`.
+                    self.with_impl_trait(false, |this| visit::walk_ty(this, &type_binding.ty));
+                }
+            }
+            ast::PathParameters::Parenthesized(ref params) => {
+                for type_ in &params.inputs {
+                    self.visit_ty(type_);
+                }
+                if let Some(ref type_) = params.output {
+                    // `-> Foo` syntax is essentially an associated type binding,
+                    // so it is also allowed to contain nested `impl Trait`.
+                    self.with_impl_trait(false, |this| visit::walk_ty(this, type_));
+                }
+            }
+        }
+    }
+}
+
 impl<'a> PostExpansionVisitor<'a> {
-    fn whole_crate_feature_gates(&mut self) {
+    fn whole_crate_feature_gates(&mut self, krate: &ast::Crate) {
+        visit::walk_crate(
+            &mut NestedImplTraitVisitor {
+                context: self.context,
+                is_in_impl_trait: false,
+            }, krate);
+
         for &(ident, span) in &*self.context.parse_sess.non_modrs_mods.borrow() {
             if !span.allows_unstable() {
                 let cx = &self.context;
@@ -1378,7 +1470,9 @@
 
     fn visit_name(&mut self, sp: Span, name: ast::Name) {
         if !name.as_str().is_ascii() {
-            gate_feature_post!(&self, non_ascii_idents, sp,
+            gate_feature_post!(&self,
+                               non_ascii_idents,
+                               self.context.parse_sess.codemap().def_span(sp),
                                "non-ascii idents are not fully supported.");
         }
     }
@@ -1388,7 +1482,7 @@
             ast::ItemKind::ExternCrate(_) => {
                 if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
                     gate_feature_post!(&self, macro_reexport, attr.span,
-                                       "macros reexports are experimental \
+                                       "macros re-exports are experimental \
                                         and possibly buggy");
                 }
             }
@@ -1422,14 +1516,6 @@
             }
 
             ast::ItemKind::Struct(..) => {
-                if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
-                    gate_feature_post!(&self, simd, attr.span,
-                                       "SIMD types are experimental and possibly buggy");
-                    self.context.parse_sess.span_diagnostic.span_warn(attr.span,
-                                                                      "the `#[simd]` attribute \
-                                                                       is deprecated, use \
-                                                                       `#[repr(simd)]` instead");
-                }
                 if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
                     for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
                         if item.check_name("simd") {
@@ -1441,6 +1527,11 @@
                                                "the struct `#[repr(align(u16))]` attribute \
                                                 is experimental");
                         }
+                        if item.check_name("transparent") {
+                            gate_feature_post!(&self, repr_transparent, attr.span,
+                                               "the `#[repr(transparent)]` attribute \
+                                               is experimental");
+                        }
                     }
                 }
             }
@@ -1451,13 +1542,6 @@
                                    "trait aliases are not yet fully implemented");
             }
 
-            ast::ItemKind::AutoImpl(..) => {
-                gate_feature_post!(&self, optin_builtin_traits,
-                                   i.span,
-                                   "auto trait implementations are experimental \
-                                    and possibly buggy");
-            }
-
             ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(&self, optin_builtin_traits,
@@ -1711,6 +1795,9 @@
             if segment.identifier.name == keywords::Crate.name() {
                 gate_feature_post!(&self, crate_in_paths, segment.span,
                                    "`crate` in paths is experimental");
+            } else if segment.identifier.name == keywords::Extern.name() {
+                gate_feature_post!(&self, extern_in_paths, segment.span,
+                                   "`extern` in paths is experimental");
             }
         }
 
@@ -1889,7 +1976,7 @@
         plugin_attributes,
     };
     let visitor = &mut PostExpansionVisitor { context: &ctx };
-    visitor.whole_crate_feature_gates();
+    visitor.whole_crate_feature_gates(krate);
     visit::walk_crate(visitor, krate);
 }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 9916b74..1e605ba 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -642,6 +642,7 @@
             token::NtWhereClause(fld.fold_where_clause(where_clause)),
         token::NtArg(arg) => token::NtArg(fld.fold_arg(arg)),
         token::NtVis(vis) => token::NtVis(fld.fold_vis(vis)),
+        token::NtLifetime(lifetime) => token::NtLifetime(fld.fold_lifetime(lifetime)),
     }
 }
 
@@ -910,9 +911,6 @@
             let generics = folder.fold_generics(generics);
             ItemKind::Union(folder.fold_variant_data(struct_def), generics)
         }
-        ItemKind::AutoImpl(unsafety, ref trait_ref) => {
-            ItemKind::AutoImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
-        }
         ItemKind::Impl(unsafety,
                        polarity,
                        defaultness,
@@ -1237,8 +1235,9 @@
                 ExprKind::Match(folder.fold_expr(expr),
                           arms.move_map(|x| folder.fold_arm(x)))
             }
-            ExprKind::Closure(capture_clause, decl, body, span) => {
+            ExprKind::Closure(capture_clause, movability, decl, body, span) => {
                 ExprKind::Closure(capture_clause,
+                                  movability,
                                   folder.fold_fn_decl(decl),
                                   folder.fold_expr(body),
                                   folder.new_span(span))
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 0b51f2e..d7f7ff5 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -151,4 +151,5 @@
 #[cfg(test)]
 mod test_snippet;
 
+#[cfg(not(stage0))] // remove after the next snapshot
 __build_diagnostic_array! { libsyntax, DIAGNOSTICS }
diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs
index 23449ee..49362f0 100644
--- a/src/libsyntax/parse/lexer/comments.rs
+++ b/src/libsyntax/parse/lexer/comments.rs
@@ -101,7 +101,7 @@
                     break;
                 }
             }
-            if i > line.len() {
+            if i >= line.len() {
                 can_trim = false;
             }
             if !can_trim {
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index a38ceba..a9b1e4a 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -603,13 +603,13 @@
             err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some"));
         }
         ty = match &*suf.as_str() {
-            "isize" => ast::LitIntType::Signed(ast::IntTy::Is),
+            "isize" => ast::LitIntType::Signed(ast::IntTy::Isize),
             "i8"  => ast::LitIntType::Signed(ast::IntTy::I8),
             "i16" => ast::LitIntType::Signed(ast::IntTy::I16),
             "i32" => ast::LitIntType::Signed(ast::IntTy::I32),
             "i64" => ast::LitIntType::Signed(ast::IntTy::I64),
             "i128" => ast::LitIntType::Signed(ast::IntTy::I128),
-            "usize" => ast::LitIntType::Unsigned(ast::UintTy::Us),
+            "usize" => ast::LitIntType::Unsigned(ast::UintTy::Usize),
             "u8"  => ast::LitIntType::Unsigned(ast::UintTy::U8),
             "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
             "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a4aad81..8213d60 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -14,7 +14,7 @@
 use ast::Unsafety;
 use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
 use ast::Block;
-use ast::{BlockCheckMode, CaptureBy};
+use ast::{BlockCheckMode, CaptureBy, Movability};
 use ast::{Constness, Crate};
 use ast::Defaultness;
 use ast::EnumDef;
@@ -42,7 +42,7 @@
 use ast::{RangeEnd, RangeSyntax};
 use {ast, attr};
 use codemap::{self, CodeMap, Spanned, respan};
-use syntax_pos::{self, Span, BytePos, FileName, DUMMY_SP};
+use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, DUMMY_SP};
 use errors::{self, DiagnosticBuilder};
 use parse::{self, classify, token};
 use parse::common::SeqSep;
@@ -71,7 +71,7 @@
     }
 }
 
-type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
+type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
 
 /// How to parse a path.
 #[derive(Copy, Clone, PartialEq)]
@@ -151,10 +151,9 @@
     };
 }
 
-fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
-                -> Vec<Attribute> {
-    if let Some(ref attrs) = rhs {
-        lhs.extend(attrs.iter().cloned())
+fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> {
+    if let Some(ref mut rhs) = rhs {
+        lhs.append(rhs);
     }
     lhs
 }
@@ -448,7 +447,9 @@
 }
 
 impl Error {
-    pub fn span_err(self, sp: Span, handler: &errors::Handler) -> DiagnosticBuilder {
+    pub fn span_err<S: Into<MultiSpan>>(self,
+                                        sp: S,
+                                        handler: &errors::Handler) -> DiagnosticBuilder {
         match self {
             Error::FileNotFoundForModule { ref mod_name,
                                            ref default_path,
@@ -609,14 +610,21 @@
         Parser::token_to_string(&self.token)
     }
 
+    pub fn token_descr(&self) -> Option<&'static str> {
+        Some(match &self.token {
+            t if t.is_special_ident() => "reserved identifier",
+            t if t.is_used_keyword() => "keyword",
+            t if t.is_unused_keyword() => "reserved keyword",
+            _ => return None,
+        })
+    }
+
     pub fn this_token_descr(&self) -> String {
-        let prefix = match &self.token {
-            t if t.is_special_ident() => "reserved identifier ",
-            t if t.is_used_keyword() => "keyword ",
-            t if t.is_unused_keyword() => "reserved keyword ",
-            _ => "",
-        };
-        format!("{}`{}`", prefix, self.this_token_to_string())
+        if let Some(prefix) = self.token_descr() {
+            format!("{} `{}`", prefix, self.this_token_to_string())
+        } else {
+            format!("`{}`", self.this_token_to_string())
+        }
     }
 
     pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
@@ -752,11 +760,27 @@
     }
 
     pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
+        self.parse_ident_common(true)
+    }
+
+    fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
         match self.token {
             token::Ident(i) => {
                 if self.token.is_reserved_ident() {
-                    self.span_err(self.span, &format!("expected identifier, found {}",
-                                                      self.this_token_descr()));
+                    let mut err = self.struct_span_err(self.span,
+                                                       &format!("expected identifier, found {}",
+                                                                self.this_token_descr()));
+                    if let Some(token_descr) = self.token_descr() {
+                        err.span_label(self.span, format!("expected identifier, found {}",
+                                                          token_descr));
+                    } else {
+                        err.span_label(self.span, "expected identifier");
+                    }
+                    if recover {
+                        err.emit();
+                    } else {
+                        return Err(err);
+                    }
                 }
                 self.bump();
                 Ok(i)
@@ -767,6 +791,12 @@
                     } else {
                         let mut err = self.fatal(&format!("expected identifier, found `{}`",
                                                           self.this_token_to_string()));
+                        if let Some(token_descr) = self.token_descr() {
+                            err.span_label(self.span, format!("expected identifier, found {}",
+                                                              token_descr));
+                        } else {
+                            err.span_label(self.span, "expected identifier");
+                        }
                         if self.token == token::Underscore {
                             err.note("`_` is a wildcard pattern, not an identifier");
                         }
@@ -1238,13 +1268,16 @@
     pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
         self.sess.span_diagnostic.struct_span_fatal(self.span, m)
     }
-    pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> {
+    pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
         self.sess.span_diagnostic.struct_span_fatal(sp, m)
     }
-    pub fn span_fatal_err(&self, sp: Span, err: Error) -> DiagnosticBuilder<'a> {
+    pub fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> {
         err.span_err(sp, self.diagnostic())
     }
-    pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> {
+    pub fn span_fatal_help<S: Into<MultiSpan>>(&self,
+                                            sp: S,
+                                            m: &str,
+                                            help: &str) -> DiagnosticBuilder<'a> {
         let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m);
         err.help(help);
         err
@@ -1255,21 +1288,21 @@
     pub fn warn(&self, m: &str) {
         self.sess.span_diagnostic.span_warn(self.span, m)
     }
-    pub fn span_warn(&self, sp: Span, m: &str) {
+    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
         self.sess.span_diagnostic.span_warn(sp, m)
     }
-    pub fn span_err(&self, sp: Span, m: &str) {
+    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
         self.sess.span_diagnostic.span_err(sp, m)
     }
-    pub fn struct_span_err(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
         self.sess.span_diagnostic.struct_span_err(sp, m)
     }
-    pub fn span_err_help(&self, sp: Span, m: &str, h: &str) {
+    pub fn span_err_help<S: Into<MultiSpan>>(&self, sp: S, m: &str, h: &str) {
         let mut err = self.sess.span_diagnostic.mut_span_err(sp, m);
         err.help(h);
         err.emit();
     }
-    pub fn span_bug(&self, sp: Span, m: &str) -> ! {
+    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
         self.sess.span_diagnostic.span_bug(sp, m)
     }
     pub fn abort_if_errors(&self) {
@@ -1295,6 +1328,10 @@
     fn get_label(&mut self) -> ast::Ident {
         match self.token {
             token::Lifetime(ref ident) => *ident,
+            token::Interpolated(ref nt) => match nt.0 {
+                token::NtLifetime(lifetime) => lifetime.ident,
+                _ => self.bug("not a lifetime"),
+            },
             _ => self.bug("not a lifetime"),
         }
     }
@@ -1314,7 +1351,7 @@
         Function Style
         */
 
-        let unsafety = self.parse_unsafety()?;
+        let unsafety = self.parse_unsafety();
         let abi = if self.eat_keyword(keywords::Extern) {
             self.parse_opt_abi()?.unwrap_or(Abi::C)
         } else {
@@ -1337,11 +1374,12 @@
         })))
     }
 
-    pub fn parse_unsafety(&mut self) -> PResult<'a, Unsafety> {
+    /// Parse unsafety: `unsafe` or nothing.
+    fn parse_unsafety(&mut self) -> Unsafety {
         if self.eat_keyword(keywords::Unsafe) {
-            return Ok(Unsafety::Unsafe);
+            Unsafety::Unsafe
         } else {
-            return Ok(Unsafety::Normal);
+            Unsafety::Normal
         }
     }
 
@@ -1383,7 +1421,7 @@
                 None
             };
             (ident, TraitItemKind::Const(ty, default), ast::Generics::default())
-        } else if self.token.is_path_start() {
+        } else if self.token.is_path_start() && !self.is_extern_non_path() {
             // trait item macro.
             // code copied from parse_macro_use_or_failure... abstraction!
             let prev_span = self.prev_span;
@@ -2031,14 +2069,12 @@
     }
 
     /// Parse single lifetime 'a or panic.
-    fn expect_lifetime(&mut self) -> Lifetime {
-        match self.token {
-            token::Lifetime(ident) => {
-                let ident_span = self.span;
-                self.bump();
-                Lifetime { ident: ident, span: ident_span, id: ast::DUMMY_NODE_ID }
-            }
-            _ => self.span_bug(self.span, "not a lifetime")
+    pub fn expect_lifetime(&mut self) -> Lifetime {
+        if let Some(lifetime) = self.token.lifetime(self.span) {
+            self.bump();
+            lifetime
+        } else {
+            self.span_bug(self.span, "not a lifetime")
         }
     }
 
@@ -2056,7 +2092,7 @@
             self.bump();
             Ok(Ident::with_empty_ctxt(name))
         } else {
-            self.parse_ident()
+            self.parse_ident_common(false)
         }
     }
 
@@ -2073,7 +2109,7 @@
             hi = self.prev_span;
             (fieldname, self.parse_expr()?, false)
         } else {
-            let fieldname = self.parse_ident()?;
+            let fieldname = self.parse_ident_common(false)?;
             hi = self.prev_span;
 
             // Mimic `x: x` for the `x` field shorthand.
@@ -2222,8 +2258,7 @@
                 return self.parse_block_expr(lo, BlockCheckMode::Default, attrs);
             }
             token::BinOp(token::Or) | token::OrOr => {
-                let lo = self.span;
-                return self.parse_lambda_expr(lo, CaptureBy::Ref, attrs);
+                return self.parse_lambda_expr(attrs);
             }
             token::OpenDelim(token::Bracket) => {
                 self.bump();
@@ -2268,9 +2303,8 @@
                     hi = path.span;
                     return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
                 }
-                if self.eat_keyword(keywords::Move) {
-                    let lo = self.prev_span;
-                    return self.parse_lambda_expr(lo, CaptureBy::Value, attrs);
+                if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) {
+                    return self.parse_lambda_expr(attrs);
                 }
                 if self.eat_keyword(keywords::If) {
                     return self.parse_if_expr(attrs);
@@ -2424,6 +2458,7 @@
 
     fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Attribute>)
                          -> PResult<'a, P<Expr>> {
+        let struct_sp = lo.to(self.prev_span);
         self.bump();
         let mut fields = Vec::new();
         let mut base = None;
@@ -2458,6 +2493,7 @@
             match self.parse_field() {
                 Ok(f) => fields.push(f),
                 Err(mut e) => {
+                    e.span_label(struct_sp, "while parsing this struct");
                     e.emit();
                     self.recover_stmt();
                     break;
@@ -2592,7 +2628,7 @@
                   token::Ident(..) => {
                     e = self.parse_dot_suffix(e, lo)?;
                   }
-                  token::Literal(token::Integer(n), suf) => {
+                  token::Literal(token::Integer(index_ident), suf) => {
                     let sp = self.span;
 
                     // A tuple index may not have a suffix
@@ -2602,16 +2638,25 @@
                     hi = self.span;
                     self.bump();
 
-                    let index = n.as_str().parse::<usize>().ok();
+                    let invalid_msg = "invalid tuple or struct index";
+
+                    let index = index_ident.as_str().parse::<usize>().ok();
                     match index {
                         Some(n) => {
+                            if n.to_string() != index_ident.as_str() {
+                                let mut err = self.struct_span_err(self.prev_span, invalid_msg);
+                                err.span_suggestion(self.prev_span,
+                                                    "try simplifying the index",
+                                                    n.to_string());
+                                err.emit();
+                            }
                             let id = respan(dot_span.to(hi), n);
                             let field = self.mk_tup_field(e, id);
                             e = self.mk_expr(lo.to(hi), field, ThinVec::new());
                         }
                         None => {
                             let prev_span = self.prev_span;
-                            self.span_err(prev_span, "invalid tuple or tuple struct index");
+                            self.span_err(prev_span, invalid_msg);
                         }
                     }
                   }
@@ -3200,11 +3245,20 @@
 
     // `move |args| expr`
     pub fn parse_lambda_expr(&mut self,
-                             lo: Span,
-                             capture_clause: CaptureBy,
                              attrs: ThinVec<Attribute>)
                              -> PResult<'a, P<Expr>>
     {
+        let lo = self.span;
+        let movability = if self.eat_keyword(keywords::Static) {
+            Movability::Static
+        } else {
+            Movability::Movable
+        };
+        let capture_clause = if self.eat_keyword(keywords::Move) {
+            CaptureBy::Value
+        } else {
+            CaptureBy::Ref
+        };
         let decl = self.parse_fn_block_decl()?;
         let decl_hi = self.prev_span;
         let body = match decl.output {
@@ -3222,7 +3276,7 @@
 
         Ok(self.mk_expr(
             lo.to(body.span),
-            ExprKind::Closure(capture_clause, decl, body, lo.to(decl_hi)),
+            ExprKind::Closure(capture_clause, movability, decl, body, lo.to(decl_hi)),
             attrs))
     }
 
@@ -3420,8 +3474,20 @@
         let mut pats = Vec::new();
         loop {
             pats.push(self.parse_pat()?);
-            if self.check(&token::BinOp(token::Or)) { self.bump();}
-            else { return Ok(pats); }
+
+            if self.token == token::OrOr {
+                let mut err = self.struct_span_err(self.span,
+                                                   "unexpected token `||` after pattern");
+                err.span_suggestion(self.span,
+                                    "use a single `|` to specify multiple patterns",
+                                    "|".to_owned());
+                err.emit();
+                self.bump();
+            } else if self.check(&token::BinOp(token::Or)) {
+                self.bump();
+            } else {
+                return Ok(pats);
+            }
         };
     }
 
@@ -4026,36 +4092,18 @@
         self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
     }
 
-    fn eat_auto_trait(&mut self) -> bool {
-        if self.token.is_keyword(keywords::Auto)
-            && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
-        {
-            self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait)
-        } else {
-            false
-        }
+    fn is_extern_non_path(&self) -> bool {
+        self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep)
     }
 
-    fn is_defaultness(&self) -> bool {
-        // `pub` is included for better error messages
-        self.token.is_keyword(keywords::Default) &&
-        self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
-                        t.is_keyword(keywords::Const) ||
-                        t.is_keyword(keywords::Fn) ||
-                        t.is_keyword(keywords::Unsafe) ||
-                        t.is_keyword(keywords::Extern) ||
-                        t.is_keyword(keywords::Type) ||
-                        t.is_keyword(keywords::Pub))
-    }
-
-    fn eat_defaultness(&mut self) -> bool {
-        let is_defaultness = self.is_defaultness();
-        if is_defaultness {
-            self.bump()
-        } else {
-            self.expected_tokens.push(TokenType::Keyword(keywords::Default));
-        }
-        is_defaultness
+    fn is_auto_trait_item(&mut self) -> bool {
+        // auto trait
+        (self.token.is_keyword(keywords::Auto)
+            && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
+        || // unsafe auto trait
+        (self.token.is_keyword(keywords::Unsafe) &&
+         self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) &&
+         self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
     }
 
     fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
@@ -4136,15 +4184,19 @@
                 node: StmtKind::Item(macro_def),
                 span: lo.to(self.prev_span),
             }
-        // Starts like a simple path, but not a union item or item with `crate` visibility.
+        // Starts like a simple path, being careful to avoid contextual keywords
+        // such as a union items, item with `crate` visibility or auto trait items.
         // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
         // like a path (1 token), but it fact not a path.
         // `union::b::c` - path, `union U { ... }` - not a path.
         // `crate::b::c` - path, `crate struct S;` - not a path.
+        // `extern::b::c` - path, `extern crate c;` - not a path.
         } else if self.token.is_path_start() &&
                   !self.token.is_qpath_start() &&
                   !self.is_union_item() &&
-                  !self.is_crate_vis() {
+                  !self.is_crate_vis() &&
+                  !self.is_extern_non_path() &&
+                  !self.is_auto_trait_item() {
             let pth = self.parse_path(PathStyle::Expr)?;
 
             if !self.eat(&token::Not) {
@@ -4732,21 +4784,13 @@
         }
         let lo = self.prev_span;
 
-        // This is a temporary future proofing.
-        //
         // We are considering adding generics to the `where` keyword as an alternative higher-rank
         // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
-        // change, for now we refuse to parse `where < (ident | lifetime) (> | , | :)`.
-        if token::Lt == self.token {
-            let ident_or_lifetime = self.look_ahead(1, |t| t.is_ident() || t.is_lifetime());
-            if ident_or_lifetime {
-                let gt_comma_or_colon = self.look_ahead(2, |t| {
-                    *t == token::Gt || *t == token::Comma || *t == token::Colon
-                });
-                if gt_comma_or_colon {
-                    self.span_err(self.span, "syntax `where<T>` is reserved for future use");
-                }
-            }
+        // change we parse those generics now, but report an error.
+        if self.choose_generics_over_qpath() {
+            let generics = self.parse_generics()?;
+            self.span_err(generics.span,
+                          "generic parameters on `where` clauses are reserved for future use");
         }
 
         loop {
@@ -5064,7 +5108,7 @@
     fn parse_item_fn(&mut self,
                      unsafety: Unsafety,
                      constness: Spanned<Constness>,
-                     abi: abi::Abi)
+                     abi: Abi)
                      -> PResult<'a, ItemInfo> {
         let (ident, mut generics) = self.parse_fn_header()?;
         let decl = self.parse_fn_decl(false)?;
@@ -5088,13 +5132,10 @@
     /// - `const unsafe fn`
     /// - `extern fn`
     /// - etc
-    pub fn parse_fn_front_matter(&mut self)
-                                 -> PResult<'a, (Spanned<ast::Constness>,
-                                                ast::Unsafety,
-                                                abi::Abi)> {
+    pub fn parse_fn_front_matter(&mut self) -> PResult<'a, (Spanned<Constness>, Unsafety, Abi)> {
         let is_const_fn = self.eat_keyword(keywords::Const);
         let const_span = self.prev_span;
-        let unsafety = self.parse_unsafety()?;
+        let unsafety = self.parse_unsafety();
         let (constness, unsafety, abi) = if is_const_fn {
             (respan(const_span, Constness::Const), unsafety, Abi::Rust)
         } else {
@@ -5129,7 +5170,7 @@
                         mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
         let lo = self.span;
         let vis = self.parse_visibility(false)?;
-        let defaultness = self.parse_defaultness()?;
+        let defaultness = self.parse_defaultness();
         let (name, node, generics) = if self.eat_keyword(keywords::Type) {
             // This parses the grammar:
             //     ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
@@ -5222,10 +5263,10 @@
 
     /// Parse a method or a macro invocation in a trait impl.
     fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
-                         -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::Generics,
+                         -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
                              ast::ImplItemKind)> {
         // code copied from parse_macro_use_or_failure... abstraction!
-        if self.token.is_path_start() {
+        if self.token.is_path_start() && !self.is_extern_non_path() {
             // Method macro.
 
             let prev_span = self.prev_span;
@@ -5311,98 +5352,123 @@
         }
     }
 
-    /// Parses items implementations variants
-    ///    impl<T> Foo { ... }
-    ///    impl<T> ToString for &'static T { ... }
-    ///    impl Send for .. {}
-    fn parse_item_impl(&mut self,
-                       unsafety: ast::Unsafety,
-                       defaultness: Defaultness) -> PResult<'a, ItemInfo> {
-        let impl_span = self.span;
+    fn choose_generics_over_qpath(&self) -> bool {
+        // There's an ambiguity between generic parameters and qualified paths in impls.
+        // If we see `<` it may start both, so we have to inspect some following tokens.
+        // The following combinations can only start generics,
+        // but not qualified paths (with one exception):
+        //     `<` `>` - empty generic parameters
+        //     `<` `#` - generic parameters with attributes
+        //     `<` (LIFETIME|IDENT) `>` - single generic parameter
+        //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
+        //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
+        //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
+        // The only truly ambiguous case is
+        //     `<` IDENT `>` `::` IDENT ...
+        // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
+        // because this is what almost always expected in practice, qualified paths in impls
+        // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
+        self.token == token::Lt &&
+            (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
+             self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
+                self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
+                                       t == &token::Colon || t == &token::Eq))
+    }
 
-        // First, parse type parameters if necessary.
-        let mut generics = self.parse_generics()?;
+    fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
+        self.expect(&token::OpenDelim(token::Brace))?;
+        let attrs = self.parse_inner_attributes()?;
 
-        // Special case: if the next identifier that follows is '(', don't
-        // allow this to be parsed as a trait.
-        let could_be_trait = self.token != token::OpenDelim(token::Paren);
+        let mut impl_items = Vec::new();
+        while !self.eat(&token::CloseDelim(token::Brace)) {
+            let mut at_end = false;
+            match self.parse_impl_item(&mut at_end) {
+                Ok(impl_item) => impl_items.push(impl_item),
+                Err(mut err) => {
+                    err.emit();
+                    if !at_end {
+                        self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
+                    }
+                }
+            }
+        }
+        Ok((impl_items, attrs))
+    }
 
-        let neg_span = self.span;
-        let polarity = if self.eat(&token::Not) {
+    /// Parses an implementation item, `impl` keyword is already parsed.
+    ///    impl<'a, T> TYPE { /* impl items */ }
+    ///    impl<'a, T> TRAIT for TYPE { /* impl items */ }
+    ///    impl<'a, T> !TRAIT for TYPE { /* impl items */ }
+    /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
+    ///     `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
+    ///     `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
+    fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
+                       -> PResult<'a, ItemInfo> {
+        // First, parse generic parameters if necessary.
+        let mut generics = if self.choose_generics_over_qpath() {
+            self.parse_generics()?
+        } else {
+            ast::Generics::default()
+        };
+
+        // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
+        let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
+            self.bump(); // `!`
             ast::ImplPolarity::Negative
         } else {
             ast::ImplPolarity::Positive
         };
 
-        // Parse the trait.
-        let mut ty = self.parse_ty()?;
+        // Parse both types and traits as a type, then reinterpret if necessary.
+        let ty_first = self.parse_ty()?;
 
-        // Parse traits, if necessary.
-        let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
-            // New-style trait. Reinterpret the type as a trait.
-            match ty.node {
-                TyKind::Path(None, ref path) => {
-                    Some(TraitRef {
-                        path: (*path).clone(),
-                        ref_id: ty.id,
-                    })
-                }
-                _ => {
-                    self.span_err(ty.span, "not a trait");
-                    None
-                }
-            }
+        // If `for` is missing we try to recover.
+        let has_for = self.eat_keyword(keywords::For);
+        let missing_for_span = self.prev_span.between(self.span);
+
+        let ty_second = if self.token == token::DotDot {
+            // We need to report this error after `cfg` expansion for compatibility reasons
+            self.bump(); // `..`, do not add it to expected tokens
+            Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }))
+        } else if has_for || self.token.can_begin_type() {
+            Some(self.parse_ty()?)
         } else {
-            if polarity == ast::ImplPolarity::Negative {
-                // This is a negated type implementation
-                // `impl !MyType {}`, which is not allowed.
-                self.span_err(neg_span, "inherent implementation can't be negated");
-            }
             None
         };
 
-        if opt_trait.is_some() && self.eat(&token::DotDot) {
-            if generics.is_parameterized() {
-                self.span_err(impl_span, "auto trait implementations are not \
-                                          allowed to have generics");
-            }
+        generics.where_clause = self.parse_where_clause()?;
 
-            if let ast::Defaultness::Default = defaultness {
-                self.span_err(impl_span, "`default impl` is not allowed for \
-                                         auto trait implementations");
-            }
+        let (impl_items, attrs) = self.parse_impl_body()?;
 
-            self.expect(&token::OpenDelim(token::Brace))?;
-            self.expect(&token::CloseDelim(token::Brace))?;
-            Ok((keywords::Invalid.ident(),
-             ItemKind::AutoImpl(unsafety, opt_trait.unwrap()), None))
-        } else {
-            if opt_trait.is_some() {
-                ty = self.parse_ty()?;
-            }
-            generics.where_clause = self.parse_where_clause()?;
-
-            self.expect(&token::OpenDelim(token::Brace))?;
-            let attrs = self.parse_inner_attributes()?;
-
-            let mut impl_items = vec![];
-            while !self.eat(&token::CloseDelim(token::Brace)) {
-                let mut at_end = false;
-                match self.parse_impl_item(&mut at_end) {
-                    Ok(item) => impl_items.push(item),
-                    Err(mut e) => {
-                        e.emit();
-                        if !at_end {
-                            self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
-                        }
-                    }
+        let item_kind = match ty_second {
+            Some(ty_second) => {
+                // impl Trait for Type
+                if !has_for {
+                    self.span_err(missing_for_span, "missing `for` in a trait impl");
                 }
-            }
 
-            Ok((keywords::Invalid.ident(),
-             ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
-             Some(attrs)))
-        }
+                let ty_first = ty_first.into_inner();
+                let path = match ty_first.node {
+                    // This notably includes paths passed through `ty` macro fragments (#46438).
+                    TyKind::Path(None, path) => path,
+                    _ => {
+                        self.span_err(ty_first.span, "expected a trait, found type");
+                        ast::Path::from_ident(ty_first.span, keywords::Invalid.ident())
+                    }
+                };
+                let trait_ref = TraitRef { path, ref_id: ty_first.id };
+
+                ItemKind::Impl(unsafety, polarity, defaultness,
+                               generics, Some(trait_ref), ty_second, impl_items)
+            }
+            None => {
+                // impl Type
+                ItemKind::Impl(unsafety, polarity, defaultness,
+                               generics, None, ty_first, impl_items)
+            }
+        };
+
+        Ok((keywords::Invalid.ident(), item_kind, Some(attrs)))
     }
 
     fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
@@ -5675,12 +5741,21 @@
         Ok(Visibility::Public)
     }
 
-    /// Parse defaultness: DEFAULT or nothing
-    fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
-        if self.eat_defaultness() {
-            Ok(Defaultness::Default)
+    /// Parse defaultness: `default` or nothing.
+    fn parse_defaultness(&mut self) -> Defaultness {
+        // `pub` is included for better error messages
+        if self.check_keyword(keywords::Default) &&
+           self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
+                                  t.is_keyword(keywords::Const) ||
+                                  t.is_keyword(keywords::Fn) ||
+                                  t.is_keyword(keywords::Unsafe) ||
+                                  t.is_keyword(keywords::Extern) ||
+                                  t.is_keyword(keywords::Type) ||
+                                  t.is_keyword(keywords::Pub)) {
+            self.bump(); // `default`
+            Defaultness::Default
         } else {
-            Ok(Defaultness::Final)
+            Defaultness::Final
         }
     }
 
@@ -5750,7 +5825,7 @@
                 let (module, mut attrs) =
                     self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
                 if warn {
-                    let attr = ast::Attribute {
+                    let attr = Attribute {
                         id: attr::mk_attr_id(),
                         style: ast::AttrStyle::Outer,
                         path: ast::Path::from_ident(syntax_pos::DUMMY_SP,
@@ -5790,7 +5865,7 @@
         }
     }
 
-    pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
+    pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
         attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
     }
 
@@ -5859,16 +5934,20 @@
 
     fn submod_path(&mut self,
                    id: ast::Ident,
-                   outer_attrs: &[ast::Attribute],
+                   outer_attrs: &[Attribute],
                    id_sp: Span)
                    -> PResult<'a, ModulePathSuccess> {
         if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
             return Ok(ModulePathSuccess {
                 directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
-                    Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
-                    Some(_) => {
-                        DirectoryOwnership::Owned { relative: Some(id) }
-                    }
+                    // All `#[path]` files are treated as though they are a `mod.rs` file.
+                    // This means that `mod foo;` declarations inside `#[path]`-included
+                    // files are siblings,
+                    //
+                    // Note that this will produce weirdness when a file named `foo.rs` is
+                    // `#[path]` included and contains a `mod foo;` declaration.
+                    // If you encounter this, it's your own darn fault :P
+                    Some(_) => DirectoryOwnership::Owned { relative: None },
                     _ => DirectoryOwnership::UnownedViaMod(true),
                 },
                 path,
@@ -5948,7 +6027,7 @@
                     directory_ownership: DirectoryOwnership,
                     name: String,
                     id_sp: Span)
-                    -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
+                    -> PResult<'a, (ast::ItemKind, Vec<Attribute> )> {
         let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
         if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
             let mut err = String::from("circular modules: ");
@@ -6071,7 +6150,7 @@
     /// extern {}
     fn parse_item_foreign_mod(&mut self,
                               lo: Span,
-                              opt_abi: Option<abi::Abi>,
+                              opt_abi: Option<Abi>,
                               visibility: Visibility,
                               mut attrs: Vec<Attribute>)
                               -> PResult<'a, P<Item>> {
@@ -6174,7 +6253,7 @@
 
     /// Parses a string as an ABI spec on an extern type or module. Consumes
     /// the `extern` keyword, if one is found.
-    fn parse_opt_abi(&mut self) -> PResult<'a, Option<abi::Abi>> {
+    fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
         match self.token {
             token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
                 let sp = self.span;
@@ -6199,6 +6278,23 @@
         }
     }
 
+    fn is_static_global(&mut self) -> bool {
+        if self.check_keyword(keywords::Static) {
+            // Check if this could be a closure
+            !self.look_ahead(1, |token| {
+                if token.is_keyword(keywords::Move) {
+                    return true;
+                }
+                match *token {
+                    token::BinOp(token::Or) | token::OrOr => true,
+                    _ => false,
+                }
+            })
+        } else {
+            false
+        }
+    }
+
     /// Parse one of the items allowed by the flags.
     /// NB: this function no longer parses the items inside an
     /// extern crate.
@@ -6227,7 +6323,8 @@
             return Ok(Some(item));
         }
 
-        if self.eat_keyword(keywords::Extern) {
+        if self.check_keyword(keywords::Extern) && self.is_extern_non_path() {
+            self.bump(); // `extern`
             if self.eat_keyword(keywords::Crate) {
                 return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?));
             }
@@ -6256,7 +6353,8 @@
             self.unexpected()?;
         }
 
-        if self.eat_keyword(keywords::Static) {
+        if self.is_static_global() {
+            self.bump();
             // STATIC ITEM
             let m = if self.eat_keyword(keywords::Mut) {
                 Mutability::Mutable
@@ -6278,11 +6376,7 @@
                 || (self.check_keyword(keywords::Unsafe)
                     && self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
                 // CONST FUNCTION ITEM
-                let unsafety = if self.eat_keyword(keywords::Unsafe) {
-                    Unsafety::Unsafe
-                } else {
-                    Unsafety::Normal
-                };
+                let unsafety = self.parse_unsafety();
                 self.bump();
                 let (ident, item_, extra_attrs) =
                     self.parse_item_fn(unsafety,
@@ -6318,15 +6412,16 @@
             self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
         {
             // UNSAFE TRAIT ITEM
-            self.expect_keyword(keywords::Unsafe)?;
+            self.bump(); // `unsafe`
             let is_auto = if self.eat_keyword(keywords::Trait) {
                 IsAuto::No
             } else {
-                self.eat_auto_trait();
+                self.expect_keyword(keywords::Auto)?;
+                self.expect_keyword(keywords::Trait)?;
                 IsAuto::Yes
             };
             let (ident, item_, extra_attrs) =
-                self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
+                self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
@@ -6335,26 +6430,21 @@
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if (self.check_keyword(keywords::Unsafe) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
-           (self.check_keyword(keywords::Default) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
-            self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
-        {
+        if self.check_keyword(keywords::Impl) ||
+           self.check_keyword(keywords::Unsafe) &&
+                self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+           self.check_keyword(keywords::Default) &&
+                self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+           self.check_keyword(keywords::Default) &&
+                self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) {
             // IMPL ITEM
-            let defaultness = self.parse_defaultness()?;
-            self.expect_keyword(keywords::Unsafe)?;
+            let defaultness = self.parse_defaultness();
+            let unsafety = self.parse_unsafety();
             self.expect_keyword(keywords::Impl)?;
-            let (ident,
-                 item_,
-                 extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
+            let span = lo.to(self.prev_span);
+            return Ok(Some(self.mk_item(span, ident, item, visibility,
+                                        maybe_append(attrs, extra_attrs))));
         }
         if self.check_keyword(keywords::Fn) {
             // FUNCTION ITEM
@@ -6375,7 +6465,7 @@
         if self.check_keyword(keywords::Unsafe)
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
             // UNSAFE FUNCTION ITEM
-            self.bump();
+            self.bump(); // `unsafe`
             let abi = if self.eat_keyword(keywords::Extern) {
                 self.parse_opt_abi()?.unwrap_or(Abi::C)
             } else {
@@ -6436,30 +6526,13 @@
             let is_auto = if self.eat_keyword(keywords::Trait) {
                 IsAuto::No
             } else {
-                self.eat_auto_trait();
+                self.expect_keyword(keywords::Auto)?;
+                self.expect_keyword(keywords::Trait)?;
                 IsAuto::Yes
             };
             // TRAIT ITEM
             let (ident, item_, extra_attrs) =
-                self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
-        }
-        if (self.check_keyword(keywords::Impl)) ||
-           (self.check_keyword(keywords::Default) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
-        {
-            // IMPL ITEM
-            let defaultness = self.parse_defaultness()?;
-            self.expect_keyword(keywords::Impl)?;
-            let (ident,
-                 item_,
-                 extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
+                self.parse_item_trait(is_auto, Unsafety::Normal)?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 05368c5..2be93c0 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -251,7 +251,7 @@
             Lt | BinOp(Shl)             | // associated path
             ModSep                      => true, // global path
             Interpolated(ref nt) => match nt.0 {
-                NtIdent(..) | NtTy(..) | NtPath(..) => true,
+                NtIdent(..) | NtTy(..) | NtPath(..) | NtLifetime(..) => true,
                 _ => false,
             },
             _ => false,
@@ -314,12 +314,24 @@
         false
     }
 
+    /// Returns a lifetime with the span and a dummy id if it is a lifetime,
+    /// or the original lifetime if it is an interpolated lifetime, ignoring
+    /// the span.
+    pub fn lifetime(&self, span: Span) -> Option<ast::Lifetime> {
+        match *self {
+            Lifetime(ident) =>
+                Some(ast::Lifetime { ident: ident, span: span, id: ast::DUMMY_NODE_ID }),
+            Interpolated(ref nt) => match nt.0 {
+                NtLifetime(lifetime) => Some(lifetime),
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+
     /// Returns `true` if the token is a lifetime.
     pub fn is_lifetime(&self) -> bool {
-        match *self {
-            Lifetime(..) => true,
-            _            => false,
-        }
+        self.lifetime(syntax_pos::DUMMY_SP).is_some()
     }
 
     /// Returns `true` if the token is either the `mut` or `const` keyword.
@@ -347,6 +359,7 @@
             Some(id) => id.name == keywords::Super.name() ||
                         id.name == keywords::SelfValue.name() ||
                         id.name == keywords::SelfType.name() ||
+                        id.name == keywords::Extern.name() ||
                         id.name == keywords::Crate.name() ||
                         id.name == keywords::DollarCrate.name(),
             None => false,
@@ -486,6 +499,10 @@
                 let token = Token::Ident(ident.node);
                 tokens = Some(TokenTree::Token(ident.span, token).into());
             }
+            Nonterminal::NtLifetime(lifetime) => {
+                let token = Token::Lifetime(lifetime.ident);
+                tokens = Some(TokenTree::Token(lifetime.span, token).into());
+            }
             Nonterminal::NtTT(ref tt) => {
                 tokens = Some(tt.clone().into());
             }
@@ -524,6 +541,7 @@
     NtGenerics(ast::Generics),
     NtWhereClause(ast::WhereClause),
     NtArg(ast::Arg),
+    NtLifetime(ast::Lifetime),
 }
 
 impl fmt::Debug for Nonterminal {
@@ -546,6 +564,7 @@
             NtWhereClause(..) => f.pad("NtWhereClause(..)"),
             NtArg(..) => f.pad("NtArg(..)"),
             NtVis(..) => f.pad("NtVis(..)"),
+            NtLifetime(..) => f.pad("NtLifetime(..)"),
         }
     }
 }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8f619e8..345c592 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -279,6 +279,7 @@
             token::NtWhereClause(ref e) => where_clause_to_string(e),
             token::NtArg(ref e)         => arg_to_string(e),
             token::NtVis(ref e)         => vis_to_string(e),
+            token::NtLifetime(ref e)    => lifetime_to_string(e),
         }
     }
 }
@@ -1293,18 +1294,6 @@
                 self.head(&visibility_qualified(&item.vis, "union"))?;
                 self.print_struct(struct_def, generics, item.ident, item.span, true)?;
             }
-            ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
-                self.head("")?;
-                self.print_visibility(&item.vis)?;
-                self.print_unsafety(unsafety)?;
-                self.word_nbsp("impl")?;
-                self.print_trait_ref(trait_ref)?;
-                self.s.space()?;
-                self.word_space("for")?;
-                self.word_space("..")?;
-                self.bopen()?;
-                self.bclose(item.span)?;
-            }
             ast::ItemKind::Impl(unsafety,
                           polarity,
                           defaultness,
@@ -1850,7 +1839,7 @@
     }
 
     pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) -> io::Result<()> {
-        let needs_par = parser::expr_precedence(expr) < prec;
+        let needs_par = expr.precedence().order() < prec;
         if needs_par {
             self.popen()?;
         }
@@ -2173,7 +2162,8 @@
                 }
                 self.bclose_(expr.span, INDENT_UNIT)?;
             }
-            ast::ExprKind::Closure(capture_clause, ref decl, ref body, _) => {
+            ast::ExprKind::Closure(capture_clause, movability, ref decl, ref body, _) => {
+                self.print_movability(movability)?;
                 self.print_capture_clause(capture_clause)?;
 
                 self.print_fn_block_args(decl)?;
@@ -2788,6 +2778,14 @@
         }
     }
 
+    pub fn print_movability(&mut self, movability: ast::Movability)
+                                -> io::Result<()> {
+        match movability {
+            ast::Movability::Static => self.word_space("static"),
+            ast::Movability::Movable => Ok(()),
+        }
+    }
+
     pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy)
                                 -> io::Result<()> {
         match capture_clause {
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 1a0f4e9..eff7dd5 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -386,15 +386,15 @@
 }
 
 fn is_ignored(i: &ast::Item) -> bool {
-    i.attrs.iter().any(|attr| attr.check_name("ignore"))
+    attr::contains_name(&i.attrs, "ignore")
 }
 
 fn is_allowed_fail(i: &ast::Item) -> bool {
-    i.attrs.iter().any(|attr| attr.check_name("allow_fail"))
+    attr::contains_name(&i.attrs, "allow_fail")
 }
 
 fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic {
-    match i.attrs.iter().find(|attr| attr.check_name("should_panic")) {
+    match attr::find_by_name(&i.attrs, "should_panic") {
         Some(attr) => {
             let sd = cx.span_diagnostic;
             if attr.is_value_str() {
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 870f54e..ad04b6a 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -286,12 +286,12 @@
         TokenStream::concat(result)
     }
 
-    fn first_tree(&self) -> Option<TokenTree> {
+    fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> {
         match self.kind {
             TokenStreamKind::Empty => None,
-            TokenStreamKind::Tree(ref tree) |
-            TokenStreamKind::JointTree(ref tree) => Some(tree.clone()),
-            TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree(),
+            TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)),
+            TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)),
+            TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
         }
     }
 
@@ -315,12 +315,18 @@
         let stream = stream.into();
         let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint);
         if let Some(TokenTree::Token(last_span, last_tok)) = last_tree_if_joint {
-            if let Some(TokenTree::Token(span, tok)) = stream.first_tree() {
+            if let Some((TokenTree::Token(span, tok), is_joint)) = stream.first_tree_and_joint() {
                 if let Some(glued_tok) = last_tok.glue(tok) {
                     let last_stream = self.0.pop().unwrap();
                     self.push_all_but_last_tree(&last_stream);
                     let glued_span = last_span.to(span);
-                    self.0.push(TokenTree::Token(glued_span, glued_tok).into());
+                    let glued_tt = TokenTree::Token(glued_span, glued_tok);
+                    let glued_tokenstream = if is_joint {
+                        glued_tt.joint()
+                    } else {
+                        glued_tt.into()
+                    };
+                    self.0.push(glued_tokenstream);
                     self.push_all_but_first_tree(&stream);
                     return
                 }
@@ -669,4 +675,16 @@
         assert_eq!(test1.is_empty(), false);
         assert_eq!(test2.is_empty(), false);
     }
+
+    #[test]
+    fn test_dotdotdot() {
+        let mut builder = TokenStreamBuilder::new();
+        builder.push(TokenTree::Token(sp(0, 1), Token::Dot).joint());
+        builder.push(TokenTree::Token(sp(1, 2), Token::Dot).joint());
+        builder.push(TokenTree::Token(sp(2, 3), Token::Dot));
+        let stream = builder.build();
+        assert!(stream.eq_unspanned(&string_to_ts("...")));
+        assert_eq!(stream.trees().count(), 1);
+    }
+
 }
diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs
index 6014ec5..86963c4 100644
--- a/src/libsyntax/util/parser.rs
+++ b/src/libsyntax/util/parser.rs
@@ -9,7 +9,9 @@
 // except according to those terms.
 use parse::token::{Token, BinOpToken};
 use symbol::keywords;
-use ast::{self, BinOpKind, ExprKind};
+use ast::{self, BinOpKind};
+
+use std::cmp::Ordering;
 
 /// Associative operator with precedence.
 ///
@@ -228,66 +230,130 @@
 pub const PREC_PAREN: i8 = 99;
 pub const PREC_FORCE_PAREN: i8 = 100;
 
-pub fn expr_precedence(expr: &ast::Expr) -> i8 {
-    match expr.node {
-        ExprKind::Closure(..) => PREC_CLOSURE,
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum ExprPrecedence {
+    Closure,
+    Break,
+    Continue,
+    Ret,
+    Yield,
 
-        ExprKind::Break(..) |
-        ExprKind::Continue(..) |
-        ExprKind::Ret(..) |
-        ExprKind::Yield(..) => PREC_JUMP,
+    Range,
 
-        // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to parse,
-        // instead of parsing as `(x .. x) = x`.  Giving `Range` a lower precedence ensures that
-        // `pprust` will add parentheses in the right places to get the desired parse.
-        ExprKind::Range(..) => PREC_RANGE,
+    Binary(BinOpKind),
 
-        // Binop-like expr kinds, handled by `AssocOp`.
-        ExprKind::Binary(op, _, _) =>
-            AssocOp::from_ast_binop(op.node).precedence() as i8,
+    InPlace,
+    Cast,
+    Type,
 
-        ExprKind::InPlace(..) => AssocOp::Inplace.precedence() as i8,
-        ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
-        ExprKind::Type(..) => AssocOp::Colon.precedence() as i8,
+    Assign,
+    AssignOp,
 
-        ExprKind::Assign(..) |
-        ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
+    Box,
+    AddrOf,
+    Unary,
 
-        // Unary, prefix
-        ExprKind::Box(..) |
-        ExprKind::AddrOf(..) |
-        ExprKind::Unary(..) => PREC_PREFIX,
+    Call,
+    MethodCall,
+    Field,
+    TupField,
+    Index,
+    Try,
+    InlineAsm,
+    Mac,
 
-        // Unary, postfix
-        ExprKind::Call(..) |
-        ExprKind::MethodCall(..) |
-        ExprKind::Field(..) |
-        ExprKind::TupField(..) |
-        ExprKind::Index(..) |
-        ExprKind::Try(..) |
-        ExprKind::InlineAsm(..) |
-        ExprKind::Mac(..) => PREC_POSTFIX,
+    Array,
+    Repeat,
+    Tup,
+    Lit,
+    Path,
+    Paren,
+    If,
+    IfLet,
+    While,
+    WhileLet,
+    ForLoop,
+    Loop,
+    Match,
+    Block,
+    Catch,
+    Struct,
+}
 
-        // Never need parens
-        ExprKind::Array(..) |
-        ExprKind::Repeat(..) |
-        ExprKind::Tup(..) |
-        ExprKind::Lit(..) |
-        ExprKind::Path(..) |
-        ExprKind::Paren(..) |
-        ExprKind::If(..) |
-        ExprKind::IfLet(..) |
-        ExprKind::While(..) |
-        ExprKind::WhileLet(..) |
-        ExprKind::ForLoop(..) |
-        ExprKind::Loop(..) |
-        ExprKind::Match(..) |
-        ExprKind::Block(..) |
-        ExprKind::Catch(..) |
-        ExprKind::Struct(..) => PREC_PAREN,
+impl PartialOrd for ExprPrecedence {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.order().cmp(&other.order()))
     }
 }
 
+impl Ord for ExprPrecedence {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.order().cmp(&other.order())
+    }
+}
+
+impl ExprPrecedence {
+    pub fn order(self) -> i8 {
+        match self {
+            ExprPrecedence::Closure => PREC_CLOSURE,
+
+            ExprPrecedence::Break |
+            ExprPrecedence::Continue |
+            ExprPrecedence::Ret |
+            ExprPrecedence::Yield => PREC_JUMP,
+
+            // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
+            // parse, instead of parsing as `(x .. x) = x`.  Giving `Range` a lower precedence
+            // ensures that `pprust` will add parentheses in the right places to get the desired
+            // parse.
+            ExprPrecedence::Range => PREC_RANGE,
+
+            // Binop-like expr kinds, handled by `AssocOp`.
+            ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8,
+            ExprPrecedence::InPlace => AssocOp::Inplace.precedence() as i8,
+            ExprPrecedence::Cast => AssocOp::As.precedence() as i8,
+            ExprPrecedence::Type => AssocOp::Colon.precedence() as i8,
+
+            ExprPrecedence::Assign |
+            ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
+
+            // Unary, prefix
+            ExprPrecedence::Box |
+            ExprPrecedence::AddrOf |
+            ExprPrecedence::Unary => PREC_PREFIX,
+
+            // Unary, postfix
+            ExprPrecedence::Call |
+            ExprPrecedence::MethodCall |
+            ExprPrecedence::Field |
+            ExprPrecedence::TupField |
+            ExprPrecedence::Index |
+            ExprPrecedence::Try |
+            ExprPrecedence::InlineAsm |
+            ExprPrecedence::Mac => PREC_POSTFIX,
+
+            // Never need parens
+            ExprPrecedence::Array |
+            ExprPrecedence::Repeat |
+            ExprPrecedence::Tup |
+            ExprPrecedence::Lit |
+            ExprPrecedence::Path |
+            ExprPrecedence::Paren |
+            ExprPrecedence::If |
+            ExprPrecedence::IfLet |
+            ExprPrecedence::While |
+            ExprPrecedence::WhileLet |
+            ExprPrecedence::ForLoop |
+            ExprPrecedence::Loop |
+            ExprPrecedence::Match |
+            ExprPrecedence::Block |
+            ExprPrecedence::Catch |
+            ExprPrecedence::Struct => PREC_PAREN,
+        }
+    }
+}
+
+
 /// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any
 /// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index bd68d7c..8aeacf7 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -259,9 +259,6 @@
             visitor.visit_generics(type_parameters);
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
-        ItemKind::AutoImpl(_, ref trait_ref) => {
-            visitor.visit_trait_ref(trait_ref)
-        }
         ItemKind::Impl(_, _, _,
                  ref type_parameters,
                  ref opt_trait_reference,
@@ -742,7 +739,7 @@
             visitor.visit_expr(subexpression);
             walk_list!(visitor, visit_arm, arms);
         }
-        ExprKind::Closure(_, ref function_declaration, ref body, _decl_span) => {
+        ExprKind::Closure(_, _, ref function_declaration, ref body, _decl_span) => {
             visitor.visit_fn(FnKind::Closure(body),
                              function_declaration,
                              expression.span,
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 29f5196..3660d2f 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -830,17 +830,19 @@
     for a in type_attrs {
         for r in &attr::find_repr_attrs(diagnostic, a) {
             repr_type_name = match *r {
-                attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) => continue,
-                attr::ReprExtern => "i32",
+                attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) | attr::ReprTransparent =>
+                    continue,
 
-                attr::ReprInt(attr::SignedInt(ast::IntTy::Is)) => "isize",
+                attr::ReprC => "i32",
+
+                attr::ReprInt(attr::SignedInt(ast::IntTy::Isize)) => "isize",
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I8)) => "i8",
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16",
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32",
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64",
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I128)) => "i128",
 
-                attr::ReprInt(attr::UnsignedInt(ast::UintTy::Us)) => "usize",
+                attr::ReprInt(attr::UnsignedInt(ast::UintTy::Usize)) => "usize",
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8",
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16",
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32",
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index ad5bd39..a782241 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -814,15 +814,11 @@
                 let (sp, msg) = errs.into_iter().next().unwrap();
                 cx.ecx.struct_span_err(sp, msg)
             } else {
-                let mut diag = cx.ecx.struct_span_err(cx.fmtsp,
-                    "multiple unused formatting arguments");
-
-                // Ignoring message, as it gets repetitive
-                // Then use MultiSpan to not clutter up errors
-                for (sp, _) in errs {
-                    diag.span_label(sp, "unused");
-                }
-
+                let mut diag = cx.ecx.struct_span_err(
+                    errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
+                    "multiple unused formatting arguments"
+                );
+                diag.span_label(cx.fmtsp, "multiple unused arguments in this statement");
                 diag
             }
         };
diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs
index a58d2c9..0ba21e6 100644
--- a/src/libsyntax_ext/proc_macro_registrar.rs
+++ b/src/libsyntax_ext/proc_macro_registrar.rs
@@ -13,6 +13,7 @@
 use errors;
 
 use syntax::ast::{self, Ident, NodeId};
+use syntax::attr;
 use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute};
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::build::AstBuilder;
@@ -248,8 +249,7 @@
 impl<'a> Visitor<'a> for CollectProcMacros<'a> {
     fn visit_item(&mut self, item: &'a ast::Item) {
         if let ast::ItemKind::MacroDef(..) = item.node {
-            if self.is_proc_macro_crate &&
-               item.attrs.iter().any(|attr| attr.path == "macro_export") {
+            if self.is_proc_macro_crate && attr::contains_name(&item.attrs, "macro_export") {
                 let msg =
                     "cannot export macro_rules! macros from a `proc-macro` crate type currently";
                 self.handler.span_err(item.span, msg);
@@ -381,7 +381,7 @@
 
     let __internal = Ident::from_str("__internal");
     let registry = Ident::from_str("Registry");
-    let registrar = Ident::from_str("registrar");
+    let registrar = Ident::from_str("_registrar");
     let register_custom_derive = Ident::from_str("register_custom_derive");
     let register_attr_proc_macro = Ident::from_str("register_attr_proc_macro");
     let register_bang_proc_macro = Ident::from_str("register_bang_proc_macro");
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 55342c2..b7fba9f 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -10,10 +10,10 @@
 
 //! Machinery for hygienic macros, inspired by the MTWT[1] paper.
 //!
-//! [1] Matthew Flatt, Ryan Culpepper, David Darais, and Robert Bruce Findler.
-//! 2012. *Macros that work together: Compile-time bindings, partial expansion,
+//! [1] Matthew Flatt, Ryan Culpepper, David Darais, and Robert Bruce Findler. 2012.
+//! *Macros that work together: Compile-time bindings, partial expansion,
 //! and definition contexts*. J. Funct. Program. 22, 2 (March 2012), 181-216.
-//! DOI=10.1017/S0956796812000093 http://dx.doi.org/10.1017/S0956796812000093
+//! DOI=10.1017/S0956796812000093 <http://dx.doi.org/10.1017/S0956796812000093>
 
 use Span;
 use symbol::{Ident, Symbol};
@@ -188,6 +188,33 @@
 
     /// Extend a syntax context with a given mark
     pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
+        if mark.kind() == MarkKind::Modern {
+            return self.apply_mark_internal(mark);
+        }
+
+        let call_site_ctxt =
+            mark.expn_info().map_or(SyntaxContext::empty(), |info| info.call_site.ctxt()).modern();
+        if call_site_ctxt == SyntaxContext::empty() {
+            return self.apply_mark_internal(mark);
+        }
+
+        // Otherwise, `mark` is a macros 1.0 definition and the call site is in a
+        // macros 2.0 expansion, i.e. a macros 1.0 invocation is in a macros 2.0 definition.
+        //
+        // In this case, the tokens from the macros 1.0 definition inherit the hygiene
+        // at their invocation. That is, we pretend that the macros 1.0 definition
+        // was defined at its invocation (i.e. inside the macros 2.0 definition)
+        // so that the macros 2.0 definition remains hygienic.
+        //
+        // See the example at `test/run-pass/hygiene/legacy_interaction.rs`.
+        let mut ctxt = call_site_ctxt;
+        for mark in self.marks() {
+            ctxt = ctxt.apply_mark_internal(mark);
+        }
+        ctxt.apply_mark_internal(mark)
+    }
+
+    fn apply_mark_internal(self, mark: Mark) -> SyntaxContext {
         HygieneData::with(|data| {
             let syntax_contexts = &mut data.syntax_contexts;
             let mut modern = syntax_contexts[self.0 as usize].modern;
@@ -222,8 +249,21 @@
         })
     }
 
+    pub fn marks(mut self) -> Vec<Mark> {
+        HygieneData::with(|data| {
+            let mut marks = Vec::new();
+            while self != SyntaxContext::empty() {
+                marks.push(data.syntax_contexts[self.0 as usize].outer_mark);
+                self = data.syntax_contexts[self.0 as usize].prev_ctxt;
+            }
+            marks.reverse();
+            marks
+        })
+    }
+
     /// Adjust this context for resolution in a scope created by the given expansion.
     /// For example, consider the following three resolutions of `f`:
+    ///
     /// ```rust
     /// mod foo { pub fn f() {} } // `f`'s `SyntaxContext` is empty.
     /// m!(f);
@@ -255,7 +295,8 @@
 
     /// Adjust this context for resolution in a scope created by the given expansion
     /// via a glob import with the given `SyntaxContext`.
-    /// For example,
+    /// For example:
+    ///
     /// ```rust
     /// m!(f);
     /// macro m($i:ident) {
@@ -293,6 +334,7 @@
     }
 
     /// Undo `glob_adjust` if possible:
+    ///
     /// ```rust
     /// if let Some(privacy_checking_scope) = self.reverse_glob_adjust(expansion, glob_ctxt) {
     ///     assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 0d837c4..f7880d3 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -36,14 +36,14 @@
 
 #![feature(asm)]
 #![feature(fnbox)]
-#![cfg_attr(unix, feature(libc))]
+#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
 #![feature(set_stdio)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
 
 extern crate getopts;
 extern crate term;
-#[cfg(unix)]
+#[cfg(any(unix, target_os = "cloudabi"))]
 extern crate libc;
 extern crate panic_unwind;
 
@@ -203,13 +203,6 @@
     pub allow_fail: bool,
 }
 
-#[derive(Clone)]
-pub struct TestPaths {
-    pub file: PathBuf,         // e.g., compile-test/foo/bar/baz.rs
-    pub base: PathBuf,         // e.g., compile-test, auxiliary
-    pub relative_dir: PathBuf, // e.g., foo/bar
-}
-
 #[derive(Debug)]
 pub struct TestDescAndFn {
     pub desc: TestDesc,
@@ -984,15 +977,13 @@
     }
 }
 
-#[cfg(target_os = "redox")]
+#[cfg(any(target_os = "cloudabi",
+          target_os = "redox",
+          all(target_arch = "wasm32", not(target_os = "emscripten"))))]
 fn stdout_isatty() -> bool {
     // FIXME: Implement isatty on Redox
     false
 }
-#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
-fn stdout_isatty() -> bool {
-    false
-}
 #[cfg(unix)]
 fn stdout_isatty() -> bool {
     unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
@@ -1200,13 +1191,14 @@
         1
     }
 
-    #[cfg(any(target_os = "linux",
-              target_os = "macos",
-              target_os = "ios",
-              target_os = "android",
-              target_os = "solaris",
+    #[cfg(any(target_os = "android",
+              target_os = "cloudabi",
               target_os = "emscripten",
-              target_os = "fuchsia"))]
+              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 }
     }
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
index f04394f..9f8b4a7 100644
--- a/src/libtest/stats.rs
+++ b/src/libtest/stats.rs
@@ -53,13 +53,13 @@
 
     /// Arithmetic mean (average) of the samples: sum divided by sample-count.
     ///
-    /// See: https://en.wikipedia.org/wiki/Arithmetic_mean
+    /// 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
+    /// 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
@@ -68,7 +68,7 @@
     /// 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
+    /// See: <https://en.wikipedia.org/wiki/Variance>
     fn var(&self) -> f64;
 
     /// Standard deviation: the square root of the sample variance.
@@ -76,7 +76,7 @@
     /// 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
+    /// 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`.
@@ -91,7 +91,7 @@
     /// 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
+    /// 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`.
@@ -103,7 +103,7 @@
     ///
     /// Calculated by linear interpolation between closest ranks.
     ///
-    /// See: http://en.wikipedia.org/wiki/Percentile
+    /// 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
@@ -111,13 +111,13 @@
     /// 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
+    /// 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
+    /// See also: <https://en.wikipedia.org/wiki/Interquartile_range>
     fn iqr(&self) -> f64;
 }
 
@@ -311,7 +311,7 @@
 /// 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
+/// 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);
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index d8457da..afd1e5e 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -43,5 +43,7 @@
         println!("cargo:rustc-link-lib=gcc_s");
     } else if target.contains("redox") {
         println!("cargo:rustc-link-lib=gcc");
+    } else if target.contains("cloudabi") {
+        println!("cargo:rustc-link-lib=unwind");
     }
 }
diff --git a/src/llvm b/src/llvm
index 6d08185..2717444 160000
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 6d08185a5cf488d0a853b065a8a3a6d7a29f084f
+Subproject commit 2717444753318e461e0c3b30dacd03ffbac96903
diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs
index d33b524..7d5581b 100644
--- a/src/rtstartup/rsbegin.rs
+++ b/src/rtstartup/rsbegin.rs
@@ -30,17 +30,11 @@
 #[lang = "sized"]
 trait Sized {}
 #[lang = "sync"]
-trait Sync {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Sync for .. {}
+auto trait Sync {}
 #[lang = "copy"]
 trait Copy {}
 #[lang = "freeze"]
-trait Freeze {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
 
 #[lang = "drop_in_place"]
 #[inline]
diff --git a/src/rtstartup/rsend.rs b/src/rtstartup/rsend.rs
index 410366d..f487f1d 100644
--- a/src/rtstartup/rsend.rs
+++ b/src/rtstartup/rsend.rs
@@ -22,10 +22,7 @@
 #[lang = "copy"]
 trait Copy {}
 #[lang = "freeze"]
-trait Freeze {}
-#[allow(unknown_lints)]
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
 
 #[lang = "drop_in_place"]
 #[inline]
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 776e4a3e..54a73a0 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -746,10 +746,6 @@
   unwrap(Module)->setDataLayout(Target->createDataLayout());
 }
 
-extern "C" LLVMTargetDataRef LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
-  return wrap(&unwrap(M)->getDataLayout());
-}
-
 extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
   unwrap(M)->setPIELevel(PIELevel::Level::Large);
 }
@@ -1182,6 +1178,15 @@
   MD->addOperand(Unit);
 }
 
+extern "C" void
+LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) {
+  Module *M = unwrap(Mod);
+  for (Function &F : M->functions()) {
+    if (F.hasAvailableExternallyLinkage())
+      F.deleteBody();
+  }
+}
+
 #else
 
 extern "C" bool
@@ -1272,4 +1277,10 @@
 LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod) {
   report_fatal_error("ThinLTO not available");
 }
+
+extern "C" void
+LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) {
+  report_fatal_error("ThinLTO not available");
+}
+
 #endif // LLVM_VERSION_GE(4, 0)
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 6f51ea6..0fe533d 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -76,11 +76,17 @@
   return Ret;
 }
 
-void LLVMRustSetLastError(const char *Err) {
+extern "C" void LLVMRustSetLastError(const char *Err) {
   free((void *)LastError);
   LastError = strdup(Err);
 }
 
+extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
+  auto ctx = new LLVMContext();
+  ctx->setDiscardValueNames(shouldDiscardNames);
+  return wrap(ctx);
+}
+
 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
                                             const char *Triple) {
   unwrap(M)->setTargetTriple(Triple::normalize(Triple));
@@ -378,12 +384,6 @@
   return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
 }
 
-extern "C" void LLVMRustSetDebug(int Enabled) {
-#ifndef NDEBUG
-  DebugFlag = Enabled;
-#endif
-}
-
 enum class LLVMRustAsmDialect {
   Other,
   Att,
@@ -866,7 +866,14 @@
   return dwarf::DW_OP_deref;
 }
 
-extern "C" int64_t LLVMRustDIBuilderCreateOpPlus() { return dwarf::DW_OP_plus; }
+extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
+#if LLVM_VERSION_GE(5, 0)
+  return dwarf::DW_OP_plus_uconst;
+#else
+  // older LLVM used `plus` to behave like `plus_uconst`.
+  return dwarf::DW_OP_plus;
+#endif
+}
 
 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
   RawRustStringOstream OS(Str);
@@ -927,23 +934,6 @@
   return true;
 }
 
-extern "C" bool LLVMRustLinkInParsedExternalBitcode(
-    LLVMModuleRef DstRef, LLVMModuleRef SrcRef) {
-#if LLVM_VERSION_GE(4, 0)
-  Module *Dst = unwrap(DstRef);
-  std::unique_ptr<Module> Src(unwrap(SrcRef));
-
-  if (Linker::linkModules(*Dst, std::move(Src))) {
-    LLVMRustSetLastError("failed to link modules");
-    return false;
-  }
-  return true;
-#else
-  LLVMRustSetLastError("can't link parsed modules on this LLVM");
-  return false;
-#endif
-}
-
 // Note that the two following functions look quite similar to the
 // LLVMGetSectionName function. Sadly, it appears that this function only
 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
@@ -975,7 +965,6 @@
 }
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
 
 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
   RawRustStringOstream OS(Str);
@@ -1124,13 +1113,6 @@
   report_fatal_error("Unhandled TypeID.");
 }
 
-extern "C" void LLVMRustWriteDebugLocToString(LLVMContextRef C,
-                                              LLVMDebugLocRef DL,
-                                              RustStringRef Str) {
-  RawRustStringOstream OS(Str);
-  unwrap(DL)->print(OS);
-}
-
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
 
 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
@@ -1144,13 +1126,6 @@
   unwrap(D)->print("", OS);
 }
 
-extern "C" LLVMValueRef
-LLVMRustBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
-                        LLVMValueRef PersFn, unsigned NumClauses,
-                        const char *Name, LLVMValueRef F) {
-  return LLVMBuildLandingPad(B, Ty, PersFn, NumClauses, Name);
-}
-
 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
                                                 LLVMValueRef ParentPad,
                                                 unsigned ArgCount,
@@ -1355,10 +1330,6 @@
     return true;
 }
 
-extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {
-  return wrap(&unwrap(V)->getContext());
-}
-
 enum class LLVMRustVisibility {
   Default = 0,
   Hidden = 1,
@@ -1439,11 +1410,6 @@
 
 extern "C" uint64_t
 LLVMRustModuleCost(LLVMModuleRef M) {
-  Module &Mod = *unwrap(M);
-  uint64_t cost = 0;
-  for (auto &F : Mod.functions()) {
-    (void)F;
-    cost += 1;
-  }
-  return cost;
+  auto f = unwrap(M)->functions();
+  return std::distance(std::begin(f), std::end(f));
 }
diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger
index feb6d98..7f54d92 100644
--- a/src/rustllvm/llvm-rebuild-trigger
+++ b/src/rustllvm/llvm-rebuild-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2017-11-07
+2017-11-08
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index 8c2f855..f4bd781 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -71,7 +71,7 @@
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/Linker/Linker.h"
 
-void LLVMRustSetLastError(const char *);
+extern "C" void LLVMRustSetLastError(const char *);
 
 enum class LLVMRustResult { Success, Failure };
 
@@ -103,9 +103,7 @@
 
 typedef struct OpaqueRustString *RustStringRef;
 typedef struct LLVMOpaqueTwine *LLVMTwineRef;
-typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
 typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
-typedef struct LLVMOpaqueRustJITMemoryManager *LLVMRustJITMemoryManagerRef;
 
 extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr,
                                         size_t Size);
diff --git a/src/stage0.txt b/src/stage0.txt
index eb0bedf..38a8ef2 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2017-11-21
+date: 2018-01-02
 rustc: beta
 cargo: beta
 
diff --git a/src/test/codegen-units/item-collection/cross-crate-closures.rs b/src/test/codegen-units/item-collection/cross-crate-closures.rs
index 2b5ac7e..320be27 100644
--- a/src/test/codegen-units/item-collection/cross-crate-closures.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-closures.rs
@@ -17,12 +17,14 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 // aux-build:cgu_extern_closures.rs
 extern crate cgu_extern_closures;
 
-//~ TRANS_ITEM fn cross_crate_closures::main[0]
-fn main() {
+//~ TRANS_ITEM fn cross_crate_closures::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
 
     //~ TRANS_ITEM fn cgu_extern_closures::inlined_fn[0]
     //~ TRANS_ITEM fn cgu_extern_closures::inlined_fn[0]::{{closure}}[0]
@@ -35,6 +37,8 @@
     // Nothing should be generated for this call, we just link to the instance
     // in the extern crate.
     let _ = cgu_extern_closures::non_inlined_fn(6, 7);
+
+    0
 }
 
 //~ TRANS_ITEM drop-glue i8
diff --git a/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs b/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
index eb4f9e8..bcb3b7b 100644
--- a/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
@@ -12,13 +12,14 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 // aux-build:cgu_generic_function.rs
 extern crate cgu_generic_function;
 
-//~ TRANS_ITEM fn cross_crate_generic_functions::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn cross_crate_generic_functions::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn cgu_generic_function::bar[0]<u32>
     //~ TRANS_ITEM fn cgu_generic_function::foo[0]<u32>
     let _ = cgu_generic_function::foo(1u32);
@@ -29,4 +30,6 @@
 
     // This should not introduce a codegen item
     let _ = cgu_generic_function::exported_but_not_generic(3);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/cross-crate-trait-method.rs b/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
index 1951257..910ae00 100644
--- a/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
@@ -12,15 +12,16 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 // aux-build:cgu_export_trait_method.rs
 extern crate cgu_export_trait_method;
 
 use cgu_export_trait_method::Trait;
 
-//~ TRANS_ITEM fn cross_crate_trait_method::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn cross_crate_trait_method::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     // The object code of these methods is contained in the external crate, so
     // calling them should *not* introduce codegen items in the current crate.
     let _: (u32, u32) = Trait::without_default_impl(0);
@@ -55,4 +56,6 @@
     let _: (char, char) = Trait::without_default_impl_generic('c');
     //~ TRANS_ITEM fn cgu_export_trait_method::{{impl}}[0]::without_default_impl_generic[0]<bool>
     let _: (char, bool) = Trait::without_default_impl_generic(false);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
index b8033b8..52af816 100644
--- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
+++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
@@ -12,6 +12,8 @@
 // compile-flags:-Zprint-trans-items=eager
 // compile-flags:-Zinline-in-all-cgus
 
+#![feature(start)]
+
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic0[Internal]
 struct StructWithDtor(u32);
 
@@ -20,13 +22,16 @@
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn drop_in_place_intrinsic::main[0]
-fn main() {
+//~ TRANS_ITEM fn drop_in_place_intrinsic::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic0[Internal]
     let x = [StructWithDtor(0), StructWithDtor(1)];
 
     drop_slice_in_place(&x);
+
+    0
 }
 
 //~ TRANS_ITEM fn drop_in_place_intrinsic::drop_slice_in_place[0]
diff --git a/src/test/codegen-units/item-collection/function-as-argument.rs b/src/test/codegen-units/item-collection/function-as-argument.rs
index c3d46ff..65707c1 100644
--- a/src/test/codegen-units/item-collection/function-as-argument.rs
+++ b/src/test/codegen-units/item-collection/function-as-argument.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 fn take_fn_once<T1, T2, F: FnOnce(T1, T2)>(f: F, x: T1, y: T2) {
     (f)(x, y)
@@ -23,8 +24,9 @@
     (f)(x, y)
 }
 
-//~ TRANS_ITEM fn function_as_argument::main[0]
-fn main() {
+//~ TRANS_ITEM fn function_as_argument::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
 
     //~ TRANS_ITEM fn function_as_argument::take_fn_once[0]<u32, &str, fn(u32, &str)>
     //~ TRANS_ITEM fn function_as_argument::function[0]<u32, &str>
@@ -43,4 +45,6 @@
     //~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0]<f32, i64>
     //~ TRANS_ITEM fn function_as_argument::function[0]<f32, i64>
     take_fn_pointer(function, 0f32, 0i64);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs
index 65936d1..d3d9aa3 100644
--- a/src/test/codegen-units/item-collection/generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 struct StructWithDrop<T1, T2> {
     x: T1,
@@ -53,8 +54,9 @@
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn generic_drop_glue::main[0]
-fn main() {
+//~ TRANS_ITEM fn generic_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue0[Internal]
     //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char>
     let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
@@ -94,4 +96,6 @@
         EnumNoDrop::A(x) => x,
         EnumNoDrop::B(x) => x as f64
     };
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/generic-functions.rs b/src/test/codegen-units/item-collection/generic-functions.rs
index afe6ffc..8efe4b2 100644
--- a/src/test/codegen-units/item-collection/generic-functions.rs
+++ b/src/test/codegen-units/item-collection/generic-functions.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 fn foo1<T1>(a: T1) -> (T1, u32) {
     (a, 1)
@@ -31,8 +32,9 @@
     a
 }
 
-//~ TRANS_ITEM fn generic_functions::main[0]
-fn main() {
+//~ TRANS_ITEM fn generic_functions::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn generic_functions::foo1[0]<i32>
     let _ = foo1(2i32);
     //~ TRANS_ITEM fn generic_functions::foo1[0]<i64>
@@ -59,4 +61,6 @@
     let _ = foo3(0i16, "a", 2usize);
     //~ TRANS_ITEM fn generic_functions::foo3[0]<char, (), ()>
     let _ = foo3('v', (), ());
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/generic-impl.rs b/src/test/codegen-units/item-collection/generic-impl.rs
index 14316a5..d1ee8ee 100644
--- a/src/test/codegen-units/item-collection/generic-impl.rs
+++ b/src/test/codegen-units/item-collection/generic-impl.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 struct Struct<T> {
     x: T,
@@ -50,9 +51,9 @@
     pub fn non_instantiated<T>(&self) {}
 }
 
-
-//~ TRANS_ITEM fn generic_impl::main[0]
-fn main() {
+//~ TRANS_ITEM fn generic_impl::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i32>
     //~ TRANS_ITEM fn generic_impl::id[0]<i32>
     //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i32, i16>
@@ -76,4 +77,6 @@
     //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<generic_impl::Struct[0]<&str>>
     //~ TRANS_ITEM fn generic_impl::id[0]<generic_impl::Struct[0]<&str>>
     let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str"));
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs b/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
index c43c254..c07d26c 100644
--- a/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
+++ b/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait SomeTrait {
     fn foo(&self);
@@ -28,7 +29,10 @@
     (x, 0)
 }
 
-//~ TRANS_ITEM fn impl_in_non_instantiated_generic::main[0]
-fn main() {
+//~ TRANS_ITEM fn impl_in_non_instantiated_generic::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     0i64.foo();
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
index e32366d..2e1138e 100644
--- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
+++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait Trait {
     fn foo(&self) -> u32;
@@ -28,8 +29,9 @@
     fn bar(&self) {}
 }
 
-//~ TRANS_ITEM fn instantiation_through_vtable::main[0]
-fn main() {
+//~ TRANS_ITEM fn instantiation_through_vtable::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let s1 = Struct { _a: 0u32 };
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable0[Internal]
@@ -42,4 +44,6 @@
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
     let _ = &s1 as &Trait;
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/items-within-generic-items.rs b/src/test/codegen-units/item-collection/items-within-generic-items.rs
index 75d842d..04b54de 100644
--- a/src/test/codegen-units/item-collection/items-within-generic-items.rs
+++ b/src/test/codegen-units/item-collection/items-within-generic-items.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 fn generic_fn<T>(a: T) -> (T, i32) {
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]::nested_fn[0]
@@ -31,12 +32,15 @@
     return (a, x + nested_fn(0));
 }
 
-//~ TRANS_ITEM fn items_within_generic_items::main[0]
-fn main() {
+//~ TRANS_ITEM fn items_within_generic_items::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i64>
     let _ = generic_fn(0i64);
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<u16>
     let _ = generic_fn(0u16);
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i8>
     let _ = generic_fn(0i8);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/non-generic-closures.rs b/src/test/codegen-units/item-collection/non-generic-closures.rs
index 278e918..f0121d5 100644
--- a/src/test/codegen-units/item-collection/non-generic-closures.rs
+++ b/src/test/codegen-units/item-collection/non-generic-closures.rs
@@ -17,6 +17,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn non_generic_closures::temporary[0]
 fn temporary() {
@@ -52,12 +53,15 @@
     f(4);
 }
 
-//~ TRANS_ITEM fn non_generic_closures::main[0]
-fn main() {
+//~ TRANS_ITEM fn non_generic_closures::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     temporary();
     assigned_to_variable_but_not_executed();
     assigned_to_variable_executed_directly();
     assigned_to_variable_executed_indirectly();
+
+    0
 }
 
 //~ TRANS_ITEM fn non_generic_closures::run_closure[0]
diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
index 5765f23..bf084aa 100644
--- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue0[Internal]
 struct StructWithDrop {
@@ -42,8 +43,9 @@
     A(i32)
 }
 
-//~ TRANS_ITEM fn non_generic_drop_glue::main[0]
-fn main() {
+//~ TRANS_ITEM fn non_generic_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _ = StructWithDrop { x: 0 }.x;
     let _ = StructNoDrop { x: 0 }.x;
     let _ = match EnumWithDrop::A(0) {
@@ -52,4 +54,6 @@
     let _ = match EnumNoDrop::A(0) {
         EnumNoDrop::A(x) => x
     };
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/non-generic-functions.rs b/src/test/codegen-units/item-collection/non-generic-functions.rs
index 26f9eb1..8c487db 100644
--- a/src/test/codegen-units/item-collection/non-generic-functions.rs
+++ b/src/test/codegen-units/item-collection/non-generic-functions.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn non_generic_functions::foo[0]
 fn foo() {
@@ -69,11 +70,14 @@
     }
 }
 
-//~ TRANS_ITEM fn non_generic_functions::main[0]
-fn main() {
+//~ TRANS_ITEM fn non_generic_functions::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     foo();
     bar();
     Struct::foo();
     let x = Struct { _x: 0 };
     x.bar();
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/static-init.rs b/src/test/codegen-units/item-collection/static-init.rs
index 3c9dcf3..5ff7c34 100644
--- a/src/test/codegen-units/item-collection/static-init.rs
+++ b/src/test/codegen-units/item-collection/static-init.rs
@@ -9,6 +9,9 @@
 // except according to those terms.
 
 // compile-flags:-Zprint-trans-items=eager
+// ignore-tidy-linelength
+
+#![feature(start)]
 
 pub static FN : fn() = foo::<i32>;
 
@@ -17,6 +20,9 @@
 //~ TRANS_ITEM fn static_init::foo[0]<i32>
 //~ TRANS_ITEM static static_init::FN[0]
 
-fn main() { }
+//~ TRANS_ITEM fn static_init::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    0
+}
 
-//~ TRANS_ITEM fn static_init::main[0]
diff --git a/src/test/codegen-units/item-collection/statics-and-consts.rs b/src/test/codegen-units/item-collection/statics-and-consts.rs
index 89bc620..11df1da 100644
--- a/src/test/codegen-units/item-collection/statics-and-consts.rs
+++ b/src/test/codegen-units/item-collection/statics-and-consts.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 static STATIC1: i64 = {
     const STATIC1_CONST1: i64 = 2;
@@ -47,9 +48,13 @@
     };
 }
 
-fn main() {
+//~ TRANS_ITEM fn statics_and_consts::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     foo();
     let _ = STATIC1;
+
+    0
 }
 
 //~ TRANS_ITEM static statics_and_consts::STATIC1[0]
@@ -58,5 +63,3 @@
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[0]
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[1]
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[2]
-
-//~ TRANS_ITEM fn statics_and_consts::main[0]
diff --git a/src/test/codegen-units/item-collection/trait-implementations.rs b/src/test/codegen-units/item-collection/trait-implementations.rs
index e8a7d8f..8eb33dd 100644
--- a/src/test/codegen-units/item-collection/trait-implementations.rs
+++ b/src/test/codegen-units/item-collection/trait-implementations.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 pub trait SomeTrait {
     fn foo(&self);
@@ -55,8 +56,9 @@
     fn bar<T2>(&self, _: T, _: T2) {}
 }
 
-//~ TRANS_ITEM fn trait_implementations::main[0]
-fn main() {
+//~ TRANS_ITEM fn trait_implementations::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
    //~ TRANS_ITEM fn trait_implementations::{{impl}}[1]::bar[0]<char>
    0i32.bar('x');
 
@@ -77,4 +79,6 @@
 
    //~ TRANS_ITEM fn trait_implementations::{{impl}}[3]::bar[0]<&str, &str>
    0f32.bar("&str", "&str");
+
+   0
 }
diff --git a/src/test/codegen-units/item-collection/trait-method-as-argument.rs b/src/test/codegen-units/item-collection/trait-method-as-argument.rs
index 21c9c25..10b2163 100644
--- a/src/test/codegen-units/item-collection/trait-method-as-argument.rs
+++ b/src/test/codegen-units/item-collection/trait-method-as-argument.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait Trait : Sized {
     fn foo(self) -> Self { self }
@@ -36,8 +37,9 @@
     (f)(arg)
 }
 
-//~ TRANS_ITEM fn trait_method_as_argument::main[0]
-fn main() {
+//~ TRANS_ITEM fn trait_method_as_argument::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0]<u32, fn(u32) -> u32>
     //~ TRANS_ITEM fn trait_method_as_argument::{{impl}}[0]::foo[0]
     //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0]<fn(u32) -> u32, (u32)>
@@ -63,4 +65,6 @@
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0]<char, fn(char) -> char>
     //~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0]<fn(u32) -> u32, (u32)>
     take_foo_mut(Trait::foo, 'c');
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/trait-method-default-impl.rs b/src/test/codegen-units/item-collection/trait-method-default-impl.rs
index 5b24a21..a6ae376 100644
--- a/src/test/codegen-units/item-collection/trait-method-default-impl.rs
+++ b/src/test/codegen-units/item-collection/trait-method-default-impl.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait SomeTrait {
     fn foo(&self) { }
@@ -46,8 +47,9 @@
     // since nothing is monomorphic here, nothing should be generated unless used somewhere.
 }
 
-//~ TRANS_ITEM fn trait_method_default_impl::main[0]
-fn main() {
+//~ TRANS_ITEM fn trait_method_default_impl::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, char>
     let _ = 1i8.bar('c');
 
@@ -65,4 +67,6 @@
 
     //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i16, ()>
     0u32.bar(0i16, ());
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
index be56069..57cd101 100644
--- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue0[Internal]
 struct Root(Intermediate);
@@ -34,9 +35,9 @@
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn transitive_drop_glue::main[0]
-fn main() {
-
+//~ TRANS_ITEM fn transitive_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _ = Root(Intermediate(Leaf));
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue0[Internal]
@@ -50,4 +51,6 @@
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue0[Internal]
     //~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16>
     let _ = RootGen(IntermediateGen(LeafGen(0i16)));
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
index ad1475a..a5f2409 100644
--- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue0[Internal]
 struct Dropped;
@@ -22,12 +23,15 @@
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn tuple_drop_glue::main[0]
-fn main() {
+//~ TRANS_ITEM fn tuple_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue0[Internal]
     let x = (0u32, Dropped);
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue0[Internal]
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue0[Internal]
     let x = (0i16, (Dropped, true));
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs
index d7e457c..87d2581 100644
--- a/src/test/codegen-units/item-collection/unsizing.rs
+++ b/src/test/codegen-units/item-collection/unsizing.rs
@@ -15,6 +15,7 @@
 #![deny(dead_code)]
 #![feature(coerce_unsized)]
 #![feature(unsize)]
+#![feature(start)]
 
 use std::marker::Unsize;
 use std::ops::CoerceUnsized;
@@ -53,9 +54,9 @@
 
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
 
-//~ TRANS_ITEM fn unsizing::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn unsizing::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     // simple case
     let bool_sized = &true;
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing0[Internal]
@@ -83,4 +84,6 @@
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing0[Internal]
     //~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0]
     let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
+
+    0
 }
diff --git a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs
index 1ea5aaf..aa01289 100644
--- a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs
+++ b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs
@@ -19,6 +19,7 @@
 // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/methods-are-with-self-type
 
 #![allow(dead_code)]
+#![feature(start)]
 
 struct SomeType;
 
@@ -63,9 +64,9 @@
     pub struct Struct;
 }
 
-//~ TRANS_ITEM fn methods_are_with_self_type::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn methods_are_with_self_type::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::method[0]<u32, u64> @@ methods_are_with_self_type.volatile[WeakODR]
     SomeGenericType(0u32, 0u64).method();
     //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::associated_fn[0]<char, &str> @@ methods_are_with_self_type.volatile[WeakODR]
@@ -80,6 +81,8 @@
     type1::Struct.default();
     //~ TRANS_ITEM fn methods_are_with_self_type::Trait[0]::default[0]<methods_are_with_self_type::type2[0]::Struct[0]> @@ methods_are_with_self_type-type2.volatile[WeakODR]
     type2::Struct.default();
+
+    0
 }
 
 //~ TRANS_ITEM drop-glue i8
diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs
index 302f931..d0acddd 100644
--- a/src/test/codegen-units/partitioning/vtable-through-const.rs
+++ b/src/test/codegen-units/partitioning/vtable-through-const.rs
@@ -18,6 +18,8 @@
 // This test case makes sure, that references made through constants are
 // recorded properly in the InliningMap.
 
+#![feature(start)]
+
 mod mod1 {
     pub trait Trait1 {
         fn do_something(&self) {}
@@ -38,7 +40,7 @@
 
     fn id<T>(x: T) -> T { x }
 
-    // These are referenced, so they produce trans-items (see main())
+    // These are referenced, so they produce trans-items (see start())
     pub const TRAIT1_REF: &'static Trait1 = &0u32 as &Trait1;
     pub const TRAIT1_GEN_REF: &'static Trait1Gen<u8> = &0u32 as &Trait1Gen<u8>;
     pub const ID_CHAR: fn(char) -> char = id::<char>;
@@ -68,8 +70,9 @@
     pub const ID_I64: fn(i64) -> i64 = id::<i64>;
 }
 
-//~ TRANS_ITEM fn vtable_through_const::main[0] @@ vtable_through_const[Internal]
-fn main() {
+//~ TRANS_ITEM fn vtable_through_const::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]
 
     // Since Trait1::do_something() is instantiated via its default implementation,
@@ -90,4 +93,6 @@
 
     //~ TRANS_ITEM fn vtable_through_const::mod1[0]::id[0]<char> @@ vtable_through_const-mod1.volatile[External]
     mod1::ID_CHAR('x');
+
+    0
 }
diff --git a/src/test/codegen/align-struct.rs b/src/test/codegen/align-struct.rs
index 3b720dc..ab9f5dd 100644
--- a/src/test/codegen/align-struct.rs
+++ b/src/test/codegen/align-struct.rs
@@ -32,13 +32,14 @@
     A(i32),
     B(i32),
 }
-// CHECK: %Enum4 = type { [2 x i32] }
+// CHECK: %Enum4 = type { [0 x i32], i32, [1 x i32] }
+// CHECK: %"Enum4::A" = type { [1 x i32], i32, [0 x i32] }
 
 pub enum Enum64 {
     A(Align64),
     B(i32),
 }
-// CHECK: %Enum64 = type { [16 x i64] }
+// CHECK: %Enum64 = type { [0 x i32], i32, [31 x i32] }
 // CHECK: %"Enum64::A" = type { [8 x i64], %Align64, [0 x i64] }
 
 // CHECK-LABEL: @align64
diff --git a/src/test/codegen/dllimports/main.rs b/src/test/codegen/dllimports/main.rs
index 64f516a..d0fafbd 100644
--- a/src/test/codegen/dllimports/main.rs
+++ b/src/test/codegen/dllimports/main.rs
@@ -9,19 +9,20 @@
 // except according to those terms.
 
 // This test is for *-windows-msvc only.
-// ignore-gnu
 // ignore-android
 // ignore-bitrig
-// ignore-macos
+// ignore-cloudabi
 // ignore-dragonfly
+// ignore-emscripten
 // ignore-freebsd
+// ignore-gnu
 // ignore-haiku
 // ignore-ios
 // ignore-linux
+// ignore-macos
 // ignore-netbsd
 // ignore-openbsd
 // ignore-solaris
-// ignore-emscripten
 
 // aux-build:dummy.rs
 // aux-build:wrapper.rs
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/codegen/issue-45466.rs
similarity index 62%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/codegen/issue-45466.rs
index 5c32a75..3702b67 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/codegen/issue-45466.rs
@@ -8,9 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// min-llvm-version 4.0
+// compile-flags: -O
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#![crate_type="rlib"]
+
+// CHECK-LABEL: @memzero
+// CHECK-NOT: store
+// CHECK: call void @llvm.memset
+// CHECK-NOT: store
+#[no_mangle]
+pub fn memzero(data: &mut [u8]) {
+    for i in 0..data.len() {
+        data[i] = 0;
+    }
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/codegen/issue-47278.rs
similarity index 62%
copy from src/test/compile-fail/E0580.rs
copy to src/test/codegen/issue-47278.rs
index a2ef7da..21858b4 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/codegen/issue-47278.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+// -C no-prepopulate-passes
+#![crate_type="staticlib"]
+
+#[repr(C)]
+pub struct Foo(u64);
+
+// CHECK: define {{.*}} @foo(
+#[no_mangle]
+pub extern fn foo(_: Foo) -> Foo { loop {} }
diff --git a/src/test/codegen/issue-47442.rs b/src/test/codegen/issue-47442.rs
new file mode 100644
index 0000000..d0c9932
--- /dev/null
+++ b/src/test/codegen/issue-47442.rs
@@ -0,0 +1,32 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that we don't emit unneeded `resume` cleanup blocks for every
+// destructor.
+
+// CHECK-NOT: Unwind
+
+#![feature(test)]
+#![crate_type="rlib"]
+
+extern crate test;
+
+struct Foo {}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        test::black_box(());
+    }
+}
+
+#[no_mangle]
+pub fn foo() {
+    let _foo = Foo {};
+}
diff --git a/src/test/codegen/link-dead-code.rs b/src/test/codegen/link-dead-code.rs
new file mode 100644
index 0000000..9cabcd9
--- /dev/null
+++ b/src/test/codegen/link-dead-code.rs
@@ -0,0 +1,27 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-Clink-dead-code
+
+#![feature(const_fn)]
+#![crate_type = "rlib"]
+
+// This test makes sure that, when -Clink-dead-code is specified, we generate
+// code for functions that would otherwise be skipped.
+
+// CHECK-LABEL: define hidden i32 @_ZN14link_dead_code8const_fn
+const fn const_fn() -> i32 { 1 }
+
+// CHECK-LABEL: define hidden i32 @_ZN14link_dead_code9inline_fn
+#[inline]
+fn inline_fn() -> i32 { 2 }
+
+// CHECK-LABEL: define hidden i32 @_ZN14link_dead_code10private_fn
+fn private_fn() -> i32 { 3 }
diff --git a/src/test/codegen/panic-abort-windows.rs b/src/test/codegen/panic-abort-windows.rs
index 15688bd..f1affcc 100644
--- a/src/test/codegen/panic-abort-windows.rs
+++ b/src/test/codegen/panic-abort-windows.rs
@@ -13,16 +13,17 @@
 // This test is for *-windows-msvc only.
 // ignore-android
 // ignore-bitrig
-// ignore-macos
+// ignore-cloudabi
 // ignore-dragonfly
+// ignore-emscripten
 // ignore-freebsd
 // ignore-haiku
 // ignore-ios
 // ignore-linux
+// ignore-macos
 // ignore-netbsd
 // ignore-openbsd
 // ignore-solaris
-// ignore-emscripten
 
 // compile-flags: -C no-prepopulate-passes -C panic=abort -O
 
diff --git a/src/test/codegen/prefetch.rs b/src/test/codegen/prefetch.rs
index 9ca2f01..3a23c16 100644
--- a/src/test/codegen/prefetch.rs
+++ b/src/test/codegen/prefetch.rs
@@ -71,5 +71,3 @@
         prefetch_write_instruction(data.as_ptr(), 3);
     }
 }
-
-
diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs
new file mode 100644
index 0000000..2eeed2b
--- /dev/null
+++ b/src/test/codegen/repr-transparent-aggregates-1.rs
@@ -0,0 +1,53 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+// ignore-arm
+// ignore-mips
+// ignore-mips64
+// ignore-powerpc
+// ignore-powerpc64
+// See repr-transparent.rs
+
+#![crate_type="lib"]
+#![feature(repr_transparent)]
+
+
+#[repr(C)]
+pub struct Big([u32; 16]);
+
+#[repr(transparent)]
+pub struct BigW(Big);
+
+// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], %Big* [[BIG_ARG_ATTRS:.*]])
+#[no_mangle]
+pub extern fn test_Big(_: Big) -> Big { loop {} }
+
+// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], %BigW* [[BIG_ARG_ATTRS]])
+#[no_mangle]
+pub extern fn test_BigW(_: BigW) -> BigW { loop {} }
+
+
+#[repr(C)]
+pub union BigU {
+    foo: [u32; 16],
+}
+
+#[repr(transparent)]
+pub struct BigUw(BigU);
+
+// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], %BigU* [[BIGU_ARG_ATTRS:.*]])
+#[no_mangle]
+pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], %BigUw* [[BIGU_ARG_ATTRS]])
+#[no_mangle]
+pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} }
diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs
new file mode 100644
index 0000000..e637492
--- /dev/null
+++ b/src/test/codegen/repr-transparent-aggregates-2.rs
@@ -0,0 +1,54 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+// ignore-aarch64
+// ignore-asmjs
+// ignore-s390x
+// ignore-wasm
+// ignore-x86
+// ignore-x86_64
+// See repr-transparent.rs
+
+#![crate_type="lib"]
+#![feature(repr_transparent)]
+
+
+#[repr(C)]
+pub struct Big([u32; 16]);
+
+#[repr(transparent)]
+pub struct BigW(Big);
+
+// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], [16 x i32]
+#[no_mangle]
+pub extern fn test_Big(_: Big) -> Big { loop {} }
+
+// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigW(_: BigW) -> BigW { loop {} }
+
+
+#[repr(C)]
+pub union BigU {
+    foo: [u32; 16],
+}
+
+#[repr(transparent)]
+pub struct BigUw(BigU);
+
+// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} }
diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs
new file mode 100644
index 0000000..31020d8
--- /dev/null
+++ b/src/test/codegen/repr-transparent.rs
@@ -0,0 +1,177 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="lib"]
+#![feature(repr_transparent, repr_simd)]
+
+use std::marker::PhantomData;
+
+pub struct Zst1;
+pub struct Zst2(());
+
+#[repr(transparent)]
+pub struct F32(f32);
+
+// CHECK: define float @test_F32(float %arg0)
+#[no_mangle]
+pub extern fn test_F32(_: F32) -> F32 { loop {} }
+
+#[repr(transparent)]
+pub struct Ptr(*mut u8);
+
+// CHECK: define i8* @test_Ptr(i8* %arg0)
+#[no_mangle]
+pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} }
+
+#[repr(transparent)]
+pub struct WithZst(u64, Zst1);
+
+// CHECK: define i64 @test_WithZst(i64 %arg0)
+#[no_mangle]
+pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} }
+
+#[repr(transparent)]
+pub struct WithZeroSizedArray(*const f32, [i8; 0]);
+
+// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
+// CHECK: define i32* @test_WithZeroSizedArray(i32* %arg0)
+#[no_mangle]
+pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
+
+#[repr(transparent)]
+pub struct Generic<T>(T);
+
+// CHECK: define double @test_Generic(double %arg0)
+#[no_mangle]
+pub extern fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
+
+#[repr(transparent)]
+pub struct GenericPlusZst<T>(T, Zst2);
+
+#[repr(u8)]
+pub enum Bool { True, False, FileNotFound }
+
+// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %arg0)
+#[no_mangle]
+pub extern fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
+
+#[repr(transparent)]
+pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
+
+// CHECK: define i16* @test_LifetimePhantom(i16* %arg0)
+#[no_mangle]
+pub extern fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
+
+// This works despite current alignment resrictions because PhantomData is always align(1)
+#[repr(transparent)]
+pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> }
+
+pub struct Px;
+
+// CHECK: define float @test_UnitPhantom(float %arg0)
+#[no_mangle]
+pub extern fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
+
+#[repr(transparent)]
+pub struct TwoZsts(Zst1, i8, Zst2);
+
+// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %arg0)
+#[no_mangle]
+pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
+
+#[repr(transparent)]
+pub struct Nested1(Zst2, Generic<f64>);
+
+// CHECK: define double @test_Nested1(double %arg0)
+#[no_mangle]
+pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
+
+#[repr(transparent)]
+pub struct Nested2(Nested1, Zst1);
+
+// CHECK: define double @test_Nested2(double %arg0)
+#[no_mangle]
+pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
+
+#[repr(simd)]
+struct f32x4(f32, f32, f32, f32);
+
+#[repr(transparent)]
+pub struct Vector(f32x4);
+
+// CHECK: define <4 x float> @test_Vector(<4 x float> %arg0)
+#[no_mangle]
+pub extern fn test_Vector(_: Vector) -> Vector { loop {} }
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+
+#[repr(transparent)]
+pub struct StructWithProjection(<f32 as Mirror>::It);
+
+// CHECK: define float @test_Projection(float %arg0)
+#[no_mangle]
+pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
+
+
+// The rest of this file tests newtypes around small aggregates on an ABI where small aggregates are
+// packed into one register. This is ABI-dependent, so instead we focus on one ABI and supply a
+// dummy definition for other ABIs to keep FileCheck happy.
+//
+// Bigger aggregates are tested in separate files called repr-transparent-aggregate-*.rs because
+// there, the expected LLVM IR function signatures vary so much that it's not reasonably possible to
+// cover all of them with a single CHECK line. Instead we group ABIs by the general "shape" of the
+// signature and have a separate test file for each bin.
+//
+// PS: You may be wondering why we don't just compare the return types and argument types for
+// equality with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on
+// newtypes containing aggregates. This is OK on all ABIs we support, but because LLVM has not
+// gotten rid of pointee types yet, the IR function signature will be syntactically different (%Foo*
+// vs %FooWrapper*).
+
+#[repr(C)]
+pub struct Rgb8 { r: u8, g: u8, b: u8 }
+
+#[repr(transparent)]
+pub struct Rgb8Wrap(Rgb8);
+
+// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not
+// CHECK: define i32 @test_Rgb8Wrap(i32
+#[no_mangle]
+#[cfg(all(target_arch="x86_64", target_os="linux"))]
+pub extern fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} }
+
+#[cfg(not(all(target_arch="x86_64", target_os="linux")))]
+#[no_mangle]
+pub extern fn test_Rgb8Wrap(_: u32) -> u32 { loop {} }
+
+// Same as with the small struct above: ABI-dependent, we only test the interesting case
+// (ABIs that pack the aggregate into a scalar) and stub it out on other ABIs
+
+#[repr(C)]
+pub union FloatBits {
+    float: f32,
+    bits: u32,
+}
+
+#[repr(transparent)]
+pub struct SmallUnion(FloatBits);
+
+// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not
+// CHECK: define i32 @test_SmallUnion(i32
+#[no_mangle]
+#[cfg(all(target_arch="x86_64", target_os="linux"))]
+pub extern fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} }
+
+#[cfg(not(all(target_arch="x86_64", target_os="linux")))]
+#[no_mangle]
+pub extern fn test_SmallUnion(_: u32) -> u32 { loop {} }
diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs
index 2a20c28..8b448e4 100644
--- a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs
+++ b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that macro reexports item are gated by `macro_reexport` feature gate.
+// Test that macro re-exports item are gated by `macro_reexport` feature gate.
 
 // aux-build:macro_reexport_1.rs
 // gate-test-macro_reexport
@@ -16,6 +16,6 @@
 #![crate_type = "dylib"]
 
 #[macro_reexport(reexported)]
-//~^ ERROR macros reexports are experimental and possibly buggy
+//~^ ERROR macros re-exports are experimental and possibly buggy
 #[macro_use] #[no_link]
 extern crate macro_reexport_1;
diff --git a/src/test/compile-fail/E0004.rs b/src/test/compile-fail/E0004.rs
index 79e53c7..8df07a0 100644
--- a/src/test/compile-fail/E0004.rs
+++ b/src/test/compile-fail/E0004.rs
@@ -19,4 +19,4 @@
     match x { //~ ERROR E0004
         Terminator::TalkToMyHand => {}
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/compile-fail/E0185.rs b/src/test/compile-fail/E0185.rs
index be54c37..0cd3d00 100644
--- a/src/test/compile-fail/E0185.rs
+++ b/src/test/compile-fail/E0185.rs
@@ -9,14 +9,16 @@
 // except according to those terms.
 
 trait Foo {
-    fn foo(); //~ trait declared without `&self`
+    fn foo();
+    //~^ NOTE trait method declared without `&self`
 }
 
 struct Bar;
 
 impl Foo for Bar {
-    fn foo(&self) {} //~ ERROR E0185
-    //~^ `&self` used in impl
+    fn foo(&self) {}
+    //~^ ERROR E0185
+    //~| NOTE `&self` used in impl
 }
 
 fn main() {
diff --git a/src/test/compile-fail/E0198.rs b/src/test/compile-fail/E0198.rs
index 892989c..1a779a4 100644
--- a/src/test/compile-fail/E0198.rs
+++ b/src/test/compile-fail/E0198.rs
@@ -12,7 +12,7 @@
 
 struct Foo;
 
-unsafe impl !Clone for Foo { } //~ ERROR negative implementations are not unsafe [E0198]
+unsafe impl !Send for Foo { } //~ ERROR E0198
 
 fn main() {
 }
diff --git a/src/test/compile-fail/E0277.rs b/src/test/compile-fail/E0277.rs
index 784f746..b29e435 100644
--- a/src/test/compile-fail/E0277.rs
+++ b/src/test/compile-fail/E0277.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::path
+
 use std::path::Path;
 
 trait Foo {
diff --git a/src/test/compile-fail/E0365.rs b/src/test/compile-fail/E0365.rs
index a1efcde..18a72b0 100644
--- a/src/test/compile-fail/E0365.rs
+++ b/src/test/compile-fail/E0365.rs
@@ -13,6 +13,6 @@
 }
 
 pub use foo as foo2;
-//~^ ERROR `foo` is private, and cannot be reexported [E0365]
+//~^ ERROR `foo` is private, and cannot be re-exported [E0365]
 
 fn main() {}
diff --git a/src/test/compile-fail/E0532.rs b/src/test/compile-fail/E0532.rs
new file mode 100644
index 0000000..5dc3b5f
--- /dev/null
+++ b/src/test/compile-fail/E0532.rs
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let value = 1;
+
+    match SomeStruct(value) {
+        StructConst1(_) => { },
+        //~^ ERROR expected tuple struct/variant, found constant `StructConst1`
+        _ => { },
+    }
+
+    struct SomeStruct(u8);
+
+    const StructConst1 : SomeStruct = SomeStruct(1);
+    const StructConst2 : SomeStruct = SomeStruct(2);
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/E0599.rs
similarity index 72%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/E0599.rs
index a2ef7da..30fca2b 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/E0599.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+struct Foo;
+
+fn main() {
+    || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599
+}
diff --git a/src/test/compile-fail/E0618.rs b/src/test/compile-fail/E0618.rs
index f28ac20..f46bdb9 100644
--- a/src/test/compile-fail/E0618.rs
+++ b/src/test/compile-fail/E0618.rs
@@ -13,7 +13,9 @@
 }
 
 fn main() {
-    X::Entry(); //~ ERROR expected function, found `X::Entry` [E0618]
+    X::Entry();
+    //~^ ERROR expected function, found enum variant `X::Entry` [E0618]
     let x = 0i32;
-    x(); //~ ERROR expected function, found `i32` [E0618]
+    x();
+    //~^ ERROR expected function, found `i32` [E0618]
 }
diff --git a/src/test/compile-fail/E0657.rs b/src/test/compile-fail/E0657.rs
index b72a8f0..4595e41 100644
--- a/src/test/compile-fail/E0657.rs
+++ b/src/test/compile-fail/E0657.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 #![allow(warnings)]
-#![feature(conservative_impl_trait)]
+#![feature(conservative_impl_trait, nested_impl_trait)]
 
 trait Id<T> {}
 trait Lt<'a> {}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/E0658.rs
similarity index 76%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/E0658.rs
index a2ef7da..d30068e 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/E0658.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+fn main() {
+    let _ = ::std::u128::MAX; //~ ERROR E0658
+}
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/compile-fail/E0659.rs
similarity index 64%
copy from src/test/compile-fail/regions-escape-unboxed-closure.rs
copy to src/test/compile-fail/E0659.rs
index cf41fad..4bd452b 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/compile-fail/E0659.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,10 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: &mut FnMut(&isize)) {
+mod moon {
+    pub fn foo() {}
+}
+
+mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon::*;
+    pub use earth::*;
 }
 
 fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+    collider::foo(); //~ ERROR E0659
 }
diff --git a/src/test/compile-fail/asm-out-read-uninit.rs b/src/test/compile-fail/asm-out-read-uninit.rs
index c85a097..02462bf 100644
--- a/src/test/compile-fail/asm-out-read-uninit.rs
+++ b/src/test/compile-fail/asm-out-read-uninit.rs
@@ -13,6 +13,9 @@
 // ignore-powerpc
 // ignore-sparc
 
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
 #![feature(asm)]
 
 fn foo(x: isize) { println!("{}", x); }
@@ -24,7 +27,9 @@
 pub fn main() {
     let x: isize;
     unsafe {
-        asm!("mov $1, $0" : "=r"(x) : "r"(x)); //~ ERROR use of possibly uninitialized variable: `x`
+        asm!("mov $1, $0" : "=r"(x) : "r"(x));
+        //[ast]~^ ERROR use of possibly uninitialized variable: `x`
+        //[mir]~^^ ERROR use of possibly uninitialized variable: `x`
     }
     foo(x);
 }
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/associated-const-in-trait.rs
similarity index 67%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/associated-const-in-trait.rs
index 5c32a75..f837d9a 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/associated-const-in-trait.rs
@@ -8,9 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// #29924
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#![feature(const_fn, associated_consts)]
+
+trait Trait {
+    const N: usize;
+}
+
+impl Trait {
+    //~^ ERROR the trait `Trait` cannot be made into an object [E0038]
+    const fn n() -> usize { Self::N }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/auto-trait-validation.rs b/src/test/compile-fail/auto-trait-validation.rs
index b28b776..92b222e 100644
--- a/src/test/compile-fail/auto-trait-validation.rs
+++ b/src/test/compile-fail/auto-trait-validation.rs
@@ -11,12 +11,9 @@
 #![feature(optin_builtin_traits)]
 
 auto trait Generic<T> {}
-//~^ ERROR auto traits cannot have generics
-//~^^ traits with auto impls (`e.g. impl Trait for ..`) can not have type parameters
+//~^ auto traits cannot have generic parameters [E0567]
 auto trait Bound : Copy {}
-//~^ ERROR auto traits cannot have super traits
-//~^^ traits with auto impls (`e.g. impl Trait for ..`) cannot have predicates
+//~^ auto traits cannot have super traits [E0568]
 auto trait MyTrait { fn foo() {} }
-//~^ ERROR auto traits cannot contain items
-//~^^ traits with default impls (`e.g. impl Trait for ..`) must have no methods or associated items
+//~^ auto traits cannot have methods or associated items [E0380]
 fn main() {}
diff --git a/src/test/compile-fail/auxiliary/static_priv_by_default.rs b/src/test/compile-fail/auxiliary/static_priv_by_default.rs
index 859f38e..73597e5 100644
--- a/src/test/compile-fail/auxiliary/static_priv_by_default.rs
+++ b/src/test/compile-fail/auxiliary/static_priv_by_default.rs
@@ -32,7 +32,7 @@
         fn foo() {}
     }
 
-    // these are public so the parent can reexport them.
+    // these are public so the parent can re-export them.
     pub static reexported_a: isize = 0;
     pub fn reexported_b() {}
     pub struct reexported_c;
diff --git a/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs b/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs
index 1e1c55d..f6f7a25 100644
--- a/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs
+++ b/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs
@@ -11,8 +11,6 @@
 #![feature(optin_builtin_traits, core)]
 #![crate_type = "rlib"]
 
-pub trait DefaultedTrait { }
-#[allow(auto_impl)]
-impl DefaultedTrait for .. { }
+pub auto trait DefaultedTrait { }
 
 pub struct Something<T> { t: T }
diff --git a/src/test/compile-fail/bad-env-capture.rs b/src/test/compile-fail/bad-env-capture.rs
index 9386648..6a5e4cf 100644
--- a/src/test/compile-fail/bad-env-capture.rs
+++ b/src/test/compile-fail/bad-env-capture.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: can't capture dynamic environment in a fn item;
+// error-pattern: can't capture dynamic environment in a fn item
 fn foo() {
     let x: isize;
     fn bar() { log(debug, x); }
diff --git a/src/test/compile-fail/bad-env-capture2.rs b/src/test/compile-fail/bad-env-capture2.rs
index 39a6922..cf67c73 100644
--- a/src/test/compile-fail/bad-env-capture2.rs
+++ b/src/test/compile-fail/bad-env-capture2.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: can't capture dynamic environment in a fn item;
+// error-pattern: can't capture dynamic environment in a fn item
 fn foo(x: isize) {
     fn bar() { log(debug, x); }
 }
diff --git a/src/test/compile-fail/bad-env-capture3.rs b/src/test/compile-fail/bad-env-capture3.rs
index 8857b94..a30c677 100644
--- a/src/test/compile-fail/bad-env-capture3.rs
+++ b/src/test/compile-fail/bad-env-capture3.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: can't capture dynamic environment in a fn item;
+// error-pattern: can't capture dynamic environment in a fn item
 fn foo(x: isize) {
     fn mth() {
         fn bar() { log(debug, x); }
diff --git a/src/test/compile-fail/borrowck/borrowck-asm.rs b/src/test/compile-fail/borrowck/borrowck-asm.rs
new file mode 100644
index 0000000..6bccc83
--- /dev/null
+++ b/src/test/compile-fail/borrowck/borrowck-asm.rs
@@ -0,0 +1,97 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-s390x
+// ignore-emscripten
+// ignore-powerpc
+// ignore-sparc
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir -Z nll
+
+#![feature(asm)]
+
+#[cfg(any(target_arch = "x86",
+            target_arch = "x86_64",
+            target_arch = "arm",
+            target_arch = "aarch64"))]
+mod test_cases {
+    fn is_move() {
+        let y: &mut isize;
+        let x = &mut 0isize;
+        unsafe {
+            asm!("nop" : : "r"(x));
+        }
+        let z = x;  //[ast]~ ERROR use of moved value: `x`
+                    //[mir]~^ ERROR use of moved value: `x`
+    }
+
+    fn in_is_read() {
+        let mut x = 3;
+        let y = &mut x;
+        unsafe {
+            asm!("nop" : : "r"(x)); //[ast]~ ERROR cannot use
+                                    //[mir]~^ ERROR cannot use
+        }
+        let z = y;
+    }
+
+    fn out_is_assign() {
+        let x = 3;
+        unsafe {
+            asm!("nop" : "=r"(x));  //[ast]~ ERROR cannot assign twice
+                                    //[mir]~^ ERROR cannot assign twice
+        }
+        let mut a = &mut 3;
+        let b = &*a;
+        unsafe {
+            asm!("nop" : "=r"(a));  //[ast]~ ERROR cannot assign to `a` because it is borrowed
+                                    // No MIR error, this is a shallow write.
+        }
+        let c = b;
+        let d = *a;
+    }
+
+    fn rw_is_assign() {
+        let x = 3;
+        unsafe {
+            asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign twice
+                                    //[mir]~^ ERROR cannot assign twice
+        }
+    }
+
+    fn indirect_is_not_init() {
+        let x: i32;
+        unsafe {
+            asm!("nop" : "=*r"(x)); //[ast]~ ERROR use of possibly uninitialized variable
+                                    //[mir]~^ ERROR use of possibly uninitialized variable
+        }
+    }
+
+    fn rw_is_read() {
+        let mut x = &mut 3;
+        let y = &*x;
+        unsafe {
+            asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign to `x` because it is borrowed
+                                    //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+        }
+        let z = y;
+    }
+
+    fn two_moves() {
+        let x = &mut 2;
+        unsafe {
+            asm!("nop" : : "r"(x), "r"(x) );    //[ast]~ ERROR use of moved value
+                                                //[mir]~^ ERROR use of moved value
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs
index b6f5e17..a9797e4 100644
--- a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs
+++ b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs
@@ -56,7 +56,6 @@
     let _z = &x;
     *y += 1;
     //[lxl]~^  ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
-    //[nll]~^^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/capture1.rs b/src/test/compile-fail/capture1.rs
index fd50918..984385f 100644
--- a/src/test/compile-fail/capture1.rs
+++ b/src/test/compile-fail/capture1.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-// error-pattern: can't capture dynamic environment in a fn item;
+// error-pattern: can't capture dynamic environment in a fn item
 
 fn main() {
     let bar: isize = 5;
diff --git a/src/test/compile-fail/cdylib-deps-must-be-static.rs b/src/test/compile-fail/cdylib-deps-must-be-static.rs
index bf7189c..0a06e01 100644
--- a/src/test/compile-fail/cdylib-deps-must-be-static.rs
+++ b/src/test/compile-fail/cdylib-deps-must-be-static.rs
@@ -11,6 +11,7 @@
 // error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
 // aux-build:cdylib-dep.rs
 // ignore-musl
+// ignore-cloudabi
 // ignore-emscripten
 
 #![crate_type = "cdylib"]
diff --git a/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs b/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs
index 513a17e..1ffba68 100644
--- a/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs
+++ b/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs
@@ -13,7 +13,7 @@
 
 fn foo(x: &()) {
     bar(|| {
-        //~^ ERROR does not fulfill
+        //~^ ERROR explicit lifetime required in the type of `x` [E0621]
         let _ = x;
     })
 }
diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs
index 9c26b8b..751d0a1 100644
--- a/src/test/compile-fail/coherence-default-trait-impl.rs
+++ b/src/test/compile-fail/coherence-default-trait-impl.rs
@@ -10,25 +10,16 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MyTrait { fn foo() {} }
+auto trait MySafeTrait {}
 
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-//~^ ERROR redundant auto implementations of trait `MyTrait`
+struct Foo;
 
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-
-trait MySafeTrait {}
-
-#[allow(auto_impl)]
-unsafe impl MySafeTrait for .. {}
+unsafe impl MySafeTrait for Foo {}
 //~^ ERROR implementing the trait `MySafeTrait` is not unsafe
 
-unsafe trait MyUnsafeTrait {}
+unsafe auto trait MyUnsafeTrait {}
 
-#[allow(auto_impl)]
-impl MyUnsafeTrait for .. {}
+impl MyUnsafeTrait for Foo {}
 //~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
 
 fn main() {}
diff --git a/src/test/compile-fail/coherence-negative-impls-safe.rs b/src/test/compile-fail/coherence-negative-impls-safe.rs
index 3b335d5..1ae07b6 100644
--- a/src/test/compile-fail/coherence-negative-impls-safe.rs
+++ b/src/test/compile-fail/coherence-negative-impls-safe.rs
@@ -15,6 +15,6 @@
 struct TestType;
 
 unsafe impl !Send for TestType {}
-//~^ ERROR negative implementations are not unsafe
+//~^ ERROR negative impls cannot be unsafe
 
 fn main() {}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/conservative_impl_trait.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/conservative_impl_trait.rs
index 5c32a75..7fb0ec5 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/conservative_impl_trait.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// #39872, #39553
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#![feature(conservative_impl_trait)]
+fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
+    //~^ ERROR the trait bound `(): std::iter::Iterator` is not satisfied [E0277]
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/derive-on-trait-item-or-impl-item.rs
similarity index 63%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/derive-on-trait-item-or-impl-item.rs
index 5c32a75..9ff1c14 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/derive-on-trait-item-or-impl-item.rs
@@ -8,9 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+trait Foo {
+    #[derive(Clone)]
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    type Bar;
+}
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+impl Bar {
+    #[derive(Clone)]
+    //~^ ERROR `derive` may only be applied to structs, enums and unions
+    fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/duplicate_entry_error.rs b/src/test/compile-fail/duplicate_entry_error.rs
index ad5ea29..485519e 100644
--- a/src/test/compile-fail/duplicate_entry_error.rs
+++ b/src/test/compile-fail/duplicate_entry_error.rs
@@ -20,4 +20,4 @@
     loop {}
 }
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/extern-macro.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/extern-macro.rs
index 5c32a75..4267103a 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/extern-macro.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// #41719
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#![feature(use_extern_macros)]
+
+fn main() {
+    enum Foo {}
+    let _ = Foo::bar!(); //~ ERROR fail to resolve non-ident macro path
+}
diff --git a/src/test/compile-fail/feature-gate-nested_impl_trait.rs b/src/test/compile-fail/feature-gate-nested_impl_trait.rs
new file mode 100644
index 0000000..7c35263
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-nested_impl_trait.rs
@@ -0,0 +1,39 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(conservative_impl_trait, universal_impl_trait)]
+
+use std::fmt::Debug;
+
+fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
+
+fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+//~^ ERROR nested `impl Trait` is experimental
+
+fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+//~^ ERROR nested `impl Trait` is experimental
+
+fn bad_in_arg_position(_: impl Into<impl Debug>) { }
+//~^ ERROR nested `impl Trait` is experimental
+
+struct X;
+impl X {
+    fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+    //~^ ERROR nested `impl Trait` is experimental
+}
+
+fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
+    vec![|| println!("woot")].into_iter()
+}
+
+fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
+    || 5
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/feature-gate-termination_trait.rs
similarity index 74%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/feature-gate-termination_trait.rs
index a2ef7da..5a56445 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/feature-gate-termination_trait.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+fn main() -> i32 { //~ ERROR main function has wrong type [E0580]
+    0
+}
diff --git a/src/test/compile-fail/float-int-invalid-const-cast.rs b/src/test/compile-fail/float-int-invalid-const-cast.rs
index 2efefd9..1f07422e 100644
--- a/src/test/compile-fail/float-int-invalid-const-cast.rs
+++ b/src/test/compile-fail/float-int-invalid-const-cast.rs
@@ -58,4 +58,4 @@
     { const X: u32 = 4294967296. as u32; force(X); } //~ ERROR constant evaluation error
     { const X: u128 = 1e40 as u128; force(X); } //~ ERROR constant evaluation error
     { const X: i128 = 1e40 as i128; force(X); } //~ ERROR constant evaluation error
-}
\ No newline at end of file
+}
diff --git a/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs
index 837160b..0eb99ca 100644
--- a/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs
+++ b/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs
@@ -13,7 +13,7 @@
 use std::fmt::Debug;
 
 fn elided(x: &i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+//~^ ERROR explicit lifetime required in the type of `x` [E0621]
 
 fn explicit<'a>(x: &'a i32) -> impl Copy { x }
 //~^ ERROR cannot infer an appropriate lifetime
diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs
index af83a2d..a9fe1e0 100644
--- a/src/test/compile-fail/impl-trait/where-allowed.rs
+++ b/src/test/compile-fail/impl-trait/where-allowed.rs
@@ -10,7 +10,7 @@
 
 //! A simple test for testing many permutations of allowedness of
 //! impl Trait
-#![feature(conservative_impl_trait, universal_impl_trait, dyn_trait)]
+#![feature(conservative_impl_trait, nested_impl_trait, universal_impl_trait, dyn_trait)]
 use std::fmt::Debug;
 
 // Allowed
diff --git a/src/test/compile-fail/imports/reexports.rs b/src/test/compile-fail/imports/reexports.rs
index 65e6e8d..f50b5b0 100644
--- a/src/test/compile-fail/imports/reexports.rs
+++ b/src/test/compile-fail/imports/reexports.rs
@@ -13,7 +13,7 @@
     mod foo {}
 
     mod a {
-        pub use super::foo; //~ ERROR cannot be reexported
+        pub use super::foo; //~ ERROR cannot be re-exported
         pub use super::*; //~ ERROR must import something with the glob's visibility
     }
 }
@@ -24,17 +24,17 @@
 
     pub mod a {
         pub use super::foo; // This is OK since the value `foo` is visible enough.
-        fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` reexported).
+        fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` re-exported).
     }
 
     pub mod b {
         pub use super::*; // This is also OK since the value `foo` is visible enough.
-        fn f(_: foo::S) {} // Again, the module `foo` is imported (but not `pub` reexported).
+        fn f(_: foo::S) {} // Again, the module `foo` is imported (but not `pub` re-exported).
     }
 }
 
 mod c {
-    // Test that `foo` is not reexported.
+    // Test that `foo` is not re-exported.
     use b::a::foo::S; //~ ERROR `foo`
     use b::b::foo::S as T; //~ ERROR `foo`
 }
diff --git a/src/test/compile-fail/issue-10755.rs b/src/test/compile-fail/issue-10755.rs
index 87faff2..57915bc 100644
--- a/src/test/compile-fail/issue-10755.rs
+++ b/src/test/compile-fail/issue-10755.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags: -C linker=llllll -Z linker-flavor=ld
-// error-pattern: the linker `llllll`
+// error-pattern: linker `llllll` not found
 
 fn main() {
 }
diff --git a/src/test/compile-fail/issue-13352.rs b/src/test/compile-fail/issue-13352.rs
index 0c446f5..e9d76c7 100644
--- a/src/test/compile-fail/issue-13352.rs
+++ b/src/test/compile-fail/issue-13352.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::process
+
 fn foo(_: Box<FnMut()>) {}
 
 fn main() {
diff --git a/src/test/compile-fail/issue-16922.rs b/src/test/compile-fail/issue-16922.rs
index b525d5f..1768c83 100644
--- a/src/test/compile-fail/issue-16922.rs
+++ b/src/test/compile-fail/issue-16922.rs
@@ -12,7 +12,7 @@
 
 fn foo<T: Any>(value: &T) -> Box<Any> {
     Box::new(value) as Box<Any>
-    //~^ ERROR: cannot infer an appropriate lifetime
+    //~^ ERROR explicit lifetime required in the type of `value` [E0621]
 }
 
 fn main() {
diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs
index bf44cd5..2aa87f8 100644
--- a/src/test/compile-fail/issue-23080-2.rs
+++ b/src/test/compile-fail/issue-23080-2.rs
@@ -12,17 +12,15 @@
 
 #![feature(optin_builtin_traits)]
 
-unsafe trait Trait {
+unsafe auto trait Trait {
 //~^ ERROR E0380
     type Output;
 }
 
-#[allow(auto_impl)]
-unsafe impl Trait for .. {}
-
 fn call_method<T: Trait>(x: T) {}
 
 fn main() {
     // ICE
     call_method(());
+    //~^ ERROR
 }
diff --git a/src/test/compile-fail/issue-23080.rs b/src/test/compile-fail/issue-23080.rs
index 1fb6339..153b6fd 100644
--- a/src/test/compile-fail/issue-23080.rs
+++ b/src/test/compile-fail/issue-23080.rs
@@ -12,16 +12,13 @@
 
 #![feature(optin_builtin_traits)]
 
-unsafe trait Trait {
+unsafe auto trait Trait {
 //~^ ERROR E0380
     fn method(&self) {
         println!("Hello");
     }
 }
 
-#[allow(auto_impl)]
-unsafe impl Trait for .. {}
-
 fn call_method<T: Trait>(x: T) {
     x.method();
 }
diff --git a/src/test/compile-fail/issue-24357.rs b/src/test/compile-fail/issue-24357.rs
index 5d6b989..016ce93 100644
--- a/src/test/compile-fail/issue-24357.rs
+++ b/src/test/compile-fail/issue-24357.rs
@@ -12,9 +12,9 @@
 fn main() {
    let x = NoCopy;
    let f = move || { let y = x; };
-   //~^ value moved (into closure) here
+   //~^ NOTE value moved (into closure) here
    let z = x;
    //~^ ERROR use of moved value: `x`
-   //~| value used here after move
-   //~| move occurs because `x` has type `NoCopy`
+   //~| NOTE value used here after move
+   //~| NOTE move occurs because `x` has type `NoCopy`
 }
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/issue-27078.rs
similarity index 67%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/issue-27078.rs
index 5c32a75..f34bef6 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/issue-27078.rs
@@ -8,9 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(associated_consts)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+trait Foo {
+    const BAR: i32;
+    fn foo(self) -> &'static i32 {
+        //~^ ERROR the trait bound `Self: std::marker::Sized` is not satisfied
+        &<Self>::BAR
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-28433.rs b/src/test/compile-fail/issue-28433.rs
index 018a40e..9253a49 100644
--- a/src/test/compile-fail/issue-28433.rs
+++ b/src/test/compile-fail/issue-28433.rs
@@ -13,7 +13,7 @@
 enum bird {
     pub duck,
     //~^ ERROR: expected identifier, found keyword `pub`
-    //~^^ ERROR: expected
+    //~| ERROR: expected
     goose
 }
 
diff --git a/src/test/compile-fail/issue-28848.rs b/src/test/compile-fail/issue-28848.rs
index 3d23ce0..1a06d59 100644
--- a/src/test/compile-fail/issue-28848.rs
+++ b/src/test/compile-fail/issue-28848.rs
@@ -20,4 +20,4 @@
     Foo::<'a, 'b>::xmute(u) //~ ERROR lifetime bound not satisfied
 }
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/compile-fail/issue-37665.rs b/src/test/compile-fail/issue-37665.rs
index f86f570..81ed437 100644
--- a/src/test/compile-fail/issue-37665.rs
+++ b/src/test/compile-fail/issue-37665.rs
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z unstable-options --unpretty=mir
+// compile-flags: -Z unpretty=mir
+// ignore-cloudabi no std::path
 
 use std::path::MAIN_SEPARATOR;
 
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/issue-38857.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/issue-38857.rs
index 5c32a75..b38b1b9 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/issue-38857.rs
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
-
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+fn main() {
+    let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
+    //~^ ERROR failed to resolve. Could not find `imp` in `sys` [E0433]
+    //~^^ ERROR module `sys` is private [E0603]
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/issue-39687.rs
similarity index 67%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/issue-39687.rs
index a2ef7da..404465e 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/issue-39687.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(fn_traits)]
+
+fn main() {
+    <fn() as Fn()>::call;
+    //~^ ERROR associated type bindings are not allowed here [E0229]
+}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/issue-39848.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/issue-39848.rs
index 5c32a75..d5ca009 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/issue-39848.rs
@@ -8,9 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+macro_rules! get_opt {
+    ($tgt:expr, $field:ident) => {
+        if $tgt.has_$field() {}
+    }
+}
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+fn main() {
+    get_opt!(bar, foo);
+    //~^ ERROR expected `{`, found `foo`
+}
diff --git a/src/test/compile-fail/issue-41880.rs b/src/test/compile-fail/issue-41880.rs
new file mode 100644
index 0000000..23a2b78
--- /dev/null
+++ b/src/test/compile-fail/issue-41880.rs
@@ -0,0 +1,39 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn iterate<T, F>(initial: T, f: F) -> Iterate<T, F> {
+    Iterate {
+        state: initial,
+        f: f,
+    }
+}
+
+pub struct Iterate<T, F> {
+    state: T,
+    f: F
+}
+
+impl<T: Clone, F> Iterator for Iterate<T, F> where F: Fn(&T) -> T {
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        self.state = (self.f)(&self.state);
+        Some(self.state.clone())
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) { (std::usize::MAX, None) }
+}
+
+fn main() {
+    let a = iterate(0, |x| x+1);
+    println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
+    //~^ ERROR no method named `iter` found for type `Iterate<{integer}
+}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/issue-41974.rs
similarity index 65%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/issue-41974.rs
index 5c32a75..5c90777 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/issue-41974.rs
@@ -8,9 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#[derive(Copy, Clone)]
+struct Flags;
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+trait A {
+}
+
+impl<T> Drop for T where T: A { //~ ERROR E0119
+                                //~^ ERROR E0120
+                                //~| ERROR E0210
+    fn drop(&mut self) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-43105.rs b/src/test/compile-fail/issue-43105.rs
new file mode 100644
index 0000000..fb419d7
--- /dev/null
+++ b/src/test/compile-fail/issue-43105.rs
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn xyz() -> u8 { 42 }
+
+const NUM: u8 = xyz();
+//~^ ERROR calls in constants are limited to constant functions, struct and enum constructors
+
+fn main() {
+    match 1 {
+        NUM => unimplemented!(),
+        _ => unimplemented!(),
+    }
+}
diff --git a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs b/src/test/compile-fail/issue-43925.rs
similarity index 69%
rename from src/test/compile-fail/directory_ownership/backcompat-warnings.rs
rename to src/test/compile-fail/issue-43925.rs
index 2da07a2..8ad5764 100644
--- a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs
+++ b/src/test/compile-fail/issue-43925.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: mod statements in non-mod.rs files are unstable
+#![feature(attr_literals)]
 
-#[path="mod_file_not_owning_aux3.rs"]
-mod foo;
+#[link(name="foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
+extern {}
 
 fn main() {}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/issue-43926.rs
similarity index 72%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/issue-43926.rs
index a2ef7da..5d510b6 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/issue-43926.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#[link(name="foo", cfg())] //~ ERROR `cfg()` must have an argument
+extern {}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-45199.rs b/src/test/compile-fail/issue-45199.rs
index af8f7dc..ecddb4c 100644
--- a/src/test/compile-fail/issue-45199.rs
+++ b/src/test/compile-fail/issue-45199.rs
@@ -31,11 +31,11 @@
 }
 
 fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
-                                //[mir]~^ NOTE first assignment
+                                //[mir]~^ NOTE argument not declared as `mut`
     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
-                                //[mir]~^ ERROR cannot assign twice to immutable variable `b`
+                                //[mir]~^ ERROR cannot assign to immutable argument `b`
                                 //[ast]~| NOTE cannot assign twice to immutable
-                                //[mir]~| NOTE cannot assign twice to immutable
+                                //[mir]~| NOTE cannot assign to immutable argument
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/issue-45965.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/issue-45965.rs
index 5c32a75..0b82f2b 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/issue-45965.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
-
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+fn main() {
+    let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 };
+    //~^ ERROR expected function, found `{float}`
+}
diff --git a/src/test/compile-fail/issue-46209-private-enum-variant-reexport.rs b/src/test/compile-fail/issue-46209-private-enum-variant-reexport.rs
index 5b23e5e..f5a20dd 100644
--- a/src/test/compile-fail/issue-46209-private-enum-variant-reexport.rs
+++ b/src/test/compile-fail/issue-46209-private-enum-variant-reexport.rs
@@ -12,14 +12,14 @@
 
 mod rank {
     pub use self::Professor::*;
-    //~^ ERROR enum is private and its variants cannot be reexported
+    //~^ ERROR enum is private and its variants cannot be re-exported
     pub use self::Lieutenant::{JuniorGrade, Full};
-    //~^ ERROR variant `JuniorGrade` is private and cannot be reexported
-    //~| ERROR variant `Full` is private and cannot be reexported
+    //~^ ERROR variant `JuniorGrade` is private and cannot be re-exported
+    //~| ERROR variant `Full` is private and cannot be re-exported
     pub use self::PettyOfficer::*;
-    //~^ ERROR enum is private and its variants cannot be reexported
+    //~^ ERROR enum is private and its variants cannot be re-exported
     pub use self::Crewman::*;
-    //~^ ERROR enum is private and its variants cannot be reexported
+    //~^ ERROR enum is private and its variants cannot be re-exported
 
     enum Professor {
         Adjunct,
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/issue-46438.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/issue-46438.rs
index 5c32a75..d84b581 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/issue-46438.rs
@@ -8,9 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+macro_rules! m {
+    ($my_type: ty) => {
+        impl $my_type for u8 {}
+    }
+}
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+trait Trait {}
+
+m!(Tr);
+
+m!(&'static u8); //~ ERROR expected a trait, found type
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-46604.rs b/src/test/compile-fail/issue-46604.rs
new file mode 100644
index 0000000..06aa4c3
--- /dev/null
+++ b/src/test/compile-fail/issue-46604.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //[ast]~ ERROR E0017
+                                                //[mir]~^ ERROR E0017
+fn write<T: AsRef<[u8]>>(buffer: T) { }
+
+fn main() {
+    write(&buf);
+    buf[0]=2;                                   //[mir]~ ERROR E0594
+}
diff --git a/src/test/compile-fail/issue-5500-1.rs b/src/test/compile-fail/issue-5500-1.rs
index 75ff0a1..4bd147a 100644
--- a/src/test/compile-fail/issue-5500-1.rs
+++ b/src/test/compile-fail/issue-5500-1.rs
@@ -18,8 +18,8 @@
 fn main() {
     let a = 5;
     let _iter = TrieMapIterator{node: &a};
-    _iter.node = & //[ast]~ ERROR cannot assign to immutable field `_iter.node`
-                   //[mir]~^ ERROR cannot assign to immutable field `_iter.node` (Ast)
+    _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding
+                   //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast)
                    // MIR doesn't generate an error because the code isn't reachable. This is OK
                    // because the test is here to check that the compiler doesn't ICE (cf. #5500).
     panic!()
diff --git a/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs b/src/test/compile-fail/keyword-extern-as-identifier.rs
similarity index 77%
rename from src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
rename to src/test/compile-fail/keyword-extern-as-identifier.rs
index 3c409d1..e5927d0 100644
--- a/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
+++ b/src/test/compile-fail/keyword-extern-as-identifier.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(extern_in_paths)]
 
-trait Magic<T> {} //~ ERROR E0567
-#[allow(auto_impl)]
-impl Magic<isize> for .. {}
+fn main() {
+    let extern = 0; //~ ERROR expected unit struct/variant or constant, found module `extern`
+}
diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs
index fd82556..c22239d 100644
--- a/src/test/compile-fail/lint-ctypes.rs
+++ b/src/test/compile-fail/lint-ctypes.rs
@@ -9,10 +9,12 @@
 // except according to those terms.
 
 #![deny(improper_ctypes)]
-#![feature(libc, i128_type)]
+#![feature(libc, i128_type, repr_transparent)]
 
 extern crate libc;
 
+use std::marker::PhantomData;
+
 trait Mirror { type It: ?Sized; }
 impl<T: ?Sized> Mirror for T { type It = Self; }
 #[repr(C)]
@@ -28,6 +30,22 @@
 pub type RustBadRet = extern fn() -> Box<u32>;
 pub type CVoidRet = ();
 pub struct Foo;
+#[repr(transparent)]
+pub struct TransparentI128(i128);
+#[repr(transparent)]
+pub struct TransparentStr(&'static str);
+#[repr(transparent)]
+pub struct TransparentBadFn(RustBadRet);
+#[repr(transparent)]
+pub struct TransparentInt(u32);
+#[repr(transparent)]
+pub struct TransparentRef<'a>(&'a TransparentInt);
+#[repr(transparent)]
+pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>);
+#[repr(transparent)]
+pub struct TransparentUnit<U>(f32, PhantomData<U>);
+#[repr(transparent)]
+pub struct TransparentCustomZst(i32, ZeroSize);
 
 #[repr(C)]
 pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
@@ -51,6 +69,9 @@
     pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust
     pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust
     pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without
+    pub fn transparent_i128(p: TransparentI128); //~ ERROR: found Rust type `i128`
+    pub fn transparent_str(p: TransparentStr); //~ ERROR: found Rust type `str`
+    pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: found struct without
 
     pub fn good3(fptr: Option<extern fn()>);
     pub fn good4(aptr: &[u8; 4 as usize]);
@@ -62,6 +83,11 @@
     pub fn good10() -> CVoidRet;
     pub fn good11(size: isize);
     pub fn good12(size: usize);
+    pub fn good13(n: TransparentInt);
+    pub fn good14(p: TransparentRef);
+    pub fn good15(p: TransparentLifetime);
+    pub fn good16(p: TransparentUnit<ZeroSize>);
+    pub fn good17(p: TransparentCustomZst);
 }
 
 #[cfg(not(target_arch = "wasm32"))]
diff --git a/src/test/compile-fail/lint-non-camel-case-types.rs b/src/test/compile-fail/lint-non-camel-case-types.rs
index f6d3d62..5dcdf3a 100644
--- a/src/test/compile-fail/lint-non-camel-case-types.rs
+++ b/src/test/compile-fail/lint-non-camel-case-types.rs
@@ -45,4 +45,12 @@
 
 type __ = isize; //~ ERROR type `__` should have a camel case name such as `CamelCase`
 
+struct X86_64;
+
+struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64`
+
+struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123`
+
+struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3`
+
 fn main() { }
diff --git a/src/test/compile-fail/lint-unnecessary-parens.rs b/src/test/compile-fail/lint-unnecessary-parens.rs
index b5eac73..7cd0a6b 100644
--- a/src/test/compile-fail/lint-unnecessary-parens.rs
+++ b/src/test/compile-fail/lint-unnecessary-parens.rs
@@ -13,19 +13,19 @@
 #[derive(Eq, PartialEq)]
 struct X { y: bool }
 impl X {
-    fn foo(&self) -> bool { self.y }
+    fn foo(&self, conjunct: bool) -> bool { self.y && conjunct }
 }
 
 fn foo() -> isize {
     return (1); //~ ERROR unnecessary parentheses around `return` value
 }
-fn bar() -> X {
-    return (X { y: true }); //~ ERROR unnecessary parentheses around `return` value
+fn bar(y: bool) -> X {
+    return (X { y }); //~ ERROR unnecessary parentheses around `return` value
 }
 
 fn main() {
     foo();
-    bar();
+    bar((true)); //~ ERROR unnecessary parentheses around function argument
 
     if (true) {} //~ ERROR unnecessary parentheses around `if` condition
     while (true) {} //~ ERROR unnecessary parentheses around `while` condition
@@ -40,13 +40,15 @@
     if (X { y: true } == v) {}
     if (X { y: false }.y) {}
 
-    while (X { y: false }.foo()) {}
+    while (X { y: false }.foo(true)) {}
     while (true | X { y: false }.y) {}
 
     match (X { y: false }) {
         _ => {}
     }
 
+    X { y: false }.foo((true)); //~ ERROR unnecessary parentheses around method argument
+
     let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
     _a = (0); //~ ERROR unnecessary parentheses around assigned value
     _a += (1); //~ ERROR unnecessary parentheses around assigned value
diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs
index a3cfa13..8f0b53fd 100644
--- a/src/test/compile-fail/lint-unused-extern-crate.rs
+++ b/src/test/compile-fail/lint-unused-extern-crate.rs
@@ -20,7 +20,7 @@
 
 extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate
 
-pub extern crate lint_unused_extern_crate4; // no error, it is reexported
+pub extern crate lint_unused_extern_crate4; // no error, it is re-exported
 
 extern crate lint_unused_extern_crate3; // no error, it is used
 
diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs
index a2778a8..36a6fce 100644
--- a/src/test/compile-fail/macro-reexport-malformed-1.rs
+++ b/src/test/compile-fail/macro-reexport-malformed-1.rs
@@ -12,5 +12,5 @@
 #![feature(macro_reexport)]
 
 #[allow(unused_extern_crates)]
-#[macro_reexport]  //~ ERROR bad macro reexport
+#[macro_reexport]  //~ ERROR bad macro re-export
 extern crate std;
diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs
index c5af9e3..5f741d0 100644
--- a/src/test/compile-fail/macro-reexport-malformed-2.rs
+++ b/src/test/compile-fail/macro-reexport-malformed-2.rs
@@ -12,5 +12,5 @@
 #![feature(macro_reexport)]
 
 #[allow(unused_extern_crates)]
-#[macro_reexport="foo"]  //~ ERROR bad macro reexport
+#[macro_reexport="foo"]  //~ ERROR bad macro re-export
 extern crate std;
diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/compile-fail/macro-reexport-malformed-3.rs
index d72d1ee..1a7e3b9 100644
--- a/src/test/compile-fail/macro-reexport-malformed-3.rs
+++ b/src/test/compile-fail/macro-reexport-malformed-3.rs
@@ -12,5 +12,5 @@
 #![feature(macro_reexport)]
 
 #[allow(unused_extern_crates)]
-#[macro_reexport(foo="bar")]  //~ ERROR bad macro reexport
+#[macro_reexport(foo="bar")]  //~ ERROR bad macro re-export
 extern crate std;
diff --git a/src/test/compile-fail/macro-reexport-undef.rs b/src/test/compile-fail/macro-reexport-undef.rs
index 5bb0b87..50ac89e 100644
--- a/src/test/compile-fail/macro-reexport-undef.rs
+++ b/src/test/compile-fail/macro-reexport-undef.rs
@@ -13,7 +13,7 @@
 #![feature(macro_reexport)]
 
 #[macro_use(macro_two)]
-#[macro_reexport(no_way)] //~ ERROR reexported macro not found
+#[macro_reexport(no_way)] //~ ERROR re-exported macro not found
 extern crate two_macros;
 
 pub fn main() {
diff --git a/src/test/compile-fail/main-wrong-type-2.rs b/src/test/compile-fail/main-wrong-type-2.rs
index 9d74d1a..a63162c 100644
--- a/src/test/compile-fail/main-wrong-type-2.rs
+++ b/src/test/compile-fail/main-wrong-type-2.rs
@@ -7,8 +7,9 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+#![feature(termination_trait)]
 
 fn main() -> char {
-//~^ ERROR: main function has wrong type [E0580]
+//~^ ERROR: the trait bound `char: std::Termination` is not satisfied
     ' '
 }
diff --git a/src/test/compile-fail/mir-unpretty.rs b/src/test/compile-fail/mir-unpretty.rs
index 8950bef..fa93650 100644
--- a/src/test/compile-fail/mir-unpretty.rs
+++ b/src/test/compile-fail/mir-unpretty.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z unstable-options --unpretty=mir
+// compile-flags: -Z unpretty=mir
 
 fn main() {
     let x: () = 0; //~ ERROR: mismatched types
diff --git a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs
index 02c09aa..5329dca 100644
--- a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs
+++ b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs
@@ -17,17 +17,19 @@
 fn f00() {
     let x = "hi".to_string();
     let _y = Foo { f:x };
-    //~^ value moved here
+    //~^ NOTE value moved here
     touch(&x); //~ ERROR use of moved value: `x`
-    //~^ value used here after move
-    //~| move occurs because `x` has type `std::string::String`
+    //~^ NOTE value used here after move
+    //~| NOTE move occurs because `x` has type `std::string::String`
 }
 
 fn f05() {
     let x = "hi".to_string();
     let _y = Foo { f:(((x))) };
-    //~^ value moved here
+    //~^ NOTE value moved here
     touch(&x); //~ ERROR use of moved value: `x`
+    //~^ NOTE value used here after move
+    //~| NOTE move occurs because `x` has type `std::string::String`
 }
 
 fn f10() {
diff --git a/src/test/compile-fail/never-assign-wrong-type.rs b/src/test/compile-fail/never-assign-wrong-type.rs
index d854e6e..c0dd2ca 100644
--- a/src/test/compile-fail/never-assign-wrong-type.rs
+++ b/src/test/compile-fail/never-assign-wrong-type.rs
@@ -16,5 +16,3 @@
 fn main() {
     let x: ! = "hello"; //~ ERROR mismatched types
 }
-
-
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
similarity index 61%
copy from src/test/compile-fail/regions-escape-unboxed-closure.rs
copy to src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
index cf41fad..c7dc84c 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,10 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: &mut FnMut(&isize)) {
-}
+// Regression test for issue #47053
+
+#![feature(nll)]
+#![feature(thread_local)]
+
+#[thread_local]
+static FOO: isize = 5;
 
 fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+    FOO = 6; //~ ERROR cannot assign to immutable item `FOO` [E0594]
 }
diff --git a/src/test/compile-fail/object-lifetime-default-from-box-error.rs b/src/test/compile-fail/object-lifetime-default-from-box-error.rs
index c50f425..b253612 100644
--- a/src/test/compile-fail/object-lifetime-default-from-box-error.rs
+++ b/src/test/compile-fail/object-lifetime-default-from-box-error.rs
@@ -25,7 +25,7 @@
     // `Box<SomeTrait>` defaults to a `'static` bound, so this return
     // is illegal.
 
-    ss.r //~ ERROR cannot infer an appropriate lifetime
+    ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
 }
 
 fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
diff --git a/src/test/compile-fail/panic-runtime/abort-link-to-unwind-dylib.rs b/src/test/compile-fail/panic-runtime/abort-link-to-unwind-dylib.rs
index 1fd60b1..f392ccd 100644
--- a/src/test/compile-fail/panic-runtime/abort-link-to-unwind-dylib.rs
+++ b/src/test/compile-fail/panic-runtime/abort-link-to-unwind-dylib.rs
@@ -10,6 +10,7 @@
 
 // compile-flags:-C panic=abort -C prefer-dynamic
 // ignore-musl - no dylibs here
+// ignore-cloudabi
 // ignore-emscripten
 // error-pattern:`panic_unwind` is not compiled with this crate's panic strategy
 
diff --git a/src/test/compile-fail/phantom-oibit.rs b/src/test/compile-fail/phantom-oibit.rs
index 1c1cb39..e36c483 100644
--- a/src/test/compile-fail/phantom-oibit.rs
+++ b/src/test/compile-fail/phantom-oibit.rs
@@ -9,17 +9,13 @@
 // except according to those terms.
 
 // Ensure that OIBIT checks `T` when it encounters a `PhantomData<T>` field, instead of checking
-// the `PhantomData<T>` type itself (which almost always implements a "default" trait
-// (`impl Trait for ..`))
+// the `PhantomData<T>` type itself (which almost always implements an auto trait)
 
 #![feature(optin_builtin_traits)]
 
 use std::marker::{PhantomData};
 
-unsafe trait Zen {}
-
-#[allow(auto_impl)]
-unsafe impl Zen for .. {}
+unsafe auto trait Zen {}
 
 unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
 
diff --git a/src/test/compile-fail/privacy-sanity.rs b/src/test/compile-fail/privacy-sanity.rs
index 34082ad..f245b7c 100644
--- a/src/test/compile-fail/privacy-sanity.rs
+++ b/src/test/compile-fail/privacy-sanity.rs
@@ -10,7 +10,6 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MarkerTr {}
 pub trait Tr {
     fn f();
     const C: u8;
@@ -21,8 +20,6 @@
 }
 struct Ts(pub u8);
 
-#[allow(auto_impl)]
-pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
 pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
     pub fn f() {} //~ ERROR unnecessary visibility qualifier
     pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
@@ -39,7 +36,6 @@
 }
 
 const MAIN: u8 = {
-    trait MarkerTr {}
     pub trait Tr {
         fn f();
         const C: u8;
@@ -50,8 +46,6 @@
     }
     struct Ts(pub u8);
 
-    #[allow(auto_impl)]
-    pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
         pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
@@ -71,7 +65,6 @@
 };
 
 fn main() {
-    trait MarkerTr {}
     pub trait Tr {
         fn f();
         const C: u8;
@@ -82,8 +75,6 @@
     }
     struct Ts(pub u8);
 
-    #[allow(auto_impl)]
-    pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
         pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
diff --git a/src/test/compile-fail/privacy/legacy-ctor-visibility.rs b/src/test/compile-fail/privacy/legacy-ctor-visibility.rs
index fb65af2..9514491 100644
--- a/src/test/compile-fail/privacy/legacy-ctor-visibility.rs
+++ b/src/test/compile-fail/privacy/legacy-ctor-visibility.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 #![allow(unused)]
 
 use m::S;
@@ -19,7 +21,7 @@
         use S;
         fn f() {
             S(10);
-            //~^ ERROR private struct constructors are not usable through reexports in outer modules
+            //~^ ERROR private struct constructors are not usable through re-exports in outer modules
             //~| WARN this was previously accepted
         }
     }
diff --git a/src/test/compile-fail/privacy/restricted/test.rs b/src/test/compile-fail/privacy/restricted/test.rs
index 7f076eb..8c1d609 100644
--- a/src/test/compile-fail/privacy/restricted/test.rs
+++ b/src/test/compile-fail/privacy/restricted/test.rs
@@ -28,7 +28,7 @@
     fn f() {
         use foo::bar::S;
         pub(self) use foo::bar::f; // ok
-        pub(super) use foo::bar::f as g; //~ ERROR cannot be reexported
+        pub(super) use foo::bar::f as g; //~ ERROR cannot be re-exported
         S::default().x; // ok
         S::default().f(); // ok
         S::g(); // ok
diff --git a/src/test/compile-fail/private-in-public-ill-formed.rs b/src/test/compile-fail/private-in-public-ill-formed.rs
index 4e10614..4804060 100644
--- a/src/test/compile-fail/private-in-public-ill-formed.rs
+++ b/src/test/compile-fail/private-in-public-ill-formed.rs
@@ -21,7 +21,7 @@
         type AssocAlias = m::Pub3;
     }
 
-    impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
         pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
     }
 }
@@ -37,7 +37,7 @@
         type AssocAlias = Priv3;
     }
 
-    impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
         pub fn f(arg: Priv) {} // OK
     }
 }
diff --git a/src/test/compile-fail/private-variant-reexport.rs b/src/test/compile-fail/private-variant-reexport.rs
index 1280aba..5d770f8 100644
--- a/src/test/compile-fail/private-variant-reexport.rs
+++ b/src/test/compile-fail/private-variant-reexport.rs
@@ -9,19 +9,19 @@
 // except according to those terms.
 
 mod m1 {
-    pub use ::E::V; //~ ERROR variant `V` is private and cannot be reexported
+    pub use ::E::V; //~ ERROR variant `V` is private and cannot be re-exported
 }
 
 mod m2 {
-    pub use ::E::{V}; //~ ERROR variant `V` is private and cannot be reexported
+    pub use ::E::{V}; //~ ERROR variant `V` is private and cannot be re-exported
 }
 
 mod m3 {
-    pub use ::E::V::{self}; //~ ERROR variant `V` is private and cannot be reexported
+    pub use ::E::V::{self}; //~ ERROR variant `V` is private and cannot be re-exported
 }
 
 mod m4 {
-    pub use ::E::*; //~ ERROR enum is private and its variants cannot be reexported
+    pub use ::E::*; //~ ERROR enum is private and its variants cannot be re-exported
 }
 
 enum E { V }
diff --git a/src/test/compile-fail/pub-reexport-priv-extern-crate.rs b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
index 5479be5..2e71e00 100644
--- a/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
+++ b/src/test/compile-fail/pub-reexport-priv-extern-crate.rs
@@ -11,7 +11,7 @@
 #![allow(unused)]
 
 extern crate core;
-pub use core as reexported_core; //~ ERROR `core` is private, and cannot be reexported
+pub use core as reexported_core; //~ ERROR `core` is private, and cannot be re-exported
                                  //~^ WARN this was previously accepted
 
 mod foo1 {
@@ -19,7 +19,7 @@
 }
 
 mod foo2 {
-    use foo1::core; //~ ERROR `core` is private, and cannot be reexported
+    use foo1::core; //~ ERROR `core` is private, and cannot be re-exported
                     //~^ WARN this was previously accepted
     pub mod bar {
         extern crate core;
@@ -27,7 +27,7 @@
 }
 
 mod baz {
-    pub use foo2::bar::core; //~ ERROR `core` is private, and cannot be reexported
+    pub use foo2::bar::core; //~ ERROR `core` is private, and cannot be re-exported
                              //~^ WARN this was previously accepted
 }
 
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/quote-with-interpolated.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/quote-with-interpolated.rs
index 5c32a75..1fafb1c 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/quote-with-interpolated.rs
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
-
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#![feature(quote)]
+fn main() {
+    macro_rules! foo {
+        ($bar:expr)  => {
+            quote_expr!(cx, $bar) //~ ERROR quote! with interpolated token
+        }
+    }
+    foo!(bar);
+}
diff --git a/src/test/compile-fail/range_inclusive_gate.rs b/src/test/compile-fail/range_inclusive_gate.rs
index 69b9a4c..5b063dc 100644
--- a/src/test/compile-fail/range_inclusive_gate.rs
+++ b/src/test/compile-fail/range_inclusive_gate.rs
@@ -19,5 +19,3 @@
     //~| ERROR core_intrinsics
     //~| ERROR core_intrinsics
 }
-
-
diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
index 687b2c3..5bf397a 100644
--- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs
+++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
@@ -16,20 +16,20 @@
 
 fn a(v: &[u8]) -> Box<Foo + 'static> {
     let x: Box<Foo + 'static> = Box::new(v);
-    //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+    //~^ ERROR explicit lifetime required in the type of `v` [E0621]
     x
 }
 
 fn b(v: &[u8]) -> Box<Foo + 'static> {
     Box::new(v)
-        //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+        //~^ ERROR explicit lifetime required in the type of `v` [E0621]
 }
 
 fn c(v: &[u8]) -> Box<Foo> {
     // same as previous case due to RFC 599
 
     Box::new(v)
-        //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+        //~^ ERROR explicit lifetime required in the type of `v` [E0621]
 }
 
 fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
diff --git a/src/test/compile-fail/regions-proc-bound-capture.rs b/src/test/compile-fail/regions-proc-bound-capture.rs
index 17fd55b..dd7b2bf 100644
--- a/src/test/compile-fail/regions-proc-bound-capture.rs
+++ b/src/test/compile-fail/regions-proc-bound-capture.rs
@@ -16,7 +16,7 @@
 
 fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
     // This is illegal, because the region bound on `proc` is 'static.
-    Box::new(move|| { *x }) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/regions-static-bound.rs b/src/test/compile-fail/regions-static-bound.rs
index a217cc9..13f9309 100644
--- a/src/test/compile-fail/regions-static-bound.rs
+++ b/src/test/compile-fail/regions-static-bound.rs
@@ -22,12 +22,12 @@
 }
 
 fn error(u: &(), v: &()) {
-    static_id(&u); //[ll]~ ERROR cannot infer an appropriate lifetime
+    static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
     //[nll]~^ WARNING not reporting region error due to -Znll
-    //[nll]~| ERROR free region `` does not outlive free region `'static`
-    static_id_indirect(&v); //[ll]~ ERROR cannot infer an appropriate lifetime
+    //[nll]~| ERROR explicit lifetime required in the type of `u` [E0621]
+    static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
     //[nll]~^ WARNING not reporting region error due to -Znll
-    //[nll]~| ERROR free region `` does not outlive free region `'static`
+    //[nll]~| ERROR explicit lifetime required in the type of `v` [E0621]
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/repr-transparent-other-items.rs b/src/test/compile-fail/repr-transparent-other-items.rs
new file mode 100644
index 0000000..cf08708
--- /dev/null
+++ b/src/test/compile-fail/repr-transparent-other-items.rs
@@ -0,0 +1,40 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(repr_transparent)]
+
+// See also repr-transparent.rs
+
+#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
+enum Void {}         //~| ERROR should be applied to struct
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+enum FieldlessEnum {
+    Foo,
+    Bar,
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+enum Enum {
+    Foo(String),
+    Bar(u32),
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+union Foo {
+    u: u32,
+    s: i32
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+fn cant_repr_this() {}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+static CANT_REPR_THIS: u32 = 0;
diff --git a/src/test/compile-fail/repr-transparent-other-reprs.rs b/src/test/compile-fail/repr-transparent-other-reprs.rs
new file mode 100644
index 0000000..7b91a6f
--- /dev/null
+++ b/src/test/compile-fail/repr-transparent-other-reprs.rs
@@ -0,0 +1,28 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(repr_transparent, repr_align, attr_literals)]
+
+// See also repr-transparent.rs
+
+#[repr(transparent, C)] //~ ERROR cannot have other repr
+struct TransparentPlusC {
+    ptr: *const u8
+}
+
+#[repr(transparent, packed)] //~ ERROR cannot have other repr
+struct TransparentPlusPacked(*const u8);
+
+#[repr(transparent, align(2))] //~ ERROR cannot have other repr
+struct TransparentPlusAlign(u8);
+
+#[repr(transparent)] //~ ERROR cannot have other repr
+#[repr(C)]
+struct SeparateAttributes(*mut u8);
diff --git a/src/test/compile-fail/repr-transparent.rs b/src/test/compile-fail/repr-transparent.rs
new file mode 100644
index 0000000..b5e6a0f
--- /dev/null
+++ b/src/test/compile-fail/repr-transparent.rs
@@ -0,0 +1,51 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file tests repr(transparent)-related errors reported during typeck. Other errors
+// that are reported earlier and therefore preempt these are tested in:
+// - repr-transparent-other-reprs.rs
+// - repr-transparent-other-items.rs
+
+#![feature(repr_align, attr_literals)]
+#![feature(repr_transparent)]
+
+use std::marker::PhantomData;
+
+#[repr(transparent)]
+struct NoFields; //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsOnlyZst(()); //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsOnlyZstArray([bool; 0]); //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
+//~^ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct MultipleNonZst(u8, u8); //~ ERROR needs exactly one non-zero-sized field
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+
+#[repr(transparent)]
+pub struct StructWithProjection(f32, <f32 as Mirror>::It);
+//~^ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1
+
+#[repr(align(32))]
+struct ZstAlign32<T>(PhantomData<T>);
+
+#[repr(transparent)]
+struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/rfc-2126-extern-in-paths/auxiliary/xcrate.rs
similarity index 75%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/rfc-2126-extern-in-paths/auxiliary/xcrate.rs
index a2ef7da..c3da4a5 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/rfc-2126-extern-in-paths/auxiliary/xcrate.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#[derive(Debug)]
+pub struct S;
+
+#[derive(Debug)]
+pub struct Z;
diff --git a/src/test/ui/typeck-default-trait-impl-outside-crate.rs b/src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-1.rs
similarity index 71%
copy from src/test/ui/typeck-default-trait-impl-outside-crate.rs
copy to src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-1.rs
index ff0446e..7eba02e 100644
--- a/src/test/ui/typeck-default-trait-impl-outside-crate.rs
+++ b/src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-1.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(extern_in_paths)]
 
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
+use extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
+
 fn main() {}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-2.rs
similarity index 68%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-2.rs
index a2ef7da..4d09a05 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-2.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(extern_in_paths)]
+
+fn main() {
+    let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate`
+}
diff --git a/src/test/ui/typeck-default-trait-impl-outside-crate.rs b/src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-3.rs
similarity index 72%
copy from src/test/ui/typeck-default-trait-impl-outside-crate.rs
copy to src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-3.rs
index ff0446e..402d294 100644
--- a/src/test/ui/typeck-default-trait-impl-outside-crate.rs
+++ b/src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-3.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(extern_in_paths)]
 
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
+use extern::ycrate; //~ ERROR can't find crate for `ycrate`
+
 fn main() {}
diff --git a/src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs b/src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs
new file mode 100644
index 0000000..ebc42aa
--- /dev/null
+++ b/src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:xcrate.rs
+
+#![feature(extern_in_paths)]
+
+use extern; //~ ERROR unresolved import `extern`
+            //~^ NOTE no `extern` in the root
+use extern::*; //~ ERROR unresolved import `extern::*`
+               //~^ NOTE cannot glob-import all possible crates
+
+fn main() {
+    let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
+                            //~^ NOTE not a value
+}
diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
deleted file mode 100644
index cad43ff..0000000
--- a/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(specialization)]
-#![feature(optin_builtin_traits)]
-
-trait Foo {}
-
-#[allow(auto_impl)]
-default impl Foo for .. {}
-//~^ ERROR `default impl` is not allowed for auto trait implementations
-
-fn main() {}
diff --git a/src/test/compile-fail/specialization/defaultimpl/validation.rs b/src/test/compile-fail/specialization/defaultimpl/validation.rs
new file mode 100644
index 0000000..26b8b73
--- /dev/null
+++ b/src/test/compile-fail/specialization/defaultimpl/validation.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+#![feature(specialization)]
+
+struct S;
+struct Z;
+
+default impl S {} //~ ERROR inherent impls cannot be default
+
+default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
+default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
+
+trait Tr {}
+default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits
diff --git a/src/test/compile-fail/specialization/specialization-polarity.rs b/src/test/compile-fail/specialization/specialization-polarity.rs
index c97cb3f..b28a63c 100644
--- a/src/test/compile-fail/specialization/specialization-polarity.rs
+++ b/src/test/compile-fail/specialization/specialization-polarity.rs
@@ -13,18 +13,12 @@
 #![feature(optin_builtin_traits)]
 #![feature(specialization)]
 
-trait Foo {}
-
-#[allow(auto_impl)]
-impl Foo for .. {}
+auto trait Foo {}
 
 impl<T> Foo for T {}
 impl !Foo for u8 {} //~ ERROR E0119
 
-trait Bar {}
-
-#[allow(auto_impl)]
-impl Bar for .. {}
+auto trait Bar {}
 
 impl<T> !Bar for T {}
 impl Bar for u8 {} //~ ERROR E0119
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/static-closures.rs
similarity index 74%
copy from src/test/compile-fail/E0580.rs
copy to src/test/compile-fail/static-closures.rs
index a2ef7da..8593eb5 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/compile-fail/static-closures.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+fn main() {
+    static || {};
+    //~^ ERROR closures cannot be static
+}
diff --git a/src/test/compile-fail/static-drop-scope.rs b/src/test/compile-fail/static-drop-scope.rs
index c96cade..e22eb7e 100644
--- a/src/test/compile-fail/static-drop-scope.rs
+++ b/src/test/compile-fail/static-drop-scope.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(const_fn)]
+
 struct WithDtor;
 
 impl Drop for WithDtor {
@@ -28,4 +30,12 @@
 const EARLY_DROP_C: i32 = (WithDtor, 0).1;
 //~^ ERROR destructors cannot be evaluated at compile-time
 
+const fn const_drop<T>(_: T) {}
+//~^ ERROR destructors cannot be evaluated at compile-time
+
+const fn const_drop2<T>(x: T) {
+    (x, ()).1
+    //~^ ERROR destructors cannot be evaluated at compile-time
+}
+
 fn main () {}
diff --git a/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs b/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs
index a7ca5e3b..8d5e89c 100644
--- a/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs
+++ b/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs
@@ -14,7 +14,7 @@
 
 trait TestTrait {}
 
-unsafe impl !Send for TestType {}
+impl !Send for TestType {}
 //~^ ERROR negative trait bounds
 
 fn main() {}
diff --git a/src/test/parse-fail/syntax-trait-polarity.rs b/src/test/compile-fail/syntax-trait-polarity.rs
similarity index 70%
rename from src/test/parse-fail/syntax-trait-polarity.rs
rename to src/test/compile-fail/syntax-trait-polarity.rs
index 1971ffe..1a5d058 100644
--- a/src/test/parse-fail/syntax-trait-polarity.rs
+++ b/src/test/compile-fail/syntax-trait-polarity.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only -Z continue-parse-after-error
-
 #![feature(optin_builtin_traits)]
 
 use std::marker::Send;
@@ -17,19 +15,23 @@
 struct TestType;
 
 impl !TestType {}
-//~^ ERROR inherent implementation can't be negated
+//~^ ERROR inherent impls cannot be negative
 
 trait TestTrait {}
 
 unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
 impl !TestTrait for TestType {}
+//~^ ERROR negative impls are only allowed for auto traits
 
-struct TestType2<T>;
+struct TestType2<T>(T);
 
 impl<T> !TestType2<T> {}
-//~^ ERROR inherent implementation can't be negated
+//~^ ERROR inherent impls cannot be negative
 
 unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
 impl<T> !TestTrait for TestType2<T> {}
+//~^ ERROR negative impls are only allowed for auto traits
 
 fn main() {}
diff --git a/src/test/compile-fail/syntaxt-default-trait-impls.rs b/src/test/compile-fail/syntaxt-default-trait-impls.rs
deleted file mode 100644
index 45303cb..0000000
--- a/src/test/compile-fail/syntaxt-default-trait-impls.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(optin_builtin_traits)]
-
-trait MyAutoImpl {}
-
-#[allow(auto_impl)]
-impl<T> MyAutoImpl for .. {}
-//~^ ERROR auto trait implementations are not allowed to have generics
-
-fn main() {}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/termination-trait-not-satisfied.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/compile-fail/termination-trait-not-satisfied.rs
index 5c32a75..788c38c 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/compile-fail/termination-trait-not-satisfied.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(termination_trait)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+struct ReturnType {}
+
+fn main() -> ReturnType { //~ ERROR `ReturnType: std::Termination` is not satisfied
+    ReturnType {}
+}
diff --git a/src/test/compile-fail/trait-safety-inherent-impl.rs b/src/test/compile-fail/trait-safety-inherent-impl.rs
index 285d4c1..059fdc1 100644
--- a/src/test/compile-fail/trait-safety-inherent-impl.rs
+++ b/src/test/compile-fail/trait-safety-inherent-impl.rs
@@ -12,7 +12,7 @@
 
 struct SomeStruct;
 
-unsafe impl SomeStruct { //~ ERROR inherent impls cannot be declared as unsafe
+unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe
     fn foo(self) { }
 }
 
diff --git a/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs b/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
index 6c7928f..59d5dc6 100644
--- a/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
+++ b/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
@@ -14,9 +14,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait Magic: Copy {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic: Copy {} //~ ERROR E0568
 
 fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
 
@@ -24,6 +22,6 @@
 struct NoClone;
 
 fn main() {
-    let (a, b) = copy(NoClone);
+    let (a, b) = copy(NoClone); //~ ERROR
     println!("{:?} {:?}", a, b);
 }
diff --git a/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs b/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
index 173582e..fa63088 100644
--- a/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
+++ b/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
@@ -10,9 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
 impl<T:Magic> Magic for T {}
 
 fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
diff --git a/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs b/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
index 6802f72..c8cf96f 100644
--- a/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
+++ b/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
@@ -34,9 +34,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait Magic: Copy {} //~ ERROR E0568
-#[allow(auto_impl)]
-impl Magic for .. {}
+auto trait Magic: Copy {} //~ ERROR E0568
 impl<T:Magic> Magic for T {}
 
 fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
index a837d8c..6e7c9af 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
@@ -10,10 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MyTrait {}
-
-#[allow(auto_impl)]
-impl MyTrait for .. {}
+auto trait MyTrait {}
 
 struct MyS;
 
diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
index bed184e..4660ecf 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
@@ -10,10 +10,8 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MyTrait {}
+auto trait MyTrait {}
 
-#[allow(auto_impl)]
-impl MyTrait for .. {}
 impl<T> !MyTrait for *mut T {}
 
 struct MyS;
diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation.rs b/src/test/compile-fail/typeck-default-trait-impl-negation.rs
index f3a6d8a..b28cdd8 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-negation.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-negation.rs
@@ -10,15 +10,9 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MyTrait {}
+auto trait MyTrait {}
 
-#[allow(auto_impl)]
-impl MyTrait for .. {}
-
-unsafe trait MyUnsafeTrait {}
-
-#[allow(auto_impl)]
-unsafe impl MyUnsafeTrait for .. {}
+unsafe auto trait MyUnsafeTrait {}
 
 struct ThisImplsTrait;
 
diff --git a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs
index bdd6487..d63d70b 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs
@@ -10,14 +10,12 @@
 
 // Test that declaring that `&T` is `Defaulted` if `T:Signed` implies
 // that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In
-// other words, the `..` impl only applies if there are no existing
+// other words, the auto impl only applies if there are no existing
 // impls whose types unify.
 
 #![feature(optin_builtin_traits)]
 
-trait Defaulted { }
-#[allow(auto_impl)]
-impl Defaulted for .. { }
+auto trait Defaulted { }
 impl<'a,T:Signed> Defaulted for &'a T { }
 impl<'a,T:Signed> Defaulted for &'a mut T { }
 fn is_defaulted<T:Defaulted>() { }
diff --git a/src/test/compile-fail/typeck-negative-impls-builtin.rs b/src/test/compile-fail/typeck-negative-impls-builtin.rs
index 57a394d..d6d8fb6 100644
--- a/src/test/compile-fail/typeck-negative-impls-builtin.rs
+++ b/src/test/compile-fail/typeck-negative-impls-builtin.rs
@@ -17,6 +17,6 @@
 }
 
 impl !TestTrait for TestType {}
-//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`)
+//~^ ERROR negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
 
 fn main() {}
diff --git a/src/test/compile-fail/useless_comment.rs b/src/test/compile-fail/useless_comment.rs
index a1172bb..90eb667 100644
--- a/src/test/compile-fail/useless_comment.rs
+++ b/src/test/compile-fail/useless_comment.rs
@@ -27,4 +27,4 @@
 
 fn main() {
     foo();
-}
\ No newline at end of file
+}
diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs
index fe687da..b699efa 100644
--- a/src/test/debuginfo/basic-types-globals-metadata.rs
+++ b/src/test/debuginfo/basic-types-globals-metadata.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 // gdb-command:run
diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs
index 20bc403..51c36f8 100644
--- a/src/test/debuginfo/basic-types-globals.rs
+++ b/src/test/debuginfo/basic-types-globals.rs
@@ -15,6 +15,7 @@
 // its numerical value.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 // gdb-command:run
diff --git a/src/test/debuginfo/basic-types-metadata.rs b/src/test/debuginfo/basic-types-metadata.rs
index 8aec1a0..3dbfdea 100644
--- a/src/test/debuginfo/basic-types-metadata.rs
+++ b/src/test/debuginfo/basic-types-metadata.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 // gdb-command:run
diff --git a/src/test/debuginfo/basic-types-mut-globals.rs b/src/test/debuginfo/basic-types-mut-globals.rs
index 62325aa..2d4b4d6 100644
--- a/src/test/debuginfo/basic-types-mut-globals.rs
+++ b/src/test/debuginfo/basic-types-mut-globals.rs
@@ -15,6 +15,7 @@
 // its numerical value.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs
index 0fe08c3..9007b44 100644
--- a/src/test/debuginfo/by-value-non-immediate-argument.rs
+++ b/src/test/debuginfo/by-value-non-immediate-argument.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs
index 900b082..1f1f42e 100644
--- a/src/test/debuginfo/c-style-enum.rs
+++ b/src/test/debuginfo/c-style-enum.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-aarch64
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/drop-locations.rs b/src/test/debuginfo/drop-locations.rs
index b4f6b33..76c2826 100644
--- a/src/test/debuginfo/drop-locations.rs
+++ b/src/test/debuginfo/drop-locations.rs
@@ -10,6 +10,7 @@
 
 // ignore-windows
 // ignore-android
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 #![allow(unused)]
diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs
index 21fdc4e..90088a0 100644
--- a/src/test/debuginfo/function-arg-initialization.rs
+++ b/src/test/debuginfo/function-arg-initialization.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 // This test case checks if function arguments already have the correct value
diff --git a/src/test/debuginfo/function-prologue-stepping-regular.rs b/src/test/debuginfo/function-prologue-stepping-regular.rs
index 529a8cd..d50d105 100644
--- a/src/test/debuginfo/function-prologue-stepping-regular.rs
+++ b/src/test/debuginfo/function-prologue-stepping-regular.rs
@@ -13,6 +13,7 @@
 
 // min-lldb-version: 310
 // ignore-gdb
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // compile-flags:-g
 
 // lldb-command:breakpoint set --name immediate_args
diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs
index 8e8a194..e76f9da 100644
--- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs
+++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/limited-debuginfo.rs b/src/test/debuginfo/limited-debuginfo.rs
index e8c3597..d840f38 100644
--- a/src/test/debuginfo/limited-debuginfo.rs
+++ b/src/test/debuginfo/limited-debuginfo.rs
@@ -10,6 +10,7 @@
 
 
 // ignore-lldb
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-C debuginfo=1
 
diff --git a/src/test/debuginfo/macro-stepping.rs b/src/test/debuginfo/macro-stepping.rs
index ca2c1e0..204dd8c 100644
--- a/src/test/debuginfo/macro-stepping.rs
+++ b/src/test/debuginfo/macro-stepping.rs
@@ -12,6 +12,7 @@
 // ignore-android
 // ignore-aarch64
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // aux-build:macro-stepping.rs
 
diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs
index 7dbc0d3..ddfff0f 100644
--- a/src/test/debuginfo/method-on-enum.rs
+++ b/src/test/debuginfo/method-on-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/option-like-enum.rs b/src/test/debuginfo/option-like-enum.rs
index 39e6a4e..618587e 100644
--- a/src/test/debuginfo/option-like-enum.rs
+++ b/src/test/debuginfo/option-like-enum.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
+
 // min-lldb-version: 310
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs
index 2a28c89..7bc5664 100644
--- a/src/test/debuginfo/pretty-std.rs
+++ b/src/test/debuginfo/pretty-std.rs
@@ -10,6 +10,7 @@
 
 // ignore-windows failing on win32 bot
 // ignore-freebsd: gdb package too new
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
 // min-gdb-version 7.7
diff --git a/src/test/debuginfo/shadowed-variable.rs b/src/test/debuginfo/shadowed-variable.rs
index 4883853..6e4d94d 100644
--- a/src/test/debuginfo/shadowed-variable.rs
+++ b/src/test/debuginfo/shadowed-variable.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // min-lldb-version: 310
-
 // compile-flags:-g
 
 // === GDB TESTS ===================================================================================
@@ -34,6 +33,17 @@
 // gdb-check:$6 = 20
 // gdb-command:continue
 
+// gdb-command:print x
+// gdb-check:$7 = 10.5
+// gdb-command:print y
+// gdb-check:$8 = 20
+// gdb-command:continue
+
+// gdb-command:print x
+// gdb-check:$9 = 11.5
+// gdb-command:print y
+// gdb-check:$10 = 20
+// gdb-command:continue
 
 // === LLDB TESTS ==================================================================================
 
@@ -57,6 +67,18 @@
 // lldb-check:[...]$5 = 20
 // lldb-command:continue
 
+// lldb-command:print x
+// lldb-check:[...]$6 = 10.5
+// lldb-command:print y
+// lldb-check:[...]$7 = 20
+// lldb-command:continue
+
+// lldb-command:print x
+// lldb-check:[...]$8 = 11.5
+// lldb-command:print y
+// lldb-check:[...]$9 = 20
+// lldb-command:continue
+
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
@@ -77,6 +99,15 @@
 
     zzz(); // #break
     sentinel();
+
+    let x = {
+        zzz(); // #break
+        sentinel();
+        11.5
+    };
+
+    zzz(); // #break
+    sentinel()
 }
 
 fn zzz() {()}
diff --git a/src/test/debuginfo/should-fail.rs b/src/test/debuginfo/should-fail.rs
new file mode 100644
index 0000000..1f8acb5
--- /dev/null
+++ b/src/test/debuginfo/should-fail.rs
@@ -0,0 +1,38 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// min-lldb-version: 310
+
+// == Test [gdb|lldb]-[command|check] are parsed correctly ===
+// should-fail
+// compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print x
+// gdb-check:$1 = 5
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+
+// lldb-command:print x
+// lldb-check:[...]$0 = 5
+
+fn main() {
+    let x = 1;
+
+    zzz(); // #break
+}
+
+fn zzz() {()}
+
diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs
index ae05baf..8fdf204 100644
--- a/src/test/debuginfo/simple-struct.rs
+++ b/src/test/debuginfo/simple-struct.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs
index b3c2704..8f69672 100644
--- a/src/test/debuginfo/simple-tuple.rs
+++ b/src/test/debuginfo/simple-tuple.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs
index bd04418..14aaf67 100644
--- a/src/test/debuginfo/struct-in-enum.rs
+++ b/src/test/debuginfo/struct-in-enum.rs
@@ -11,6 +11,7 @@
 // ignore-tidy-linelength
 // min-lldb-version: 310
 // ignore-gdb-version: 7.11.90 - 7.12.9
+// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs
index 57d40cc..c89c0e4 100644
--- a/src/test/debuginfo/type-names.rs
+++ b/src/test/debuginfo/type-names.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // ignore-lldb
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // ignore-android: FIXME(#24958)
 // ignore-arm: FIXME(#24958)
 // ignore-aarch64: FIXME(#24958)
diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs
index 433196b..622c7cf 100644
--- a/src/test/debuginfo/union-smoke.rs
+++ b/src/test/debuginfo/union-smoke.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
+
 // ignore-gdb-version: 7.11.90 - 7.12.9
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs
index d321df8..888d9b2 100644
--- a/src/test/debuginfo/vec-slices.rs
+++ b/src/test/debuginfo/vec-slices.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-windows
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs
index fbb33b9..dba9475 100644
--- a/src/test/debuginfo/vec.rs
+++ b/src/test/debuginfo/vec.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // compile-flags:-g
 
diff --git a/src/test/incremental-fulldeps/auxiliary/incremental_proc_macro_aux.rs b/src/test/incremental-fulldeps/auxiliary/incremental_proc_macro_aux.rs
new file mode 100644
index 0000000..e9f9ba8
--- /dev/null
+++ b/src/test/incremental-fulldeps/auxiliary/incremental_proc_macro_aux.rs
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+// Add a function to shift DefIndex of registrar function
+#[cfg(cfail2)]
+fn foo() {}
+
+#[proc_macro_derive(IncrementalMacro)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    #[cfg(cfail2)]
+    {
+        foo();
+    }
+
+    "".parse().unwrap()
+}
diff --git a/src/test/incremental-fulldeps/incremental_proc_macro.rs b/src/test/incremental-fulldeps/incremental_proc_macro.rs
new file mode 100644
index 0000000..e434507
--- /dev/null
+++ b/src/test/incremental-fulldeps/incremental_proc_macro.rs
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:incremental_proc_macro_aux.rs
+// ignore-stage1
+// revisions: cfail1 cfail2
+// must-compile-successfully
+
+// This test makes sure that we still find the proc-macro registrar function
+// when we compile proc-macros incrementally (see #47292).
+
+#![crate_type = "rlib"]
+
+#[macro_use]
+extern crate incremental_proc_macro_aux;
+
+#[derive(IncrementalMacro)]
+pub struct Foo {
+    x: u32
+}
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index 0274678..36cbd22 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -651,5 +651,3 @@
         Variant1(T)
     }
 }
-
-
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
index b93a965..3996e92 100644
--- a/src/test/incremental/hashes/inline_asm.rs
+++ b/src/test/incremental/hashes/inline_asm.rs
@@ -236,6 +236,3 @@
     }
     _out
 }
-
-
-
diff --git a/src/test/mir-opt/return_an_array.rs b/src/test/mir-opt/return_an_array.rs
index 4409f16..bfae5b9 100644
--- a/src/test/mir-opt/return_an_array.rs
+++ b/src/test/mir-opt/return_an_array.rs
@@ -15,4 +15,4 @@
         return x;
 }
 
-fn main() { }
\ No newline at end of file
+fn main() { }
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/parse-fail/impl-qpath.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/parse-fail/impl-qpath.rs
index 5c32a75..48dd888 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/parse-fail/impl-qpath.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// compile-flags: -Z parse-only
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+impl <*const u8>::AssocTy {} // OK
+impl <Type as Trait>::AssocTy {} // OK
+impl <'a + Trait>::AssocTy {} // OK
+impl <<Type>::AssocTy>::AssocTy {} // OK
+
+FAIL //~ ERROR
diff --git a/src/test/parse-fail/issue-32501.rs b/src/test/parse-fail/issue-32501.rs
index 10df093..f29c1fa 100644
--- a/src/test/parse-fail/issue-32501.rs
+++ b/src/test/parse-fail/issue-32501.rs
@@ -18,4 +18,5 @@
     let mut _b = 0;
     let mut _ = 0; //~ ERROR expected identifier, found `_`
     //~^ NOTE `_` is a wildcard pattern, not an identifier
+    //~| NOTE expected identifier
 }
diff --git a/src/test/parse-fail/issue-37113.rs b/src/test/parse-fail/issue-37113.rs
index caf4510..14c6f39 100644
--- a/src/test/parse-fail/issue-37113.rs
+++ b/src/test/parse-fail/issue-37113.rs
@@ -18,4 +18,4 @@
 
 fn main() {
     test_macro!(String,);
-}
\ No newline at end of file
+}
diff --git a/src/test/parse-fail/mod_file_not_exist_windows.rs b/src/test/parse-fail/mod_file_not_exist_windows.rs
index c58603b..5cf8217 100644
--- a/src/test/parse-fail/mod_file_not_exist_windows.rs
+++ b/src/test/parse-fail/mod_file_not_exist_windows.rs
@@ -8,19 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-gnu
 // ignore-android
 // ignore-bitrig
-// ignore-macos
+// ignore-cloudabi
 // ignore-dragonfly
+// ignore-emscripten
 // ignore-freebsd
+// ignore-gnu
 // ignore-haiku
 // ignore-ios
 // ignore-linux
+// ignore-macos
 // ignore-netbsd
 // ignore-openbsd
 // ignore-solaris
-// ignore-emscripten
 
 // compile-flags: -Z parse-only
 
diff --git a/src/test/parse-fail/range_inclusive_gate.rs b/src/test/parse-fail/range_inclusive_gate.rs
index de690c3..6b6afc5 100644
--- a/src/test/parse-fail/range_inclusive_gate.rs
+++ b/src/test/parse-fail/range_inclusive_gate.rs
@@ -72,5 +72,3 @@
     o!(); // not allowed in macros that output cfgs
     p!(); // not allowed in cfg'ed macros that output cfgs
 }
-
-
diff --git a/src/test/parse-fail/trait-bounds-not-on-impl.rs b/src/test/parse-fail/trait-bounds-not-on-impl.rs
index b7dcc8a..7cd2774 100644
--- a/src/test/parse-fail/trait-bounds-not-on-impl.rs
+++ b/src/test/parse-fail/trait-bounds-not-on-impl.rs
@@ -15,9 +15,7 @@
 
 struct Bar;
 
-impl Foo + Owned for Bar {
-//~^ ERROR not a trait
-//~^^ ERROR expected one of `where` or `{`, found `Bar`
+impl Foo + Owned for Bar { //~ ERROR expected a trait, found type
 }
 
 fn main() { }
diff --git a/src/test/parse-fail/where_with_bound.rs b/src/test/parse-fail/where_with_bound.rs
index cb57500..2948619 100644
--- a/src/test/parse-fail/where_with_bound.rs
+++ b/src/test/parse-fail/where_with_bound.rs
@@ -11,6 +11,6 @@
 // compile-flags: -Z parse-only
 
 fn foo<T>() where <T>::Item: ToString, T: Iterator { }
-               //~^ syntax `where<T>` is reserved for future use
+//~^ ERROR generic parameters on `where` clauses are reserved for future use
 
 fn main() {}
diff --git a/src/test/run-fail/mir_dynamic_drops_1.rs b/src/test/run-fail/mir_dynamic_drops_1.rs
index 69f9342..856fc50 100644
--- a/src/test/run-fail/mir_dynamic_drops_1.rs
+++ b/src/test/run-fail/mir_dynamic_drops_1.rs
@@ -7,9 +7,10 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+
 // error-pattern:drop 1
 // error-pattern:drop 2
-
+// ignore-cloudabi no std::process
 
 /// Structure which will not allow to be dropped twice.
 struct Droppable<'a>(&'a mut bool, u32);
diff --git a/src/test/run-fail/mir_dynamic_drops_2.rs b/src/test/run-fail/mir_dynamic_drops_2.rs
index d2fe504..9645623 100644
--- a/src/test/run-fail/mir_dynamic_drops_2.rs
+++ b/src/test/run-fail/mir_dynamic_drops_2.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // error-pattern:drop 1
-
+// ignore-cloudabi no std::process
 
 /// Structure which will not allow to be dropped twice.
 struct Droppable<'a>(&'a mut bool, u32);
diff --git a/src/test/run-fail/mir_dynamic_drops_3.rs b/src/test/run-fail/mir_dynamic_drops_3.rs
index ecc35ee..4c07031 100644
--- a/src/test/run-fail/mir_dynamic_drops_3.rs
+++ b/src/test/run-fail/mir_dynamic_drops_3.rs
@@ -12,7 +12,7 @@
 // error-pattern:drop 3
 // error-pattern:drop 2
 // error-pattern:drop 1
-
+// ignore-cloudabi no std::process
 
 /// Structure which will not allow to be dropped twice.
 struct Droppable<'a>(&'a mut bool, u32);
diff --git a/src/test/run-fail/mir_trans_no_landing_pads.rs b/src/test/run-fail/mir_trans_no_landing_pads.rs
index bafb78f..aded273 100644
--- a/src/test/run-fail/mir_trans_no_landing_pads.rs
+++ b/src/test/run-fail/mir_trans_no_landing_pads.rs
@@ -10,6 +10,8 @@
 
 // compile-flags: -Z no-landing-pads -C codegen-units=1
 // error-pattern:converging_fn called
+// ignore-cloudabi no std::process
+
 use std::io::{self, Write};
 
 struct Droppable;
diff --git a/src/test/run-fail/mir_trans_no_landing_pads_diverging.rs b/src/test/run-fail/mir_trans_no_landing_pads_diverging.rs
index 998ee74..d3a8613 100644
--- a/src/test/run-fail/mir_trans_no_landing_pads_diverging.rs
+++ b/src/test/run-fail/mir_trans_no_landing_pads_diverging.rs
@@ -10,6 +10,8 @@
 
 // compile-flags: -Z no-landing-pads -C codegen-units=1
 // error-pattern:diverging_fn called
+// ignore-cloudabi no std::process
+
 use std::io::{self, Write};
 
 struct Droppable;
diff --git a/src/test/run-fail/return-never-coerce.rs b/src/test/run-fail/return-never-coerce.rs
index 4cd93ac..ddcecd9 100644
--- a/src/test/run-fail/return-never-coerce.rs
+++ b/src/test/run-fail/return-never-coerce.rs
@@ -24,5 +24,3 @@
     let x: i32 = call_another_fn(wub);
     let y: u32 = wub();
 }
-
-
diff --git a/src/test/run-fail/tls-exit-status.rs b/src/test/run-fail/tls-exit-status.rs
index be619e3..d9b81c5 100644
--- a/src/test/run-fail/tls-exit-status.rs
+++ b/src/test/run-fail/tls-exit-status.rs
@@ -10,6 +10,7 @@
 
 // error-pattern:nonzero
 // exec-env:RUST_NEWRT=1
+// ignore-cloudabi no std::env
 
 use std::env;
 
diff --git a/src/test/run-make/a-b-a-linker-guard/a.rs b/src/test/run-make/a-b-a-linker-guard/a.rs
index e6cbe2e..c6680a7 100644
--- a/src/test/run-make/a-b-a-linker-guard/a.rs
+++ b/src/test/run-make/a-b-a-linker-guard/a.rs
@@ -16,5 +16,3 @@
 
 #[cfg(y)]
 pub fn foo(x: i32) { }
-
-
diff --git a/src/test/run-make/hir-tree/Makefile b/src/test/run-make/hir-tree/Makefile
index bedb2b7..2e100b2 100644
--- a/src/test/run-make/hir-tree/Makefile
+++ b/src/test/run-make/hir-tree/Makefile
@@ -4,6 +4,5 @@
 # the string constant we would expect to see.
 
 all:
-	$(RUSTC) -o $(TMPDIR)/input.hir -Z unstable-options \
-		--unpretty=hir-tree input.rs
+	$(RUSTC) -o $(TMPDIR)/input.hir -Z unpretty=hir-tree input.rs
 	$(CGREP) '"Hello, Rustaceans!\n"' < $(TMPDIR)/input.hir
diff --git a/src/test/run-make/hotplug_codegen_backend/Makefile b/src/test/run-make/hotplug_codegen_backend/Makefile
new file mode 100644
index 0000000..9a216d1
--- /dev/null
+++ b/src/test/run-make/hotplug_codegen_backend/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+all:
+	/bin/echo || exit 0 # This test requires /bin/echo to exist
+	$(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \
+		-o $(TMPDIR)/the_backend.dylib
+	$(RUSTC) some_crate.rs --crate-name some_crate --crate-type bin -o $(TMPDIR)/some_crate \
+		-Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options
+	grep -x "This has been \"compiled\" succesfully." $(TMPDIR)/some_crate
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-make/hotplug_codegen_backend/some_crate.rs
similarity index 78%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-make/hotplug_codegen_backend/some_crate.rs
index a2ef7da..26ffce0 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-make/hotplug_codegen_backend/some_crate.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+fn main() {
+    ::std::process::exit(1);
+}
diff --git a/src/test/run-make/hotplug_codegen_backend/the_backend.rs b/src/test/run-make/hotplug_codegen_backend/the_backend.rs
new file mode 100644
index 0000000..0de404e
--- /dev/null
+++ b/src/test/run-make/hotplug_codegen_backend/the_backend.rs
@@ -0,0 +1,82 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_private)]
+
+extern crate syntax;
+extern crate rustc;
+extern crate rustc_trans_utils;
+
+use std::any::Any;
+use std::sync::mpsc;
+use syntax::symbol::Symbol;
+use rustc::session::{Session, CompileIncomplete};
+use rustc::session::config::OutputFilenames;
+use rustc::ty::TyCtxt;
+use rustc::ty::maps::Providers;
+use rustc::middle::cstore::MetadataLoader;
+use rustc::dep_graph::DepGraph;
+use rustc_trans_utils::trans_crate::{TransCrate, MetadataOnlyTransCrate};
+
+struct TheBackend(Box<TransCrate>);
+
+impl TransCrate for TheBackend {
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
+        self.0.metadata_loader()
+    }
+
+    fn provide(&self, providers: &mut Providers) {
+        self.0.provide(providers);
+    }
+
+    fn provide_extern(&self, providers: &mut Providers) {
+        self.0.provide_extern(providers);
+    }
+
+    fn trans_crate<'a, 'tcx>(
+        &self,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        _rx: mpsc::Receiver<Box<Any + Send>>
+    ) -> Box<Any> {
+        use rustc::hir::def_id::LOCAL_CRATE;
+
+        Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol)
+    }
+
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
+        sess: &Session,
+        _dep_graph: &DepGraph,
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete> {
+        use std::io::Write;
+        use rustc::session::config::CrateType;
+        use rustc_trans_utils::link::out_filename;
+        let crate_name = trans.downcast::<Symbol>()
+            .expect("in join_trans_and_link: trans is not a Symbol");
+        for &crate_type in sess.opts.crate_types.iter() {
+            if crate_type != CrateType::CrateTypeExecutable {
+                sess.fatal(&format!("Crate type is {:?}", crate_type));
+            }
+            let output_name =
+                out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
+            let mut out_file = ::std::fs::File::create(output_name).unwrap();
+            write!(out_file, "This has been \"compiled\" succesfully.").unwrap();
+        }
+        Ok(())
+    }
+}
+
+/// This is the entrypoint for a hot plugged rustc_trans
+#[no_mangle]
+pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
+    Box::new(TheBackend(MetadataOnlyTransCrate::new(sess)))
+}
diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs
index f0ab1d5..c360dde 100644
--- a/src/test/run-make/issue-19371/foo.rs
+++ b/src/test/run-make/issue-19371/foo.rs
@@ -16,6 +16,7 @@
 extern crate rustc_metadata;
 extern crate rustc_errors;
 extern crate rustc_trans;
+extern crate rustc_trans_utils;
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
@@ -25,6 +26,7 @@
 use rustc_metadata::cstore::CStore;
 use rustc_errors::registry::Registry;
 use syntax::codemap::FileName;
+use rustc_trans_utils::trans_crate::TransCrate;
 
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -51,7 +53,7 @@
     compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
 }
 
-fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
+fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>, Box<TransCrate>) {
     let mut opts = basic_options();
     opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
     opts.maybe_sysroot = Some(sysroot);
@@ -60,16 +62,26 @@
     }
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
-    let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader)));
     let sess = build_session(opts, None, descriptions);
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-    (sess, cstore)
+    (sess, cstore, trans)
 }
 
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
-    let (sess, cstore) = basic_sess(sysroot);
+    let (sess, cstore, trans) = basic_sess(sysroot);
     let control = CompileController::basic();
     let input = Input::Str { name: FileName::Anon, input: code };
-    let _ = compile_input(&sess, &cstore, &None, &input, &None, &Some(output), None, &control);
+    let _ = compile_input(
+        trans,
+        &sess,
+        &cstore,
+        &None,
+        &input,
+        &None,
+        &Some(output),
+        None,
+        &control
+    );
 }
diff --git a/src/test/run-make/linker-output-non-utf8/Makefile b/src/test/run-make/linker-output-non-utf8/Makefile
index 76d4b13..5f1577a 100644
--- a/src/test/run-make/linker-output-non-utf8/Makefile
+++ b/src/test/run-make/linker-output-non-utf8/Makefile
@@ -2,15 +2,16 @@
 
 # Make sure we don't ICE if the linker prints a non-UTF-8 error message.
 
-ifdef IS_WINDOWS
-# ignore windows
+# Ignore Windows and Apple
 
 # This does not work in its current form on windows, possibly due to
 # gcc bugs or something about valid Windows paths.  See issue #29151
 # for more information.
-all:
+ifndef IS_WINDOWS
 
-else
+# This also does not work on Apple APFS due to the filesystem requiring
+# valid UTF-8 paths.
+ifneq ($(shell uname),Darwin)
 
 # The zzz it to allow humans to tab complete or glob this thing.
 bad_dir := $(TMPDIR)/zzz$$'\xff'
@@ -20,5 +21,12 @@
 	mkdir $(bad_dir)
 	mv $(TMPDIR)/liblibrary.a $(bad_dir)
 	LIBRARY_PATH=$(bad_dir) $(RUSTC) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined
+else
+all:
+
+endif
+
+else
+all:
 
 endif
diff --git a/src/test/run-make/llvm-phase/Makefile b/src/test/run-make/llvm-phase/Makefile
deleted file mode 100644
index 6a8e172..0000000
--- a/src/test/run-make/llvm-phase/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
--include ../tools.mk
-
-all:
-	$(RUSTC) test.rs
-	$(call RUN,test $(RUSTC))
diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs
deleted file mode 100644
index 2ff4593..0000000
--- a/src/test/run-make/llvm-phase/test.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(plugin, rustc_private, box_syntax)]
-
-extern crate rustc;
-extern crate rustc_driver;
-extern crate rustc_llvm;
-extern crate rustc_trans;
-#[macro_use] extern crate syntax;
-extern crate getopts;
-
-use rustc_driver::{CompilerCalls, Compilation};
-use rustc_driver::driver::CompileController;
-use rustc_trans::ModuleSource;
-use rustc::session::Session;
-use syntax::codemap::FileLoader;
-use std::env;
-use std::io;
-use std::path::{PathBuf, Path};
-
-struct JitLoader;
-
-impl FileLoader for JitLoader {
-    fn file_exists(&self, _: &Path) -> bool { true }
-    fn abs_path(&self, _: &Path) -> Option<PathBuf> { None }
-    fn read_file(&self, _: &Path) -> io::Result<String> {
-        Ok(r#"
-#[no_mangle]
-pub fn test_add(a: i32, b: i32) -> i32 { a + b }
-"#.to_string())
-    }
-}
-
-#[derive(Copy, Clone)]
-struct JitCalls;
-
-impl<'a> CompilerCalls<'a> for JitCalls {
-    fn build_controller(&mut self,
-                        _: &Session,
-                        _: &getopts::Matches)
-                        -> CompileController<'a> {
-        let mut cc = CompileController::basic();
-        cc.after_llvm.stop = Compilation::Stop;
-        cc.after_llvm.run_callback_on_error = true;
-        cc.after_llvm.callback = Box::new(|state| {
-            state.session.abort_if_errors();
-            let trans = state.trans.unwrap();
-            assert_eq!(trans.modules.len(), 1);
-            println!("name of compiled module = {}", trans.modules[0].name);
-        });
-        cc
-    }
-}
-
-fn main() {
-    use rustc_driver;
-
-    let mut path = match std::env::args().nth(2) {
-        Some(path) => PathBuf::from(&path),
-        None => panic!("missing rustc path")
-    };
-
-    // Remove two segments from rustc path to get sysroot.
-    path.pop();
-    path.pop();
-
-    let mut args: Vec<String> =
-        format!("_ _ --sysroot {} --crate-type dylib", path.to_str().unwrap())
-        .split(' ').map(|s| s.to_string()).collect();
-    args.push("--out-dir".to_string());
-    args.push(env::var("TMPDIR").unwrap());
-    args.push("-Ccodegen-units=1".to_string());
-
-    let (result, _) = rustc_driver::run_compiler(
-        &args, &mut JitCalls, Some(box JitLoader), None);
-    if let Err(n) = result {
-        panic!("Error {:?}", n);
-    }
-}
diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/Makefile b/src/test/run-make/long-linker-command-lines-cmd-exe/Makefile
new file mode 100644
index 0000000..debe9e9
--- /dev/null
+++ b/src/test/run-make/long-linker-command-lines-cmd-exe/Makefile
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all:
+	$(RUSTC) foo.rs -g
+	cp foo.bat $(TMPDIR)/
+	OUT_DIR="$(TMPDIR)" RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo)
diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat
new file mode 100644
index 0000000..a9350f1
--- /dev/null
+++ b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat
@@ -0,0 +1 @@
+%MY_LINKER% %*
diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs
new file mode 100644
index 0000000..f9168a8
--- /dev/null
+++ b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs
@@ -0,0 +1,96 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Like the `long-linker-command-lines` test this test attempts to blow
+// a command line limit for running the linker. Unlike that test, however,
+// this test is testing `cmd.exe` specifically rather than the OS.
+//
+// Unfortunately `cmd.exe` has a 8192 limit which is relatively small
+// in the grand scheme of things and anyone sripting rustc's linker
+// is probably using a `*.bat` script and is likely to hit this limit.
+//
+// This test uses a `foo.bat` script as the linker which just simply
+// delegates back to this program. The compiler should use a lower
+// limit for arguments before passing everything via `@`, which
+// means that everything should still succeed here.
+
+use std::env;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write, Read};
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+    if !cfg!(windows) {
+        return
+    }
+
+    let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+    let ok = tmpdir.join("ok");
+    let not_ok = tmpdir.join("not_ok");
+    if env::var("YOU_ARE_A_LINKER").is_ok() {
+        match env::args().find(|a| a.contains("@")) {
+            Some(file) => { fs::copy(&file[1..], &ok).unwrap(); }
+            None => { File::create(&not_ok).unwrap(); }
+        }
+        return
+    }
+
+    let rustc = env::var_os("RUSTC").unwrap_or("rustc".into());
+    let me = env::current_exe().unwrap();
+    let bat = me.parent()
+        .unwrap()
+        .join("foo.bat");
+    let bat_linker = format!("linker={}", bat.display());
+    for i in (1..).map(|i| i * 10) {
+        println!("attempt: {}", i);
+
+        let file = tmpdir.join("bar.rs");
+        let mut f = BufWriter::new(File::create(&file).unwrap());
+        let mut lib_name = String::new();
+        for _ in 0..i {
+            lib_name.push_str("foo");
+        }
+        for j in 0..i {
+            writeln!(f, "#[link(name = \"{}{}\")]", lib_name, j).unwrap();
+        }
+        writeln!(f, "extern {{}}\nfn main() {{}}").unwrap();
+        f.into_inner().unwrap();
+
+        drop(fs::remove_file(&ok));
+        drop(fs::remove_file(&not_ok));
+        let status = Command::new(&rustc)
+            .arg(&file)
+            .arg("-C").arg(&bat_linker)
+            .arg("--out-dir").arg(&tmpdir)
+            .env("YOU_ARE_A_LINKER", "1")
+            .env("MY_LINKER", &me)
+            .status()
+            .unwrap();
+
+        if !status.success() {
+            panic!("rustc didn't succeed: {}", status);
+        }
+
+        if !ok.exists() {
+            assert!(not_ok.exists());
+            continue
+        }
+
+        let mut contents = String::new();
+        File::open(&ok).unwrap().read_to_string(&mut contents).unwrap();
+
+        for j in 0..i {
+            assert!(contents.contains(&format!("{}{}", lib_name, j)));
+        }
+
+        break
+    }
+}
diff --git a/src/test/run-make/pretty-print-path-suffix/Makefile b/src/test/run-make/pretty-print-path-suffix/Makefile
index d530050..899457f 100644
--- a/src/test/run-make/pretty-print-path-suffix/Makefile
+++ b/src/test/run-make/pretty-print-path-suffix/Makefile
@@ -1,9 +1,9 @@
 -include ../tools.mk
 
 all:
-	$(RUSTC) -o $(TMPDIR)/foo.out -Z unstable-options --unpretty hir=foo input.rs
-	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unstable-options --unpretty hir=nest::foo input.rs
-	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unstable-options --unpretty hir=foo_method input.rs
+	$(RUSTC) -o $(TMPDIR)/foo.out -Z unpretty=hir=foo input.rs
+	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unpretty=hir=nest::foo input.rs
+	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unpretty=hir=foo_method input.rs
 	diff -u $(TMPDIR)/foo.out foo.pp
 	diff -u $(TMPDIR)/nest_foo.out nest_foo.pp
 	diff -u $(TMPDIR)/foo_method.out foo_method.pp
diff --git a/src/test/run-make/reproducible-build/reproducible-build.rs b/src/test/run-make/reproducible-build/reproducible-build.rs
index dc7c702..b47d780 100644
--- a/src/test/run-make/reproducible-build/reproducible-build.rs
+++ b/src/test/run-make/reproducible-build/reproducible-build.rs
@@ -124,5 +124,3 @@
 
     TupleStruct(1, 2, 3, 4).bar();
 }
-
-
diff --git a/src/test/run-make/rustdoc-error-lines/Makefile b/src/test/run-make/rustdoc-error-lines/Makefile
new file mode 100644
index 0000000..0019e5e
--- /dev/null
+++ b/src/test/run-make/rustdoc-error-lines/Makefile
@@ -0,0 +1,8 @@
+-include ../tools.mk
+
+# Test that hir-tree output doens't crash and includes
+# the string constant we would expect to see.
+
+all:
+	$(RUSTDOC) --test input.rs > $(TMPDIR)/output || true
+	$(CGREP) 'input.rs:17:15' < $(TMPDIR)/output
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-make/rustdoc-error-lines/input.rs
similarity index 62%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-make/rustdoc-error-lines/input.rs
index a2ef7da..6dc7060 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-make/rustdoc-error-lines/input.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+// Test for #45868
+
+// random #![feature] to ensure that crate attrs
+// do not offset things
+/// ```rust
+/// #![feature(nll)]
+/// let x: char = 1;
+/// ```
+pub fn foo() {
+
+}
diff --git a/src/test/run-make/sepcomp-inlining/foo.rs b/src/test/run-make/sepcomp-inlining/foo.rs
index 20fd18b..5b62c1b 100644
--- a/src/test/run-make/sepcomp-inlining/foo.rs
+++ b/src/test/run-make/sepcomp-inlining/foo.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(start)]
+
 #[inline]
 fn inlined() -> u32 {
     1234
@@ -29,7 +31,10 @@
     }
 }
 
-fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     a::f();
     b::f();
+
+    0
 }
diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs
index 185476f..94b91c7 100644
--- a/src/test/run-make/simd-ffi/simd.rs
+++ b/src/test/run-make/simd-ffi/simd.rs
@@ -80,6 +80,4 @@
 }
 
 #[lang = "freeze"]
-trait Freeze {}
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs
index a0feb72..bbd1c5d9 100644
--- a/src/test/run-make/target-specs/foo.rs
+++ b/src/test/run-make/target-specs/foo.rs
@@ -18,9 +18,7 @@
 trait Sized { }
 
 #[lang = "freeze"]
-trait Freeze {}
-#[allow(auto_impl)]
-impl Freeze for .. {}
+auto trait Freeze {}
 
 #[lang="start"]
 fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 }
diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateC.rs b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs
index da869d2..210bc4c 100644
--- a/src/test/run-make/type-mismatch-same-crate-name/crateC.rs
+++ b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs
@@ -18,7 +18,7 @@
 // compile-fail/type-mismatch-same-crate-name.rs
 // but deals with the case where one of the crates
 // is only introduced as an indirect dependency.
-// and the type is accessed via a reexport.
+// and the type is accessed via a re-export.
 // This is similar to how the error can be introduced
 // when using cargo's automatic dependency resolution.
 
diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs
index 1a9358f..0f90cb3 100644
--- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs
@@ -21,6 +21,7 @@
 extern crate rustc_plugin;
 
 use syntax::ast;
+use syntax::attr;
 use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
 use syntax::ext::build::AstBuilder;
 use syntax::symbol::Symbol;
@@ -80,7 +81,7 @@
     };
 
     fields.iter().fold(cx.expr_isize(trait_span, 0), |acc, ref item| {
-        if item.attrs.iter().find(|a| a.check_name("ignore")).is_some() {
+        if attr::contains_name(&item.attrs, "ignore") {
             acc
         } else {
             cx.expr_binary(item.span, ast::BinOpKind::Add, acc,
diff --git a/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs b/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs
index d3f921e..878d64c 100644
--- a/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs
@@ -23,26 +23,57 @@
 use rustc::hir;
 use syntax::attr;
 
-declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
+macro_rules! fake_lint_pass {
+    ($struct:ident, $lints:expr, $($attr:expr),*) => {
+        struct $struct;
 
-struct Pass;
+        impl LintPass for $struct {
+            fn get_lints(&self) -> LintArray {
+                $lints
+            }
+        }
 
-impl LintPass for Pass {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(CRATE_NOT_OKAY)
+        impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct {
+            fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
+                $(
+                    if !attr::contains_name(&krate.attrs, $attr) {
+                        cx.span_lint(CRATE_NOT_OKAY, krate.span,
+                                     &format!("crate is not marked with #![{}]", $attr));
+                    }
+                )*
+            }
+        }
+
     }
 }
 
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
-    fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
-        if !attr::contains_name(&krate.attrs, "crate_okay") {
-            cx.span_lint(CRATE_NOT_OKAY, krate.span,
-                         "crate is not marked with #![crate_okay]");
-        }
-    }
+declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
+declare_lint!(CRATE_NOT_RED, Warn, "crate not marked with #![crate_red]");
+declare_lint!(CRATE_NOT_BLUE, Warn, "crate not marked with #![crate_blue]");
+declare_lint!(CRATE_NOT_GREY, Warn, "crate not marked with #![crate_grey]");
+declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]");
+
+fake_lint_pass! {
+    PassOkay,
+    lint_array!(CRATE_NOT_OKAY), // Single lint
+    "crate_okay"
+}
+
+fake_lint_pass! {
+    PassRedBlue,
+    lint_array!(CRATE_NOT_RED, CRATE_NOT_BLUE), // Multiple lints
+    "crate_red", "crate_blue"
+}
+
+fake_lint_pass! {
+    PassGreyGreen,
+    lint_array!(CRATE_NOT_GREY, CRATE_NOT_GREEN, ), // Trailing comma
+    "crate_grey", "crate_green"
 }
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_late_lint_pass(box Pass);
+    reg.register_late_lint_pass(box PassOkay);
+    reg.register_late_lint_pass(box PassRedBlue);
+    reg.register_late_lint_pass(box PassGreyGreen);
 }
diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs
index b5c1ee0..85aa92c 100644
--- a/src/test/run-pass-fulldeps/compiler-calls.rs
+++ b/src/test/run-pass-fulldeps/compiler-calls.rs
@@ -18,6 +18,7 @@
 extern crate getopts;
 extern crate rustc;
 extern crate rustc_driver;
+extern crate rustc_trans_utils;
 extern crate syntax;
 extern crate rustc_errors as errors;
 
@@ -25,6 +26,7 @@
 use rustc::session::Session;
 use rustc::session::config::{self, Input};
 use rustc_driver::{driver, CompilerCalls, Compilation};
+use rustc_trans_utils::trans_crate::TransCrate;
 use syntax::ast;
 
 use std::path::PathBuf;
@@ -46,6 +48,7 @@
     }
 
     fn late_callback(&mut self,
+                     _: &TransCrate,
                      _: &getopts::Matches,
                      _: &Session,
                      _: &CrateStore,
diff --git a/src/test/run-pass-fulldeps/issue-15778-pass.rs b/src/test/run-pass-fulldeps/issue-15778-pass.rs
index a767779..25800d4 100644
--- a/src/test/run-pass-fulldeps/issue-15778-pass.rs
+++ b/src/test/run-pass-fulldeps/issue-15778-pass.rs
@@ -15,5 +15,9 @@
 #![feature(plugin, custom_attribute)]
 #![plugin(lint_for_crate)]
 #![crate_okay]
+#![crate_blue]
+#![crate_red]
+#![crate_grey]
+#![crate_green]
 
 pub fn main() { }
diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
index 5afa9a2..10c44c8 100644
--- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
@@ -142,7 +142,11 @@
                     variadic: false,
                 });
                 iter_exprs(depth - 1, &mut |e| g(
-                        ExprKind::Closure(CaptureBy::Value, decl.clone(), e, DUMMY_SP)));
+                        ExprKind::Closure(CaptureBy::Value,
+                                          Movability::Movable,
+                                          decl.clone(),
+                                          e,
+                                          DUMMY_SP)));
             },
             10 => {
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x())));
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/empty-crate.rs
similarity index 73%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-pass-fulldeps/proc-macro/auxiliary/empty-crate.rs
index a2ef7da..b45d4bf 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/empty-crate.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(unused_variables)]
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs
index 29b6cc0..0433b11 100644
--- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs
@@ -17,6 +17,7 @@
 extern crate syntax;
 
 use rustc_plugin::Registry;
+use syntax::attr;
 use syntax::ext::base::*;
 use syntax::feature_gate::AttributeType::Whitelisted;
 use syntax::symbol::Symbol;
@@ -59,9 +60,9 @@
             _ => cx.tcx.hir.expect_item(cx.tcx.hir.get_parent(id)),
         };
 
-        if !item.attrs.iter().any(|a| a.check_name("whitelisted_attr")) {
+        if !attr::contains_name(&item.attrs, "whitelisted_attr") {
             cx.span_lint(MISSING_WHITELISTED_ATTR, span,
-                         "Missing 'whitelited_attr' attribute");
+                         "Missing 'whitelisted_attr' attribute");
         }
     }
 }
diff --git a/src/test/ui/typeck-default-trait-impl-outside-crate.rs b/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs
similarity index 72%
copy from src/test/ui/typeck-default-trait-impl-outside-crate.rs
copy to src/test/run-pass-fulldeps/proc-macro/empty-crate.rs
index ff0446e..38a2716 100644
--- a/src/test/ui/typeck-default-trait-impl-outside-crate.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// aux-build:empty-crate.rs
+// ignore-stage1
 
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
+#[macro_use]
+extern crate empty_crate;
+
 fn main() {}
diff --git a/src/test/run-pass-valgrind/exit-flushes.rs b/src/test/run-pass-valgrind/exit-flushes.rs
index b72d265..bb0d564 100644
--- a/src/test/run-pass-valgrind/exit-flushes.rs
+++ b/src/test/run-pass-valgrind/exit-flushes.rs
@@ -9,9 +9,10 @@
 // except according to those terms.
 
 // no-prefer-dynamic
+// ignore-cloudabi
+// ignore-emscripten
 // ignore-macos this needs valgrind 3.11 or higher; see
 // https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679
-// ignore-emscripten
 
 use std::env;
 use std::process::{exit, Command};
diff --git a/src/test/run-pass/abi-sysv64-register-usage.rs b/src/test/run-pass/abi-sysv64-register-usage.rs
index 1cae867..e701329 100644
--- a/src/test/run-pass/abi-sysv64-register-usage.rs
+++ b/src/test/run-pass/abi-sysv64-register-usage.rs
@@ -102,4 +102,4 @@
 }
 
 #[cfg(not(target_arch = "x86_64"))]
-pub fn main() {}
\ No newline at end of file
+pub fn main() {}
diff --git a/src/test/run-pass/abort-on-c-abi.rs b/src/test/run-pass/abort-on-c-abi.rs
new file mode 100644
index 0000000..17661c0
--- /dev/null
+++ b/src/test/run-pass/abort-on-c-abi.rs
@@ -0,0 +1,44 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
+// we never unwind through them.
+
+// ignore-cloudabi no env and process
+// ignore-emscripten no processes
+
+use std::{env, panic};
+use std::io::prelude::*;
+use std::io;
+use std::process::{Command, Stdio};
+
+extern "C" fn panic_in_ffi() {
+    panic!("Test");
+}
+
+fn test() {
+    let _ = panic::catch_unwind(|| { panic_in_ffi(); });
+    // The process should have aborted by now.
+    io::stdout().write(b"This should never be printed.\n");
+    let _ = io::stdout().flush();
+}
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() > 1 && args[1] == "test" {
+        return test();
+    }
+
+    let mut p = Command::new(&args[0])
+                        .stdout(Stdio::piped())
+                        .stdin(Stdio::piped())
+                        .arg("test").spawn().unwrap();
+    assert!(!p.wait().unwrap().success());
+}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/run-pass/align-with-extern-c-fn.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/run-pass/align-with-extern-c-fn.rs
index 5c32a75..db25960 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/run-pass/align-with-extern-c-fn.rs
@@ -8,9 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// #45662
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#![feature(repr_align)]
+#![feature(attr_literals)]
+
+#[repr(align(16))]
+pub struct A {
+    y: i64,
+}
+
+pub extern "C" fn foo(x: A) {}
+
+fn main() {}
diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs
index 712fa2d..eaa5bc9 100644
--- a/src/test/run-pass/allocator-alloc-one.rs
+++ b/src/test/run-pass/allocator-alloc-one.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(allocator_api, unique)]
+#![feature(allocator_api, nonnull)]
 
 use std::heap::{Heap, Alloc};
 
diff --git a/src/test/run-pass/asm-in-moved.rs b/src/test/run-pass/asm-in-moved.rs
new file mode 100644
index 0000000..246dd83
--- /dev/null
+++ b/src/test/run-pass/asm-in-moved.rs
@@ -0,0 +1,41 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(asm)]
+
+use std::cell::Cell;
+
+#[repr(C)]
+struct NoisyDrop<'a>(&'a Cell<&'static str>);
+impl<'a> Drop for NoisyDrop<'a> {
+    fn drop(&mut self) {
+        self.0.set("destroyed");
+    }
+}
+
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn main() {
+    let status = Cell::new("alive");
+    {
+        let _y: Box<NoisyDrop>;
+        let x = Box::new(NoisyDrop(&status));
+        unsafe {
+            asm!("mov $1, $0" : "=r"(_y) : "r"(x));
+        }
+        assert_eq!(status.get(), "alive");
+    }
+    assert_eq!(status.get(), "destroyed");
+}
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+fn main() {}
diff --git a/src/test/run-pass/asm-out-assign.rs b/src/test/run-pass/asm-out-assign.rs
index d7913b4..6acb905 100644
--- a/src/test/run-pass/asm-out-assign.rs
+++ b/src/test/run-pass/asm-out-assign.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions ast mir
+//[mir]compile-flags: -Z borrowck=mir
 
 #![feature(asm)]
 
diff --git a/src/test/run-pass/atomic-print.rs b/src/test/run-pass/atomic-print.rs
index ebc9f80..914b89d 100644
--- a/src/test/run-pass/atomic-print.rs
+++ b/src/test/run-pass/atomic-print.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no process support
 // ignore-emscripten no threads support
 
 use std::{env, fmt, process, sync, thread};
diff --git a/src/test/run-pass/auto-traits.rs b/src/test/run-pass/auto-traits.rs
index e42aca9..2a18b40 100644
--- a/src/test/run-pass/auto-traits.rs
+++ b/src/test/run-pass/auto-traits.rs
@@ -11,10 +11,6 @@
 #![feature(optin_builtin_traits)]
 
 auto trait Auto {}
-// Redundant but accepted until we remove it.
-#[allow(auto_impl)]
-impl Auto for .. {}
-
 unsafe auto trait AutoUnsafe {}
 
 impl !Auto for bool {}
@@ -29,6 +25,10 @@
 fn take_auto_unsafe<T: AutoUnsafe>(_: T) {}
 
 fn main() {
+    // Parse inside functions.
+    auto trait AutoInner {}
+    unsafe auto trait AutoUnsafeInner {}
+
     take_auto(0);
     take_auto(AutoBool(true));
     take_auto_unsafe(0);
diff --git a/src/test/run-pass/auxiliary/issue_42007_s.rs b/src/test/run-pass/auxiliary/issue_42007_s.rs
index b965e91..91ad986 100644
--- a/src/test/run-pass/auxiliary/issue_42007_s.rs
+++ b/src/test/run-pass/auxiliary/issue_42007_s.rs
@@ -11,4 +11,4 @@
 #[repr(u8)]
 pub enum E {
     B = 1 as u8,
-}
\ No newline at end of file
+}
diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs
index f923302..2f1c5c0 100644
--- a/src/test/run-pass/backtrace-debuginfo.rs
+++ b/src/test/run-pass/backtrace-debuginfo.rs
@@ -17,6 +17,7 @@
 
 // compile-flags:-g -Cllvm-args=-enable-tail-merge=0
 // ignore-pretty issue #37195
+// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 
 use std::env;
diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs
index b3a9e89..3e1ae73 100644
--- a/src/test/run-pass/backtrace.rs
+++ b/src/test/run-pass/backtrace.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-android FIXME #17520
+// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-openbsd no support for libbacktrace without filename
 // compile-flags:-g
diff --git a/src/test/run-pass/cast-rfc0401-vtable-kinds.rs b/src/test/run-pass/cast-rfc0401-vtable-kinds.rs
index 3a9f24a..32a155c 100644
--- a/src/test/run-pass/cast-rfc0401-vtable-kinds.rs
+++ b/src/test/run-pass/cast-rfc0401-vtable-kinds.rs
@@ -11,6 +11,8 @@
 // Check that you can cast between different pointers to trait objects
 // whose vtable have the same kind (both lengths, or both trait pointers).
 
+#![feature(unsized_tuple_coercion)]
+
 trait Foo<T> {
     fn foo(&self, _: T) -> u32 { 42 }
 }
@@ -39,6 +41,11 @@
     u as *const BarS<T>
 }
 
+fn tuple_i32_to_u32<T:?Sized>(u: *const (i32, T)) -> *const (u32, T) {
+    u as *const (u32, T)
+}
+
+
 fn main() {
     let x = 4u32;
     let y : &Foo<u32> = &x;
@@ -51,4 +58,14 @@
     let bar_ref : *const BarS<[u32]> = foo_to_bar(u);
     let z : &BarS<[u32]> = unsafe{&*bar_ref};
     assert_eq!(&z.0, &[0,1,2]);
+
+    // this assumes that tuple reprs for (i32, _) and (u32, _) are
+    // the same.
+    let s = (0i32, [0, 1, 2]);
+    let u: &(i32, [u8]) = &s;
+    let u: *const (i32, [u8]) = u;
+    let u_u32 : *const (u32, [u8]) = tuple_i32_to_u32(u);
+    unsafe {
+        assert_eq!(&(*u_u32).1, &[0, 1, 2]);
+    }
 }
diff --git a/src/test/run-pass/cfg-family.rs b/src/test/run-pass/cfg-family.rs
index 1797ad1..e45e35b 100644
--- a/src/test/run-pass/cfg-family.rs
+++ b/src/test/run-pass/cfg-family.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // pretty-expanded FIXME #23616
+// ignore-cloudabi no target_family
 // ignore-wasm32-bare no target_family
 
 #[cfg(windows)]
diff --git a/src/test/run-pass/cfg-target-family.rs b/src/test/run-pass/cfg-target-family.rs
index 0b8574e..7c279e4 100644
--- a/src/test/run-pass/cfg-target-family.rs
+++ b/src/test/run-pass/cfg-target-family.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no target_family
 // ignore-wasm32-bare no target_family
 
 // pretty-expanded FIXME #23616
diff --git a/src/test/run-pass/cleanup-shortcircuit.rs b/src/test/run-pass/cleanup-shortcircuit.rs
index 6744d7d..2460fa9 100644
--- a/src/test/run-pass/cleanup-shortcircuit.rs
+++ b/src/test/run-pass/cleanup-shortcircuit.rs
@@ -11,6 +11,7 @@
 // Test that cleanups for the RHS of shortcircuiting operators work.
 
 // pretty-expanded FIXME #23616
+// ignore-cloudabi no std::env support
 
 use std::env;
 
diff --git a/src/test/run-pass/command-before-exec.rs b/src/test/run-pass/command-before-exec.rs
index 9e782cc..9599f65 100644
--- a/src/test/run-pass/command-before-exec.rs
+++ b/src/test/run-pass/command-before-exec.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-windows - this is a unix-specific test
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(process_exec, libc)]
diff --git a/src/test/run-pass/command-exec.rs b/src/test/run-pass/command-exec.rs
index e378f55..d6d0c2b 100644
--- a/src/test/run-pass/command-exec.rs
+++ b/src/test/run-pass/command-exec.rs
@@ -10,6 +10,7 @@
 
 // ignore-windows - this is a unix-specific test
 // ignore-pretty issue #37199
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(process_exec)]
diff --git a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs b/src/test/run-pass/conservative_impl_trait.rs
similarity index 68%
copy from src/test/compile-fail/directory_ownership/backcompat-warnings.rs
copy to src/test/run-pass/conservative_impl_trait.rs
index 2da07a2..3009001 100644
--- a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs
+++ b/src/test/run-pass/conservative_impl_trait.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: mod statements in non-mod.rs files are unstable
+// #39665
 
-#[path="mod_file_not_owning_aux3.rs"]
-mod foo;
+#![feature(conservative_impl_trait)]
+
+fn batches(n: &u32) -> impl Iterator<Item=&u32> {
+    std::iter::once(n)
+}
 
 fn main() {}
diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs
index 863f3cf..13118c4 100644
--- a/src/test/run-pass/core-run-destroy.rs
+++ b/src/test/run-pass/core-run-destroy.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags:--test
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 // NB: These tests kill child processes. Valgrind sees these children as leaking
diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs
index 09318e7..e2a51bb 100644
--- a/src/test/run-pass/dynamic-drop.rs
+++ b/src/test/run-pass/dynamic-drop.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions:lexical nll
+#![cfg_attr(nll, feature(nll))]
+
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait, untagged_unions, slice_patterns, advanced_slice_patterns)]
diff --git a/src/test/run-pass/env-args-reverse-iterator.rs b/src/test/run-pass/env-args-reverse-iterator.rs
index dddf1ae..0645c65 100644
--- a/src/test/run-pass/env-args-reverse-iterator.rs
+++ b/src/test/run-pass/env-args-reverse-iterator.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::env::args;
diff --git a/src/test/run-pass/env-funky-keys.rs b/src/test/run-pass/env-funky-keys.rs
index 86ffaf1..12e1cbe 100644
--- a/src/test/run-pass/env-funky-keys.rs
+++ b/src/test/run-pass/env-funky-keys.rs
@@ -12,6 +12,7 @@
 
 // ignore-android
 // ignore-windows
+// ignore-cloudabi no execve
 // ignore-emscripten no execve
 // no-prefer-dynamic
 
diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs
index 3693e86..22e440c 100644
--- a/src/test/run-pass/env-home-dir.rs
+++ b/src/test/run-pass/env-home-dir.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no environment variables present
 // ignore-emscripten env vars don't work?
 
 #![feature(path)]
diff --git a/src/test/run-pass/env-vars.rs b/src/test/run-pass/env-vars.rs
index af44a65..d7b4c81 100644
--- a/src/test/run-pass/env-vars.rs
+++ b/src/test/run-pass/env-vars.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no env vars
 // ignore-wasm32-bare no env vars
 
 use std::env::*;
diff --git a/src/test/run-pass/exec-env.rs b/src/test/run-pass/exec-env.rs
index a96d189..b2d2e70 100644
--- a/src/test/run-pass/exec-env.rs
+++ b/src/test/run-pass/exec-env.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // exec-env:TEST_EXEC_ENV=22
+// ignore-cloudabi no env vars
 // ignore-emscripten FIXME: issue #31622
 
 use std::env;
diff --git a/src/test/run-pass/fds-are-cloexec.rs b/src/test/run-pass/fds-are-cloexec.rs
index f558761..a5ae0ae 100644
--- a/src/test/run-pass/fds-are-cloexec.rs
+++ b/src/test/run-pass/fds-are-cloexec.rs
@@ -10,6 +10,7 @@
 
 // ignore-windows
 // ignore-android
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-haiku
 
diff --git a/src/test/run-pass/for-loop-mut-ref-element.rs b/src/test/run-pass/for-loop-mut-ref-element.rs
index 14ce23b..556c846 100644
--- a/src/test/run-pass/for-loop-mut-ref-element.rs
+++ b/src/test/run-pass/for-loop-mut-ref-element.rs
@@ -12,4 +12,4 @@
 
 fn main() {
     for ref mut _a in std::iter::once(true) {}
-}
\ No newline at end of file
+}
diff --git a/src/test/run-pass/generator/borrow-in-tail-expr.rs b/src/test/run-pass/generator/borrow-in-tail-expr.rs
index df1a1dc..486fe3c 100644
--- a/src/test/run-pass/generator/borrow-in-tail-expr.rs
+++ b/src/test/run-pass/generator/borrow-in-tail-expr.rs
@@ -16,4 +16,4 @@
         let a = String::new();
         a.len()
     };
-}
\ No newline at end of file
+}
diff --git a/src/test/run-pass/generator/issue-44197.rs b/src/test/run-pass/generator/issue-44197.rs
new file mode 100644
index 0000000..7cb80ea
--- /dev/null
+++ b/src/test/run-pass/generator/issue-44197.rs
@@ -0,0 +1,40 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(conservative_impl_trait, generators, generator_trait)]
+
+use std::ops::{ Generator, GeneratorState };
+
+fn foo(_: &str) -> String {
+    String::new()
+}
+
+fn bar(baz: String) -> impl Generator<Yield = String, Return = ()> {
+    move || {
+        yield foo(&baz);
+    }
+}
+
+fn foo2(_: &str) -> Result<String, ()> {
+    Err(())
+}
+
+fn bar2(baz: String) -> impl Generator<Yield = String, Return = ()> {
+    move || {
+        if let Ok(quux) = foo2(&baz) {
+            yield quux;
+        }
+    }
+}
+
+fn main() {
+    assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new()));
+    assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(()));
+}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/run-pass/generator/live-upvar-across-yield.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/run-pass/generator/live-upvar-across-yield.rs
index 5c32a75..e34b0b3 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/run-pass/generator/live-upvar-across-yield.rs
@@ -8,9 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(generators, generator_trait)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+use std::ops::Generator;
+
+fn main() {
+    let b = |_| 3;
+    let mut a = || {
+        b(yield);
+    };
+    a.resume();
+}
diff --git a/src/test/run-pass/generator/match-bindings.rs b/src/test/run-pass/generator/match-bindings.rs
index 9c6b057..231aa1b 100644
--- a/src/test/run-pass/generator/match-bindings.rs
+++ b/src/test/run-pass/generator/match-bindings.rs
@@ -27,4 +27,4 @@
             yield;
         }
     };
-}
\ No newline at end of file
+}
diff --git a/src/test/run-pass/generator/nested_generators.rs b/src/test/run-pass/generator/nested_generators.rs
new file mode 100644
index 0000000..f70d414
--- /dev/null
+++ b/src/test/run-pass/generator/nested_generators.rs
@@ -0,0 +1,30 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators)]
+#![feature(generator_trait)]
+
+use std::ops::Generator;
+use std::ops::GeneratorState;
+
+fn main() {
+    let _generator = || {
+        let mut sub_generator = || {
+            yield 2;
+        };
+
+        match sub_generator.resume() {
+            GeneratorState::Yielded(x) => {
+                yield x;
+            }
+            _ => panic!(),
+        };
+    };
+}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/run-pass/generator/reborrow-mut-upvar.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/run-pass/generator/reborrow-mut-upvar.rs
index 5c32a75..8353066 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/run-pass/generator/reborrow-mut-upvar.rs
@@ -8,9 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(generators)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+fn _run(bar: &mut i32) {
+    || {
+        {
+            let _baz = &*bar;
+            yield;
+        }
+
+        *bar = 2;
+    };
+}
+
+fn main() {}
diff --git a/src/test/run-pass/generator/static-generators.rs b/src/test/run-pass/generator/static-generators.rs
new file mode 100644
index 0000000..9504414
--- /dev/null
+++ b/src/test/run-pass/generator/static-generators.rs
@@ -0,0 +1,26 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+
+fn main() {
+    let mut generator = unsafe {
+        static || {
+            let a = true;
+            let b = &a;
+            yield;
+            assert_eq!(b as *const _, &a as *const _);
+        }
+    };
+    assert_eq!(generator.resume(), GeneratorState::Yielded(()));
+    assert_eq!(generator.resume(), GeneratorState::Complete(()));
+}
diff --git a/src/test/run-pass/generator/yield-subtype.rs b/src/test/run-pass/generator/yield-subtype.rs
index 5ff070f..7e8a0d1 100644
--- a/src/test/run-pass/generator/yield-subtype.rs
+++ b/src/test/run-pass/generator/yield-subtype.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions:lexical nll
+#![cfg_attr(nll, feature(nll))]
+
 #![feature(generators)]
 
 fn bar<'a>() {
@@ -20,4 +23,4 @@
     };
 }
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/run-pass/hygiene/auxiliary/legacy_interaction.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/run-pass/hygiene/auxiliary/legacy_interaction.rs
index 5c32a75..c614ee4 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/run-pass/hygiene/auxiliary/legacy_interaction.rs
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// ignore-pretty pretty-printing is unhygienic
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#[macro_export]
+macro_rules! m {
+    () => {
+        fn f() {} // (2)
+        g(); // (1)
+    }
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass/hygiene/auxiliary/my_crate.rs
similarity index 79%
rename from src/test/compile-fail/E0580.rs
rename to src/test/run-pass/hygiene/auxiliary/my_crate.rs
index a2ef7da..e10d20b 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-pass/hygiene/auxiliary/my_crate.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+pub fn f() {}
diff --git a/src/test/run-pass/hygiene/auxiliary/unhygienic_example.rs b/src/test/run-pass/hygiene/auxiliary/unhygienic_example.rs
new file mode 100644
index 0000000..298e020
--- /dev/null
+++ b/src/test/run-pass/hygiene/auxiliary/unhygienic_example.rs
@@ -0,0 +1,37 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+
+extern crate my_crate;
+
+pub fn g() {} // (a)
+
+#[macro_export]
+macro_rules! unhygienic_macro {
+    () => {
+        // (1) unhygienic: depends on `my_crate` in the crate root at the invocation site.
+        ::my_crate::f();
+
+        // (2) unhygienic: defines `f` at the invocation site (in addition to the above point).
+        use my_crate::f;
+        f();
+
+        g(); // (3) unhygienic: `g` needs to be in scope at use site.
+
+        $crate::g(); // (4) hygienic: this always resolves to (a)
+    }
+}
+
+#[allow(unused)]
+fn test_unhygienic() {
+    unhygienic_macro!();
+    f(); // `f` was defined at the use site
+}
diff --git a/src/test/run-pass/hygiene/legacy_interaction.rs b/src/test/run-pass/hygiene/legacy_interaction.rs
new file mode 100644
index 0000000..683a15b
--- /dev/null
+++ b/src/test/run-pass/hygiene/legacy_interaction.rs
@@ -0,0 +1,50 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:legacy_interaction.rs
+
+#![feature(decl_macro)]
+#[allow(unused)]
+
+extern crate legacy_interaction;
+// ^ defines
+// ```rust
+//  macro_rules! m {
+//     () => {
+//         fn f() // (1)
+//         g() // (2)
+//     }
+// }
+// ```rust
+
+mod def_site {
+    // Unless this macro opts out of hygiene, it should resolve the same wherever it is invoked.
+    pub macro m2() {
+        ::legacy_interaction::m!();
+        f(); // This should resolve to (1)
+        fn g() {} // We want (2) resolve to this, not to (4)
+    }
+}
+
+mod use_site {
+    fn test() {
+        fn f() -> bool { true } // (3)
+        fn g() -> bool { true } // (4)
+
+        ::def_site::m2!();
+
+        let _: bool = f(); // This should resolve to (3)
+        let _: bool = g(); // This should resolve to (4)
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
new file mode 100644
index 0000000..5520695
--- /dev/null
+++ b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
@@ -0,0 +1,43 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:my_crate.rs
+// aux-build:unhygienic_example.rs
+
+#![feature(decl_macro)]
+
+extern crate unhygienic_example;
+extern crate my_crate; // (b)
+
+// Hygienic version of `unhygienic_macro`.
+pub macro hygienic_macro() {
+    fn g() {} // (c)
+    ::unhygienic_example::unhygienic_macro!();
+    // ^ Even though we invoke an unhygienic macro, `hygienic_macro` remains hygienic.
+    // In the above expansion:
+    // (1) `my_crate` always resolves to (b) regardless of invocation site.
+    // (2) The defined function `f` is only usable inside this macro definition.
+    // (3) `g` always resolves to (c) regardless of invocation site.
+    // (4) `$crate::g` remains hygienic and continues to resolve to (a).
+
+    f();
+}
+
+#[allow(unused)]
+fn test_hygienic_macro() {
+    hygienic_macro!();
+
+    fn f() {} // (d) no conflict
+    f(); // resolves to (d)
+}
+
+fn main() {}
diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs
index 8d035ba..aca1005 100644
--- a/src/test/run-pass/impl-trait/example-calendar.rs
+++ b/src/test/run-pass/impl-trait/example-calendar.rs
@@ -15,7 +15,9 @@
            universal_impl_trait,
            fn_traits,
            step_trait,
-           unboxed_closures
+           unboxed_closures,
+           copy_closures,
+           clone_closures
 )]
 
 //! Derived from: <https://raw.githubusercontent.com/quickfur/dcal/master/dcal.d>.
@@ -234,42 +236,6 @@
     }
 }
 
-/// Wrapper for zero-sized closures.
-// HACK(eddyb) Only needed because closures can't implement Copy.
-struct Fn0<F>(std::marker::PhantomData<F>);
-
-impl<F> Copy for Fn0<F> {}
-impl<F> Clone for Fn0<F> {
-    fn clone(&self) -> Self { *self }
-}
-
-impl<F: FnOnce<A>, A> FnOnce<A> for Fn0<F> {
-    type Output = F::Output;
-
-    extern "rust-call" fn call_once(self, args: A) -> Self::Output {
-        let f = unsafe { std::mem::uninitialized::<F>() };
-        f.call_once(args)
-    }
-}
-
-impl<F: FnMut<A>, A> FnMut<A> for Fn0<F> {
-    extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output {
-        let mut f = unsafe { std::mem::uninitialized::<F>() };
-        f.call_mut(args)
-    }
-}
-
-trait AsFn0<A>: Sized {
-    fn copyable(self) -> Fn0<Self>;
-}
-
-impl<F: FnMut<A>, A> AsFn0<A> for F {
-    fn copyable(self) -> Fn0<Self> {
-        assert_eq!(std::mem::size_of::<F>(), 0);
-        Fn0(std::marker::PhantomData)
-    }
-}
-
 /// GroupBy implementation.
 struct GroupBy<It: Iterator, F> {
     it: std::iter::Peekable<It>,
@@ -277,11 +243,15 @@
 }
 
 impl<It, F> Clone for GroupBy<It, F>
-where It: Iterator + Clone, It::Item: Clone, F: Clone {
-    fn clone(&self) -> GroupBy<It, F> {
+where
+    It: Iterator + Clone,
+    It::Item: Clone,
+    F: Clone,
+{
+    fn clone(&self) -> Self {
         GroupBy {
             it: self.it.clone(),
-            f: self.f.clone()
+            f: self.f.clone(),
         }
     }
 }
@@ -331,14 +301,11 @@
 }
 
 trait IteratorExt: Iterator + Sized {
-    fn group_by<G, F>(self, f: F) -> GroupBy<Self, Fn0<F>>
-    where F: FnMut(&Self::Item) -> G,
+    fn group_by<G, F>(self, f: F) -> GroupBy<Self, F>
+    where F: Clone + FnMut(&Self::Item) -> G,
           G: Eq
     {
-        GroupBy {
-            it: self.peekable(),
-            f: f.copyable(),
-        }
+        GroupBy { it: self.peekable(), f }
     }
 
     fn join(mut self, sep: &str) -> String
@@ -382,7 +349,7 @@
 fn dates_in_year(year: i32) -> impl Iterator<Item=NaiveDate>+Clone {
     InGroup {
         it: NaiveDate::from_ymd(year, 1, 1)..,
-        f: (|d: &NaiveDate| d.year()).copyable(),
+        f: |d: &NaiveDate| d.year(),
         g: year
     }
 }
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/run-pass/impl-trait/issue-42479.rs
similarity index 67%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/run-pass/impl-trait/issue-42479.rs
index 5c32a75..629948a 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/run-pass/impl-trait/issue-42479.rs
@@ -8,9 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(conservative_impl_trait)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+use std::iter::once;
+
+struct Foo {
+    x: i32,
+}
+
+impl Foo {
+    fn inside(&self) -> impl Iterator<Item = &i32> {
+        once(&self.x)
+    }
+}
+
+fn main() {
+    println!("hi");
+}
diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs
index a56f083..1f2d76f 100644
--- a/src/test/run-pass/impl-trait/lifetimes.rs
+++ b/src/test/run-pass/impl-trait/lifetimes.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(conservative_impl_trait, underscore_lifetimes, universal_impl_trait)]
+#![feature(conservative_impl_trait, underscore_lifetimes, universal_impl_trait, nested_impl_trait)]
 #![allow(warnings)]
 
 use std::fmt::Debug;
diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs
index 99edd255..c7aa78e 100644
--- a/src/test/run-pass/intrinsic-alignment.rs
+++ b/src/test/run-pass/intrinsic-alignment.rs
@@ -19,14 +19,15 @@
     }
 }
 
-#[cfg(any(target_os = "linux",
-          target_os = "macos",
-          target_os = "freebsd",
+#[cfg(any(target_os = "cloudabi",
           target_os = "dragonfly",
+          target_os = "emscripten",
+          target_os = "freebsd",
+          target_os = "linux",
+          target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "solaris",
-          target_os = "emscripten"))]
+          target_os = "solaris"))]
 mod m {
     #[main]
     #[cfg(target_arch = "x86")]
diff --git a/src/test/run-pass/issue-10626.rs b/src/test/run-pass/issue-10626.rs
index e9d3781..9262fc3 100644
--- a/src/test/run-pass/issue-10626.rs
+++ b/src/test/run-pass/issue-10626.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 // Make sure that if a process doesn't have its stdio/stderr descriptors set up
diff --git a/src/test/run-pass/issue-12133-3.rs b/src/test/run-pass/issue-12133-3.rs
index 8f455c2..2b36c94 100644
--- a/src/test/run-pass/issue-12133-3.rs
+++ b/src/test/run-pass/issue-12133-3.rs
@@ -11,8 +11,9 @@
 // aux-build:issue-12133-rlib.rs
 // aux-build:issue-12133-dylib.rs
 // aux-build:issue-12133-dylib2.rs
-// ignore-musl
+// ignore-cloudabi no dylib support
 // ignore-emscripten no dylib support
+// ignore-musl
 
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/run-pass/issue-13304.rs b/src/test/run-pass/issue-13304.rs
index 9214d6b..264db10 100644
--- a/src/test/run-pass/issue-13304.rs
+++ b/src/test/run-pass/issue-13304.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(io, process_capture)]
diff --git a/src/test/run-pass/issue-14456.rs b/src/test/run-pass/issue-14456.rs
index 2edb45c..c4745a6 100644
--- a/src/test/run-pass/issue-14456.rs
+++ b/src/test/run-pass/issue-14456.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(io, process_capture)]
diff --git a/src/test/run-pass/issue-14940.rs b/src/test/run-pass/issue-14940.rs
index 588fa63..c074182 100644
--- a/src/test/run-pass/issue-14940.rs
+++ b/src/test/run-pass/issue-14940.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::env;
diff --git a/src/test/run-pass/issue-16272.rs b/src/test/run-pass/issue-16272.rs
index cd02cbf..f8d6e43 100644
--- a/src/test/run-pass/issue-16272.rs
+++ b/src/test/run-pass/issue-16272.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::process::Command;
diff --git a/src/test/run-pass/issue-17121.rs b/src/test/run-pass/issue-17121.rs
index dcbcc2d..6eb8130 100644
--- a/src/test/run-pass/issue-17121.rs
+++ b/src/test/run-pass/issue-17121.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // pretty-expanded FIXME #23616
+// ignore-cloudabi no std::fs
 
 use std::fs::File;
 use std::io::{self, BufReader, Read};
diff --git a/src/test/run-pass/issue-20091.rs b/src/test/run-pass/issue-20091.rs
index c8ba5db..f84cfd2 100644
--- a/src/test/run-pass/issue-20091.rs
+++ b/src/test/run-pass/issue-20091.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(std_misc, os)]
diff --git a/src/test/run-pass/issue-20644.rs b/src/test/run-pass/issue-20644.rs
index 72ccd82..7cacc2e 100644
--- a/src/test/run-pass/issue-20644.rs
+++ b/src/test/run-pass/issue-20644.rs
@@ -12,6 +12,7 @@
 // had to do with trans ignoring binders.
 
 // pretty-expanded FIXME #23616
+// ignore-cloudabi no std::fs
 
 #![feature(os)]
 
diff --git a/src/test/run-pass/issue-20797.rs b/src/test/run-pass/issue-20797.rs
index e45582d..3a4be58 100644
--- a/src/test/run-pass/issue-20797.rs
+++ b/src/test/run-pass/issue-20797.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::fs
+
 // Regression test for #20797.
 
 use std::default::Default;
diff --git a/src/test/run-pass/issue-22066.rs b/src/test/run-pass/issue-22066.rs
index 2817ef7..c2486f0 100644
--- a/src/test/run-pass/issue-22066.rs
+++ b/src/test/run-pass/issue-22066.rs
@@ -18,4 +18,4 @@
     }
 }
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/run-pass/issue-2214.rs b/src/test/run-pass/issue-2214.rs
index 7b7ecc9..a87af59 100644
--- a/src/test/run-pass/issue-2214.rs
+++ b/src/test/run-pass/issue-2214.rs
@@ -34,7 +34,7 @@
 
     #[link_name = "m"]
     extern {
-        #[cfg(unix)]
+        #[cfg(any(unix, target_os = "cloudabi"))]
         #[link_name="lgamma_r"]
         pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double;
         #[cfg(windows)]
diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs
index 96e77c0..ec4be81 100644
--- a/src/test/run-pass/issue-22577.rs
+++ b/src/test/run-pass/issue-22577.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // pretty-expanded FIXME #23616
+// ignore-cloudabi no std::fs
 
 #![feature(fs, net)]
 
diff --git a/src/test/run-pass/issue-23036.rs b/src/test/run-pass/issue-23036.rs
index 0ed4126..c3c9ede 100644
--- a/src/test/run-pass/issue-23036.rs
+++ b/src/test/run-pass/issue-23036.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::path
+
 use std::collections::HashMap;
 use std::path::Path;
 
diff --git a/src/test/run-pass/issue-23433.rs b/src/test/run-pass/issue-23433.rs
index aa13d6f..7af732f 100644
--- a/src/test/run-pass/issue-23433.rs
+++ b/src/test/run-pass/issue-23433.rs
@@ -10,13 +10,11 @@
 
 // Don't fail if we encounter a NonZero<*T> where T is an unsized type
 
-#![feature(unique)]
-
-use std::ptr::Unique;
+use std::ptr::NonNull;
 
 fn main() {
     let mut a = [0u8; 5];
-    let b: Option<Unique<[u8]>> = Some(Unique::from(&mut a));
+    let b: Option<NonNull<[u8]>> = Some(NonNull::from(&mut a));
     match b {
         Some(_) => println!("Got `Some`"),
         None => panic!("Unexpected `None`"),
diff --git a/src/test/run-pass/issue-23649-2.rs b/src/test/run-pass/issue-23649-2.rs
index 018c069..c48ae41 100644
--- a/src/test/run-pass/issue-23649-2.rs
+++ b/src/test/run-pass/issue-23649-2.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::path
+
 use std::collections::HashMap;
 use std::path::{Path, PathBuf};
 
diff --git a/src/test/run-pass/issue-24313.rs b/src/test/run-pass/issue-24313.rs
index ad385ee..2e7d2e4 100644
--- a/src/test/run-pass/issue-24313.rs
+++ b/src/test/run-pass/issue-24313.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no threads
 
 use std::thread;
diff --git a/src/test/run-pass/issue-25693.rs b/src/test/run-pass/issue-25693.rs
index aee89be..0d9dc3c 100644
--- a/src/test/run-pass/issue-25693.rs
+++ b/src/test/run-pass/issue-25693.rs
@@ -8,16 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub trait Paramters { type SelfRef; }
+pub trait Parameters { type SelfRef; }
 
 struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> }
 struct BP;
 
-impl<'a> Paramters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
-impl Paramters for BP { type SelfRef = Box<X<BP>>; }
+impl<'a> Parameters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
+impl Parameters for BP { type SelfRef = Box<X<BP>>; }
 
 pub struct Y;
-pub enum X<P: Paramters> {
+pub enum X<P: Parameters> {
     Nothing,
     SameAgain(P::SelfRef, Y)
 }
diff --git a/src/test/run-pass/issue-26322.rs b/src/test/run-pass/issue-26322.rs
index 766d1ce..7f8c7f5 100644
--- a/src/test/run-pass/issue-26322.rs
+++ b/src/test/run-pass/issue-26322.rs
@@ -28,9 +28,9 @@
         columnline!()
     } else { (0, 0) };
     let cl = columnline!();
-    assert_eq!(closure(), (8, 25));
-    assert_eq!(iflet, (8, 28));
-    assert_eq!(cl, (13, 30));
+    assert_eq!(closure(), (9, 25));
+    assert_eq!(iflet, (9, 28));
+    assert_eq!(cl, (14, 30));
     let indirect = indirectcolumnline!();
-    assert_eq!(indirect, (19, 34));
+    assert_eq!(indirect, (20, 34));
 }
diff --git a/src/test/run-pass/issue-27859.rs b/src/test/run-pass/issue-27859.rs
index 56036ca..d184724 100644
--- a/src/test/run-pass/issue-27859.rs
+++ b/src/test/run-pass/issue-27859.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::env
 // ignore-wasm32 issue 42629
 
 #[inline(never)]
diff --git a/src/test/run-pass/issue-29516.rs b/src/test/run-pass/issue-29516.rs
index 5fa0a00..4659865 100644
--- a/src/test/run-pass/issue-29516.rs
+++ b/src/test/run-pass/issue-29516.rs
@@ -10,9 +10,8 @@
 
 #![feature(optin_builtin_traits)]
 
-trait NotSame {}
-#[allow(auto_impl)]
-impl NotSame for .. {}
+auto trait NotSame {}
+
 impl<A> !NotSame for (A, A) {}
 
 trait OneOfEach {}
diff --git a/src/test/run-pass/issue-30490.rs b/src/test/run-pass/issue-30490.rs
index 4296107..633bd53 100644
--- a/src/test/run-pass/issue-30490.rs
+++ b/src/test/run-pass/issue-30490.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 // Previously libstd would set stdio descriptors of a child process
diff --git a/src/test/run-pass/issue-32292.rs b/src/test/run-pass/issue-32292.rs
index 3995caa..ed319b1 100644
--- a/src/test/run-pass/issue-32292.rs
+++ b/src/test/run-pass/issue-32292.rs
@@ -15,4 +15,4 @@
 
 fn main() {
     let _ = Foo;
-}
\ No newline at end of file
+}
diff --git a/src/test/run-pass/issue-33770.rs b/src/test/run-pass/issue-33770.rs
index 3806270..7fad2b3 100644
--- a/src/test/run-pass/issue-33770.rs
+++ b/src/test/run-pass/issue-33770.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::process::{Command, Stdio};
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/run-pass/issue-33903.rs
similarity index 67%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/run-pass/issue-33903.rs
index 5c32a75..ab36853 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/run-pass/issue-33903.rs
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// Issue 33903:
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Only built-in indexing can be used in constant expresssions
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+const FOO: i32 = [12, 34][0 + 1];
+
+fn main() {}
+
diff --git a/src/test/run-pass/issue-33992.rs b/src/test/run-pass/issue-33992.rs
index 5729469..98da7d4 100644
--- a/src/test/run-pass/issue-33992.rs
+++ b/src/test/run-pass/issue-33992.rs
@@ -37,4 +37,4 @@
 #[linkage = "weak_odr"]
 pub static TEST8: bool = true;
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/run-pass/issue-35376.rs b/src/test/run-pass/issue-35376.rs
index 25895cd..9e4eb84 100644
--- a/src/test/run-pass/issue-35376.rs
+++ b/src/test/run-pass/issue-35376.rs
@@ -48,4 +48,4 @@
 
 impl Beta for Handle {
     type Event = ();
-}
\ No newline at end of file
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass/issue-36792.rs
similarity index 71%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-pass/issue-36792.rs
index a2ef7da..faf983f 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-pass/issue-36792.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(conservative_impl_trait)]
+fn foo() -> impl Copy {
+    foo
+}
+fn main() {
+    foo();
+}
diff --git a/src/test/run-pass/issue-38091.rs b/src/test/run-pass/issue-38091.rs
new file mode 100644
index 0000000..3405024
--- /dev/null
+++ b/src/test/run-pass/issue-38091.rs
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+trait Iterate<'a> {
+    type Ty: Valid;
+    fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T where T: Check {
+    default type Ty = ();
+    default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+fn main() {
+    Iterate::iterate(0);
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass/issue-42148.rs
similarity index 71%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-pass/issue-42148.rs
index a2ef7da..0196649 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-pass/issue-42148.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+struct Zst;
+
+fn main() {
+    unsafe { ::std::ptr::write_volatile(1 as *mut Zst, Zst) }
+}
diff --git a/src/test/run-pass/issue-42956.rs b/src/test/run-pass/issue-42956.rs
new file mode 100644
index 0000000..9bda6ee
--- /dev/null
+++ b/src/test/run-pass/issue-42956.rs
@@ -0,0 +1,33 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+impl A for i32 {
+    type Foo = u32;
+}
+impl B for u32 {
+    const BAR: i32 = 0;
+}
+
+trait A {
+    type Foo: B;
+}
+
+trait B {
+    const BAR: i32;
+}
+
+fn generic<T: A>() {
+    // This panics if the universal function call syntax is used as well
+    println!("{}", T::Foo::BAR);
+}
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/issue-44953/issue-44953.rs b/src/test/run-pass/issue-43291.rs
similarity index 63%
copy from src/test/ui-fulldeps/issue-44953/issue-44953.rs
copy to src/test/run-pass/issue-43291.rs
index de798e2..98de8f7 100644
--- a/src/test/ui-fulldeps/issue-44953/issue-44953.rs
+++ b/src/test/run-pass/issue-43291.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -7,14 +7,12 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-//
-
-
-#![feature(proc_macro)]
-#![allow(unused_macros)]
-
-#[macro_use] extern crate log; //~ ERROR use of unstable library feature
 
 pub fn main() {
-    info!("This is a log message.");
+    assert_eq!(!0usize as *const (), foo(0, 1));
+    assert_eq!(!0usize as *const (), (0i8 - 1) as *const ());
+}
+
+pub fn foo(a: i8, b: i8) -> *const () {
+    (a - b) as *const ()
 }
diff --git a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs b/src/test/run-pass/issue-43483.rs
similarity index 69%
copy from src/test/compile-fail/directory_ownership/backcompat-warnings.rs
copy to src/test/run-pass/issue-43483.rs
index 2da07a2..48482af 100644
--- a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs
+++ b/src/test/run-pass/issue-43483.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: mod statements in non-mod.rs files are unstable
+trait VecN {
+    const DIM: usize;
+}
 
-#[path="mod_file_not_owning_aux3.rs"]
-mod foo;
+trait Mat {
+    type Row: VecN;
+}
+
+fn m<M: Mat>() {
+    let x = M::Row::DIM;
+}
 
 fn main() {}
diff --git a/src/test/run-pass/issue-45152.rs b/src/test/run-pass/issue-45152.rs
new file mode 100644
index 0000000..a5c349a
--- /dev/null
+++ b/src/test/run-pass/issue-45152.rs
@@ -0,0 +1,31 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unsize, coerce_unsized)]
+
+#[repr(packed)]
+struct UnalignedPtr<'a, T: ?Sized>
+    where T: 'a,
+{
+    data: &'a T,
+}
+
+fn main() {
+
+    impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
+        where
+        T: std::marker::Unsize<U> + ?Sized,
+        U: ?Sized,
+    { }
+
+    let arr = [1, 2, 3];
+    let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
+    let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
+}
diff --git a/src/test/run-pass/issue-4541.rs b/src/test/run-pass/issue-4541.rs
index 1f090d8..68f6945 100644
--- a/src/test/run-pass/issue-4541.rs
+++ b/src/test/run-pass/issue-4541.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::env
+
 fn parse_args() -> String {
     let args: Vec<_> = ::std::env::args().collect();
     let mut n = 0;
diff --git a/src/test/run-pass/issue-4542.rs b/src/test/run-pass/issue-4542.rs
index 23e8f5b..59837e4 100644
--- a/src/test/run-pass/issue-4542.rs
+++ b/src/test/run-pass/issue-4542.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // pretty-expanded FIXME #23616
+// ignore-cloudabi no std::env
 
 use std::env;
 
diff --git a/src/test/run-pass/issue-45731.rs b/src/test/run-pass/issue-45731.rs
index ec35035..e2c04c9 100644
--- a/src/test/run-pass/issue-45731.rs
+++ b/src/test/run-pass/issue-45731.rs
@@ -10,11 +10,11 @@
 
 // compile-flags:--test -g
 
-use std::{env, panic, fs};
-
 #[cfg(target_os = "macos")]
 #[test]
 fn simple_test() {
+    use std::{env, panic, fs};
+
     // Find our dSYM and replace the DWARF binary with an empty file
     let mut dsym_path = env::current_exe().unwrap();
     let executable_name = dsym_path.file_name().unwrap().to_str().unwrap().to_string();
diff --git a/src/test/run-pass/issue-46095.rs b/src/test/run-pass/issue-46095.rs
new file mode 100644
index 0000000..35e51eb
--- /dev/null
+++ b/src/test/run-pass/issue-46095.rs
@@ -0,0 +1,39 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct A;
+
+impl A {
+    fn take_mutably(&mut self) {}
+}
+
+fn identity<T>(t: T) -> T {
+    t
+}
+
+// Issue 46095
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Overloaded indexing would cause wrapped to be borrowed mutably
+
+fn main() {
+    let mut a1 = A;
+    let mut a2 = A;
+
+    let wrapped = [&mut a1, &mut a2];
+
+    {
+        wrapped[0 + 1 - 1].take_mutably();
+    }
+
+    {
+        wrapped[identity(0)].take_mutably();
+    }
+}
diff --git a/src/test/run-pass/issue-46845.rs b/src/test/run-pass/issue-46845.rs
new file mode 100644
index 0000000..235d398
--- /dev/null
+++ b/src/test/run-pass/issue-46845.rs
@@ -0,0 +1,39 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// To work around #46855
+// compile-flags: -Z mir-opt-level=0
+// Regression test for the inhabitedness of unions with uninhabited variants, issue #46845
+
+use std::mem;
+
+#[derive(Copy, Clone)]
+enum Never { }
+
+// A single uninhabited variant shouldn't make the whole union uninhabited.
+union Foo {
+    a: u64,
+    _b: Never
+}
+
+// If all the variants are uninhabited, however, the union should be uninhabited.
+union Bar {
+    _a: (Never, u64),
+    _b: (u64, Never)
+}
+
+fn main() {
+    assert_eq!(mem::size_of::<Foo>(), 8);
+    assert_eq!(mem::size_of::<Bar>(), 0);
+
+    let f = [Foo { a: 42 }, Foo { a: 10 }];
+    println!("{}", unsafe { f[0].a });
+    assert_eq!(unsafe { f[1].a }, 10);
+}
diff --git a/src/test/run-pass/issue-46855.rs b/src/test/run-pass/issue-46855.rs
new file mode 100644
index 0000000..d864d55
--- /dev/null
+++ b/src/test/run-pass/issue-46855.rs
@@ -0,0 +1,34 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Zmir-opt-level=1
+
+#![feature(slice_patterns)]
+
+use std::mem;
+
+#[derive(Copy, Clone)]
+enum Never {}
+
+union Foo {
+    a: u64,
+    b: Never
+}
+
+fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 }
+
+fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x }
+
+fn main() {
+    println!("{}", mem::size_of::<Foo>());
+
+    let f = [Foo { a: 42 }, Foo { a: 10 }];
+    println!("{:?}", unsafe { f[0].a });
+}
diff --git a/src/test/run-pass/issue-46920-byte-array-patterns.rs b/src/test/run-pass/issue-46920-byte-array-patterns.rs
new file mode 100644
index 0000000..236f699
--- /dev/null
+++ b/src/test/run-pass/issue-46920-byte-array-patterns.rs
@@ -0,0 +1,37 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const CURSOR_PARTITION_LABEL: &'static [u8] = b"partition";
+const CURSOR_EVENT_TYPE_LABEL: &'static [u8] = b"event_type";
+const BYTE_PATTERN: &'static [u8; 5] = b"hello";
+
+fn match_slice(x: &[u8]) -> u32 {
+    match x {
+        CURSOR_PARTITION_LABEL => 0,
+        CURSOR_EVENT_TYPE_LABEL => 1,
+        _ => 2,
+    }
+}
+
+fn match_array(x: &[u8; 5]) -> bool {
+    match x {
+        BYTE_PATTERN => true,
+        _ => false
+    }
+}
+
+fn main() {
+    assert_eq!(match_slice(b"abcde"), 2);
+    assert_eq!(match_slice(b"event_type"), 1);
+    assert_eq!(match_slice(b"partition"), 0);
+
+    assert_eq!(match_array(b"hello"), true);
+    assert_eq!(match_array(b"hella"), false);
+}
diff --git a/src/test/run-pass/issue-46959.rs b/src/test/run-pass/issue-46959.rs
new file mode 100644
index 0000000..0826f5e
--- /dev/null
+++ b/src/test/run-pass/issue-46959.rs
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(universal_impl_trait)]
+#![feature(conservative_impl_trait)]
+#![deny(non_camel_case_types)]
+
+#[allow(dead_code)]
+fn qqq(lol: impl Iterator<Item=u32>) -> impl Iterator<Item=u64> {
+        lol.map(|x|x as u64)
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-46964.rs b/src/test/run-pass/issue-46964.rs
new file mode 100644
index 0000000..2a82c6d
--- /dev/null
+++ b/src/test/run-pass/issue-46964.rs
@@ -0,0 +1,28 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod my_mod {
+    #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
+    pub struct Name<'a> {
+        source: &'a str,
+    }
+
+    pub const JSON: Name = Name { source: "JSON" };
+}
+
+pub fn crash() -> bool {
+  match (my_mod::JSON, None) {
+    (_, Some(my_mod::JSON)) => true,
+    (my_mod::JSON, None) => true,
+    _ => false,
+  }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/run-pass/macro-lifetime-used-with-bound.rs
similarity index 60%
copy from src/test/compile-fail/regions-escape-unboxed-closure.rs
copy to src/test/run-pass/macro-lifetime-used-with-bound.rs
index cf41fad..b0c9280 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/run-pass/macro-lifetime-used-with-bound.rs
@@ -8,10 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: &mut FnMut(&isize)) {
+#![feature(macro_lifetime_matcher)]
+
+macro_rules! foo {
+    ($l:lifetime, $l2:lifetime) => {
+        fn f<$l: $l2, $l2>(arg: &$l str, arg2: &$l2 str) -> &$l str {
+            arg
+        }
+    }
 }
 
-fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+pub fn main() {
+    foo!('a, 'b);
+    let x: &'static str = f("hi", "there");
+    assert_eq!("hi", x);
 }
diff --git a/src/test/run-pass/macro-lifetime-used-with-labels.rs b/src/test/run-pass/macro-lifetime-used-with-labels.rs
new file mode 100644
index 0000000..8a2d76e
--- /dev/null
+++ b/src/test/run-pass/macro-lifetime-used-with-labels.rs
@@ -0,0 +1,44 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unreachable_code)]
+#![feature(macro_lifetime_matcher)]
+
+macro_rules! x {
+    ($a:lifetime) => {
+        $a: loop {
+            break $a;
+            panic!("failed");
+        }
+    }
+}
+macro_rules! br {
+    ($a:lifetime) => {
+        break $a;
+    }
+}
+macro_rules! br2 {
+    ($b:lifetime) => {
+        'b: loop {
+            break $b; // this $b should refer to the outer loop.
+        }
+    }
+}
+fn main() {
+    x!('a);
+    'c: loop {
+        br!('c);
+        panic!("failed");
+    }
+    'b: loop {
+        br2!('b);
+        panic!("failed");
+    }
+}
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/run-pass/macro-lifetime-used-with-static.rs
similarity index 65%
copy from src/test/compile-fail/regions-escape-unboxed-closure.rs
copy to src/test/run-pass/macro-lifetime-used-with-static.rs
index cf41fad..468ee2e 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/run-pass/macro-lifetime-used-with-static.rs
@@ -8,10 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: &mut FnMut(&isize)) {
+#![feature(macro_lifetime_matcher)]
+
+macro_rules! foo {
+    ($l:lifetime) => {
+        fn f(arg: &$l str) -> &$l str {
+            arg
+        }
+    }
 }
 
-fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+pub fn main() {
+    foo!('static);
+    let x: &'static str = f("hi");
+    assert_eq!("hi", x);
 }
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/run-pass/macro-lifetime.rs
similarity index 65%
copy from src/test/compile-fail/regions-escape-unboxed-closure.rs
copy to src/test/run-pass/macro-lifetime.rs
index cf41fad..db521ca 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/run-pass/macro-lifetime.rs
@@ -8,10 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: &mut FnMut(&isize)) {
+#![feature(macro_lifetime_matcher)]
+
+macro_rules! foo {
+    ($l:lifetime) => {
+        fn f<$l>(arg: &$l str) -> &$l str {
+            arg
+        }
+    }
 }
 
-fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+pub fn main() {
+    foo!('a);
+    let x: &'static str = f("hi");
+    assert_eq!("hi", x);
 }
diff --git a/src/test/run-pass/macro-nested_expr.rs b/src/test/run-pass/macro-nested_expr.rs
new file mode 100644
index 0000000..993ded6
--- /dev/null
+++ b/src/test/run-pass/macro-nested_expr.rs
@@ -0,0 +1,32 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// #42164
+
+#![feature(decl_macro)]
+#![allow(dead_code)]
+
+pub macro m($inner_str:expr) {
+    #[doc = $inner_str]
+    struct S;
+}
+
+macro_rules! define_f {
+    ($name:expr) => {
+        #[export_name = $name]
+        fn f() {}
+    }
+}
+
+fn main() {
+    define_f!(concat!("exported_", "f"));
+    m!(stringify!(foo));
+}
+
diff --git a/src/test/run-pass/multi-panic.rs b/src/test/run-pass/multi-panic.rs
index c15b40d..2e6e109 100644
--- a/src/test/run-pass/multi-panic.rs
+++ b/src/test/run-pass/multi-panic.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 fn check_for_no_backtrace(test: std::process::Output) {
diff --git a/src/test/parse-fail/keyword-extern-as-identifier.rs b/src/test/run-pass/nll/issue-47153-generic-const.rs
similarity index 64%
rename from src/test/parse-fail/keyword-extern-as-identifier.rs
rename to src/test/run-pass/nll/issue-47153-generic-const.rs
index 3bbe24e..9708ca1 100644
--- a/src/test/parse-fail/keyword-extern-as-identifier.rs
+++ b/src/test/run-pass/nll/issue-47153-generic-const.rs
@@ -8,10 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
+// Regression test for #47153: constants in a generic context (such as
+// a trait) used to ICE.
 
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py extern'
+#![feature(nll)]
+#![allow(warnings)]
 
-fn main() {
-    let extern = "foo"; //~ error: expected pattern, found keyword `extern`
+trait Foo {
+    const B: bool = true;
 }
+
+struct Bar<T> { x: T }
+
+impl<T> Bar<T> {
+    const B: bool = true;
+}
+
+fn main() { }
diff --git a/src/test/run-pass/no-stdio.rs b/src/test/run-pass/no-stdio.rs
index 7b6b711..d342417 100644
--- a/src/test/run-pass/no-stdio.rs
+++ b/src/test/run-pass/no-stdio.rs
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten no processes
 // ignore-android
+// ignore-cloudabi no processes
+// ignore-emscripten no processes
 
 #![feature(libc)]
 
diff --git a/src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/innest.rs b/src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs
similarity index 100%
rename from src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/innest.rs
rename to src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs
diff --git a/src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/mod.rs b/src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs
similarity index 100%
rename from src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/mod.rs
rename to src/test/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs
diff --git a/src/test/run-pass/optimization-fuel-1.rs b/src/test/run-pass/optimization-fuel-1.rs
index 5f294e2..e3529eb 100644
--- a/src/test/run-pass/optimization-fuel-1.rs
+++ b/src/test/run-pass/optimization-fuel-1.rs
@@ -22,5 +22,3 @@
         +(size_of::<S2>() == 4) as usize;
     assert_eq!(optimized, 1);
 }
-
-
diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs
index 485335a..6ed07fb 100644
--- a/src/test/run-pass/out-of-stack.rs
+++ b/src/test/run-pass/out-of-stack.rs
@@ -10,6 +10,7 @@
 
 // ignore-android: FIXME (#20004)
 // ignore-musl
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(asm)]
diff --git a/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs b/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs
index d1fdc8a..6917c2d 100644
--- a/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs
+++ b/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs
@@ -11,6 +11,7 @@
 // compile-flags:-C panic=abort
 // aux-build:exit-success-if-unwind.rs
 // no-prefer-dynamic
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 extern crate exit_success_if_unwind;
diff --git a/src/test/run-pass/panic-runtime/abort.rs b/src/test/run-pass/panic-runtime/abort.rs
index bb541b2..3a3b86a 100644
--- a/src/test/run-pass/panic-runtime/abort.rs
+++ b/src/test/run-pass/panic-runtime/abort.rs
@@ -10,6 +10,7 @@
 
 // compile-flags:-C panic=abort
 // no-prefer-dynamic
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::process::Command;
diff --git a/src/test/run-pass/panic-runtime/lto-abort.rs b/src/test/run-pass/panic-runtime/lto-abort.rs
index 59e9474..54e02fb 100644
--- a/src/test/run-pass/panic-runtime/lto-abort.rs
+++ b/src/test/run-pass/panic-runtime/lto-abort.rs
@@ -10,6 +10,7 @@
 
 // compile-flags:-C lto -C panic=abort
 // no-prefer-dynamic
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::process::Command;
diff --git a/src/test/run-pass/panic-runtime/lto-unwind.rs b/src/test/run-pass/panic-runtime/lto-unwind.rs
index 6d28b8d..52f1068 100644
--- a/src/test/run-pass/panic-runtime/lto-unwind.rs
+++ b/src/test/run-pass/panic-runtime/lto-unwind.rs
@@ -10,6 +10,7 @@
 
 // compile-flags:-C lto -C panic=unwind
 // no-prefer-dynamic
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::process::Command;
diff --git a/src/test/run-pass/paths-containing-nul.rs b/src/test/run-pass/paths-containing-nul.rs
index 9f39146..e0fe1ea 100644
--- a/src/test/run-pass/paths-containing-nul.rs
+++ b/src/test/run-pass/paths-containing-nul.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no files or I/O
 // ignore-wasm32-bare no files or I/O
 
 use std::fs;
diff --git a/src/test/run-pass/print-stdout-eprint-stderr.rs b/src/test/run-pass/print-stdout-eprint-stderr.rs
index 0a0f30a..9e36089 100644
--- a/src/test/run-pass/print-stdout-eprint-stderr.rs
+++ b/src/test/run-pass/print-stdout-eprint-stderr.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 
 use std::{env, process};
diff --git a/src/test/run-pass/process-envs.rs b/src/test/run-pass/process-envs.rs
index 1622517..e399bc2 100644
--- a/src/test/run-pass/process-envs.rs
+++ b/src/test/run-pass/process-envs.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::process::Command;
diff --git a/src/test/run-pass/process-exit.rs b/src/test/run-pass/process-exit.rs
index 5abc06b..44ef4a9 100644
--- a/src/test/run-pass/process-exit.rs
+++ b/src/test/run-pass/process-exit.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::env;
diff --git a/src/test/run-pass/process-remove-from-env.rs b/src/test/run-pass/process-remove-from-env.rs
index 7a9b431..9011ffc 100644
--- a/src/test/run-pass/process-remove-from-env.rs
+++ b/src/test/run-pass/process-remove-from-env.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::process::Command;
diff --git a/src/test/run-pass/process-sigpipe.rs b/src/test/run-pass/process-sigpipe.rs
index ebc7f13..a436e48 100644
--- a/src/test/run-pass/process-sigpipe.rs
+++ b/src/test/run-pass/process-sigpipe.rs
@@ -18,6 +18,7 @@
 // (instead of running forever), and that it does not print an error
 // message about a broken pipe.
 
+// ignore-cloudabi no subprocesses support
 // ignore-emscripten no threads support
 
 use std::process;
diff --git a/src/test/run-pass/process-spawn-with-unicode-params.rs b/src/test/run-pass/process-spawn-with-unicode-params.rs
index 7b85420..1e22f17 100644
--- a/src/test/run-pass/process-spawn-with-unicode-params.rs
+++ b/src/test/run-pass/process-spawn-with-unicode-params.rs
@@ -16,6 +16,7 @@
 // non-ASCII characters.  The child process ensures all the strings are
 // intact.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::io::prelude::*;
diff --git a/src/test/run-pass/process-status-inherits-stdin.rs b/src/test/run-pass/process-status-inherits-stdin.rs
index 5ea48a4..fdf5cf5 100644
--- a/src/test/run-pass/process-status-inherits-stdin.rs
+++ b/src/test/run-pass/process-status-inherits-stdin.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::env;
diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs
index d051e05..3ff8961 100644
--- a/src/test/run-pass/rec-align-u64.rs
+++ b/src/test/run-pass/rec-align-u64.rs
@@ -38,14 +38,15 @@
 }
 
 
-#[cfg(any(target_os = "linux",
-          target_os = "macos",
-          target_os = "freebsd",
+#[cfg(any(target_os = "cloudabi",
           target_os = "dragonfly",
+          target_os = "emscripten",
+          target_os = "freebsd",
+          target_os = "linux",
+          target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "solaris",
-          target_os = "emscripten"))]
+          target_os = "solaris"))]
 mod m {
     #[cfg(target_arch = "x86")]
     pub mod m {
diff --git a/src/test/run-pass/result-opt-conversions.rs b/src/test/run-pass/result-opt-conversions.rs
new file mode 100644
index 0000000..0f6da00
--- /dev/null
+++ b/src/test/run-pass/result-opt-conversions.rs
@@ -0,0 +1,57 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(transpose_result)]
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+struct BadNumErr;
+
+fn try_num(x: i32) -> Result<i32, BadNumErr> {
+    if x <= 5 {
+        Ok(x + 1)
+    } else {
+        Err(BadNumErr)
+    }
+}
+
+type ResOpt = Result<Option<i32>, BadNumErr>;
+type OptRes = Option<Result<i32, BadNumErr>>;
+
+fn main() {
+    let mut x: ResOpt = Ok(Some(5));
+    let mut y: OptRes = Some(Ok(5));
+    assert_eq!(x, y.transpose());
+    assert_eq!(x.transpose(), y);
+
+    x = Ok(None);
+    y = None;
+    assert_eq!(x, y.transpose());
+    assert_eq!(x.transpose(), y);
+
+    x = Err(BadNumErr);
+    y = Some(Err(BadNumErr));
+    assert_eq!(x, y.transpose());
+    assert_eq!(x.transpose(), y);
+
+    let res: Result<Vec<i32>, BadNumErr> =
+        (0..10)
+            .map(|x| {
+                let y = try_num(x)?;
+                Ok(if y % 2 == 0 {
+                    Some(y - 1)
+                } else {
+                    None
+                })
+            })
+            .filter_map(Result::transpose)
+            .collect();
+
+    assert_eq!(res, Err(BadNumErr))
+}
diff --git a/src/test/run-pass/rfc-1014.rs b/src/test/run-pass/rfc-1014.rs
index 950c2e0..61487b6 100644
--- a/src/test/run-pass/rfc-1014.rs
+++ b/src/test/run-pass/rfc-1014.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi stdout does not map to file descriptor 1 by default
 // ignore-wasm32-bare no libc
 
 #![feature(libc)]
diff --git a/src/test/run-pass/rfc-2126-extern-absolute-paths/extern.rs b/src/test/run-pass/rfc-2126-extern-absolute-paths/extern.rs
new file mode 100644
index 0000000..52b52b2
--- /dev/null
+++ b/src/test/run-pass/rfc-2126-extern-absolute-paths/extern.rs
@@ -0,0 +1,31 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:xcrate.rs
+
+#![feature(extern_in_paths)]
+
+use extern::xcrate::Z;
+
+fn f() {
+    use extern::xcrate;
+    use extern::xcrate as ycrate;
+    let s = xcrate::S;
+    assert_eq!(format!("{:?}", s), "S");
+    let z = ycrate::Z;
+    assert_eq!(format!("{:?}", z), "Z");
+}
+
+fn main() {
+    let s = extern::xcrate::S;
+    assert_eq!(format!("{:?}", s), "S");
+    let z = Z;
+    assert_eq!(format!("{:?}", z), "Z");
+}
diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs
index 6f696c1..a0b83ba 100644
--- a/src/test/run-pass/running-with-no-runtime.rs
+++ b/src/test/run-pass/running-with-no-runtime.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 
 #![feature(start)]
diff --git a/src/test/run-pass/segfault-no-out-of-stack.rs b/src/test/run-pass/segfault-no-out-of-stack.rs
index 0f98cfe..307ead4 100644
--- a/src/test/run-pass/segfault-no-out-of-stack.rs
+++ b/src/test/run-pass/segfault-no-out-of-stack.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi can't run commands
 // ignore-emscripten can't run commands
 
 #![feature(libc)]
diff --git a/src/test/run-pass/signal-alternate-stack-cleanup.rs b/src/test/run-pass/signal-alternate-stack-cleanup.rs
index 73ccd28..508fbe8 100644
--- a/src/test/run-pass/signal-alternate-stack-cleanup.rs
+++ b/src/test/run-pass/signal-alternate-stack-cleanup.rs
@@ -12,8 +12,9 @@
 // main thread exit while still being in use by signal handlers. This test
 // triggers this situation by sending signal from atexit handler.
 //
-// ignore-windows
+// ignore-cloudabi no signal handling support
 // ignore-wasm32-bare no libc
+// ignore-windows
 
 #![feature(libc)]
 extern crate libc;
diff --git a/src/test/run-pass/signal-exit-status.rs b/src/test/run-pass/signal-exit-status.rs
index 0f6832a..76171a4 100644
--- a/src/test/run-pass/signal-exit-status.rs
+++ b/src/test/run-pass/signal-exit-status.rs
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-windows
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-windows
 
 use std::env;
 use std::process::Command;
diff --git a/src/test/run-pass/sigpipe-should-be-ignored.rs b/src/test/run-pass/sigpipe-should-be-ignored.rs
index 465feb4..f5e2239 100644
--- a/src/test/run-pass/sigpipe-should-be-ignored.rs
+++ b/src/test/run-pass/sigpipe-should-be-ignored.rs
@@ -11,6 +11,7 @@
 // Be sure that when a SIGPIPE would have been received that the entire process
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::env;
diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs
index c27f830..c2414e5 100644
--- a/src/test/run-pass/sse2.rs
+++ b/src/test/run-pass/sse2.rs
@@ -7,7 +7,9 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+
 // min-llvm-version 4.0
+// ignore-cloudabi no std::env
 
 #![feature(cfg_target_feature)]
 
diff --git a/src/test/run-pass/stack-probes-lto.rs b/src/test/run-pass/stack-probes-lto.rs
index 78a1019..22555c8 100644
--- a/src/test/run-pass/stack-probes-lto.rs
+++ b/src/test/run-pass/stack-probes-lto.rs
@@ -11,6 +11,7 @@
 // ignore-arm
 // ignore-aarch64
 // ignore-wasm
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-musl FIXME #31506
 // ignore-pretty
diff --git a/src/test/run-pass/stack-probes.rs b/src/test/run-pass/stack-probes.rs
index bb9471e..248ad70 100644
--- a/src/test/run-pass/stack-probes.rs
+++ b/src/test/run-pass/stack-probes.rs
@@ -11,6 +11,7 @@
 // ignore-arm
 // ignore-aarch64
 // ignore-wasm
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-musl FIXME #31506
 // no-system-llvm
diff --git a/src/test/run-pass/stdio-is-blocking.rs b/src/test/run-pass/stdio-is-blocking.rs
index cce1077..8d4ee14 100644
--- a/src/test/run-pass/stdio-is-blocking.rs
+++ b/src/test/run-pass/stdio-is-blocking.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 use std::env;
diff --git a/src/test/run-pass/sync-send-in-std.rs b/src/test/run-pass/sync-send-in-std.rs
index 4dadfdf..f033879 100644
--- a/src/test/run-pass/sync-send-in-std.rs
+++ b/src/test/run-pass/sync-send-in-std.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi networking not available
 // ignore-wasm32-bare networking not available
 
 #![feature(lookup_host)]
diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs
index 25c7417..1b2741f 100644
--- a/src/test/run-pass/syntax-extension-source-utils.rs
+++ b/src/test/run-pass/syntax-extension-source-utils.rs
@@ -22,7 +22,7 @@
 
 pub fn main() {
     assert_eq!(line!(), 24);
-    assert_eq!(column!(), 15);
+    assert_eq!(column!(), 16);
     assert_eq!(indirect_line!(), 26);
     assert!((file!().ends_with("syntax-extension-source-utils.rs")));
     assert_eq!(stringify!((2*3) + 5).to_string(), "( 2 * 3 ) + 5".to_string());
diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs
index 0ba019c..30da1e5 100644
--- a/src/test/run-pass/tcp-stress.rs
+++ b/src/test/run-pass/tcp-stress.rs
@@ -10,9 +10,10 @@
 
 // ignore-android needs extra network permissions
 // ignore-bitrig system ulimit (Too many open files)
+// ignore-cloudabi no global network namespace access
+// ignore-emscripten no threads or sockets support
 // ignore-netbsd system ulimit (Too many open files)
 // ignore-openbsd system ulimit (Too many open files)
-// ignore-emscripten no threads or sockets support
 
 use std::io::prelude::*;
 use std::net::{TcpListener, TcpStream};
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass/termination-trait-for-empty.rs
similarity index 78%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-pass/termination-trait-for-empty.rs
index a2ef7da..5e534da 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-pass/termination-trait-for-empty.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(termination_trait)]
+
+fn main() {}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass/termination-trait-for-i32.rs
similarity index 76%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-pass/termination-trait-for-i32.rs
index a2ef7da..fa7cb02 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-pass/termination-trait-for-i32.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(termination_trait)]
+
+fn main() -> i32 {
+    0
+}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass/termination-trait-for-result.rs
similarity index 70%
copy from src/test/compile-fail/E0580.rs
copy to src/test/run-pass/termination-trait-for-result.rs
index a2ef7da..751db0f 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/run-pass/termination-trait-for-result.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(termination_trait)]
+
+use std::io::Error;
+
+fn main() -> Result<(), Error> {
+    Ok(())
+}
diff --git a/src/test/run-pass/try-operator.rs b/src/test/run-pass/try-operator.rs
index 29de636..d615c5f 100644
--- a/src/test/run-pass/try-operator.rs
+++ b/src/test/run-pass/try-operator.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::fs
+
 use std::fs::File;
 use std::io::{Read, self};
 use std::num::ParseIntError;
diff --git a/src/test/run-pass/try-wait.rs b/src/test/run-pass/try-wait.rs
index 0ee2cb9..b8c0d80 100644
--- a/src/test/run-pass/try-wait.rs
+++ b/src/test/run-pass/try-wait.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(process_try_wait)]
diff --git a/src/test/run-pass/unboxed-closures-prelude.rs b/src/test/run-pass/unboxed-closures-prelude.rs
index b783532..f82b04f 100644
--- a/src/test/run-pass/unboxed-closures-prelude.rs
+++ b/src/test/run-pass/unboxed-closures-prelude.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Tests that the reexports of `FnOnce` et al from the prelude work.
+// Tests that the re-exports of `FnOnce` et al from the prelude work.
 
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs
index 744f298..dc47108 100644
--- a/src/test/run-pass/wait-forked-but-failed-child.rs
+++ b/src/test/run-pass/wait-forked-but-failed-child.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no processes
 // ignore-emscripten no processes
 
 #![feature(libc)]
diff --git a/src/test/run-pass/weird-exit-code.rs b/src/test/run-pass/weird-exit-code.rs
index 27c7f9b..cdd6a9b 100644
--- a/src/test/run-pass/weird-exit-code.rs
+++ b/src/test/run-pass/weird-exit-code.rs
@@ -17,13 +17,10 @@
 // Note that this is disabled on unix as processes exiting with 259 will have
 // their exit status truncated to 3 (only the lower 8 bits are used).
 
-use std::process::{self, Command};
-use std::env;
-
+#[cfg(windows)]
 fn main() {
-    if !cfg!(windows) {
-        return
-    }
+    use std::process::{self, Command};
+    use std::env;
 
     if env::args().len() == 1 {
         let status = Command::new(env::current_exe().unwrap())
@@ -35,3 +32,6 @@
         process::exit(259);
     }
 }
+
+#[cfg(not(windows))]
+fn main() {}
diff --git a/src/test/run-pass/x86stdcall.rs b/src/test/run-pass/x86stdcall.rs
index e2e64dd..69ac68d 100644
--- a/src/test/run-pass/x86stdcall.rs
+++ b/src/test/run-pass/x86stdcall.rs
@@ -32,14 +32,15 @@
     }
 }
 
-#[cfg(any(target_os = "macos",
-          target_os = "linux",
-          target_os = "freebsd",
-          target_os = "dragonfly",
+#[cfg(any(target_os = "android",
           target_os = "bitrig",
+          target_os = "cloudabi",
+          target_os = "dragonfly",
+          target_os = "emscripten",
+          target_os = "freebsd",
+          target_os = "linux",
+          target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "android",
-          target_os = "solaris",
-          target_os = "emscripten"))]
+          target_os = "solaris"))]
 pub fn main() { }
diff --git a/src/test/rustdoc-js/basic.js b/src/test/rustdoc-js/basic.js
new file mode 100644
index 0000000..863437c
--- /dev/null
+++ b/src/test/rustdoc-js/basic.js
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = 'String';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::string', 'name': 'String' },
+        { 'path': 'std::ffi', 'name': 'OsString' },
+        { 'path': 'std::ffi', 'name': 'CString' },
+    ],
+    'in_args': [
+        { 'path': 'std::str', 'name': 'eq' },
+    ],
+    'returned': [
+        { 'path': 'std::string::String', 'name': 'add' },
+    ],
+};
diff --git a/src/test/compile-fail/E0580.rs b/src/test/rustdoc-js/enum-option.js
similarity index 67%
copy from src/test/compile-fail/E0580.rs
copy to src/test/rustdoc-js/enum-option.js
index a2ef7da..3dac983 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/rustdoc-js/enum-option.js
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+const QUERY = 'enum:Option';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::option', 'name': 'Option' },
+    ],
+};
diff --git a/src/test/compile-fail/E0580.rs b/src/test/rustdoc-js/fn-forget.js
similarity index 62%
copy from src/test/compile-fail/E0580.rs
copy to src/test/rustdoc-js/fn-forget.js
index a2ef7da..10310d5 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/rustdoc-js/fn-forget.js
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+const QUERY = 'fn:forget';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::mem', 'name': 'forget' },
+        { 'path': 'std::fmt', 'name': 'format' },
+    ],
+};
diff --git a/src/test/rustdoc-js/from_u.js b/src/test/rustdoc-js/from_u.js
new file mode 100644
index 0000000..0296788
--- /dev/null
+++ b/src/test/rustdoc-js/from_u.js
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = 'from_u';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::char', 'name': 'from_u32' },
+        { 'path': 'std::str', 'name': 'from_utf8' },
+        { 'path': 'std::string::String', 'name': 'from_utf8' },
+        { 'path': 'std::i32', 'name': 'from_unsigned' },
+        { 'path': 'std::i128', 'name': 'from_unsigned' },
+    ],
+};
diff --git a/src/test/rustdoc-js/macro-print.js b/src/test/rustdoc-js/macro-print.js
new file mode 100644
index 0000000..811ba34
--- /dev/null
+++ b/src/test/rustdoc-js/macro-print.js
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = 'macro:print';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'print' },
+        { 'path': 'std', 'name': 'eprint' },
+        { 'path': 'std', 'name': 'println' },
+        { 'path': 'std', 'name': 'eprintln' },
+    ],
+};
diff --git a/src/test/rustdoc-js/quoted.js b/src/test/rustdoc-js/quoted.js
new file mode 100644
index 0000000..dcb85b5
--- /dev/null
+++ b/src/test/rustdoc-js/quoted.js
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = '"error"';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'error' },
+        { 'path': 'std::fmt', 'name': 'Error' },
+        { 'path': 'std::io', 'name': 'Error' },
+    ],
+    'in_args': [],
+    'returned': [
+        { 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
+    ],
+};
diff --git a/src/test/rustdoc-js/string-from_ut.js b/src/test/rustdoc-js/string-from_ut.js
new file mode 100644
index 0000000..3d08ee3
--- /dev/null
+++ b/src/test/rustdoc-js/string-from_ut.js
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = 'String::from_ut';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::string::String', 'name': 'from_utf8' },
+        { 'path': 'std::string::String', 'name': 'from_utf8' },
+        { 'path': 'std::string::String', 'name': 'from_utf8_lossy' },
+        { 'path': 'std::string::String', 'name': 'from_utf16_lossy' },
+        { 'path': 'std::string::String', 'name': 'from_utf8_unchecked' },
+    ],
+};
diff --git a/src/test/rustdoc-js/struct-vec.js b/src/test/rustdoc-js/struct-vec.js
new file mode 100644
index 0000000..a91bc2d
--- /dev/null
+++ b/src/test/rustdoc-js/struct-vec.js
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const QUERY = 'struct:Vec';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::vec', 'name': 'Vec' },
+        { 'path': 'std::collections', 'name': 'VecDeque' },
+        { 'path': 'alloc::raw_vec', 'name': 'RawVec' },
+    ],
+};
diff --git a/src/test/rustdoc/auto-traits.rs b/src/test/rustdoc/auto-traits.rs
new file mode 100644
index 0000000..1753c0e
--- /dev/null
+++ b/src/test/rustdoc/auto-traits.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:auto-traits.rs
+
+#![feature(optin_builtin_traits)]
+
+#![crate_name = "foo"]
+
+extern crate auto_traits;
+
+// @has 'foo/trait.Foo.html' '//pre' 'pub unsafe auto trait Foo'
+pub unsafe auto trait Foo {}
+
+// @has 'foo/trait.Bar.html' '//pre' 'pub unsafe auto trait Bar'
+pub use auto_traits::Bar;
diff --git a/src/test/ui/typeck-default-trait-impl-outside-crate.rs b/src/test/rustdoc/auxiliary/auto-traits.rs
similarity index 76%
rename from src/test/ui/typeck-default-trait-impl-outside-crate.rs
rename to src/test/rustdoc/auxiliary/auto-traits.rs
index ff0446e..7029933 100644
--- a/src/test/ui/typeck-default-trait-impl-outside-crate.rs
+++ b/src/test/rustdoc/auxiliary/auto-traits.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -10,6 +10,4 @@
 
 #![feature(optin_builtin_traits)]
 
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
-fn main() {}
+pub unsafe auto trait Bar {}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/rustdoc/auxiliary/issue-46727.rs
similarity index 68%
copy from src/test/compile-fail/E0580.rs
copy to src/test/rustdoc/auxiliary/issue-46727.rs
index a2ef7da..f0869f0 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/rustdoc/auxiliary/issue-46727.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+// compile-flags: -Cmetadata=aux
+
+pub trait Foo {}
+
+pub struct Bar<T> { x: T }
+
+impl<T> Foo for Bar<[T; 1 + 1 + 1]> {}
diff --git a/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs b/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
index 4fd55bd..34a1331 100644
--- a/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
+++ b/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
@@ -14,10 +14,7 @@
 pub mod bar {
     use std::marker;
 
-    pub trait Bar {}
-
-    #[allow(auto_impl)]
-    impl Bar for .. {}
+    pub auto trait Bar {}
 
     pub trait Foo {
         fn foo(&self) {}
diff --git a/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs b/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
index d886778..977d98c 100644
--- a/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
+++ b/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
@@ -10,7 +10,4 @@
 
 #![feature(optin_builtin_traits)]
 
-pub trait AnOibit {}
-
-#[allow(auto_impl)]
-impl AnOibit for .. {}
+pub auto trait AnOibit {}
diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs
index cfb3791..8499e5c 100644
--- a/src/test/rustdoc/doc-cfg.rs
+++ b/src/test/rustdoc/doc-cfg.rs
@@ -44,4 +44,4 @@
     impl ArmOnly for super::Portable {
         fn unix_and_arm_only_function() {}
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs
index f74f66c..6e472da 100644
--- a/src/test/rustdoc/impl-parts.rs
+++ b/src/test/rustdoc/impl-parts.rs
@@ -10,10 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
-pub trait AnOibit {}
-
-#[allow(auto_impl)]
-impl AnOibit for .. {}
+pub auto trait AnOibit {}
 
 pub struct Foo<T> { field: T }
 
diff --git a/src/test/compile-fail/E0580.rs b/src/test/rustdoc/inline_cross/auxiliary/impl-inline-without-trait.rs
similarity index 66%
copy from src/test/compile-fail/E0580.rs
copy to src/test/rustdoc/inline_cross/auxiliary/impl-inline-without-trait.rs
index a2ef7da..5d4adb2 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/rustdoc/inline_cross/auxiliary/impl-inline-without-trait.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+pub trait MyTrait {
+    /// docs for my_trait_method
+    fn my_trait_method() {}
+}
+
+pub struct MyStruct;
+
+impl MyTrait for MyStruct {}
diff --git a/src/test/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs b/src/test/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs
index 22a311d..5fee369 100644
--- a/src/test/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs
+++ b/src/test/rustdoc/inline_cross/auxiliary/rustdoc-nonreachable-impls.rs
@@ -36,7 +36,7 @@
     pub struct Wobble;
 
 
-    // these should only be shown if they're reexported correctly
+    // these should only be shown if they're re-exported correctly
     impl Qux for ::Foo {}
     impl Qux for Wobble {}
     impl ::Bark for Wobble {}
diff --git a/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs b/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs
new file mode 100644
index 0000000..ea97d9d
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:impl-inline-without-trait.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+extern crate impl_inline_without_trait;
+
+// @has 'foo/struct.MyStruct.html'
+// @has - '//*[@id="method.my_trait_method"]' 'fn my_trait_method()'
+// @has - '//*[@class="docblock"]' 'docs for my_trait_method'
+pub use impl_inline_without_trait::MyStruct;
diff --git a/src/test/rustdoc/intra-links.rs b/src/test/rustdoc/intra-links.rs
new file mode 100644
index 0000000..aa6f553
--- /dev/null
+++ b/src/test/rustdoc/intra-links.rs
@@ -0,0 +1,60 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// @has intra_links/index.html
+// @has - '//a/@href' '../intra_links/struct.ThisType.html'
+// @has - '//a/@href' '../intra_links/enum.ThisEnum.html'
+// @has - '//a/@href' '../intra_links/trait.ThisTrait.html'
+// @has - '//a/@href' '../intra_links/type.ThisAlias.html'
+// @has - '//a/@href' '../intra_links/union.ThisUnion.html'
+// @has - '//a/@href' '../intra_links/fn.this_function.html'
+// @has - '//a/@href' '../intra_links/constant.THIS_CONST.html'
+// @has - '//a/@href' '../intra_links/static.THIS_STATIC.html'
+// @has - '//a/@href' '../intra_links/macro.this_macro.html'
+// @has - '//a/@href' '../intra_links/trait.SoAmbiguous.html'
+// @has - '//a/@href' '../intra_links/fn.SoAmbiguous.html'
+//! In this crate we would like to link to:
+//!
+//! * [`ThisType`](ThisType)
+//! * [`ThisEnum`](ThisEnum)
+//! * [`ThisTrait`](ThisTrait)
+//! * [`ThisAlias`](ThisAlias)
+//! * [`ThisUnion`](ThisUnion)
+//! * [`this_function`](this_function())
+//! * [`THIS_CONST`](const@THIS_CONST)
+//! * [`THIS_STATIC`](static@THIS_STATIC)
+//! * [`this_macro`](this_macro!)
+//!
+//! In addition, there's some specifics we want to look at. There's [a trait called
+//! SoAmbiguous][ambig-trait], but there's also [a function called SoAmbiguous][ambig-fn] too!
+//! Whatever shall we do?
+//!
+//! [ambig-trait]: trait@SoAmbiguous
+//! [ambig-fn]: SoAmbiguous()
+
+#[macro_export]
+macro_rules! this_macro {
+    () => {};
+}
+
+pub struct ThisType;
+pub enum ThisEnum { ThisVariant, }
+pub trait ThisTrait {}
+pub type ThisAlias = Result<(), ()>;
+pub union ThisUnion { this_field: usize, }
+
+pub fn this_function() {}
+pub const THIS_CONST: usize = 5usize;
+pub static THIS_STATIC: usize = 5usize;
+
+pub trait SoAmbiguous {}
+
+#[allow(bad_style)]
+pub fn SoAmbiguous() {}
diff --git a/src/test/rustdoc/issue-43893.rs b/src/test/rustdoc/issue-43893.rs
index 96bd9d7..a5e343a 100644
--- a/src/test/rustdoc/issue-43893.rs
+++ b/src/test/rustdoc/issue-43893.rs
@@ -22,3 +22,8 @@
 impl SomeTrait for SomeStruct {
     // deliberately multi-line impl
 }
+
+pub trait AnotherTrait {}
+
+// @has foo/trait.AnotherTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#29'
+impl<T> AnotherTrait for T {}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/rustdoc/issue-46727.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/rustdoc/issue-46727.rs
index 5c32a75..5b202d8 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/rustdoc/issue-46727.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// aux-build:issue-46727.rs
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+extern crate issue_46727;
+
+// @has issue_46727/trait.Foo.html
+// @has - '//code' 'impl<T> Foo for Bar<[T; 3]>'
+pub use issue_46727::{Foo, Bar};
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/rustdoc/issue-46766.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/rustdoc/issue-46766.rs
index 5c32a75..cf2dd58 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/rustdoc/issue-46766.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![crate_name = "foo"]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+pub enum Enum{Variant}
+pub use self::Enum::Variant;
+
+// @!has foo/index.html '//a/@href' './Enum/index.html'
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/rustdoc/issue-46767.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/rustdoc/issue-46767.rs
index 5c32a75..855de15 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/rustdoc/issue-46767.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![crate_name = "foo"]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+mod private {
+    pub enum Enum{Variant}
+}
+pub use self::private::Enum::*;
+
+// @!has foo/index.html '//a/@href' './private/index.html'
diff --git a/src/test/compile-fail/E0580.rs b/src/test/rustdoc/issue-46976.rs
similarity index 75%
copy from src/test/compile-fail/E0580.rs
copy to src/test/rustdoc/issue-46976.rs
index a2ef7da..0df80fe 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/rustdoc/issue-46976.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(universal_impl_trait)]
+pub fn ice(f: impl Fn()) {}
diff --git a/src/test/compile-fail/E0580.rs b/src/test/rustdoc/issue-47038.rs
similarity index 60%
copy from src/test/compile-fail/E0580.rs
copy to src/test/rustdoc/issue-47038.rs
index a2ef7da..453cd66 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/rustdoc/issue-47038.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+#![feature(decl_macro)]
+
+#![crate_name = "foo"]
+
+use std::vec;
+
+// @has 'foo/index.html'
+// @!has - '//*[@id="macros"]' 'Macros'
+// @!has - '//a/@href' 'macro.vec.html'
+// @!has 'foo/macro.vec.html'
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/rustdoc/issue-47197-blank-line-in-doc-block.rs
similarity index 68%
rename from src/test/compile-fail/auto-impl-future-compat.rs
rename to src/test/rustdoc/issue-47197-blank-line-in-doc-block.rs
index 5c32a75..8c4d984 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/rustdoc/issue-47197-blank-line-in-doc-block.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// @has issue_47197_blank_line_in_doc_block/fn.whose_woods_these_are_i_think_i_know.html
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+/**
+* snow
+
+* ice
+*/
+pub fn whose_woods_these_are_i_think_i_know() {}
diff --git a/src/test/ui-fulldeps/issue-44953/issue-44953.stderr b/src/test/ui-fulldeps/issue-44953/issue-44953.stderr
deleted file mode 100644
index e0e96ec..0000000
--- a/src/test/ui-fulldeps/issue-44953/issue-44953.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
-  --> $DIR/issue-44953.rs:16:14
-   |
-16 | #[macro_use] extern crate log; //~ ERROR use of unstable library feature
-   |              ^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(rustc_private)] to the crate attributes to enable
-
-error: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
-  --> $DIR/issue-44953.rs:19:5
-   |
-19 |     info!("This is a log message.");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(rustc_private)] to the crate attributes to enable
-   = 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 2 previous errors
-
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/parent-source-spans.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/parent-source-spans.rs
new file mode 100644
index 0000000..3eb96c2
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/auxiliary/parent-source-spans.rs
@@ -0,0 +1,51 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, TokenNode, Span};
+
+fn lit_span(tt: TokenTree) -> (Span, String) {
+    use TokenNode::*;
+    match tt.kind {
+        Literal(..) | Group(..) => (tt.span, tt.to_string().trim().into()),
+        _ => panic!("expected a literal in token tree, got: {:?}", tt)
+    }
+}
+
+#[proc_macro]
+pub fn parent_source_spans(input: TokenStream) -> TokenStream {
+    let mut tokens = input.into_iter();
+    let (sp1, str1) = lit_span(tokens.next().expect("first string"));
+    let _ = tokens.next();
+    let (sp2, str2) = lit_span(tokens.next().expect("second string"));
+
+    sp1.error(format!("first final: {}", str1)).emit();
+    sp2.error(format!("second final: {}", str2)).emit();
+
+    if let (Some(p1), Some(p2)) = (sp1.parent(), sp2.parent()) {
+        p1.error(format!("first parent: {}", str1)).emit();
+        p2.error(format!("second parent: {}", str2)).emit();
+
+        if let (Some(gp1), Some(gp2)) = (p1.parent(), p2.parent()) {
+            gp1.error(format!("first grandparent: {}", str1)).emit();
+            gp2.error(format!("second grandparent: {}", str2)).emit();
+        }
+    }
+
+    sp1.source().error(format!("first source: {}", str1)).emit();
+    sp2.source().error(format!("second source: {}", str2)).emit();
+
+    "ok".parse().unwrap()
+}
diff --git a/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs b/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs
new file mode 100644
index 0000000..4c71afb
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs
@@ -0,0 +1,61 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:parent-source-spans.rs
+// ignore-stage1
+
+#![feature(proc_macro, decl_macro)]
+
+extern crate parent_source_spans;
+
+use parent_source_spans::parent_source_spans;
+
+macro one($a:expr, $b:expr) {
+    two!($a, $b);
+    //~^ ERROR first parent: "hello"
+    //~| ERROR second parent: "world"
+}
+
+macro two($a:expr, $b:expr) {
+    three!($a, $b);
+    //~^ ERROR first final: "hello"
+    //~| ERROR second final: "world"
+    //~| ERROR first final: "yay"
+    //~| ERROR second final: "rust"
+}
+
+// forwarding tokens directly doesn't create a new source chain
+macro three($($tokens:tt)*) {
+    four!($($tokens)*);
+}
+
+macro four($($tokens:tt)*) {
+    parent_source_spans!($($tokens)*);
+}
+
+fn main() {
+    one!("hello", "world");
+    //~^ ERROR first grandparent: "hello"
+    //~| ERROR second grandparent: "world"
+    //~| ERROR first source: "hello"
+    //~| ERROR second source: "world"
+
+    two!("yay", "rust");
+    //~^ ERROR first parent: "yay"
+    //~| ERROR second parent: "rust"
+    //~| ERROR first source: "yay"
+    //~| ERROR second source: "rust"
+
+    three!("hip", "hop");
+    //~^ ERROR first final: "hip"
+    //~| ERROR second final: "hop"
+    //~| ERROR first source: "hip"
+    //~| ERROR second source: "hop"
+}
diff --git a/src/test/ui-fulldeps/proc-macro/parent-source-spans.stderr b/src/test/ui-fulldeps/proc-macro/parent-source-spans.stderr
new file mode 100644
index 0000000..7194b05
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/parent-source-spans.stderr
@@ -0,0 +1,128 @@
+error: first final: "hello"
+  --> $DIR/parent-source-spans.rs:27:12
+   |
+27 |     three!($a, $b);
+   |            ^^
+...
+44 |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: second final: "world"
+  --> $DIR/parent-source-spans.rs:27:16
+   |
+27 |     three!($a, $b);
+   |                ^^
+...
+44 |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: first parent: "hello"
+  --> $DIR/parent-source-spans.rs:21:5
+   |
+21 |     two!($a, $b);
+   |     ^^^^^^^^^^^^^
+...
+44 |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: second parent: "world"
+  --> $DIR/parent-source-spans.rs:21:5
+   |
+21 |     two!($a, $b);
+   |     ^^^^^^^^^^^^^
+...
+44 |     one!("hello", "world");
+   |     ----------------------- in this macro invocation
+
+error: first grandparent: "hello"
+  --> $DIR/parent-source-spans.rs:44:5
+   |
+44 |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: second grandparent: "world"
+  --> $DIR/parent-source-spans.rs:44:5
+   |
+44 |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: first source: "hello"
+  --> $DIR/parent-source-spans.rs:44:5
+   |
+44 |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: second source: "world"
+  --> $DIR/parent-source-spans.rs:44:5
+   |
+44 |     one!("hello", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: first final: "yay"
+  --> $DIR/parent-source-spans.rs:27:12
+   |
+27 |     three!($a, $b);
+   |            ^^
+...
+50 |     two!("yay", "rust");
+   |     -------------------- in this macro invocation
+
+error: second final: "rust"
+  --> $DIR/parent-source-spans.rs:27:16
+   |
+27 |     three!($a, $b);
+   |                ^^
+...
+50 |     two!("yay", "rust");
+   |     -------------------- in this macro invocation
+
+error: first parent: "yay"
+  --> $DIR/parent-source-spans.rs:50:5
+   |
+50 |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: second parent: "rust"
+  --> $DIR/parent-source-spans.rs:50:5
+   |
+50 |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: first source: "yay"
+  --> $DIR/parent-source-spans.rs:50:5
+   |
+50 |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: second source: "rust"
+  --> $DIR/parent-source-spans.rs:50:5
+   |
+50 |     two!("yay", "rust");
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: first final: "hip"
+  --> $DIR/parent-source-spans.rs:56:12
+   |
+56 |     three!("hip", "hop");
+   |            ^^^^^
+
+error: second final: "hop"
+  --> $DIR/parent-source-spans.rs:56:19
+   |
+56 |     three!("hip", "hop");
+   |                   ^^^^^
+
+error: first source: "hip"
+  --> $DIR/parent-source-spans.rs:56:12
+   |
+56 |     three!("hip", "hop");
+   |            ^^^^^
+
+error: second source: "hop"
+  --> $DIR/parent-source-spans.rs:56:19
+   |
+56 |     three!("hip", "hop");
+   |                   ^^^^^
+
+error: aborting due to 18 previous errors
+
diff --git a/src/test/ui-fulldeps/resolve-error.stderr b/src/test/ui-fulldeps/resolve-error.stderr
index be7ebae..9121ce1 100644
--- a/src/test/ui-fulldeps/resolve-error.stderr
+++ b/src/test/ui-fulldeps/resolve-error.stderr
@@ -38,13 +38,13 @@
   --> $DIR/resolve-error.rs:62:5
    |
 62 |     FooWithLongNama!();
-   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!`
+   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam`
 
 error: cannot find macro `attr_proc_macra!` in this scope
   --> $DIR/resolve-error.rs:65:5
    |
 65 |     attr_proc_macra!();
-   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!`
+   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac`
 
 error: cannot find macro `Dlona!` in this scope
   --> $DIR/resolve-error.rs:68:5
@@ -56,7 +56,7 @@
   --> $DIR/resolve-error.rs:71:5
    |
 71 |     bang_proc_macrp!();
-   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!`
+   |     ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro`
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui-fulldeps/update-references.sh b/src/test/ui-fulldeps/update-references.sh
old mode 100644
new mode 100755
index b9ded7d..c2c842f
--- a/src/test/ui-fulldeps/update-references.sh
+++ b/src/test/ui-fulldeps/update-references.sh
@@ -46,5 +46,3 @@
         cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME
     fi
 done
-
-
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
index e364a4d..4bd3b68 100644
--- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
@@ -6,7 +6,11 @@
    |     |
    |     expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _`
    |
-   = note: required by `f1`
+note: required by `f1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:26:1
+   |
+26 | fn f1<F>(_: F) where F: Fn(&(), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:13:5
@@ -16,7 +20,11 @@
    |     |
    |     expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _`
    |
-   = note: required by `f2`
+note: required by `f2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1
+   |
+27 | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
@@ -26,7 +34,11 @@
    |     |
    |     expected signature of `for<'r> fn(&(), &'r ()) -> _`
    |
-   = note: required by `f3`
+note: required by `f3`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1
+   |
+28 | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:15:5
@@ -36,7 +48,11 @@
    |     |
    |     expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _`
    |
-   = note: required by `f4`
+note: required by `f4`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1
+   |
+29 | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
@@ -46,7 +62,11 @@
    |     |
    |     expected signature of `for<'r> fn(&'r (), &'r ()) -> _`
    |
-   = note: required by `f5`
+note: required by `f5`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1
+   |
+30 | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:17:5
@@ -56,7 +76,11 @@
    |     |
    |     expected signature of `for<'r> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>) -> _`
    |
-   = note: required by `g1`
+note: required by `g1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:33:1
+   |
+33 | fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
@@ -66,7 +90,11 @@
    |     |
    |     expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _`
    |
-   = note: required by `g2`
+note: required by `g2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
+   |
+34 | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:19:5
@@ -76,7 +104,11 @@
    |     |
    |     expected signature of `for<'s> fn(&'s (), std::boxed::Box<for<'r> std::ops::Fn(&'r ()) + 'static>) -> _`
    |
-   = note: required by `g3`
+note: required by `g3`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
+   |
+35 | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
@@ -86,7 +118,11 @@
    |     |
    |     expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _`
    |
-   = note: required by `g4`
+note: required by `g4`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
+   |
+36 | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:21:5
@@ -96,7 +132,11 @@
    |     |
    |     expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<for<'t0> std::ops::Fn(&'t0 ()) + 'static>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
    |
-   = note: required by `h1`
+note: required by `h1`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:39:1
+   |
+39 | fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
@@ -106,7 +146,11 @@
    |     |
    |     expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
    |
-   = note: required by `h2`
+note: required by `h2`
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
+   |
+40 | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/compile-fail/attr-usage-repr.rs b/src/test/ui/attr-usage-repr.rs
similarity index 97%
rename from src/test/compile-fail/attr-usage-repr.rs
rename to src/test/ui/attr-usage-repr.rs
index c0bfd36..db5cd47 100644
--- a/src/test/compile-fail/attr-usage-repr.rs
+++ b/src/test/ui/attr-usage-repr.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code)]
 #![feature(attr_literals)]
 #![feature(repr_simd)]
 
diff --git a/src/test/ui/attr-usage-repr.stderr b/src/test/ui/attr-usage-repr.stderr
new file mode 100644
index 0000000..b9c0126
--- /dev/null
+++ b/src/test/ui/attr-usage-repr.stderr
@@ -0,0 +1,42 @@
+error[E0517]: attribute should be applied to struct, enum or union
+  --> $DIR/attr-usage-repr.rs:14:8
+   |
+14 | #[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union
+   |        ^
+15 | fn f() {}
+   | --------- not a struct, enum or union
+
+error[E0517]: attribute should be applied to enum
+  --> $DIR/attr-usage-repr.rs:26:8
+   |
+26 | #[repr(i8)] //~ ERROR: attribute should be applied to enum
+   |        ^^
+27 | struct SInt(f64, f64);
+   | ---------------------- not an enum
+
+error[E0517]: attribute should be applied to struct or union
+  --> $DIR/attr-usage-repr.rs:32:8
+   |
+32 | #[repr(align(8))] //~ ERROR: attribute should be applied to struct
+   |        ^^^^^^^^
+33 | enum EAlign { A, B }
+   | -------------------- not a struct or union
+
+error[E0517]: attribute should be applied to struct or union
+  --> $DIR/attr-usage-repr.rs:35:8
+   |
+35 | #[repr(packed)] //~ ERROR: attribute should be applied to struct
+   |        ^^^^^^
+36 | enum EPacked { A, B }
+   | --------------------- not a struct or union
+
+error[E0517]: attribute should be applied to struct
+  --> $DIR/attr-usage-repr.rs:38:8
+   |
+38 | #[repr(simd)] //~ ERROR: attribute should be applied to struct
+   |        ^^^^
+39 | enum ESimd { A, B }
+   | ------------------- not a struct
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr
index 7c88d78..3b4f514 100644
--- a/src/test/ui/block-result/issue-20862.stderr
+++ b/src/test/ui/block-result/issue-20862.stderr
@@ -13,7 +13,7 @@
   --> $DIR/issue-20862.rs:17:13
    |
 17 |     let x = foo(5)(2);
-   |             ^^^^^^^^^
+   |             ^^^^^^^^^ not a function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr
index 9f08bd1..f36ed05 100644
--- a/src/test/ui/borrowck/borrowck-reinit.stderr
+++ b/src/test/ui/borrowck/borrowck-reinit.stderr
@@ -15,6 +15,8 @@
    |          - value moved here
 18 |     let _ = (1,x); //~ ERROR use of moved value: `x` (Ast)
    |                ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/immutable-arg.rs b/src/test/ui/borrowck/immutable-arg.rs
new file mode 100644
index 0000000..7c387ed
--- /dev/null
+++ b/src/test/ui/borrowck/immutable-arg.rs
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//compile-flags: -Z emit-end-regions -Z borrowck=compare
+
+fn foo(_x: u32) {
+    _x = 4;
+    //~^ ERROR cannot assign to immutable argument `_x` (Mir)
+    //~^^ ERROR cannot assign twice to immutable variable `_x` (Ast)
+}
+
+fn main() {}
+
diff --git a/src/test/ui/borrowck/immutable-arg.stderr b/src/test/ui/borrowck/immutable-arg.stderr
new file mode 100644
index 0000000..40e1878
--- /dev/null
+++ b/src/test/ui/borrowck/immutable-arg.stderr
@@ -0,0 +1,18 @@
+error[E0384]: cannot assign twice to immutable variable `_x` (Ast)
+  --> $DIR/immutable-arg.rs:14:5
+   |
+13 | fn foo(_x: u32) {
+   |        -- first assignment to `_x`
+14 |     _x = 4;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign to immutable argument `_x` (Mir)
+  --> $DIR/immutable-arg.rs:14:5
+   |
+13 | fn foo(_x: u32) {
+   |        -- argument not declared as `mut`
+14 |     _x = 4;
+   |     ^^^^^^ cannot assign to immutable argument
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs
new file mode 100644
index 0000000..d592be1
--- /dev/null
+++ b/src/test/ui/borrowck/issue-41962.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z borrowck=compare
+
+pub fn main(){
+    let maybe = Some(vec![true, true]);
+
+    loop {
+        if let Some(thing) = maybe {
+        //~^ ERROR use of partially moved value: `maybe` (Ast) [E0382]
+        //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382]
+        //~| ERROR use of moved value: `maybe` (Mir) [E0382]
+        //~| ERROR use of moved value: `maybe.0` (Mir) [E0382]
+        }
+    }
+}
diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr
new file mode 100644
index 0000000..50d51c4
--- /dev/null
+++ b/src/test/ui/borrowck/issue-41962.stderr
@@ -0,0 +1,39 @@
+error[E0382]: use of partially moved value: `maybe` (Ast)
+  --> $DIR/issue-41962.rs:17:30
+   |
+17 |         if let Some(thing) = maybe {
+   |                     -----    ^^^^^ value used here after move
+   |                     |
+   |                     value moved here
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast)
+  --> $DIR/issue-41962.rs:17:21
+   |
+17 |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `maybe` (Mir)
+  --> $DIR/issue-41962.rs:17:16
+   |
+17 |         if let Some(thing) = maybe {
+   |                ^^^^^-----^
+   |                |    |
+   |                |    value moved here
+   |                value used here after move
+   |
+   = note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `maybe.0` (Mir)
+  --> $DIR/issue-41962.rs:17:21
+   |
+17 |         if let Some(thing) = maybe {
+   |                     ^^^^^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `maybe.0` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/ui/borrowck/issue-45983.rs
similarity index 63%
copy from src/test/compile-fail/regions-escape-unboxed-closure.rs
copy to src/test/ui/borrowck/issue-45983.rs
index cf41fad..a6e5067 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/ui/borrowck/issue-45983.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: &mut FnMut(&isize)) {
+fn give_any<F: for<'r> FnOnce(&'r ())>(f: F) {
+    f(&());
 }
 
 fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+    let x = None;
+    give_any(|y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
 }
diff --git a/src/test/ui/borrowck/issue-45983.stderr b/src/test/ui/borrowck/issue-45983.stderr
new file mode 100644
index 0000000..496f15c
--- /dev/null
+++ b/src/test/ui/borrowck/issue-45983.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/issue-45983.rs:17:27
+   |
+16 |     let x = None;
+   |         - borrowed data cannot be stored into here...
+17 |     give_any(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/issue-7573.rs b/src/test/ui/borrowck/issue-7573.rs
similarity index 75%
rename from src/test/compile-fail/issue-7573.rs
rename to src/test/ui/borrowck/issue-7573.rs
index d13da1d..8f1545f 100644
--- a/src/test/compile-fail/issue-7573.rs
+++ b/src/test/ui/borrowck/issue-7573.rs
@@ -24,9 +24,14 @@
 }
 
 pub fn remove_package_from_database() {
-    let mut lines_to_use: Vec<&CrateId> = Vec::new(); //~ ERROR E0495
+    let mut lines_to_use: Vec<&CrateId> = Vec::new();
+        //~^ NOTE cannot infer an appropriate lifetime
     let push_id = |installed_id: &CrateId| {
+        //~^ NOTE borrowed data cannot outlive this closure
+        //~| NOTE ...so that variable is valid at time of its declaration
         lines_to_use.push(installed_id);
+        //~^ ERROR borrowed data cannot be stored outside of its closure
+        //~| NOTE cannot be stored outside of its closure
     };
     list_database(push_id);
 
diff --git a/src/test/ui/borrowck/issue-7573.stderr b/src/test/ui/borrowck/issue-7573.stderr
new file mode 100644
index 0000000..99b48d9
--- /dev/null
+++ b/src/test/ui/borrowck/issue-7573.stderr
@@ -0,0 +1,16 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/issue-7573.rs:32:27
+   |
+27 |     let mut lines_to_use: Vec<&CrateId> = Vec::new();
+   |                               - cannot infer an appropriate lifetime...
+28 |         //~^ NOTE cannot infer an appropriate lifetime
+29 |     let push_id = |installed_id: &CrateId| {
+   |         -------   ------------------------ borrowed data cannot outlive this closure
+   |         |
+   |         ...so that variable is valid at time of its declaration
+...
+32 |         lines_to_use.push(installed_id);
+   |                           ^^^^^^^^^^^^ cannot be stored outside of its closure
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/regions-escape-bound-fn-2.rs b/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
similarity index 89%
rename from src/test/compile-fail/regions-escape-bound-fn-2.rs
rename to src/test/ui/borrowck/regions-escape-bound-fn-2.rs
index 1329d05..1c38dee 100644
--- a/src/test/compile-fail/regions-escape-bound-fn-2.rs
+++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
@@ -16,5 +16,5 @@
 fn main() {
     let mut x = None;
     with_int(|y| x = Some(y));
-         //~^ ERROR cannot infer
+    //~^ ERROR borrowed data cannot be stored outside of its closure
 }
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr b/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
new file mode 100644
index 0000000..3d88f4f
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-bound-fn-2.rs:18:27
+   |
+17 |     let mut x = None;
+   |         ----- borrowed data cannot be stored into here...
+18 |     with_int(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/regions-escape-bound-fn.rs b/src/test/ui/borrowck/regions-escape-bound-fn.rs
similarity index 85%
rename from src/test/compile-fail/regions-escape-bound-fn.rs
rename to src/test/ui/borrowck/regions-escape-bound-fn.rs
index 02e62ff..c227423 100644
--- a/src/test/compile-fail/regions-escape-bound-fn.rs
+++ b/src/test/ui/borrowck/regions-escape-bound-fn.rs
@@ -15,5 +15,6 @@
 
 fn main() {
     let mut x: Option<&isize> = None;
-    with_int(|y| x = Some(y));   //~ ERROR cannot infer
+    with_int(|y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
 }
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.stderr
new file mode 100644
index 0000000..a2ad7c3
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-bound-fn.rs:18:27
+   |
+17 |     let mut x: Option<&isize> = None;
+   |         ----- borrowed data cannot be stored into here...
+18 |     with_int(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
similarity index 83%
rename from src/test/compile-fail/regions-escape-unboxed-closure.rs
rename to src/test/ui/borrowck/regions-escape-unboxed-closure.rs
index cf41fad..5a21450 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
@@ -13,5 +13,6 @@
 
 fn main() {
     let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+    with_int(&mut |y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
 }
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
new file mode 100644
index 0000000..4b01e42
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-unboxed-closure.rs:16:32
+   |
+15 |     let mut x: Option<&isize> = None;
+   |         ----- borrowed data cannot be stored into here...
+16 |     with_int(&mut |y| x = Some(y));
+   |                   ---          ^ cannot be stored outside of its closure
+   |                   |
+   |                   ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/ui/cast-errors-issue-43825.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/ui/cast-errors-issue-43825.rs
index 5c32a75..65b3912 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/ui/cast-errors-issue-43825.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+fn main() {
+    let error = error; //~ ERROR cannot find value `error`
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+    // These used to cause errors.
+    0 as f32;
+    0.0 as u32;
+}
diff --git a/src/test/ui/cast-errors-issue-43825.stderr b/src/test/ui/cast-errors-issue-43825.stderr
new file mode 100644
index 0000000..db0a33e
--- /dev/null
+++ b/src/test/ui/cast-errors-issue-43825.stderr
@@ -0,0 +1,8 @@
+error[E0425]: cannot find value `error` in this scope
+  --> $DIR/cast-errors-issue-43825.rs:12:17
+   |
+12 |     let error = error; //~ ERROR cannot find value `error`
+   |                 ^^^^^ not found in this scope
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/casts-differing-anon.rs b/src/test/ui/casts-differing-anon.rs
new file mode 100644
index 0000000..74c8ff3
--- /dev/null
+++ b/src/test/ui/casts-differing-anon.rs
@@ -0,0 +1,34 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(conservative_impl_trait)]
+
+use std::fmt;
+
+fn foo() -> Box<impl fmt::Debug+?Sized> {
+    let x : Box<[u8]> = Box::new([0]);
+    x
+}
+fn bar() -> Box<impl fmt::Debug+?Sized> {
+    let y: Box<fmt::Debug> = Box::new([0]);
+    y
+}
+
+fn main() {
+    let f = foo();
+    let b = bar();
+
+    // this is an `*mut [u8]` in practice
+    let f_raw : *mut _ = Box::into_raw(f);
+    // this is an `*mut fmt::Debug` in practice
+    let mut b_raw = Box::into_raw(b);
+    // ... and they should not be mixable
+    b_raw = f_raw as *mut _; //~ ERROR is invalid
+}
diff --git a/src/test/ui/casts-differing-anon.stderr b/src/test/ui/casts-differing-anon.stderr
new file mode 100644
index 0000000..8db6854
--- /dev/null
+++ b/src/test/ui/casts-differing-anon.stderr
@@ -0,0 +1,10 @@
+error[E0606]: casting `*mut impl std::fmt::Debug+?Sized` as `*mut impl std::fmt::Debug+?Sized` is invalid
+  --> $DIR/casts-differing-anon.rs:33:13
+   |
+33 |     b_raw = f_raw as *mut _; //~ ERROR is invalid
+   |             ^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/ui/casts-issue-46365.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/ui/casts-issue-46365.rs
index 5c32a75..79f636e 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/ui/casts-issue-46365.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+struct Lorem {
+    ipsum: Ipsum //~ ERROR cannot find type `Ipsum`
+}
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+fn main() {
+    let _foo: *mut Lorem = 0 as *mut _; // no error here
+}
diff --git a/src/test/ui/casts-issue-46365.stderr b/src/test/ui/casts-issue-46365.stderr
new file mode 100644
index 0000000..ce3c859
--- /dev/null
+++ b/src/test/ui/casts-issue-46365.stderr
@@ -0,0 +1,8 @@
+error[E0412]: cannot find type `Ipsum` in this scope
+  --> $DIR/casts-issue-46365.rs:12:12
+   |
+12 |     ipsum: Ipsum //~ ERROR cannot find type `Ipsum`
+   |            ^^^^^ not found in this scope
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs b/src/test/ui/closure-expected-type/expect-region-supply-region.rs
similarity index 90%
rename from src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs
rename to src/test/ui/closure-expected-type/expect-region-supply-region.rs
index 9da12dc..a464c58 100644
--- a/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs
+++ b/src/test/ui/closure-expected-type/expect-region-supply-region.rs
@@ -25,7 +25,7 @@
     // it to escape into `f`:
     let mut f: Option<&u32> = None;
     closure_expecting_bound(|x| {
-        f = Some(x); //~ ERROR E0495
+        f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
     });
 }
 
@@ -35,7 +35,7 @@
     // closure:
     let mut f: Option<&u32> = None;
     closure_expecting_bound(|x: &u32| {
-        f = Some(x); //~ ERROR E0495
+        f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
     });
 }
 
@@ -50,7 +50,7 @@
 
         // And we still cannot let `x` escape into `f`.
         f = Some(x);
-        //~^ ERROR cannot infer
+        //~^ ERROR borrowed data cannot be stored outside of its closure
     });
 }
 
diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr
new file mode 100644
index 0000000..ebb1e56
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr
@@ -0,0 +1,98 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:28:18
+   |
+26 |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+27 |     closure_expecting_bound(|x| {
+   |                             --- ...because it cannot outlive this closure
+28 |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |                  ^ cannot be stored outside of its closure
+
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:38:18
+   |
+36 |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+37 |     closure_expecting_bound(|x: &u32| {
+   |                             --------- ...because it cannot outlive this closure
+38 |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |                  ^ cannot be stored outside of its closure
+
+error[E0308]: mismatched types
+  --> $DIR/expect-region-supply-region.rs:47:33
+   |
+47 |     closure_expecting_bound(|x: &'x u32| {
+   |                                 ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&u32`
+              found type `&'x u32`
+note: the anonymous lifetime #2 defined on the body at 47:29...
+  --> $DIR/expect-region-supply-region.rs:47:29
+   |
+47 |       closure_expecting_bound(|x: &'x u32| {
+   |  _____________________________^
+48 | |         //~^ ERROR mismatched types
+49 | |         //~| ERROR mismatched types
+50 | |
+...  |
+53 | |         //~^ ERROR borrowed data cannot be stored outside of its closure
+54 | |     });
+   | |_____^
+note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:1
+  --> $DIR/expect-region-supply-region.rs:42:1
+   |
+42 | / fn expect_bound_supply_named<'x>() {
+43 | |     let mut f: Option<&u32> = None;
+44 | |
+45 | |     // Here we give a type annotation that `x` should be free. We get
+...  |
+54 | |     });
+55 | | }
+   | |_^
+
+error[E0308]: mismatched types
+  --> $DIR/expect-region-supply-region.rs:47:33
+   |
+47 |     closure_expecting_bound(|x: &'x u32| {
+   |                                 ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&u32`
+              found type `&'x u32`
+note: the lifetime 'x as defined on the function body at 42:1...
+  --> $DIR/expect-region-supply-region.rs:42:1
+   |
+42 | / fn expect_bound_supply_named<'x>() {
+43 | |     let mut f: Option<&u32> = None;
+44 | |
+45 | |     // Here we give a type annotation that `x` should be free. We get
+...  |
+54 | |     });
+55 | | }
+   | |_^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 47:29
+  --> $DIR/expect-region-supply-region.rs:47:29
+   |
+47 |       closure_expecting_bound(|x: &'x u32| {
+   |  _____________________________^
+48 | |         //~^ ERROR mismatched types
+49 | |         //~| ERROR mismatched types
+50 | |
+...  |
+53 | |         //~^ ERROR borrowed data cannot be stored outside of its closure
+54 | |     });
+   | |_____^
+
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:52:18
+   |
+43 |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+...
+47 |     closure_expecting_bound(|x: &'x u32| {
+   |                             ------------ ...because it cannot outlive this closure
+...
+52 |         f = Some(x);
+   |                  ^ cannot be stored outside of its closure
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/codemap_tests/unicode_3.stderr b/src/test/ui/codemap_tests/unicode_3.stderr
index d2c850d..3547acc 100644
--- a/src/test/ui/codemap_tests/unicode_3.stderr
+++ b/src/test/ui/codemap_tests/unicode_3.stderr
@@ -2,9 +2,7 @@
   --> $DIR/unicode_3.rs:14:45
    |
 14 |     let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
-   |                       ----------^^^^^^^^^^^
-   |                       |
-   |                       help: use `loop`
+   |                       ^^^^^^^^^^ help: use `loop`
    |
    = note: #[warn(while_true)] on by default
 
diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr
index 98ec3d9..4c2896e 100644
--- a/src/test/ui/deref-suggestion.stderr
+++ b/src/test/ui/deref-suggestion.stderr
@@ -2,16 +2,13 @@
   --> $DIR/deref-suggestion.rs:18:9
    |
 18 |     foo(s); //~ ERROR mismatched types
-   |         ^ expected struct `std::string::String`, found reference
+   |         ^
+   |         |
+   |         expected struct `std::string::String`, found reference
+   |         help: try using a conversion method: `s.to_string()`
    |
    = note: expected type `std::string::String`
               found type `&std::string::String`
-   = help: here are some functions which might fulfill your needs:
-           - .escape_debug()
-           - .escape_default()
-           - .escape_unicode()
-           - .to_ascii_lowercase()
-           - .to_ascii_uppercase()
 
 error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:23:10
diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr
index ec44755..cfaff97 100644
--- a/src/test/ui/did_you_mean/issue-35937.stderr
+++ b/src/test/ui/did_you_mean/issue-35937.stderr
@@ -1,26 +1,26 @@
-error[E0596]: cannot borrow immutable field `f.v` as mutable
+error[E0596]: cannot borrow field `f.v` of immutable binding as mutable
   --> $DIR/issue-35937.rs:17:5
    |
 16 |     let f = Foo { v: Vec::new() };
    |         - consider changing this to `mut f`
 17 |     f.v.push("cat".to_string()); //~ ERROR cannot borrow
-   |     ^^^ cannot mutably borrow immutable field
+   |     ^^^ cannot mutably borrow field of immutable binding
 
-error[E0594]: cannot assign to immutable field `s.x`
+error[E0594]: cannot assign to field `s.x` of immutable binding
   --> $DIR/issue-35937.rs:26:5
    |
 25 |     let s = S { x: 42 };
    |         - consider changing this to `mut s`
 26 |     s.x += 1; //~ ERROR cannot assign
-   |     ^^^^^^^^ cannot mutably borrow immutable field
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0594]: cannot assign to immutable field `s.x`
+error[E0594]: cannot assign to field `s.x` of immutable binding
   --> $DIR/issue-35937.rs:30:5
    |
 29 | fn bar(s: S) {
    |        - consider changing this to `mut s`
 30 |     s.x += 1; //~ ERROR cannot assign
-   |     ^^^^^^^^ cannot mutably borrow immutable field
+   |     ^^^^^^^^ cannot mutably borrow field of immutable binding
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-38147-2.rs b/src/test/ui/did_you_mean/issue-38147-2.rs
index cc6be98..1a24f47 100644
--- a/src/test/ui/did_you_mean/issue-38147-2.rs
+++ b/src/test/ui/did_you_mean/issue-38147-2.rs
@@ -14,7 +14,8 @@
 
 impl<'a> Bar<'a> {
     fn f(&mut self) {
-        self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
+        self.s.push('x');
+        //~^ ERROR cannot borrow borrowed content `*self.s` of immutable binding as mutable
     }
 }
 
diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr
index b09ecf9..569bfa1 100644
--- a/src/test/ui/did_you_mean/issue-38147-2.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-2.stderr
@@ -1,10 +1,10 @@
-error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable
+error[E0596]: cannot borrow borrowed content `*self.s` of immutable binding as mutable
   --> $DIR/issue-38147-2.rs:17:9
    |
 12 |     s: &'a String
    |        ---------- use `&'a mut String` here to make mutable
 ...
-17 |         self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
+17 |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
 error: aborting due to previous error
diff --git a/src/test/ui/did_you_mean/issue-38147-3.rs b/src/test/ui/did_you_mean/issue-38147-3.rs
index 42b2910..5e2bf06 100644
--- a/src/test/ui/did_you_mean/issue-38147-3.rs
+++ b/src/test/ui/did_you_mean/issue-38147-3.rs
@@ -14,7 +14,8 @@
 
 impl<'a> Qux<'a> {
     fn f(&self) {
-        self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
+        self.s.push('x');
+        //~^ ERROR cannot borrow borrowed content `*self.s` of immutable binding as mutable
     }
 }
 
diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr
index ca721f1..75d904d 100644
--- a/src/test/ui/did_you_mean/issue-38147-3.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-3.stderr
@@ -1,10 +1,10 @@
-error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable
+error[E0596]: cannot borrow borrowed content `*self.s` of immutable binding as mutable
   --> $DIR/issue-38147-3.rs:17:9
    |
 12 |     s: &'a String
    |        ---------- use `&'a mut String` here to make mutable
 ...
-17 |         self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
+17 |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
 error: aborting due to previous error
diff --git a/src/test/ui/did_you_mean/issue-39544.rs b/src/test/ui/did_you_mean/issue-39544.rs
index 7cd7768..205cbce 100644
--- a/src/test/ui/did_you_mean/issue-39544.rs
+++ b/src/test/ui/did_you_mean/issue-39544.rs
@@ -55,5 +55,6 @@
 pub fn with_tuple() {
     let mut y = 0;
     let x = (&y,);
-    *x.0 = 1; //~ ERROR cannot assign to immutable borrowed content
+    *x.0 = 1;
+    //~^ ERROR cannot assign to borrowed content `*x.0` of immutable binding
 }
diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr
index 1fcb053..d8c0898 100644
--- a/src/test/ui/did_you_mean/issue-39544.stderr
+++ b/src/test/ui/did_you_mean/issue-39544.stderr
@@ -1,99 +1,99 @@
-error[E0596]: cannot borrow immutable field `z.x` as mutable
+error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:21:18
    |
 20 |     let z = Z { x: X::Y };
    |         - consider changing this to `mut z`
 21 |     let _ = &mut z.x; //~ ERROR cannot borrow
-   |                  ^^^ cannot mutably borrow immutable field
+   |                  ^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `self.x` as mutable
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:26:22
    |
 25 |     fn foo<'z>(&'z self) {
    |                -------- use `&'z mut self` here to make mutable
 26 |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                      ^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `self.x` as mutable
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:30:22
    |
 29 |     fn foo1(&self, other: &Z) {
    |             ----- use `&mut self` here to make mutable
 30 |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                      ^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `other.x` as mutable
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:31:22
    |
 29 |     fn foo1(&self, other: &Z) {
    |                           -- use `&mut Z` here to make mutable
 30 |         let _ = &mut self.x; //~ ERROR cannot borrow
 31 |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                      ^^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `self.x` as mutable
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:35:22
    |
 34 |     fn foo2<'a>(&'a self, other: &Z) {
    |                 -------- use `&'a mut self` here to make mutable
 35 |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                      ^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `other.x` as mutable
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:36:22
    |
 34 |     fn foo2<'a>(&'a self, other: &Z) {
    |                                  -- use `&mut Z` here to make mutable
 35 |         let _ = &mut self.x; //~ ERROR cannot borrow
 36 |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                      ^^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `self.x` as mutable
+error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:40:22
    |
 39 |     fn foo3<'a>(self: &'a Self, other: &Z) {
    |                       -------- use `&'a mut Self` here to make mutable
 40 |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                      ^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `other.x` as mutable
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:41:22
    |
 39 |     fn foo3<'a>(self: &'a Self, other: &Z) {
    |                                        -- use `&mut Z` here to make mutable
 40 |         let _ = &mut self.x; //~ ERROR cannot borrow
 41 |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                      ^^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `other.x` as mutable
+error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:45:22
    |
 44 |     fn foo4(other: &Z) {
    |                    -- use `&mut Z` here to make mutable
 45 |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                      ^^^^^^^ cannot mutably borrow immutable field
+   |                      ^^^^^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `z.x` as mutable
+error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:51:18
    |
 50 | pub fn with_arg(z: Z, w: &Z) {
    |                 - consider changing this to `mut z`
 51 |     let _ = &mut z.x; //~ ERROR cannot borrow
-   |                  ^^^ cannot mutably borrow immutable field
+   |                  ^^^ cannot mutably borrow field of immutable binding
 
-error[E0596]: cannot borrow immutable field `w.x` as mutable
+error[E0596]: cannot borrow field `w.x` of immutable binding as mutable
   --> $DIR/issue-39544.rs:52:18
    |
 50 | pub fn with_arg(z: Z, w: &Z) {
    |                          -- use `&mut Z` here to make mutable
 51 |     let _ = &mut z.x; //~ ERROR cannot borrow
 52 |     let _ = &mut w.x; //~ ERROR cannot borrow
-   |                  ^^^ cannot mutably borrow immutable field
+   |                  ^^^ cannot mutably borrow field of immutable binding
 
-error[E0594]: cannot assign to immutable borrowed content `*x.0`
+error[E0594]: cannot assign to borrowed content `*x.0` of immutable binding
   --> $DIR/issue-39544.rs:58:5
    |
-58 |     *x.0 = 1; //~ ERROR cannot assign to immutable borrowed content
+58 |     *x.0 = 1;
    |     ^^^^^^^^ cannot borrow as mutable
 
 error: aborting due to 12 previous errors
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index d5c4add..7ca3e87 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -10,7 +10,11 @@
              <i8 as Foo<u32>>
              <i8 as Foo<u64>>
              <i8 as Foo<bool>>
-   = note: required by `Foo::bar`
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:12:5
+   |
+12 |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:35:5
@@ -23,7 +27,11 @@
              <u8 as Foo<u32>>
              <u8 as Foo<u64>>
              <u8 as Foo<bool>>
-   = note: required by `Foo::bar`
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:12:5
+   |
+12 |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:36:5
@@ -37,7 +45,11 @@
              <bool as Foo<u32>>
              <bool as Foo<u64>>
            and 2 others
-   = note: required by `Foo::bar`
+note: required by `Foo::bar`
+  --> $DIR/issue-39802-show-5-trait-impls.rs:12:5
+   |
+12 |     fn bar(&self){}
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/compile-fail/E0580.rs b/src/test/ui/did_you_mean/multiple-pattern-typo.rs
similarity index 66%
copy from src/test/compile-fail/E0580.rs
copy to src/test/ui/did_you_mean/multiple-pattern-typo.rs
index a2ef7da..a8994fd 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/ui/did_you_mean/multiple-pattern-typo.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+fn main() {
+    let x = 3;
+    match x {
+        1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern
+        _ => (),
+    }
+}
diff --git a/src/test/ui/did_you_mean/multiple-pattern-typo.stderr b/src/test/ui/did_you_mean/multiple-pattern-typo.stderr
new file mode 100644
index 0000000..a35aa6f
--- /dev/null
+++ b/src/test/ui/did_you_mean/multiple-pattern-typo.stderr
@@ -0,0 +1,8 @@
+error: unexpected token `||` after pattern
+  --> $DIR/multiple-pattern-typo.rs:14:15
+   |
+14 |         1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern
+   |               ^^ help: use a single `|` to specify multiple patterns: `|`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
index 7fac604..2bc7e9e 100644
--- a/src/test/ui/did_you_mean/recursion_limit.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -15,7 +15,11 @@
    = note: required because it appears within the type `C`
    = note: required because it appears within the type `B`
    = note: required because it appears within the type `A`
-   = note: required by `is_send`
+note: required by `is_send`
+  --> $DIR/recursion_limit.rs:41:1
+   |
+41 | fn is_send<T:Send>() { }
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
index 951b0b1..860c6bb 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -4,11 +4,11 @@
 62 |     let x: &Bottom = &t; //~ ERROR mismatched types
    |                      ^^ deref recursion limit reached
    |
-   = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
 
 error[E0055]: reached the recursion limit while auto-dereferencing I
   |
-  = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+  = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
 
 error[E0308]: mismatched types
   --> $DIR/recursion_limit_deref.rs:62:22
diff --git a/src/test/ui/empty-struct-unit-expr.rs b/src/test/ui/empty-struct-unit-expr.rs
index c339601..941292a 100644
--- a/src/test/ui/empty-struct-unit-expr.rs
+++ b/src/test/ui/empty-struct-unit-expr.rs
@@ -24,8 +24,8 @@
 fn main() {
     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
     let e4 = E::Empty4();
-    //~^ ERROR expected function, found `E::Empty4` [E0618]
+    //~^ ERROR expected function, found enum variant `E::Empty4` [E0618]
     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
     let xe4 = XE::XEmpty4();
-    //~^ ERROR expected function, found `XE::XEmpty4` [E0618]
+    //~^ ERROR expected function, found enum variant `XE::XEmpty4` [E0618]
 }
diff --git a/src/test/ui/empty-struct-unit-expr.stderr b/src/test/ui/empty-struct-unit-expr.stderr
index 3ce63ed..aa242a5 100644
--- a/src/test/ui/empty-struct-unit-expr.stderr
+++ b/src/test/ui/empty-struct-unit-expr.stderr
@@ -1,41 +1,40 @@
 error[E0618]: expected function, found `Empty2`
   --> $DIR/empty-struct-unit-expr.rs:25:14
    |
-25 |     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
-   |              ^^^^^^^^
-   |
-note: defined here
-  --> $DIR/empty-struct-unit-expr.rs:18:1
-   |
 18 | struct Empty2;
-   | ^^^^^^^^^^^^^^
+   | -------------- `Empty2` defined here
+...
+25 |     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
+   |              ^^^^^^^^ not a function
 
-error[E0618]: expected function, found `E::Empty4`
+error[E0618]: expected function, found enum variant `E::Empty4`
   --> $DIR/empty-struct-unit-expr.rs:26:14
    |
-26 |     let e4 = E::Empty4();
-   |              ^^^^^^^^^^^
-   |
-   = help: did you mean to write `E::Empty4`?
-note: defined here
-  --> $DIR/empty-struct-unit-expr.rs:21:5
-   |
 21 |     Empty4
-   |     ^^^^^^
+   |     ------ `E::Empty4` defined here
+...
+26 |     let e4 = E::Empty4();
+   |              ^^^^^^^^^^^ not a function
+help: `E::Empty4` is a unit variant, you need to write it without the parenthesis
+   |
+26 |     let e4 = E::Empty4;
+   |              ^^^^^^^^^
 
 error[E0618]: expected function, found `empty_struct::XEmpty2`
   --> $DIR/empty-struct-unit-expr.rs:28:15
    |
 28 |     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
-   |               ^^^^^^^^^
+   |               ^^^^^^^^^ not a function
 
-error[E0618]: expected function, found `XE::XEmpty4`
+error[E0618]: expected function, found enum variant `XE::XEmpty4`
   --> $DIR/empty-struct-unit-expr.rs:29:15
    |
 29 |     let xe4 = XE::XEmpty4();
-   |               ^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^ not a function
+help: `XE::XEmpty4` is a unit variant, you need to write it without the parenthesis
    |
-   = help: did you mean to write `XE::XEmpty4`?
+29 |     let xe4 = XE::XEmpty4;
+   |               ^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/fat-ptr-cast.stderr b/src/test/ui/fat-ptr-cast.stderr
index 35a9774..b3c2b23 100644
--- a/src/test/ui/fat-ptr-cast.stderr
+++ b/src/test/ui/fat-ptr-cast.stderr
@@ -11,18 +11,24 @@
    |
 21 |     a as isize; //~ ERROR casting
    |     ^^^^^^^^^^
+   |
+   = help: cast through a raw pointer first
 
 error[E0606]: casting `&[i32]` as `i16` is invalid
   --> $DIR/fat-ptr-cast.rs:22:5
    |
 22 |     a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
    |     ^^^^^^^^
+   |
+   = help: cast through a raw pointer first
 
 error[E0606]: casting `&[i32]` as `u32` is invalid
   --> $DIR/fat-ptr-cast.rs:23:5
    |
 23 |     a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
    |     ^^^^^^^^
+   |
+   = help: cast through a raw pointer first
 
 error[E0605]: non-primitive cast: `std::boxed::Box<[i32]>` as `usize`
   --> $DIR/fat-ptr-cast.rs:24:5
diff --git a/src/test/ui/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr
index b05be6e..e1621d3 100644
--- a/src/test/ui/feature-gate-abi-msp430-interrupt.stderr
+++ b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr
@@ -1,4 +1,4 @@
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:14:1
    |
 14 | extern "msp430-interrupt" fn foo() {}
diff --git a/src/test/ui/feature-gate-abi.stderr b/src/test/ui/feature-gate-abi.stderr
index 7d2ad0b..ce31474 100644
--- a/src/test/ui/feature-gate-abi.stderr
+++ b/src/test/ui/feature-gate-abi.stderr
@@ -1,4 +1,4 @@
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-abi.rs:19:1
    |
 19 | extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-abi.rs:20:1
    |
 20 | extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:21:1
    |
 21 | extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-abi.rs:22:1
    |
 22 | extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
@@ -30,7 +30,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi.rs:23:1
    |
 23 | extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
@@ -38,7 +38,7 @@
    |
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:24:1
    |
 24 | extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
@@ -46,7 +46,7 @@
    |
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
   --> $DIR/feature-gate-abi.rs:25:1
    |
 25 | extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -54,7 +54,7 @@
    |
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:26:1
    |
 26 | extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change
@@ -62,7 +62,7 @@
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-abi.rs:30:5
    |
 30 |     extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
@@ -70,7 +70,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-abi.rs:31:5
    |
 31 |     extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
@@ -78,7 +78,7 @@
    |
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:32:5
    |
 32 |     extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
@@ -86,7 +86,7 @@
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-abi.rs:33:5
    |
 33 |     extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
@@ -94,7 +94,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi.rs:34:5
    |
 34 |     extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
@@ -102,7 +102,7 @@
    |
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:35:5
    |
 35 |     extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
@@ -110,7 +110,7 @@
    |
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
   --> $DIR/feature-gate-abi.rs:36:5
    |
 36 |     extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
@@ -118,7 +118,7 @@
    |
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:37:5
    |
 37 |     extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
@@ -126,7 +126,7 @@
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-abi.rs:39:5
    |
 39 |     extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
@@ -134,7 +134,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-abi.rs:40:5
    |
 40 |     extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
@@ -142,7 +142,7 @@
    |
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:41:5
    |
 41 |     extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
@@ -150,7 +150,7 @@
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-abi.rs:42:5
    |
 42 |     extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
@@ -158,7 +158,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi.rs:43:5
    |
 43 |     extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
@@ -166,7 +166,7 @@
    |
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:44:5
    |
 44 |     extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
@@ -174,7 +174,7 @@
    |
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
   --> $DIR/feature-gate-abi.rs:45:5
    |
 45 |     extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -182,7 +182,7 @@
    |
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:46:5
    |
 46 |     extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change
@@ -190,7 +190,7 @@
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-abi.rs:53:5
    |
 53 |     extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
@@ -198,7 +198,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-abi.rs:54:5
    |
 54 |     extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
@@ -206,7 +206,7 @@
    |
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:55:5
    |
 55 |     extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
@@ -214,7 +214,7 @@
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-abi.rs:56:5
    |
 56 |     extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
@@ -222,7 +222,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi.rs:57:5
    |
 57 |     extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
@@ -230,7 +230,7 @@
    |
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:58:5
    |
 58 |     extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
@@ -238,7 +238,7 @@
    |
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
   --> $DIR/feature-gate-abi.rs:59:5
    |
 59 |     extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -246,7 +246,7 @@
    |
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:60:5
    |
 60 |     extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change
@@ -254,7 +254,7 @@
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-abi.rs:65:5
    |
 65 |     extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
@@ -262,7 +262,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-abi.rs:66:5
    |
 66 |     extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
@@ -270,7 +270,7 @@
    |
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:67:5
    |
 67 |     extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
@@ -278,7 +278,7 @@
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-abi.rs:68:5
    |
 68 |     extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
@@ -286,7 +286,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi.rs:69:5
    |
 69 |     extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
@@ -294,7 +294,7 @@
    |
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:70:5
    |
 70 |     extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
@@ -302,7 +302,7 @@
    |
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
   --> $DIR/feature-gate-abi.rs:71:5
    |
 71 |     extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -310,7 +310,7 @@
    |
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:72:5
    |
 72 |     extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change
@@ -318,7 +318,7 @@
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-abi.rs:76:11
    |
 76 | type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
@@ -326,7 +326,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-abi.rs:77:11
    |
 77 | type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
@@ -334,7 +334,7 @@
    |
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:78:11
    |
 78 | type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
@@ -342,7 +342,7 @@
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-abi.rs:79:11
    |
 79 | type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
@@ -350,7 +350,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi.rs:80:11
    |
 80 | type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
@@ -358,7 +358,7 @@
    |
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:81:11
    |
 81 | type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
@@ -366,7 +366,7 @@
    |
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
   --> $DIR/feature-gate-abi.rs:82:11
    |
 82 | type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
@@ -374,7 +374,7 @@
    |
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:83:11
    |
 83 | type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change
@@ -382,7 +382,7 @@
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-abi.rs:86:1
    |
 86 | extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
@@ -390,7 +390,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-abi.rs:87:1
    |
 87 | extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
@@ -398,7 +398,7 @@
    |
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
-error: vectorcall is experimental and subject to change
+error[E0658]: vectorcall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:88:1
    |
 88 | extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
@@ -406,7 +406,7 @@
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-abi.rs:89:1
    |
 89 | extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
@@ -414,7 +414,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
   --> $DIR/feature-gate-abi.rs:90:1
    |
 90 | extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
@@ -422,7 +422,7 @@
    |
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error: PTX ABIs are experimental and subject to change
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:91:1
    |
 91 | extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
@@ -430,7 +430,7 @@
    |
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
   --> $DIR/feature-gate-abi.rs:92:1
    |
 92 | extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
@@ -438,7 +438,7 @@
    |
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
-error: thiscall is experimental and subject to change
+error[E0658]: thiscall is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:93:1
    |
 93 | extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change
diff --git a/src/test/ui/feature-gate-abi_unadjusted.stderr b/src/test/ui/feature-gate-abi_unadjusted.stderr
index 3cc4384..b3f7cd2 100644
--- a/src/test/ui/feature-gate-abi_unadjusted.stderr
+++ b/src/test/ui/feature-gate-abi_unadjusted.stderr
@@ -1,4 +1,4 @@
-error: unadjusted ABI is an implementation detail and perma-unstable
+error[E0658]: unadjusted ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi_unadjusted.rs:11:1
    |
 11 | / extern "unadjusted" fn foo() {
diff --git a/src/test/ui/feature-gate-advanced-slice-features.stderr b/src/test/ui/feature-gate-advanced-slice-features.stderr
index 815593d..63ede50 100644
--- a/src/test/ui/feature-gate-advanced-slice-features.stderr
+++ b/src/test/ui/feature-gate-advanced-slice-features.stderr
@@ -1,4 +1,4 @@
-error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
+error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
   --> $DIR/feature-gate-advanced-slice-features.rs:18:9
    |
 18 |         [ xs.., 4, 5 ] => {}    //~ ERROR multiple-element slice matches
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
 
-error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
+error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
   --> $DIR/feature-gate-advanced-slice-features.rs:19:9
    |
 19 |         [ 1, xs.., 5 ] => {}    //~ ERROR multiple-element slice matches
diff --git a/src/test/ui/feature-gate-allocator_internals.stderr b/src/test/ui/feature-gate-allocator_internals.stderr
index f1f4705..76d96f9 100644
--- a/src/test/ui/feature-gate-allocator_internals.stderr
+++ b/src/test/ui/feature-gate-allocator_internals.stderr
@@ -1,4 +1,4 @@
-error: the `#[default_lib_allocator]` attribute is an experimental feature
+error[E0658]: the `#[default_lib_allocator]` attribute is an experimental feature
   --> $DIR/feature-gate-allocator_internals.rs:11:1
    |
 11 | #![default_lib_allocator] //~ ERROR: attribute is an experimental feature
diff --git a/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr
index 40bdde3..31de8d7 100644
--- a/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr
+++ b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr
@@ -1,4 +1,4 @@
-error: allow_internal_unsafe side-steps the unsafe_code lint
+error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
   --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:18:9
    |
 18 |         #[allow_internal_unsafe] //~ ERROR allow_internal_unsafe side-steps
diff --git a/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr
index 60d72fb..3e2573e 100644
--- a/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr
+++ b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr
@@ -1,4 +1,4 @@
-error: allow_internal_unstable side-steps feature gating and stability checks
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
   --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:18:9
    |
 18 |         #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
diff --git a/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr
index 2fb86ce..e19f328 100644
--- a/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr
+++ b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr
@@ -1,4 +1,4 @@
-error: allow_internal_unstable side-steps feature gating and stability checks
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
   --> $DIR/feature-gate-allow-internal-unstable-struct.rs:14:1
    |
 14 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
diff --git a/src/test/ui/feature-gate-allow-internal-unstable.stderr b/src/test/ui/feature-gate-allow-internal-unstable.stderr
index a5740a1..f110afb 100644
--- a/src/test/ui/feature-gate-allow-internal-unstable.stderr
+++ b/src/test/ui/feature-gate-allow-internal-unstable.stderr
@@ -1,4 +1,4 @@
-error: allow_internal_unstable side-steps feature gating and stability checks
+error[E0658]: allow_internal_unstable side-steps feature gating and stability checks
   --> $DIR/feature-gate-allow-internal-unstable.rs:13:1
    |
 13 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
diff --git a/src/test/ui/feature-gate-allow_fail.stderr b/src/test/ui/feature-gate-allow_fail.stderr
index 65cd137..e04f448 100644
--- a/src/test/ui/feature-gate-allow_fail.stderr
+++ b/src/test/ui/feature-gate-allow_fail.stderr
@@ -1,4 +1,4 @@
-error: allow_fail attribute is currently unstable (see issue #42219)
+error[E0658]: allow_fail attribute is currently unstable (see issue #42219)
   --> $DIR/feature-gate-allow_fail.rs:13:1
    |
 13 | #[allow_fail] //~ ERROR allow_fail attribute is currently unstable
diff --git a/src/test/ui/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gate-arbitrary-self-types.stderr
index 2ef517c..ca47d40 100644
--- a/src/test/ui/feature-gate-arbitrary-self-types.stderr
+++ b/src/test/ui/feature-gate-arbitrary-self-types.stderr
@@ -1,4 +1,4 @@
-error: arbitrary `self` types are unstable (see issue #44874)
+error[E0658]: arbitrary `self` types are unstable (see issue #44874)
   --> $DIR/feature-gate-arbitrary-self-types.rs:14:18
    |
 14 |     fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
@@ -7,7 +7,7 @@
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error: arbitrary `self` types are unstable (see issue #44874)
+error[E0658]: arbitrary `self` types are unstable (see issue #44874)
   --> $DIR/feature-gate-arbitrary-self-types.rs:20:18
    |
 20 |     fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
@@ -16,7 +16,7 @@
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error: arbitrary `self` types are unstable (see issue #44874)
+error[E0658]: arbitrary `self` types are unstable (see issue #44874)
   --> $DIR/feature-gate-arbitrary-self-types.rs:24:18
    |
 24 |     fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
diff --git a/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr
index d629ac4..33e8806 100644
--- a/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr
+++ b/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -1,4 +1,4 @@
-error: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: raw pointer `self` is unstable (see issue #44874)
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:19:18
    |
 19 |     fn bar(self: *const Self);
@@ -7,7 +7,7 @@
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: raw pointer `self` is unstable (see issue #44874)
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
    |
 14 |     fn foo(self: *const Self) {}
@@ -16,7 +16,7 @@
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: raw pointer `self` is unstable (see issue #44874)
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:24:18
    |
 24 |     fn bar(self: *const Self) {}
diff --git a/src/test/ui/feature-gate-asm.stderr b/src/test/ui/feature-gate-asm.stderr
index ff68a4f..481e6dc 100644
--- a/src/test/ui/feature-gate-asm.stderr
+++ b/src/test/ui/feature-gate-asm.stderr
@@ -1,4 +1,4 @@
-error: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
   --> $DIR/feature-gate-asm.rs:13:9
    |
 13 |         asm!(""); //~ ERROR inline assembly is not stable enough
diff --git a/src/test/ui/feature-gate-asm2.stderr b/src/test/ui/feature-gate-asm2.stderr
index 1e02ced..aba0f72 100644
--- a/src/test/ui/feature-gate-asm2.stderr
+++ b/src/test/ui/feature-gate-asm2.stderr
@@ -1,4 +1,4 @@
-error: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
   --> $DIR/feature-gate-asm2.rs:15:24
    |
 15 |         println!("{}", asm!("")); //~ ERROR inline assembly is not stable
diff --git a/src/test/ui/feature-gate-assoc-type-defaults.stderr b/src/test/ui/feature-gate-assoc-type-defaults.stderr
index 5e28846..1d44797 100644
--- a/src/test/ui/feature-gate-assoc-type-defaults.stderr
+++ b/src/test/ui/feature-gate-assoc-type-defaults.stderr
@@ -1,4 +1,4 @@
-error: associated type defaults are unstable (see issue #29661)
+error[E0658]: associated type defaults are unstable (see issue #29661)
   --> $DIR/feature-gate-assoc-type-defaults.rs:14:5
    |
 14 |     type Bar = u8; //~ ERROR associated type defaults are unstable
diff --git a/src/test/ui/feature-gate-box-expr.stderr b/src/test/ui/feature-gate-box-expr.stderr
index cef5adb..f9cccde 100644
--- a/src/test/ui/feature-gate-box-expr.stderr
+++ b/src/test/ui/feature-gate-box-expr.stderr
@@ -1,4 +1,4 @@
-error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
   --> $DIR/feature-gate-box-expr.rs:22:13
    |
 22 |     let x = box 'c'; //~ ERROR box expression syntax is experimental
diff --git a/src/test/ui/feature-gate-box_patterns.stderr b/src/test/ui/feature-gate-box_patterns.stderr
index 0a30de5..ca00933 100644
--- a/src/test/ui/feature-gate-box_patterns.stderr
+++ b/src/test/ui/feature-gate-box_patterns.stderr
@@ -1,4 +1,4 @@
-error: box pattern syntax is experimental (see issue #29641)
+error[E0658]: box pattern syntax is experimental (see issue #29641)
   --> $DIR/feature-gate-box_patterns.rs:12:9
    |
 12 |     let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
diff --git a/src/test/ui/feature-gate-box_syntax.stderr b/src/test/ui/feature-gate-box_syntax.stderr
index 9b21dd0..eefaa72 100644
--- a/src/test/ui/feature-gate-box_syntax.stderr
+++ b/src/test/ui/feature-gate-box_syntax.stderr
@@ -1,4 +1,4 @@
-error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
   --> $DIR/feature-gate-box_syntax.rs:14:13
    |
 14 |     let x = box 3;
diff --git a/src/test/ui/feature-gate-catch_expr.stderr b/src/test/ui/feature-gate-catch_expr.stderr
index f486373..4b3bfbb 100644
--- a/src/test/ui/feature-gate-catch_expr.stderr
+++ b/src/test/ui/feature-gate-catch_expr.stderr
@@ -1,4 +1,4 @@
-error: `catch` expression is experimental (see issue #31436)
+error[E0658]: `catch` expression is experimental (see issue #31436)
   --> $DIR/feature-gate-catch_expr.rs:12:24
    |
 12 |       let catch_result = do catch { //~ ERROR `catch` expression is experimental
diff --git a/src/test/ui/feature-gate-cfg-target-feature.stderr b/src/test/ui/feature-gate-cfg-target-feature.stderr
index 60dc6fb..f808e78 100644
--- a/src/test/ui/feature-gate-cfg-target-feature.stderr
+++ b/src/test/ui/feature-gate-cfg-target-feature.stderr
@@ -1,4 +1,4 @@
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
   --> $DIR/feature-gate-cfg-target-feature.rs:12:12
    |
 12 | #[cfg_attr(target_feature = "x", x)] //~ ERROR `cfg(target_feature)` is experimental
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
 
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
   --> $DIR/feature-gate-cfg-target-feature.rs:11:7
    |
 11 | #[cfg(target_feature = "x")] //~ ERROR `cfg(target_feature)` is experimental
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
 
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
   --> $DIR/feature-gate-cfg-target-feature.rs:15:19
    |
 15 | #[cfg(not(any(all(target_feature = "x"))))] //~ ERROR `cfg(target_feature)` is experimental
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
 
-error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+error[E0658]: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
   --> $DIR/feature-gate-cfg-target-feature.rs:19:10
    |
 19 |     cfg!(target_feature = "x");
diff --git a/src/test/ui/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr
index 5daf5de..ace23b3 100644
--- a/src/test/ui/feature-gate-cfg-target-has-atomic.stderr
+++ b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr
@@ -1,4 +1,4 @@
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:23:7
    |
 23 | #[cfg(target_has_atomic = "8")]
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:29:7
    |
 29 | #[cfg(target_has_atomic = "8")]
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:34:7
    |
 34 | #[cfg(target_has_atomic = "16")]
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:39:7
    |
 39 | #[cfg(target_has_atomic = "16")]
@@ -30,7 +30,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:44:7
    |
 44 | #[cfg(target_has_atomic = "32")]
@@ -38,7 +38,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:49:7
    |
 49 | #[cfg(target_has_atomic = "32")]
@@ -46,7 +46,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:54:7
    |
 54 | #[cfg(target_has_atomic = "64")]
@@ -54,7 +54,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:59:7
    |
 59 | #[cfg(target_has_atomic = "64")]
@@ -62,7 +62,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:64:7
    |
 64 | #[cfg(target_has_atomic = "ptr")]
@@ -70,7 +70,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:69:7
    |
 69 | #[cfg(target_has_atomic = "ptr")]
@@ -78,7 +78,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:76:10
    |
 76 |     cfg!(target_has_atomic = "8");
@@ -86,7 +86,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10
    |
 78 |     cfg!(target_has_atomic = "16");
@@ -94,7 +94,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10
    |
 80 |     cfg!(target_has_atomic = "32");
@@ -102,7 +102,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10
    |
 82 |     cfg!(target_has_atomic = "64");
@@ -110,7 +110,7 @@
    |
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10
    |
 84 |     cfg!(target_has_atomic = "ptr");
diff --git a/src/test/ui/feature-gate-cfg-target-thread-local.stderr b/src/test/ui/feature-gate-cfg-target-thread-local.stderr
index 9e2eea6..a0a03bd 100644
--- a/src/test/ui/feature-gate-cfg-target-thread-local.stderr
+++ b/src/test/ui/feature-gate-cfg-target-thread-local.stderr
@@ -1,4 +1,4 @@
-error: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
+error[E0658]: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
   --> $DIR/feature-gate-cfg-target-thread-local.rs:19:16
    |
 19 |     #[cfg_attr(target_thread_local, thread_local)]
diff --git a/src/test/ui/feature-gate-cfg-target-vendor.stderr b/src/test/ui/feature-gate-cfg-target-vendor.stderr
index c570960..3e4a746 100644
--- a/src/test/ui/feature-gate-cfg-target-vendor.stderr
+++ b/src/test/ui/feature-gate-cfg-target-vendor.stderr
@@ -1,4 +1,4 @@
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
   --> $DIR/feature-gate-cfg-target-vendor.rs:12:12
    |
 12 | #[cfg_attr(target_vendor = "x", x)] //~ ERROR `cfg(target_vendor)` is experimental
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
 
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
   --> $DIR/feature-gate-cfg-target-vendor.rs:11:7
    |
 11 | #[cfg(target_vendor = "x")] //~ ERROR `cfg(target_vendor)` is experimental
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
 
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
   --> $DIR/feature-gate-cfg-target-vendor.rs:15:19
    |
 15 | #[cfg(not(any(all(target_vendor = "x"))))] //~ ERROR `cfg(target_vendor)` is experimental
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
 
-error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+error[E0658]: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
   --> $DIR/feature-gate-cfg-target-vendor.rs:19:10
    |
 19 |     cfg!(target_vendor = "x");
diff --git a/src/test/ui/feature-gate-compiler-builtins.stderr b/src/test/ui/feature-gate-compiler-builtins.stderr
index ebf42b2..edb3c5d 100644
--- a/src/test/ui/feature-gate-compiler-builtins.stderr
+++ b/src/test/ui/feature-gate-compiler-builtins.stderr
@@ -1,4 +1,4 @@
-error: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable
+error[E0658]: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable
   --> $DIR/feature-gate-compiler-builtins.rs:11:1
    |
 11 | #![compiler_builtins] //~ ERROR the `#[compiler_builtins]` attribute is
diff --git a/src/test/ui/feature-gate-concat_idents.stderr b/src/test/ui/feature-gate-concat_idents.stderr
index c980668..d0a07e3 100644
--- a/src/test/ui/feature-gate-concat_idents.stderr
+++ b/src/test/ui/feature-gate-concat_idents.stderr
@@ -1,4 +1,4 @@
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
   --> $DIR/feature-gate-concat_idents.rs:15:13
    |
 15 |     let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(concat_idents)] to the crate attributes to enable
 
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
   --> $DIR/feature-gate-concat_idents.rs:16:13
    |
 16 |     let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable
diff --git a/src/test/ui/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gate-concat_idents2.stderr
index 9cfd954..0ef6921 100644
--- a/src/test/ui/feature-gate-concat_idents2.stderr
+++ b/src/test/ui/feature-gate-concat_idents2.stderr
@@ -1,4 +1,4 @@
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
   --> $DIR/feature-gate-concat_idents2.rs:14:5
    |
 14 |     concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
diff --git a/src/test/ui/feature-gate-concat_idents3.stderr b/src/test/ui/feature-gate-concat_idents3.stderr
index 8399ca3..a9a1e49 100644
--- a/src/test/ui/feature-gate-concat_idents3.stderr
+++ b/src/test/ui/feature-gate-concat_idents3.stderr
@@ -1,4 +1,4 @@
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
   --> $DIR/feature-gate-concat_idents3.rs:17:20
    |
 17 |     assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(concat_idents)] to the crate attributes to enable
 
-error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
   --> $DIR/feature-gate-concat_idents3.rs:18:20
    |
 18 |     assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable
diff --git a/src/test/ui/feature-gate-conservative_impl_trait.stderr b/src/test/ui/feature-gate-conservative_impl_trait.stderr
index 72a4f52..f3d3947 100644
--- a/src/test/ui/feature-gate-conservative_impl_trait.stderr
+++ b/src/test/ui/feature-gate-conservative_impl_trait.stderr
@@ -1,4 +1,4 @@
-error: `impl Trait` in return position is experimental (see issue #34511)
+error[E0658]: `impl Trait` in return position is experimental (see issue #34511)
   --> $DIR/feature-gate-conservative_impl_trait.rs:11:13
    |
 11 | fn foo() -> impl Fn() { || {} }
diff --git a/src/test/ui/feature-gate-const_fn.stderr b/src/test/ui/feature-gate-const_fn.stderr
index c62229a..ecd1ff5 100644
--- a/src/test/ui/feature-gate-const_fn.stderr
+++ b/src/test/ui/feature-gate-const_fn.stderr
@@ -16,7 +16,7 @@
 27 |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
    |     ^^^^^ trait fns cannot be const
 
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
   --> $DIR/feature-gate-const_fn.rs:13:1
    |
 13 | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
@@ -24,7 +24,7 @@
    |
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
   --> $DIR/feature-gate-const_fn.rs:16:5
    |
 16 |     const fn foo() -> u32; //~ ERROR const fn is unstable
@@ -32,7 +32,7 @@
    |
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
   --> $DIR/feature-gate-const_fn.rs:18:5
    |
 18 |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
@@ -40,7 +40,7 @@
    |
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
   --> $DIR/feature-gate-const_fn.rs:23:5
    |
 23 |     const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
@@ -48,7 +48,7 @@
    |
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #24111)
   --> $DIR/feature-gate-const_fn.rs:27:5
    |
 27 |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
diff --git a/src/test/ui/feature-gate-crate_in_paths.stderr b/src/test/ui/feature-gate-crate_in_paths.stderr
index b13c82e..322a38a 100644
--- a/src/test/ui/feature-gate-crate_in_paths.stderr
+++ b/src/test/ui/feature-gate-crate_in_paths.stderr
@@ -1,4 +1,4 @@
-error: `crate` in paths is experimental (see issue #45477)
+error[E0658]: `crate` in paths is experimental (see issue #45477)
   --> $DIR/feature-gate-crate_in_paths.rs:14:15
    |
 14 |     let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
diff --git a/src/test/ui/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gate-crate_visibility_modifier.stderr
index 0862744..fadc76b 100644
--- a/src/test/ui/feature-gate-crate_visibility_modifier.stderr
+++ b/src/test/ui/feature-gate-crate_visibility_modifier.stderr
@@ -1,4 +1,4 @@
-error: `crate` visibility modifier is experimental (see issue #45388)
+error[E0658]: `crate` visibility modifier is experimental (see issue #45388)
   --> $DIR/feature-gate-crate_visibility_modifier.rs:11:1
    |
 11 | crate struct Bender { //~ ERROR `crate` visibility modifier is experimental
diff --git a/src/test/ui/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gate-custom_attribute.stderr
index 866ebfe..f4d726c 100644
--- a/src/test/ui/feature-gate-custom_attribute.stderr
+++ b/src/test/ui/feature-gate-custom_attribute.stderr
@@ -1,4 +1,4 @@
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:17:1
    |
 17 | #[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:18:1
    |
 18 | #[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:19:1
    |
 19 | #[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:20:1
    |
 20 | #[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
@@ -30,7 +30,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:21:1
    |
 21 | #[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
@@ -38,7 +38,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:22:1
    |
 22 | #[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
@@ -46,7 +46,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:23:1
    |
 23 | #[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
@@ -54,7 +54,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:24:1
    |
 24 | #[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
@@ -62,7 +62,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:25:1
    |
 25 | #[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
@@ -70,7 +70,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:26:1
    |
 26 | #[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
@@ -78,7 +78,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:27:1
    |
 27 | #[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
@@ -86,7 +86,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:28:1
    |
 28 | #[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
@@ -94,7 +94,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute.rs:29:1
    |
 29 | #[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
diff --git a/src/test/ui/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gate-custom_attribute2.stderr
index 3e4ea58..08878e1 100644
--- a/src/test/ui/feature-gate-custom_attribute2.stderr
+++ b/src/test/ui/feature-gate-custom_attribute2.stderr
@@ -1,4 +1,4 @@
-error: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:23:13
    |
 23 | struct StLt<#[lt_struct] 'a>(&'a u32);
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:25:13
    |
 25 | struct StTy<#[ty_struct] I>(I);
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:28:11
    |
 28 | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:30:11
    |
 30 | enum EnTy<#[ty_enum] J> { A(J), B }
@@ -30,7 +30,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:33:12
    |
 33 | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
@@ -38,7 +38,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:35:12
    |
 35 | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
@@ -46,7 +46,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:38:11
    |
 38 | type TyLt<#[lt_type] 'd> = &'d u32;
@@ -54,7 +54,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:40:11
    |
 40 | type TyTy<#[ty_type] L> = (L, );
@@ -62,7 +62,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:43:6
    |
 43 | impl<#[lt_inherent] 'e> StLt<'e> { }
@@ -70,7 +70,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:45:6
    |
 45 | impl<#[ty_inherent] M> StTy<M> { }
@@ -78,7 +78,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:48:6
    |
 48 | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
@@ -86,7 +86,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:52:6
    |
 52 | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
@@ -94,7 +94,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:57:9
    |
 57 | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
@@ -102,7 +102,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:59:9
    |
 59 | fn f_ty<#[ty_fn] O>(_: O) { }
@@ -110,7 +110,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:63:13
    |
 63 |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
@@ -118,7 +118,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:65:13
    |
 65 |     fn m_ty<#[ty_meth] P>(_: P) { }
@@ -126,7 +126,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/feature-gate-custom_attribute2.rs:70:19
    |
 70 |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
diff --git a/src/test/ui/feature-gate-custom_derive.stderr b/src/test/ui/feature-gate-custom_derive.stderr
index e806c80..8606628 100644
--- a/src/test/ui/feature-gate-custom_derive.stderr
+++ b/src/test/ui/feature-gate-custom_derive.stderr
@@ -1,4 +1,4 @@
-error: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
+error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
   --> $DIR/feature-gate-custom_derive.rs:11:1
    |
 11 | #[derive_Clone]
diff --git a/src/test/ui/feature-gate-decl_macro.stderr b/src/test/ui/feature-gate-decl_macro.stderr
index 49ce4eb..c7144f09 100644
--- a/src/test/ui/feature-gate-decl_macro.stderr
+++ b/src/test/ui/feature-gate-decl_macro.stderr
@@ -1,4 +1,4 @@
-error: `macro` is experimental (see issue #39412)
+error[E0658]: `macro` is experimental (see issue #39412)
   --> $DIR/feature-gate-decl_macro.rs:13:1
    |
 13 | macro m() {} //~ ERROR `macro` is experimental (see issue #39412)
diff --git a/src/test/ui/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gate-doc_cfg.stderr
index c2d8a93..e009e0b 100644
--- a/src/test/ui/feature-gate-doc_cfg.stderr
+++ b/src/test/ui/feature-gate-doc_cfg.stderr
@@ -1,4 +1,4 @@
-error: #[doc(cfg(...))] is experimental (see issue #43781)
+error[E0658]: #[doc(cfg(...))] is experimental (see issue #43781)
   --> $DIR/feature-gate-doc_cfg.rs:11:1
    |
 11 | #[doc(cfg(unix))] //~ ERROR: #[doc(cfg(...))] is experimental
diff --git a/src/test/ui/feature-gate-doc_masked.stderr b/src/test/ui/feature-gate-doc_masked.stderr
index 1102076..ee2d384 100644
--- a/src/test/ui/feature-gate-doc_masked.stderr
+++ b/src/test/ui/feature-gate-doc_masked.stderr
@@ -1,4 +1,4 @@
-error: #[doc(masked)] is experimental (see issue #44027)
+error[E0658]: #[doc(masked)] is experimental (see issue #44027)
   --> $DIR/feature-gate-doc_masked.rs:11:1
    |
 11 | #[doc(masked)] //~ ERROR: #[doc(masked)] is experimental
diff --git a/src/test/ui/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gate-doc_spotlight.stderr
index b743a1e..36d8548 100644
--- a/src/test/ui/feature-gate-doc_spotlight.stderr
+++ b/src/test/ui/feature-gate-doc_spotlight.stderr
@@ -1,4 +1,4 @@
-error: #[doc(spotlight)] is experimental (see issue #45040)
+error[E0658]: #[doc(spotlight)] is experimental (see issue #45040)
   --> $DIR/feature-gate-doc_spotlight.rs:11:1
    |
 11 | #[doc(spotlight)] //~ ERROR: #[doc(spotlight)] is experimental
diff --git a/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr b/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr
index 5319dce..2d26c6a 100644
--- a/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr
+++ b/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr
@@ -1,4 +1,4 @@
-error: `..=` syntax in patterns is experimental (see issue #28237)
+error[E0658]: `..=` syntax in patterns is experimental (see issue #28237)
   --> $DIR/feature-gate-dotdoteq_in_patterns.rs:13:9
    |
 13 |         0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental
diff --git a/src/test/ui/feature-gate-dropck-ugeh.stderr b/src/test/ui/feature-gate-dropck-ugeh.stderr
index b030ebc..cdeca70 100644
--- a/src/test/ui/feature-gate-dropck-ugeh.stderr
+++ b/src/test/ui/feature-gate-dropck-ugeh.stderr
@@ -1,4 +1,4 @@
-error: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498)
+error[E0658]: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498)
   --> $DIR/feature-gate-dropck-ugeh.rs:29:5
    |
 29 |     #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
diff --git a/src/test/ui/feature-gate-dyn-trait.stderr b/src/test/ui/feature-gate-dyn-trait.stderr
index 28ecfdf..d6ba4b8 100644
--- a/src/test/ui/feature-gate-dyn-trait.stderr
+++ b/src/test/ui/feature-gate-dyn-trait.stderr
@@ -1,4 +1,4 @@
-error: `dyn Trait` syntax is unstable (see issue #44662)
+error[E0658]: `dyn Trait` syntax is unstable (see issue #44662)
   --> $DIR/feature-gate-dyn-trait.rs:12:14
    |
 12 | type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
diff --git a/src/test/ui/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gate-exclusive-range-pattern.stderr
index c6785d6..3185281 100644
--- a/src/test/ui/feature-gate-exclusive-range-pattern.stderr
+++ b/src/test/ui/feature-gate-exclusive-range-pattern.stderr
@@ -1,4 +1,4 @@
-error: exclusive range pattern syntax is experimental (see issue #37854)
+error[E0658]: exclusive range pattern syntax is experimental (see issue #37854)
   --> $DIR/feature-gate-exclusive-range-pattern.rs:13:9
    |
 13 |         0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
diff --git a/src/test/compile-fail/E0580.rs b/src/test/ui/feature-gate-extern_in_paths.rs
similarity index 69%
copy from src/test/compile-fail/E0580.rs
copy to src/test/ui/feature-gate-extern_in_paths.rs
index a2ef7da..3c01fcf6 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/ui/feature-gate-extern_in_paths.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+struct S;
+
+fn main() {
+    let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
+}
diff --git a/src/test/ui/feature-gate-extern_in_paths.stderr b/src/test/ui/feature-gate-extern_in_paths.stderr
new file mode 100644
index 0000000..022e53b
--- /dev/null
+++ b/src/test/ui/feature-gate-extern_in_paths.stderr
@@ -0,0 +1,10 @@
+error[E0658]: `extern` in paths is experimental (see issue #44660)
+  --> $DIR/feature-gate-extern_in_paths.rs:14:13
+   |
+14 |     let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
+   |             ^^^^^^
+   |
+   = help: add #![feature(extern_in_paths)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate-extern_types.stderr b/src/test/ui/feature-gate-extern_types.stderr
index 3815862..71caa37 100644
--- a/src/test/ui/feature-gate-extern_types.stderr
+++ b/src/test/ui/feature-gate-extern_types.stderr
@@ -1,4 +1,4 @@
-error: extern types are experimental (see issue #43467)
+error[E0658]: extern types are experimental (see issue #43467)
   --> $DIR/feature-gate-extern_types.rs:12:5
    |
 12 |     type T; //~ ERROR extern types are experimental
diff --git a/src/test/ui/feature-gate-external_doc.stderr b/src/test/ui/feature-gate-external_doc.stderr
index 5479ab8..db6c99b 100644
--- a/src/test/ui/feature-gate-external_doc.stderr
+++ b/src/test/ui/feature-gate-external_doc.stderr
@@ -1,4 +1,4 @@
-error: #[doc(include = "...")] is experimental (see issue #44732)
+error[E0658]: #[doc(include = "...")] is experimental (see issue #44732)
   --> $DIR/feature-gate-external_doc.rs:11:1
    |
 11 | #[doc(include="asdf.md")] //~ ERROR: #[doc(include = "...")] is experimental
diff --git a/src/test/ui/feature-gate-fundamental.stderr b/src/test/ui/feature-gate-fundamental.stderr
index 0fc75ee..28d8a80 100644
--- a/src/test/ui/feature-gate-fundamental.stderr
+++ b/src/test/ui/feature-gate-fundamental.stderr
@@ -1,4 +1,4 @@
-error: the `#[fundamental]` attribute is an experimental feature (see issue #29635)
+error[E0658]: the `#[fundamental]` attribute is an experimental feature (see issue #29635)
   --> $DIR/feature-gate-fundamental.rs:11:1
    |
 11 | #[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental feature
diff --git a/src/test/ui/feature-gate-generators.stderr b/src/test/ui/feature-gate-generators.stderr
index 82acb40..f559227 100644
--- a/src/test/ui/feature-gate-generators.stderr
+++ b/src/test/ui/feature-gate-generators.stderr
@@ -1,4 +1,4 @@
-error: yield syntax is experimental
+error[E0658]: yield syntax is experimental
   --> $DIR/feature-gate-generators.rs:12:5
    |
 12 |     yield true; //~ ERROR yield syntax is experimental
diff --git a/src/test/ui/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gate-generic_associated_types.stderr
index 7b2507e..c047914 100644
--- a/src/test/ui/feature-gate-generic_associated_types.stderr
+++ b/src/test/ui/feature-gate-generic_associated_types.stderr
@@ -1,4 +1,4 @@
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
   --> $DIR/feature-gate-generic_associated_types.rs:14:5
    |
 14 |     type Pointer<T>: Deref<Target = T>;
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
   --> $DIR/feature-gate-generic_associated_types.rs:16:5
    |
 16 |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
   --> $DIR/feature-gate-generic_associated_types.rs:22:5
    |
 22 |     type Pointer<usize> = Box<usize>;
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable (see issue #44265)
   --> $DIR/feature-gate-generic_associated_types.rs:24:5
    |
 24 |     type Pointer2<u32> = Box<u32>;
diff --git a/src/test/ui/feature-gate-generic_param_attrs.stderr b/src/test/ui/feature-gate-generic_param_attrs.stderr
index da2e640..a18d104 100644
--- a/src/test/ui/feature-gate-generic_param_attrs.stderr
+++ b/src/test/ui/feature-gate-generic_param_attrs.stderr
@@ -1,4 +1,4 @@
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:22:13
    |
 22 | struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:24:13
    |
 24 | struct StTy<#[rustc_ty_struct] I>(I);
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:27:11
    |
 27 | enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:29:11
    |
 29 | enum EnTy<#[rustc_ty_enum] J> { A(J), B }
@@ -30,7 +30,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:32:12
    |
 32 | trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
@@ -38,7 +38,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:34:12
    |
 34 | trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
@@ -46,7 +46,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:37:11
    |
 37 | type TyLt<#[rustc_lt_type] 'd> = &'d u32;
@@ -54,7 +54,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:39:11
    |
 39 | type TyTy<#[rustc_ty_type] L> = (L, );
@@ -62,7 +62,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:42:6
    |
 42 | impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
@@ -70,7 +70,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:44:6
    |
 44 | impl<#[rustc_ty_inherent] M> StTy<M> { }
@@ -78,7 +78,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:47:6
    |
 47 | impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
@@ -86,7 +86,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:51:6
    |
 51 | impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
@@ -94,7 +94,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:56:9
    |
 56 | fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
@@ -102,7 +102,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:58:9
    |
 58 | fn f_ty<#[rustc_ty_fn] O>(_: O) { }
@@ -110,7 +110,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:62:13
    |
 62 |     fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
@@ -118,7 +118,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on type parameter bindings are experimental (see issue #34761)
+error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:64:13
    |
 64 |     fn m_ty<#[rustc_ty_meth] P>(_: P) { }
@@ -126,7 +126,7 @@
    |
    = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
 
-error: attributes on lifetime bindings are experimental (see issue #34761)
+error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
   --> $DIR/feature-gate-generic_param_attrs.rs:69:19
    |
 69 |     where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
diff --git a/src/test/ui/feature-gate-global_allocator.stderr b/src/test/ui/feature-gate-global_allocator.stderr
index 7e6c428..8d82f6e 100644
--- a/src/test/ui/feature-gate-global_allocator.stderr
+++ b/src/test/ui/feature-gate-global_allocator.stderr
@@ -1,4 +1,4 @@
-error: the `#[global_allocator]` attribute is an experimental feature
+error[E0658]: the `#[global_allocator]` attribute is an experimental feature
   --> $DIR/feature-gate-global_allocator.rs:11:1
    |
 11 | #[global_allocator] //~ ERROR: attribute is an experimental feature
diff --git a/src/test/ui/feature-gate-global_asm.stderr b/src/test/ui/feature-gate-global_asm.stderr
index de0ba1a..ca94657 100644
--- a/src/test/ui/feature-gate-global_asm.stderr
+++ b/src/test/ui/feature-gate-global_asm.stderr
@@ -1,4 +1,4 @@
-error: `global_asm!` is not stable enough for use and is subject to change (see issue #35119)
+error[E0658]: `global_asm!` is not stable enough for use and is subject to change (see issue #35119)
   --> $DIR/feature-gate-global_asm.rs:11:1
    |
 11 | global_asm!(""); //~ ERROR `global_asm!` is not stable
diff --git a/src/test/ui/feature-gate-i128_type.stderr b/src/test/ui/feature-gate-i128_type.stderr
index df623ca..06fdead 100644
--- a/src/test/ui/feature-gate-i128_type.stderr
+++ b/src/test/ui/feature-gate-i128_type.stderr
@@ -1,4 +1,4 @@
-error: 128-bit integers are not stable (see issue #35118)
+error[E0658]: 128-bit integers are not stable (see issue #35118)
   --> $DIR/feature-gate-i128_type.rs:12:5
    |
 12 |     0i128; //~ ERROR 128-bit integers are not stable
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(i128_type)] to the crate attributes to enable
 
-error: 128-bit integers are not stable (see issue #35118)
+error[E0658]: 128-bit integers are not stable (see issue #35118)
   --> $DIR/feature-gate-i128_type.rs:16:5
    |
 16 |     0u128; //~ ERROR 128-bit integers are not stable
diff --git a/src/test/ui/feature-gate-i128_type2.stderr b/src/test/ui/feature-gate-i128_type2.stderr
index 26653a57..ee81a26 100644
--- a/src/test/ui/feature-gate-i128_type2.stderr
+++ b/src/test/ui/feature-gate-i128_type2.stderr
@@ -1,4 +1,4 @@
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
   --> $DIR/feature-gate-i128_type2.rs:13:15
    |
 13 | fn test1() -> i128 { //~ ERROR 128-bit type is unstable
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(i128_type)] to the crate attributes to enable
 
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
   --> $DIR/feature-gate-i128_type2.rs:17:17
    |
 17 | fn test1_2() -> u128 { //~ ERROR 128-bit type is unstable
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(i128_type)] to the crate attributes to enable
 
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
   --> $DIR/feature-gate-i128_type2.rs:22:12
    |
 22 |     let x: i128 = 0; //~ ERROR 128-bit type is unstable
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(i128_type)] to the crate attributes to enable
 
-error: 128-bit type is unstable (see issue #35118)
+error[E0658]: 128-bit type is unstable (see issue #35118)
   --> $DIR/feature-gate-i128_type2.rs:26:12
    |
 26 |     let x: u128 = 0; //~ ERROR 128-bit type is unstable
@@ -32,7 +32,7 @@
 
 error[E0601]: main function not found
 
-error: repr with 128-bit type is unstable (see issue #35118)
+error[E0658]: repr with 128-bit type is unstable (see issue #35118)
   --> $DIR/feature-gate-i128_type2.rs:30:1
    |
 30 | / enum A { //~ ERROR 128-bit type is unstable
diff --git a/src/test/ui/feature-gate-intrinsics.stderr b/src/test/ui/feature-gate-intrinsics.stderr
index 5382122..918c749 100644
--- a/src/test/ui/feature-gate-intrinsics.stderr
+++ b/src/test/ui/feature-gate-intrinsics.stderr
@@ -1,4 +1,4 @@
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-intrinsics.rs:11:1
    |
 11 | / extern "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
@@ -8,7 +8,7 @@
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error: intrinsics are subject to change
+error[E0658]: intrinsics are subject to change
   --> $DIR/feature-gate-intrinsics.rs:15:1
    |
 15 | / extern "rust-intrinsic" fn baz() {  //~ ERROR intrinsics are subject to change
diff --git a/src/test/ui/feature-gate-lang-items.stderr b/src/test/ui/feature-gate-lang-items.stderr
index dab8ce2..28e3dab 100644
--- a/src/test/ui/feature-gate-lang-items.stderr
+++ b/src/test/ui/feature-gate-lang-items.stderr
@@ -1,4 +1,4 @@
-error: language items are subject to change
+error[E0658]: language items are subject to change
   --> $DIR/feature-gate-lang-items.rs:11:1
    |
 11 | #[lang="foo"]   //~ ERROR language items are subject to change
diff --git a/src/test/ui/feature-gate-link_args.stderr b/src/test/ui/feature-gate-link_args.stderr
index d6d05900..78070d5 100644
--- a/src/test/ui/feature-gate-link_args.stderr
+++ b/src/test/ui/feature-gate-link_args.stderr
@@ -1,4 +1,4 @@
-error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
   --> $DIR/feature-gate-link_args.rs:22:1
    |
 22 | #[link_args = "-l expected_use_case"]
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(link_args)] to the crate attributes to enable
 
-error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
   --> $DIR/feature-gate-link_args.rs:26:1
    |
 26 | #[link_args = "-l unexected_use_on_non_extern_item"]
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(link_args)] to the crate attributes to enable
 
-error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
   --> $DIR/feature-gate-link_args.rs:19:1
    |
 19 | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
diff --git a/src/test/ui/feature-gate-link_cfg.stderr b/src/test/ui/feature-gate-link_cfg.stderr
index bbc52bd..8aada72 100644
--- a/src/test/ui/feature-gate-link_cfg.stderr
+++ b/src/test/ui/feature-gate-link_cfg.stderr
@@ -1,4 +1,4 @@
-error: is feature gated (see issue #37406)
+error[E0658]: is feature gated (see issue #37406)
   --> $DIR/feature-gate-link_cfg.rs:11:1
    |
 11 | #[link(name = "foo", cfg(foo))]
diff --git a/src/test/ui/feature-gate-link_llvm_intrinsics.stderr b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr
index b2e2caa..136658f 100644
--- a/src/test/ui/feature-gate-link_llvm_intrinsics.stderr
+++ b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr
@@ -1,4 +1,4 @@
-error: linking to LLVM intrinsics is experimental (see issue #29602)
+error[E0658]: linking to LLVM intrinsics is experimental (see issue #29602)
   --> $DIR/feature-gate-link_llvm_intrinsics.rs:13:5
    |
 13 |     fn sqrt(x: f32) -> f32;
diff --git a/src/test/ui/feature-gate-linkage.stderr b/src/test/ui/feature-gate-linkage.stderr
index 62d857d..54764b1 100644
--- a/src/test/ui/feature-gate-linkage.stderr
+++ b/src/test/ui/feature-gate-linkage.stderr
@@ -1,4 +1,4 @@
-error: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
+error[E0658]: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
   --> $DIR/feature-gate-linkage.rs:12:5
    |
 12 |     #[linkage = "extern_weak"] static foo: isize;
diff --git a/src/test/ui/feature-gate-linker-flavor.stderr b/src/test/ui/feature-gate-linker-flavor.stderr
index 383e75e..e58693d 100644
--- a/src/test/ui/feature-gate-linker-flavor.stderr
+++ b/src/test/ui/feature-gate-linker-flavor.stderr
@@ -1,4 +1,4 @@
-error: the `#[used]` attribute is an experimental feature (see issue #40289)
+error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
   --> $DIR/feature-gate-linker-flavor.rs:16:1
    |
 16 | #[used]
diff --git a/src/test/ui/feature-gate-log_syntax.stderr b/src/test/ui/feature-gate-log_syntax.stderr
index f1c0d30..363b175 100644
--- a/src/test/ui/feature-gate-log_syntax.stderr
+++ b/src/test/ui/feature-gate-log_syntax.stderr
@@ -1,4 +1,4 @@
-error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
   --> $DIR/feature-gate-log_syntax.rs:12:5
    |
 12 |     log_syntax!() //~ ERROR `log_syntax!` is not stable enough
diff --git a/src/test/ui/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gate-log_syntax2.stderr
index b1bb555..f47a507 100644
--- a/src/test/ui/feature-gate-log_syntax2.stderr
+++ b/src/test/ui/feature-gate-log_syntax2.stderr
@@ -1,4 +1,4 @@
-error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
   --> $DIR/feature-gate-log_syntax2.rs:14:20
    |
 14 |     println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/ui/feature-gate-macro-lifetime-matcher.rs
similarity index 63%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/ui/feature-gate-macro-lifetime-matcher.rs
index 5c32a75..0d107d2 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/ui/feature-gate-macro-lifetime-matcher.rs
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+// Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher
+// feature gate is not used.
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+macro_rules! m { ($lt:lifetime) => {} }
+//~^ ERROR :lifetime fragment specifier is experimental and subject to change
+
+fn main() {
+    m!('a);
+}
diff --git a/src/test/ui/feature-gate-macro-lifetime-matcher.stderr b/src/test/ui/feature-gate-macro-lifetime-matcher.stderr
new file mode 100644
index 0000000..553a7d3
--- /dev/null
+++ b/src/test/ui/feature-gate-macro-lifetime-matcher.stderr
@@ -0,0 +1,10 @@
+error[E0658]: :lifetime fragment specifier is experimental and subject to change (see issue #46895)
+  --> $DIR/feature-gate-macro-lifetime-matcher.rs:14:19
+   |
+14 | macro_rules! m { ($lt:lifetime) => {} }
+   |                   ^^^^^^^^^^^^
+   |
+   = help: add #![feature(macro_lifetime_matcher)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate-macro-vis-matcher.stderr b/src/test/ui/feature-gate-macro-vis-matcher.stderr
index 09db500..ee1844c 100644
--- a/src/test/ui/feature-gate-macro-vis-matcher.stderr
+++ b/src/test/ui/feature-gate-macro-vis-matcher.stderr
@@ -1,4 +1,4 @@
-error: :vis fragment specifier is experimental and subject to change (see issue #41022)
+error[E0658]: :vis fragment specifier is experimental and subject to change (see issue #41022)
   --> $DIR/feature-gate-macro-vis-matcher.rs:14:19
    |
 14 | macro_rules! m { ($v:vis) => {} }
diff --git a/src/test/ui/feature-gate-main.stderr b/src/test/ui/feature-gate-main.stderr
index 90cf128..56e9c8b 100644
--- a/src/test/ui/feature-gate-main.stderr
+++ b/src/test/ui/feature-gate-main.stderr
@@ -1,4 +1,4 @@
-error: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634)
+error[E0658]: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634)
   --> $DIR/feature-gate-main.rs:12:1
    |
 12 | fn foo() {} //~ ERROR: declaration of a nonstandard #[main] function may change over time
diff --git a/src/test/ui/feature-gate-match_beginning_vert.stderr b/src/test/ui/feature-gate-match_beginning_vert.stderr
index 88053ad..1d45ded 100644
--- a/src/test/ui/feature-gate-match_beginning_vert.stderr
+++ b/src/test/ui/feature-gate-match_beginning_vert.stderr
@@ -1,4 +1,4 @@
-error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
   --> $DIR/feature-gate-match_beginning_vert.rs:24:9
    |
 24 |         | A => println!("A"),
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
 
-error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
   --> $DIR/feature-gate-match_beginning_vert.rs:26:9
    |
 26 |         | B | C => println!("BC!"),
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
 
-error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
   --> $DIR/feature-gate-match_beginning_vert.rs:28:9
    |
 28 |         | _ => {},
diff --git a/src/test/ui/feature-gate-match_default_bindings.stderr b/src/test/ui/feature-gate-match_default_bindings.stderr
index d86e824..1bedfb7 100644
--- a/src/test/ui/feature-gate-match_default_bindings.stderr
+++ b/src/test/ui/feature-gate-match_default_bindings.stderr
@@ -1,4 +1,4 @@
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
   --> $DIR/feature-gate-match_default_bindings.rs:13:9
    |
 13 |         Some(n) => {},
diff --git a/src/test/ui/feature-gate-may-dangle.stderr b/src/test/ui/feature-gate-may-dangle.stderr
index e51723d..a3a3f7b 100644
--- a/src/test/ui/feature-gate-may-dangle.stderr
+++ b/src/test/ui/feature-gate-may-dangle.stderr
@@ -1,4 +1,4 @@
-error: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
+error[E0658]: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
   --> $DIR/feature-gate-may-dangle.rs:18:6
    |
 18 | impl<#[may_dangle] A> Drop for Pt<A> {
diff --git a/src/test/ui/feature-gate-naked_functions.stderr b/src/test/ui/feature-gate-naked_functions.stderr
index 9655982..5f72234 100644
--- a/src/test/ui/feature-gate-naked_functions.stderr
+++ b/src/test/ui/feature-gate-naked_functions.stderr
@@ -1,4 +1,4 @@
-error: the `#[naked]` attribute is an experimental feature (see issue #32408)
+error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
   --> $DIR/feature-gate-naked_functions.rs:11:1
    |
 11 | #[naked]
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(naked_functions)] to the crate attributes to enable
 
-error: the `#[naked]` attribute is an experimental feature (see issue #32408)
+error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
   --> $DIR/feature-gate-naked_functions.rs:15:1
    |
 15 | #[naked]
diff --git a/src/test/ui/feature-gate-needs-allocator.stderr b/src/test/ui/feature-gate-needs-allocator.stderr
index 5124c10..11b8c31 100644
--- a/src/test/ui/feature-gate-needs-allocator.stderr
+++ b/src/test/ui/feature-gate-needs-allocator.stderr
@@ -1,4 +1,4 @@
-error: the `#[needs_allocator]` attribute is an experimental feature
+error[E0658]: the `#[needs_allocator]` attribute is an experimental feature
   --> $DIR/feature-gate-needs-allocator.rs:11:1
    |
 11 | #![needs_allocator] //~ ERROR the `#[needs_allocator]` attribute is
diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr
index c242e61..2fd04f5 100644
--- a/src/test/ui/feature-gate-never_type.stderr
+++ b/src/test/ui/feature-gate-never_type.stderr
@@ -1,4 +1,4 @@
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
   --> $DIR/feature-gate-never_type.rs:17:17
    |
 17 | type Ma = (u32, !, i32); //~ ERROR type is experimental
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
   --> $DIR/feature-gate-never_type.rs:18:20
    |
 18 | type Meeshka = Vec<!>; //~ ERROR type is experimental
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
   --> $DIR/feature-gate-never_type.rs:19:16
    |
 19 | type Mow = &fn(!) -> !; //~ ERROR type is experimental
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
   --> $DIR/feature-gate-never_type.rs:20:19
    |
 20 | type Skwoz = &mut !; //~ ERROR type is experimental
@@ -30,7 +30,7 @@
    |
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental (see issue #35121)
   --> $DIR/feature-gate-never_type.rs:23:16
    |
 23 |     type Wub = !; //~ ERROR type is experimental
diff --git a/src/test/ui/feature-gate-no-debug.stderr b/src/test/ui/feature-gate-no-debug.stderr
index 83a8189..c7af8cf 100644
--- a/src/test/ui/feature-gate-no-debug.stderr
+++ b/src/test/ui/feature-gate-no-debug.stderr
@@ -1,4 +1,4 @@
-error: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721)
+error[E0658]: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721)
   --> $DIR/feature-gate-no-debug.rs:13:1
    |
 13 | #[no_debug] //~ ERROR the `#[no_debug]` attribute was
diff --git a/src/test/ui/feature-gate-no_core.stderr b/src/test/ui/feature-gate-no_core.stderr
index 02e0b17..7fc8985 100644
--- a/src/test/ui/feature-gate-no_core.stderr
+++ b/src/test/ui/feature-gate-no_core.stderr
@@ -1,4 +1,4 @@
-error: no_core is experimental (see issue #29639)
+error[E0658]: no_core is experimental (see issue #29639)
   --> $DIR/feature-gate-no_core.rs:11:1
    |
 11 | #![no_core] //~ ERROR no_core is experimental
diff --git a/src/test/ui/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gate-non_ascii_idents.stderr
index df6ce6b..deb7077 100644
--- a/src/test/ui/feature-gate-non_ascii_idents.stderr
+++ b/src/test/ui/feature-gate-non_ascii_idents.stderr
@@ -1,4 +1,4 @@
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:11:1
    |
 11 | extern crate core as bäz; //~ ERROR non-ascii idents
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:13:5
    |
 13 | use föö::bar; //~ ERROR non-ascii idents
@@ -14,17 +14,15 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:15:1
    |
-15 | / mod föö { //~ ERROR non-ascii idents
-16 | |     pub fn bar() {}
-17 | | }
-   | |_^
+15 | mod föö { //~ ERROR non-ascii idents
+   | ^^^^^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:19:1
    |
 19 | / fn bär( //~ ERROR non-ascii idents
@@ -38,7 +36,7 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:20:5
    |
 20 |     bäz: isize //~ ERROR non-ascii idents
@@ -46,7 +44,7 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:22:9
    |
 22 |     let _ö: isize; //~ ERROR non-ascii idents
@@ -54,7 +52,7 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:25:10
    |
 25 |         (_ä, _) => {} //~ ERROR non-ascii idents
@@ -62,17 +60,15 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:29:1
    |
-29 | / struct Föö { //~ ERROR non-ascii idents
-30 | |     föö: isize //~ ERROR non-ascii idents
-31 | | }
-   | |_^
+29 | struct Föö { //~ ERROR non-ascii idents
+   | ^^^^^^^^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:30:5
    |
 30 |     föö: isize //~ ERROR non-ascii idents
@@ -80,29 +76,23 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:33:1
    |
-33 | / enum Bär { //~ ERROR non-ascii idents
-34 | |     Bäz { //~ ERROR non-ascii idents
-35 | |         qüx: isize //~ ERROR non-ascii idents
-36 | |     }
-37 | | }
-   | |_^
+33 | enum Bär { //~ ERROR non-ascii idents
+   | ^^^^^^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:34:5
    |
-34 | /     Bäz { //~ ERROR non-ascii idents
-35 | |         qüx: isize //~ ERROR non-ascii idents
-36 | |     }
-   | |_____^
+34 |     Bäz { //~ ERROR non-ascii idents
+   |     ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:35:9
    |
 35 |         qüx: isize //~ ERROR non-ascii idents
@@ -110,7 +100,7 @@
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error: non-ascii idents are not fully supported. (see issue #28979)
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:40:5
    |
 40 |     fn qüx();  //~ ERROR non-ascii idents
diff --git a/src/test/ui/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gate-non_exhaustive.stderr
index 775e65b..320f40e 100644
--- a/src/test/ui/feature-gate-non_exhaustive.stderr
+++ b/src/test/ui/feature-gate-non_exhaustive.stderr
@@ -1,4 +1,4 @@
-error: non exhaustive is an experimental feature (see issue #44109)
+error[E0658]: non exhaustive is an experimental feature (see issue #44109)
   --> $DIR/feature-gate-non_exhaustive.rs:13:1
    |
 13 | #[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109)
diff --git a/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr
index e50e1b4..4ceb697 100644
--- a/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr
+++ b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr
@@ -1,4 +1,4 @@
-error: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite
+error[E0658]: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite
   --> $DIR/feature-gate-omit-gdb-pretty-printer-section.rs:11:1
    |
 11 | #[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer_section]` attribute is
diff --git a/src/test/ui/feature-gate-on-unimplemented.stderr b/src/test/ui/feature-gate-on-unimplemented.stderr
index 06944a14..b1658c3 100644
--- a/src/test/ui/feature-gate-on-unimplemented.stderr
+++ b/src/test/ui/feature-gate-on-unimplemented.stderr
@@ -1,4 +1,4 @@
-error: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628)
+error[E0658]: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628)
   --> $DIR/feature-gate-on-unimplemented.rs:14:1
    |
 14 | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
diff --git a/src/test/ui/feature-gate-optin-builtin-traits.rs b/src/test/ui/feature-gate-optin-builtin-traits.rs
index 4c5502c..ab3313a 100644
--- a/src/test/ui/feature-gate-optin-builtin-traits.rs
+++ b/src/test/ui/feature-gate-optin-builtin-traits.rs
@@ -20,10 +20,6 @@
 auto trait AutoDummyTrait {}
 //~^ ERROR auto traits are experimental and possibly buggy
 
-#[allow(auto_impl)]
-impl DummyTrait for .. {}
-//~^ ERROR auto trait implementations are experimental and possibly buggy
-
 impl !DummyTrait for DummyStruct {}
 //~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
 
diff --git a/src/test/ui/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gate-optin-builtin-traits.stderr
index c5e9614..beb734a 100644
--- a/src/test/ui/feature-gate-optin-builtin-traits.stderr
+++ b/src/test/ui/feature-gate-optin-builtin-traits.stderr
@@ -1,4 +1,4 @@
-error: auto traits are experimental and possibly buggy (see issue #13231)
+error[E0658]: auto traits are experimental and possibly buggy (see issue #13231)
   --> $DIR/feature-gate-optin-builtin-traits.rs:20:1
    |
 20 | auto trait AutoDummyTrait {}
@@ -6,21 +6,13 @@
    |
    = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
 
-error: auto trait implementations are experimental and possibly buggy (see issue #13231)
-  --> $DIR/feature-gate-optin-builtin-traits.rs:24:1
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
+  --> $DIR/feature-gate-optin-builtin-traits.rs:23:1
    |
-24 | impl DummyTrait for .. {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
-
-error: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
-  --> $DIR/feature-gate-optin-builtin-traits.rs:27:1
-   |
-27 | impl !DummyTrait for DummyStruct {}
+23 | impl !DummyTrait for DummyStruct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gate-placement-expr.stderr b/src/test/ui/feature-gate-placement-expr.stderr
index fdb7b50..c588cab 100644
--- a/src/test/ui/feature-gate-placement-expr.stderr
+++ b/src/test/ui/feature-gate-placement-expr.stderr
@@ -1,4 +1,4 @@
-error: placement-in expression syntax is experimental and subject to change. (see issue #27779)
+error[E0658]: placement-in expression syntax is experimental and subject to change. (see issue #27779)
   --> $DIR/feature-gate-placement-expr.rs:24:13
    |
 24 |     let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental
diff --git a/src/test/ui/feature-gate-plugin.stderr b/src/test/ui/feature-gate-plugin.stderr
index b94d329..b54b2d8 100644
--- a/src/test/ui/feature-gate-plugin.stderr
+++ b/src/test/ui/feature-gate-plugin.stderr
@@ -1,4 +1,4 @@
-error: compiler plugins are experimental and possibly buggy (see issue #29597)
+error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
   --> $DIR/feature-gate-plugin.rs:13:1
    |
 13 | #![plugin(foo)]
diff --git a/src/test/ui/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gate-plugin_registrar.stderr
index 3710239..fb5bd9d 100644
--- a/src/test/ui/feature-gate-plugin_registrar.stderr
+++ b/src/test/ui/feature-gate-plugin_registrar.stderr
@@ -1,4 +1,4 @@
-error: compiler plugins are experimental and possibly buggy (see issue #29597)
+error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
   --> $DIR/feature-gate-plugin_registrar.rs:16:1
    |
 16 | pub fn registrar() {}
diff --git a/src/test/ui/feature-gate-prelude_import.stderr b/src/test/ui/feature-gate-prelude_import.stderr
index df44dff..5487ae2 100644
--- a/src/test/ui/feature-gate-prelude_import.stderr
+++ b/src/test/ui/feature-gate-prelude_import.stderr
@@ -1,4 +1,4 @@
-error: `#[prelude_import]` is for use by rustc only
+error[E0658]: `#[prelude_import]` is for use by rustc only
   --> $DIR/feature-gate-prelude_import.rs:11:1
    |
 11 | #[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only
diff --git a/src/test/ui/feature-gate-profiler-runtime.stderr b/src/test/ui/feature-gate-profiler-runtime.stderr
index c316543..f2893cb 100644
--- a/src/test/ui/feature-gate-profiler-runtime.stderr
+++ b/src/test/ui/feature-gate-profiler-runtime.stderr
@@ -1,4 +1,4 @@
-error: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable
+error[E0658]: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable
   --> $DIR/feature-gate-profiler-runtime.rs:11:1
    |
 11 | #![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is
diff --git a/src/test/ui/feature-gate-repr-simd.stderr b/src/test/ui/feature-gate-repr-simd.stderr
index a2ff06d..e430a04 100644
--- a/src/test/ui/feature-gate-repr-simd.stderr
+++ b/src/test/ui/feature-gate-repr-simd.stderr
@@ -1,4 +1,4 @@
-error: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-repr-simd.rs:11:1
    |
 11 | #[repr(simd)] //~ error: SIMD types are experimental
diff --git a/src/test/ui/feature-gate-repr128.stderr b/src/test/ui/feature-gate-repr128.stderr
index c5996488..982ebb0 100644
--- a/src/test/ui/feature-gate-repr128.stderr
+++ b/src/test/ui/feature-gate-repr128.stderr
@@ -1,4 +1,4 @@
-error: repr with 128-bit type is unstable (see issue #35118)
+error[E0658]: repr with 128-bit type is unstable (see issue #35118)
   --> $DIR/feature-gate-repr128.rs:12:1
    |
 12 | / enum A { //~ ERROR repr with 128-bit type is unstable
diff --git a/src/test/ui/feature-gate-repr_align.stderr b/src/test/ui/feature-gate-repr_align.stderr
index 16fdc13..dd88067 100644
--- a/src/test/ui/feature-gate-repr_align.stderr
+++ b/src/test/ui/feature-gate-repr_align.stderr
@@ -1,4 +1,4 @@
-error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
+error[E0658]: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
   --> $DIR/feature-gate-repr_align.rs:12:1
    |
 12 | #[repr(align(64))] //~ error: the struct `#[repr(align(u16))]` attribute is experimental
diff --git a/src/test/ui/typeck-default-trait-impl-outside-crate.rs b/src/test/ui/feature-gate-repr_transparent.rs
similarity index 71%
copy from src/test/ui/typeck-default-trait-impl-outside-crate.rs
copy to src/test/ui/feature-gate-repr_transparent.rs
index ff0446e..deadf2e 100644
--- a/src/test/ui/typeck-default-trait-impl-outside-crate.rs
+++ b/src/test/ui/feature-gate-repr_transparent.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#[repr(transparent)] //~ error: the `#[repr(transparent)]` attribute is experimental
+struct Foo(u64);
 
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
 fn main() {}
diff --git a/src/test/ui/feature-gate-repr_transparent.stderr b/src/test/ui/feature-gate-repr_transparent.stderr
new file mode 100644
index 0000000..d1292e9
--- /dev/null
+++ b/src/test/ui/feature-gate-repr_transparent.stderr
@@ -0,0 +1,10 @@
+error[E0658]: the `#[repr(transparent)]` attribute is experimental (see issue #43036)
+  --> $DIR/feature-gate-repr_transparent.rs:11:1
+   |
+11 | #[repr(transparent)] //~ error: the `#[repr(transparent)]` attribute is experimental
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_transparent)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gate-rustc-attrs.stderr
index c818b57..f47588c 100644
--- a/src/test/ui/feature-gate-rustc-attrs.stderr
+++ b/src/test/ui/feature-gate-rustc-attrs.stderr
@@ -1,4 +1,4 @@
-error: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
   --> $DIR/feature-gate-rustc-attrs.rs:15:1
    |
 15 | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
-error: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
   --> $DIR/feature-gate-rustc-attrs.rs:16:1
    |
 16 | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
-error: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
   --> $DIR/feature-gate-rustc-attrs.rs:17:1
    |
 17 | #[rustc_foo]
diff --git a/src/test/ui/feature-gate-rustc_const_unstable.stderr b/src/test/ui/feature-gate-rustc_const_unstable.stderr
index c32abb8..922898b 100644
--- a/src/test/ui/feature-gate-rustc_const_unstable.stderr
+++ b/src/test/ui/feature-gate-rustc_const_unstable.stderr
@@ -1,4 +1,4 @@
-error: the `#[rustc_const_unstable]` attribute is an internal feature
+error[E0658]: the `#[rustc_const_unstable]` attribute is an internal feature
   --> $DIR/feature-gate-rustc_const_unstable.rs:18:1
    |
 18 | #[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature
diff --git a/src/test/ui/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gate-sanitizer-runtime.stderr
index b9a43f8..6d77161 100644
--- a/src/test/ui/feature-gate-sanitizer-runtime.stderr
+++ b/src/test/ui/feature-gate-sanitizer-runtime.stderr
@@ -1,4 +1,4 @@
-error: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
+error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
   --> $DIR/feature-gate-sanitizer-runtime.rs:11:1
    |
 11 | #![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
diff --git a/src/test/ui/feature-gate-simd-ffi.rs b/src/test/ui/feature-gate-simd-ffi.rs
index 31c055f..a603658 100644
--- a/src/test/ui/feature-gate-simd-ffi.rs
+++ b/src/test/ui/feature-gate-simd-ffi.rs
@@ -13,7 +13,6 @@
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
-#[repr(C)]
 struct LocalSimd(u8, u8);
 
 extern {
diff --git a/src/test/ui/feature-gate-simd-ffi.stderr b/src/test/ui/feature-gate-simd-ffi.stderr
index fa47e1a..ab1ebef 100644
--- a/src/test/ui/feature-gate-simd-ffi.stderr
+++ b/src/test/ui/feature-gate-simd-ffi.stderr
@@ -1,15 +1,15 @@
 error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code
-  --> $DIR/feature-gate-simd-ffi.rs:20:17
+  --> $DIR/feature-gate-simd-ffi.rs:19:17
    |
-20 |     fn baz() -> LocalSimd; //~ ERROR use of SIMD type
+19 |     fn baz() -> LocalSimd; //~ ERROR use of SIMD type
    |                 ^^^^^^^^^
    |
    = help: add #![feature(simd_ffi)] to the crate attributes to enable
 
 error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code
-  --> $DIR/feature-gate-simd-ffi.rs:21:15
+  --> $DIR/feature-gate-simd-ffi.rs:20:15
    |
-21 |     fn qux(x: LocalSimd); //~ ERROR use of SIMD type
+20 |     fn qux(x: LocalSimd); //~ ERROR use of SIMD type
    |               ^^^^^^^^^
    |
    = help: add #![feature(simd_ffi)] to the crate attributes to enable
diff --git a/src/test/ui/feature-gate-simd.stderr b/src/test/ui/feature-gate-simd.stderr
index b3225d5..447706a 100644
--- a/src/test/ui/feature-gate-simd.stderr
+++ b/src/test/ui/feature-gate-simd.stderr
@@ -1,4 +1,4 @@
-error: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
   --> $DIR/feature-gate-simd.rs:14:1
    |
 14 | #[repr(simd)] //~ ERROR SIMD types are experimental
diff --git a/src/test/ui/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gate-slice-patterns.stderr
index e5ba318b..7a2e67c 100644
--- a/src/test/ui/feature-gate-slice-patterns.stderr
+++ b/src/test/ui/feature-gate-slice-patterns.stderr
@@ -1,4 +1,4 @@
-error: slice pattern syntax is experimental (see issue #23121)
+error[E0658]: slice pattern syntax is experimental (see issue #23121)
   --> $DIR/feature-gate-slice-patterns.rs:16:9
    |
 16 |         [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
diff --git a/src/test/ui/feature-gate-start.stderr b/src/test/ui/feature-gate-start.stderr
index b36fae2..61cbe42 100644
--- a/src/test/ui/feature-gate-start.stderr
+++ b/src/test/ui/feature-gate-start.stderr
@@ -1,4 +1,4 @@
-error: a #[start] function is an experimental feature whose signature may change over time (see issue #29633)
+error[E0658]: a #[start] function is an experimental feature whose signature may change over time (see issue #29633)
   --> $DIR/feature-gate-start.rs:12:1
    |
 12 | fn foo() {} //~ ERROR: a #[start] function is an experimental feature
diff --git a/src/test/ui/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gate-static-nobundle.stderr
index 052516f..9ec4f64 100644
--- a/src/test/ui/feature-gate-static-nobundle.stderr
+++ b/src/test/ui/feature-gate-static-nobundle.stderr
@@ -1,4 +1,4 @@
-error: kind="static-nobundle" is feature gated (see issue #37403)
+error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
   --> $DIR/feature-gate-static-nobundle.rs:11:1
    |
 11 | #[link(name="foo", kind="static-nobundle")]
diff --git a/src/test/ui/feature-gate-stmt_expr_attributes.stderr b/src/test/ui/feature-gate-stmt_expr_attributes.stderr
index 8091059..4d2e2f6 100644
--- a/src/test/ui/feature-gate-stmt_expr_attributes.stderr
+++ b/src/test/ui/feature-gate-stmt_expr_attributes.stderr
@@ -1,4 +1,4 @@
-error: attributes on non-item statements and expressions are experimental. (see issue #15701)
+error[E0658]: attributes on non-item statements and expressions are experimental. (see issue #15701)
   --> $DIR/feature-gate-stmt_expr_attributes.rs:11:16
    |
 11 | const X: i32 = #[allow(dead_code)] 8;
diff --git a/src/test/ui/feature-gate-target_feature.stderr b/src/test/ui/feature-gate-target_feature.stderr
index 8c89eab..b6ad1b6 100644
--- a/src/test/ui/feature-gate-target_feature.stderr
+++ b/src/test/ui/feature-gate-target_feature.stderr
@@ -1,4 +1,4 @@
-error: the `#[target_feature]` attribute is an experimental feature
+error[E0658]: the `#[target_feature]` attribute is an experimental feature
   --> $DIR/feature-gate-target_feature.rs:11:1
    |
 11 | #[target_feature = "+sse2"]
diff --git a/src/test/ui/feature-gate-thread_local.stderr b/src/test/ui/feature-gate-thread_local.stderr
index 2608018..0f932ab 100644
--- a/src/test/ui/feature-gate-thread_local.stderr
+++ b/src/test/ui/feature-gate-thread_local.stderr
@@ -1,4 +1,4 @@
-error: `#[thread_local]` is an experimental feature, and does not currently handle destructors. There is no corresponding `#[task_local]` mapping to the task model (see issue #29594)
+error[E0658]: `#[thread_local]` is an experimental feature, and does not currently handle destructors. There is no corresponding `#[task_local]` mapping to the task model (see issue #29594)
   --> $DIR/feature-gate-thread_local.rs:18:1
    |
 18 | #[thread_local] //~ ERROR `#[thread_local]` is an experimental feature
diff --git a/src/test/ui/feature-gate-trace_macros.stderr b/src/test/ui/feature-gate-trace_macros.stderr
index aca7409..eae3baa 100644
--- a/src/test/ui/feature-gate-trace_macros.stderr
+++ b/src/test/ui/feature-gate-trace_macros.stderr
@@ -1,4 +1,4 @@
-error: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
   --> $DIR/feature-gate-trace_macros.rs:12:5
    |
 12 |     trace_macros!(true); //~ ERROR: `trace_macros` is not stable
diff --git a/src/test/ui/feature-gate-type_ascription.stderr b/src/test/ui/feature-gate-type_ascription.stderr
index d2a3ee2..fa6ef84 100644
--- a/src/test/ui/feature-gate-type_ascription.stderr
+++ b/src/test/ui/feature-gate-type_ascription.stderr
@@ -1,4 +1,4 @@
-error: type ascription is experimental (see issue #23416)
+error[E0658]: type ascription is experimental (see issue #23416)
   --> $DIR/feature-gate-type_ascription.rs:14:13
    |
 14 |     let a = 10: u8; //~ ERROR type ascription is experimental
diff --git a/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr
index 280fc12..ae14054 100644
--- a/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr
+++ b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr
@@ -1,4 +1,4 @@
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:20:5
    |
 20 |     extern "rust-call" fn call(self, args: ()) -> () {}
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:25:5
    |
 25 |     extern "rust-call" fn call_once(self, args: ()) -> () {}
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:5
    |
 30 |     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
@@ -22,7 +22,7 @@
    |
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:5
    |
 35 |     extern "rust-call" fn call_once(&self, args: ()) -> () {}
diff --git a/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr
index 1167bf0..a27b00a 100644
--- a/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr
+++ b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr
@@ -1,4 +1,4 @@
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:14:7
    |
 14 |     f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:15:7
    |
 15 |     f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:16:7
    |
 16 |     f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
diff --git a/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr
index 7eb491c..3d0dd15 100644
--- a/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr
+++ b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr
@@ -1,4 +1,4 @@
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:14:5
    |
 14 |     Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:15:5
    |
 15 |     FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:16:5
    |
 16 |     FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
diff --git a/src/test/ui/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gate-unboxed-closures.stderr
index b791651..ca8a592 100644
--- a/src/test/ui/feature-gate-unboxed-closures.stderr
+++ b/src/test/ui/feature-gate-unboxed-closures.stderr
@@ -1,4 +1,4 @@
-error: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change (see issue #29625)
   --> $DIR/feature-gate-unboxed-closures.rs:16:5
    |
 16 | /     extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
diff --git a/src/test/ui/feature-gate-underscore-lifetimes.stderr b/src/test/ui/feature-gate-underscore-lifetimes.stderr
index 875b958..07c5e1a 100644
--- a/src/test/ui/feature-gate-underscore-lifetimes.stderr
+++ b/src/test/ui/feature-gate-underscore-lifetimes.stderr
@@ -1,4 +1,4 @@
-error: underscore lifetimes are unstable (see issue #44524)
+error[E0658]: underscore lifetimes are unstable (see issue #44524)
   --> $DIR/feature-gate-underscore-lifetimes.rs:13:23
    |
 13 | fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable
diff --git a/src/test/ui/feature-gate-universal.stderr b/src/test/ui/feature-gate-universal.stderr
index 7f889f9..978ce59 100644
--- a/src/test/ui/feature-gate-universal.stderr
+++ b/src/test/ui/feature-gate-universal.stderr
@@ -1,4 +1,4 @@
-error: `impl Trait` in argument position is experimental (see issue #34511)
+error[E0658]: `impl Trait` in argument position is experimental (see issue #34511)
   --> $DIR/feature-gate-universal.rs:13:11
    |
 13 | fn foo(x: impl std::fmt::Debug) { print!("{:?}", x); }
diff --git a/src/test/ui/feature-gate-unsized_tuple_coercion.stderr b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr
index f166b10..4714df9 100644
--- a/src/test/ui/feature-gate-unsized_tuple_coercion.stderr
+++ b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr
@@ -1,4 +1,4 @@
-error: Unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877)
+error[E0658]: Unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877)
   --> $DIR/feature-gate-unsized_tuple_coercion.rs:12:24
    |
 12 |     let _ : &(Send,) = &((),);
diff --git a/src/test/ui/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gate-untagged_unions.stderr
index 26b6989..14b66cb 100644
--- a/src/test/ui/feature-gate-untagged_unions.stderr
+++ b/src/test/ui/feature-gate-untagged_unions.stderr
@@ -1,4 +1,4 @@
-error: unions with non-`Copy` fields are unstable (see issue #32836)
+error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
   --> $DIR/feature-gate-untagged_unions.rs:19:1
    |
 19 | / union U3 { //~ ERROR unions with non-`Copy` fields are unstable
@@ -8,7 +8,7 @@
    |
    = help: add #![feature(untagged_unions)] to the crate attributes to enable
 
-error: unions with non-`Copy` fields are unstable (see issue #32836)
+error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
   --> $DIR/feature-gate-untagged_unions.rs:23:1
    |
 23 | / union U4<T> { //~ ERROR unions with non-`Copy` fields are unstable
@@ -18,7 +18,7 @@
    |
    = help: add #![feature(untagged_unions)] to the crate attributes to enable
 
-error: unions with `Drop` implementations are unstable (see issue #32836)
+error[E0658]: unions with `Drop` implementations are unstable (see issue #32836)
   --> $DIR/feature-gate-untagged_unions.rs:27:1
    |
 27 | / union U5 { //~ ERROR unions with `Drop` implementations are unstable
diff --git a/src/test/ui/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gate-unwind-attributes.stderr
index 02d8bf9..d9b555e 100644
--- a/src/test/ui/feature-gate-unwind-attributes.stderr
+++ b/src/test/ui/feature-gate-unwind-attributes.stderr
@@ -1,4 +1,4 @@
-error: #[unwind] is experimental
+error[E0658]: #[unwind] is experimental
   --> $DIR/feature-gate-unwind-attributes.rs:21:5
    |
 21 |     #[unwind] //~ ERROR #[unwind] is experimental
diff --git a/src/test/ui/feature-gate-use_nested_groups.stderr b/src/test/ui/feature-gate-use_nested_groups.stderr
index 79f1d1a..6ae691c 100644
--- a/src/test/ui/feature-gate-use_nested_groups.stderr
+++ b/src/test/ui/feature-gate-use_nested_groups.stderr
@@ -1,4 +1,4 @@
-error: nested groups in `use` are experimental (see issue #44494)
+error[E0658]: nested groups in `use` are experimental (see issue #44494)
   --> $DIR/feature-gate-use_nested_groups.rs:27:12
    |
 27 | use a::{B, d::{*, g::H}};  //~ ERROR glob imports in `use` groups are experimental
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(use_nested_groups)] to the crate attributes to enable
 
-error: glob imports in `use` groups are experimental (see issue #44494)
+error[E0658]: glob imports in `use` groups are experimental (see issue #44494)
   --> $DIR/feature-gate-use_nested_groups.rs:27:16
    |
 27 | use a::{B, d::{*, g::H}};  //~ ERROR glob imports in `use` groups are experimental
@@ -14,7 +14,7 @@
    |
    = help: add #![feature(use_nested_groups)] to the crate attributes to enable
 
-error: paths in `use` groups are experimental (see issue #44494)
+error[E0658]: paths in `use` groups are experimental (see issue #44494)
   --> $DIR/feature-gate-use_nested_groups.rs:27:19
    |
 27 | use a::{B, d::{*, g::H}};  //~ ERROR glob imports in `use` groups are experimental
diff --git a/src/test/ui/feature-gate-used.stderr b/src/test/ui/feature-gate-used.stderr
index 228cf12..6d5ab1f 100644
--- a/src/test/ui/feature-gate-used.stderr
+++ b/src/test/ui/feature-gate-used.stderr
@@ -1,4 +1,4 @@
-error: the `#[used]` attribute is an experimental feature (see issue #40289)
+error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
   --> $DIR/feature-gate-used.rs:11:1
    |
 11 | #[used]
diff --git a/src/test/ui/feature-gate-wasm_import_memory.stderr b/src/test/ui/feature-gate-wasm_import_memory.stderr
index c0486d0..10190ef 100644
--- a/src/test/ui/feature-gate-wasm_import_memory.stderr
+++ b/src/test/ui/feature-gate-wasm_import_memory.stderr
@@ -1,4 +1,4 @@
-error: wasm_import_memory attribute is currently unstable
+error[E0658]: wasm_import_memory attribute is currently unstable
   --> $DIR/feature-gate-wasm_import_memory.rs:11:1
    |
 11 | #![wasm_import_memory] //~ ERROR: currently unstable
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index ab2fe02..029949b 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -60,7 +60,6 @@
 #![start                     = "x4300"] //~ WARN unused attribute
 // see issue-43106-gating-of-test.rs for crate-level; but non crate-level is below at "4200"
 // see issue-43106-gating-of-bench.rs for crate-level; but non crate-level is below at "4100"
-#![simd                       = "4000"] //~ WARN unused attribute
 #![repr                       = "3900"] //~ WARN unused attribute
 #![path                       = "3800"] //~ WARN unused attribute
 #![abi                        = "3700"] //~ WARN unused attribute
@@ -328,24 +327,6 @@
     impl S { }
 }
 
-#[simd = "4000"]
-//~^ WARN unused attribute
-mod simd {
-    mod inner { #![simd="4000"] }
-    //~^ WARN unused attribute
-
-    #[simd = "4000"] fn f() { }
-    //~^ WARN unused attribute
-
-    struct S; // for `struct S` case, see feature-gate-repr-simd.rs
-
-    #[simd = "4000"] type T = S;
-    //~^ WARN unused attribute
-
-    #[simd = "4000"] impl S { }
-    //~^ WARN unused attribute
-}
-
 #[repr = "3900"]
 //~^ WARN unused attribute
 mod repr {
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
index be340b1..df831de 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,21 +1,21 @@
 warning: macro_escape is a deprecated synonym for macro_use
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:1
     |
-532 | #[macro_escape]
+513 | #[macro_escape]
     | ^^^^^^^^^^^^^^^
 
 warning: macro_escape is a deprecated synonym for macro_use
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17
     |
-535 |     mod inner { #![macro_escape] }
+516 |     mod inner { #![macro_escape] }
     |                 ^^^^^^^^^^^^^^^^
     |
     = help: consider an outer attribute, #[macro_use] mod ...
 
 warning: `#[must_use]` on functions is experimental (see issue #43302)
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
     |
-682 |     #[must_use = "1400"] fn f() { }
+663 |     #[must_use = "1400"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^
     |
     = help: add #![feature(fn_must_use)] to the crate attributes to enable
@@ -51,153 +51,153 @@
    |                                 ^^^^^
 
 warning: unknown lint: `x5400`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:8
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:8
     |
-114 | #[warn(x5400)]
+113 | #[warn(x5400)]
     |        ^^^^^
 
 warning: unknown lint: `x5400`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:25
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:25
     |
-117 |     mod inner { #![warn(x5400)] }
+116 |     mod inner { #![warn(x5400)] }
     |                         ^^^^^
 
 warning: unknown lint: `x5400`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12
     |
-120 |     #[warn(x5400)] fn f() { }
+119 |     #[warn(x5400)] fn f() { }
     |            ^^^^^
 
 warning: unknown lint: `x5400`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:12
     |
-123 |     #[warn(x5400)] struct S;
+122 |     #[warn(x5400)] struct S;
     |            ^^^^^
 
 warning: unknown lint: `x5400`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:12
     |
-126 |     #[warn(x5400)] type T = S;
+125 |     #[warn(x5400)] type T = S;
     |            ^^^^^
 
 warning: unknown lint: `x5400`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:12
     |
-129 |     #[warn(x5400)] impl S { }
+128 |     #[warn(x5400)] impl S { }
     |            ^^^^^
 
 warning: unknown lint: `x5300`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:9
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:9
     |
-133 | #[allow(x5300)]
+132 | #[allow(x5300)]
     |         ^^^^^
 
 warning: unknown lint: `x5300`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:26
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:26
     |
-136 |     mod inner { #![allow(x5300)] }
+135 |     mod inner { #![allow(x5300)] }
     |                          ^^^^^
 
 warning: unknown lint: `x5300`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13
     |
-139 |     #[allow(x5300)] fn f() { }
+138 |     #[allow(x5300)] fn f() { }
     |             ^^^^^
 
 warning: unknown lint: `x5300`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:13
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:13
     |
-142 |     #[allow(x5300)] struct S;
+141 |     #[allow(x5300)] struct S;
     |             ^^^^^
 
 warning: unknown lint: `x5300`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:13
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:13
     |
-145 |     #[allow(x5300)] type T = S;
+144 |     #[allow(x5300)] type T = S;
     |             ^^^^^
 
 warning: unknown lint: `x5300`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:13
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:13
     |
-148 |     #[allow(x5300)] impl S { }
+147 |     #[allow(x5300)] impl S { }
     |             ^^^^^
 
 warning: unknown lint: `x5200`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:10
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:10
     |
-152 | #[forbid(x5200)]
+151 | #[forbid(x5200)]
     |          ^^^^^
 
 warning: unknown lint: `x5200`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:27
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:27
     |
-155 |     mod inner { #![forbid(x5200)] }
+154 |     mod inner { #![forbid(x5200)] }
     |                           ^^^^^
 
 warning: unknown lint: `x5200`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14
     |
-158 |     #[forbid(x5200)] fn f() { }
+157 |     #[forbid(x5200)] fn f() { }
     |              ^^^^^
 
 warning: unknown lint: `x5200`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:14
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:14
     |
-161 |     #[forbid(x5200)] struct S;
+160 |     #[forbid(x5200)] struct S;
     |              ^^^^^
 
 warning: unknown lint: `x5200`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:14
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:14
     |
-164 |     #[forbid(x5200)] type T = S;
+163 |     #[forbid(x5200)] type T = S;
     |              ^^^^^
 
 warning: unknown lint: `x5200`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:14
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:14
     |
-167 |     #[forbid(x5200)] impl S { }
+166 |     #[forbid(x5200)] impl S { }
     |              ^^^^^
 
 warning: unknown lint: `x5100`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:8
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:8
     |
-171 | #[deny(x5100)]
+170 | #[deny(x5100)]
     |        ^^^^^
 
 warning: unknown lint: `x5100`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:25
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:25
     |
-174 |     mod inner { #![deny(x5100)] }
+173 |     mod inner { #![deny(x5100)] }
     |                         ^^^^^
 
 warning: unknown lint: `x5100`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12
     |
-177 |     #[deny(x5100)] fn f() { }
+176 |     #[deny(x5100)] fn f() { }
     |            ^^^^^
 
 warning: unknown lint: `x5100`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:180:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:12
     |
-180 |     #[deny(x5100)] struct S;
+179 |     #[deny(x5100)] struct S;
     |            ^^^^^
 
 warning: unknown lint: `x5100`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:12
     |
-183 |     #[deny(x5100)] type T = S;
+182 |     #[deny(x5100)] type T = S;
     |            ^^^^^
 
 warning: unknown lint: `x5100`
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:186:12
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:12
     |
-186 |     #[deny(x5100)] impl S { }
+185 |     #[deny(x5100)] impl S { }
     |            ^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:17
     |
-193 |     mod inner { #![macro_reexport="5000"] }
+192 |     mod inner { #![macro_reexport="5000"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
     |
 note: lint level defined here
@@ -207,345 +207,315 @@
     |         ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:196:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5
     |
-196 |     #[macro_reexport = "5000"] fn f() { }
+195 |     #[macro_reexport = "5000"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5
     |
-199 |     #[macro_reexport = "5000"] struct S;
+198 |     #[macro_reexport = "5000"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:202:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5
     |
-202 |     #[macro_reexport = "5000"] type T = S;
+201 |     #[macro_reexport = "5000"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5
     |
-205 |     #[macro_reexport = "5000"] impl S { }
+204 |     #[macro_reexport = "5000"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:1
     |
-190 | #[macro_reexport = "5000"]
+189 | #[macro_reexport = "5000"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5
     |
-213 |     #[macro_use] fn f() { }
+212 |     #[macro_use] fn f() { }
     |     ^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:215:5
     |
-216 |     #[macro_use] struct S;
+215 |     #[macro_use] struct S;
     |     ^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:218:5
     |
-219 |     #[macro_use] type T = S;
+218 |     #[macro_use] type T = S;
     |     ^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:222:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:5
     |
-222 |     #[macro_use] impl S { }
+221 |     #[macro_use] impl S { }
     |     ^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:229:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17
     |
-229 |     mod inner { #![macro_export="4800"] }
+228 |     mod inner { #![macro_export="4800"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:5
     |
-232 |     #[macro_export = "4800"] fn f() { }
+231 |     #[macro_export = "4800"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:5
     |
-235 |     #[macro_export = "4800"] struct S;
+234 |     #[macro_export = "4800"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:237:5
     |
-238 |     #[macro_export = "4800"] type T = S;
+237 |     #[macro_export = "4800"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:241:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:5
     |
-241 |     #[macro_export = "4800"] impl S { }
+240 |     #[macro_export = "4800"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:226:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:225:1
     |
-226 | #[macro_export = "4800"]
+225 | #[macro_export = "4800"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:247:17
     |
-248 |     mod inner { #![plugin_registrar="4700"] }
+247 |     mod inner { #![plugin_registrar="4700"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:5
     |
-253 |     #[plugin_registrar = "4700"] struct S;
+252 |     #[plugin_registrar = "4700"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5
     |
-256 |     #[plugin_registrar = "4700"] type T = S;
+255 |     #[plugin_registrar = "4700"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:5
     |
-259 |     #[plugin_registrar = "4700"] impl S { }
+258 |     #[plugin_registrar = "4700"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:1
     |
-245 | #[plugin_registrar = "4700"]
+244 | #[plugin_registrar = "4700"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:17
     |
-266 |     mod inner { #![main="4300"] }
+265 |     mod inner { #![main="4300"] }
     |                 ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:5
     |
-271 |     #[main = "4400"] struct S;
+270 |     #[main = "4400"] struct S;
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5
     |
-274 |     #[main = "4400"] type T = S;
+273 |     #[main = "4400"] type T = S;
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:277:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:5
     |
-277 |     #[main = "4400"] impl S { }
+276 |     #[main = "4400"] impl S { }
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:1
     |
-263 | #[main = "4400"]
+262 | #[main = "4400"]
     | ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:17
     |
-284 |     mod inner { #![start="4300"] }
+283 |     mod inner { #![start="4300"] }
     |                 ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:5
     |
-289 |     #[start = "4300"] struct S;
+288 |     #[start = "4300"] struct S;
     |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:291:5
     |
-292 |     #[start = "4300"] type T = S;
+291 |     #[start = "4300"] type T = S;
     |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:294:5
     |
-295 |     #[start = "4300"] impl S { }
+294 |     #[start = "4300"] impl S { }
     |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1
     |
-281 | #[start = "4300"]
+280 | #[start = "4300"]
     | ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:17
     |
-334 |     mod inner { #![simd="4000"] }
+333 |     mod inner { #![repr="3900"] }
     |                 ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:5
     |
-337 |     #[simd = "4000"] fn f() { }
+336 |     #[repr = "3900"] fn f() { }
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
     |
-342 |     #[simd = "4000"] type T = S;
+341 |     #[repr = "3900"] type T = S;
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
     |
-345 |     #[simd = "4000"] impl S { }
+344 |     #[repr = "3900"] impl S { }
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:1
     |
-331 | #[simd = "4000"]
+330 | #[repr = "3900"]
     | ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5
     |
-352 |     mod inner { #![repr="3900"] }
-    |                 ^^^^^^^^^^^^^^^
+352 |     #[path = "3800"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
     |
-355 |     #[repr = "3900"] fn f() { }
+355 |     #[path = "3800"]  struct S;
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:5
     |
-360 |     #[repr = "3900"] type T = S;
+358 |     #[path = "3800"] type T = S;
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5
     |
-363 |     #[repr = "3900"] impl S { }
+361 |     #[path = "3800"] impl S { }
     |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:17
     |
-349 | #[repr = "3900"]
-    | ^^^^^^^^^^^^^^^^
+368 |     mod inner { #![abi="3700"] }
+    |                 ^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
     |
-371 |     #[path = "3800"] fn f() { }
-    |     ^^^^^^^^^^^^^^^^
+371 |     #[abi = "3700"] fn f() { }
+    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
     |
-374 |     #[path = "3800"]  struct S;
-    |     ^^^^^^^^^^^^^^^^
+374 |     #[abi = "3700"] struct S;
+    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
     |
-377 |     #[path = "3800"] type T = S;
-    |     ^^^^^^^^^^^^^^^^
+377 |     #[abi = "3700"] type T = S;
+    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
     |
-380 |     #[path = "3800"] impl S { }
-    |     ^^^^^^^^^^^^^^^^
+380 |     #[abi = "3700"] impl S { }
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:1
+    |
+365 | #[abi = "3700"]
+    | ^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17
     |
-387 |     mod inner { #![abi="3700"] }
-    |                 ^^^^^^^^^^^^^^
+387 |     mod inner { #![automatically_derived="3600"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
     |
-390 |     #[abi = "3700"] fn f() { }
-    |     ^^^^^^^^^^^^^^^
+390 |     #[automatically_derived = "3600"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
     |
-393 |     #[abi = "3700"] struct S;
-    |     ^^^^^^^^^^^^^^^
+393 |     #[automatically_derived = "3600"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5
     |
-396 |     #[abi = "3700"] type T = S;
-    |     ^^^^^^^^^^^^^^^
+396 |     #[automatically_derived = "3600"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5
     |
-399 |     #[abi = "3700"] impl S { }
-    |     ^^^^^^^^^^^^^^^
+399 |     #[automatically_derived = "3600"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1
     |
-384 | #[abi = "3700"]
-    | ^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:17
-    |
-406 |     mod inner { #![automatically_derived="3600"] }
-    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5
-    |
-409 |     #[automatically_derived = "3600"] fn f() { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5
-    |
-412 |     #[automatically_derived = "3600"] struct S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:415:5
-    |
-415 |     #[automatically_derived = "3600"] type T = S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:5
-    |
-418 |     #[automatically_derived = "3600"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:1
-    |
-403 | #[automatically_derived = "3600"]
+384 | #[automatically_derived = "3600"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: function is marked #[no_mangle], but not exported
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:27
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:27
     |
-426 |     #[no_mangle = "3500"] fn f() { }
+407 |     #[no_mangle = "3500"] fn f() { }
     |                           -^^^^^^^^^
     |                           |
     |                           help: try making it public: `pub`
@@ -553,711 +523,711 @@
     = note: #[warn(private_no_mangle_fns)] on by default
 
 warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17
+    |
+420 |     mod inner { #![no_link="3400"] }
+    |                 ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
+    |
+423 |     #[no_link = "3400"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5
+    |
+426 |     #[no_link = "3400"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5
+    |
+429 |     #[no_link = "3400"]type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5
+    |
+432 |     #[no_link = "3400"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1
+    |
+417 | #[no_link = "3400"]
+    | ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17
     |
-439 |     mod inner { #![no_link="3400"] }
-    |                 ^^^^^^^^^^^^^^^^^^
+439 |     mod inner { #![should_panic="3200"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
     |
-442 |     #[no_link = "3400"] fn f() { }
-    |     ^^^^^^^^^^^^^^^^^^^
+442 |     #[should_panic = "3200"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
     |
-445 |     #[no_link = "3400"] struct S;
-    |     ^^^^^^^^^^^^^^^^^^^
+445 |     #[should_panic = "3200"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
     |
-448 |     #[no_link = "3400"]type T = S;
-    |     ^^^^^^^^^^^^^^^^^^^
+448 |     #[should_panic = "3200"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
     |
-451 |     #[no_link = "3400"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^^
+451 |     #[should_panic = "3200"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1
     |
-436 | #[no_link = "3400"]
-    | ^^^^^^^^^^^^^^^^^^^
+436 | #[should_panic = "3200"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17
     |
-458 |     mod inner { #![should_panic="3200"] }
-    |                 ^^^^^^^^^^^^^^^^^^^^^^^
+458 |     mod inner { #![ignore="3100"] }
+    |                 ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
     |
-461 |     #[should_panic = "3200"] fn f() { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+461 |     #[ignore = "3100"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
     |
-464 |     #[should_panic = "3200"] struct S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+464 |     #[ignore = "3100"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
     |
-467 |     #[should_panic = "3200"] type T = S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+467 |     #[ignore = "3100"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
     |
-470 |     #[should_panic = "3200"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+470 |     #[ignore = "3100"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1
     |
-455 | #[should_panic = "3200"]
-    | ^^^^^^^^^^^^^^^^^^^^^^^^
+455 | #[ignore = "3100"]
+    | ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17
     |
-477 |     mod inner { #![ignore="3100"] }
-    |                 ^^^^^^^^^^^^^^^^^
+477 |     mod inner { #![no_implicit_prelude="3000"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5
     |
-480 |     #[ignore = "3100"] fn f() { }
-    |     ^^^^^^^^^^^^^^^^^^
+480 |     #[no_implicit_prelude = "3000"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
     |
-483 |     #[ignore = "3100"] struct S;
-    |     ^^^^^^^^^^^^^^^^^^
+483 |     #[no_implicit_prelude = "3000"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
     |
-486 |     #[ignore = "3100"] type T = S;
-    |     ^^^^^^^^^^^^^^^^^^
+486 |     #[no_implicit_prelude = "3000"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
     |
-489 |     #[ignore = "3100"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^
+489 |     #[no_implicit_prelude = "3000"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1
     |
-474 | #[ignore = "3100"]
-    | ^^^^^^^^^^^^^^^^^^
+474 | #[no_implicit_prelude = "3000"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
     |
-496 |     mod inner { #![no_implicit_prelude="3000"] }
-    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+496 |     mod inner { #![reexport_test_harness_main="2900"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
     |
-499 |     #[no_implicit_prelude = "3000"] fn f() { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+499 |     #[reexport_test_harness_main = "2900"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
     |
-502 |     #[no_implicit_prelude = "3000"] struct S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+502 |     #[reexport_test_harness_main = "2900"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
     |
-505 |     #[no_implicit_prelude = "3000"] type T = S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+505 |     #[reexport_test_harness_main = "2900"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
     |
-508 |     #[no_implicit_prelude = "3000"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+508 |     #[reexport_test_harness_main = "2900"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
     |
-493 | #[no_implicit_prelude = "3000"]
-    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:17
-    |
-515 |     mod inner { #![reexport_test_harness_main="2900"] }
-    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:5
-    |
-518 |     #[reexport_test_harness_main = "2900"] fn f() { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5
-    |
-521 |     #[reexport_test_harness_main = "2900"] struct S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5
-    |
-524 |     #[reexport_test_harness_main = "2900"] type T = S;
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
-    |
-527 |     #[reexport_test_harness_main = "2900"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1
-    |
-512 | #[reexport_test_harness_main = "2900"]
+493 | #[reexport_test_harness_main = "2900"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:5
     |
-538 |     #[macro_escape] fn f() { }
+519 |     #[macro_escape] fn f() { }
     |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
     |
-541 |     #[macro_escape] struct S;
+522 |     #[macro_escape] struct S;
     |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:5
+    |
+525 |     #[macro_escape] type T = S;
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
+    |
+528 |     #[macro_escape] impl S { }
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
+    |
+536 |     mod inner { #![no_std="2600"] }
+    |                 ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
+    |
+536 |     mod inner { #![no_std="2600"] }
+    |                 ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
+    |
+540 |     #[no_std = "2600"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
+    |
+540 |     #[no_std = "2600"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
    --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
     |
-544 |     #[macro_escape] type T = S;
-    |     ^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
-    |
-547 |     #[macro_escape] impl S { }
-    |     ^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
-    |
-555 |     mod inner { #![no_std="2600"] }
-    |                 ^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be in the root module
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
-    |
-555 |     mod inner { #![no_std="2600"] }
-    |                 ^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
-    |
-559 |     #[no_std = "2600"] fn f() { }
+544 |     #[no_std = "2600"] struct S;
     |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
     |
-559 |     #[no_std = "2600"] fn f() { }
+544 |     #[no_std = "2600"] struct S;
     |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
     |
-563 |     #[no_std = "2600"] struct S;
+548 |     #[no_std = "2600"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
     |
-563 |     #[no_std = "2600"] struct S;
+548 |     #[no_std = "2600"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
     |
-567 |     #[no_std = "2600"] type T = S;
+552 |     #[no_std = "2600"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
     |
-567 |     #[no_std = "2600"] type T = S;
+552 |     #[no_std = "2600"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
     |
-571 |     #[no_std = "2600"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
-    |
-571 |     #[no_std = "2600"] impl S { }
-    |     ^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
-    |
-551 | #[no_std = "2600"]
+532 | #[no_std = "2600"]
     | ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
     |
-551 | #[no_std = "2600"]
+532 | #[no_std = "2600"]
     | ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
     |
-711 |     mod inner { #![crate_name="0900"] }
+692 |     mod inner { #![crate_name="0900"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
     |
-711 |     mod inner { #![crate_name="0900"] }
+692 |     mod inner { #![crate_name="0900"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
     |
-715 |     #[crate_name = "0900"] fn f() { }
+696 |     #[crate_name = "0900"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
     |
-715 |     #[crate_name = "0900"] fn f() { }
+696 |     #[crate_name = "0900"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
     |
-719 |     #[crate_name = "0900"] struct S;
+700 |     #[crate_name = "0900"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
     |
-719 |     #[crate_name = "0900"] struct S;
+700 |     #[crate_name = "0900"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
     |
-723 |     #[crate_name = "0900"] type T = S;
+704 |     #[crate_name = "0900"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
     |
-723 |     #[crate_name = "0900"] type T = S;
+704 |     #[crate_name = "0900"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
     |
-727 |     #[crate_name = "0900"] impl S { }
+708 |     #[crate_name = "0900"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
     |
-727 |     #[crate_name = "0900"] impl S { }
+708 |     #[crate_name = "0900"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
     |
-707 | #[crate_name = "0900"]
+688 | #[crate_name = "0900"]
     | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
     |
-707 | #[crate_name = "0900"]
+688 | #[crate_name = "0900"]
     | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
     |
-736 |     mod inner { #![crate_type="0800"] }
+717 |     mod inner { #![crate_type="0800"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
     |
-736 |     mod inner { #![crate_type="0800"] }
+717 |     mod inner { #![crate_type="0800"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
     |
-740 |     #[crate_type = "0800"] fn f() { }
+721 |     #[crate_type = "0800"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
     |
-740 |     #[crate_type = "0800"] fn f() { }
+721 |     #[crate_type = "0800"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
     |
-744 |     #[crate_type = "0800"] struct S;
+725 |     #[crate_type = "0800"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
     |
-744 |     #[crate_type = "0800"] struct S;
+725 |     #[crate_type = "0800"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
     |
-748 |     #[crate_type = "0800"] type T = S;
+729 |     #[crate_type = "0800"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
     |
-748 |     #[crate_type = "0800"] type T = S;
+729 |     #[crate_type = "0800"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
     |
-752 |     #[crate_type = "0800"] impl S { }
+733 |     #[crate_type = "0800"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
     |
-752 |     #[crate_type = "0800"] impl S { }
+733 |     #[crate_type = "0800"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
     |
-732 | #[crate_type = "0800"]
+713 | #[crate_type = "0800"]
     | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
     |
-732 | #[crate_type = "0800"]
+713 | #[crate_type = "0800"]
     | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
     |
-761 |     mod inner { #![feature(x0600)] }
+742 |     mod inner { #![feature(x0600)] }
     |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
     |
-761 |     mod inner { #![feature(x0600)] }
+742 |     mod inner { #![feature(x0600)] }
     |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
     |
-765 |     #[feature(x0600)] fn f() { }
+746 |     #[feature(x0600)] fn f() { }
     |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
     |
-765 |     #[feature(x0600)] fn f() { }
+746 |     #[feature(x0600)] fn f() { }
     |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
     |
-769 |     #[feature(x0600)] struct S;
+750 |     #[feature(x0600)] struct S;
     |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
     |
-769 |     #[feature(x0600)] struct S;
+750 |     #[feature(x0600)] struct S;
     |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
     |
-773 |     #[feature(x0600)] type T = S;
+754 |     #[feature(x0600)] type T = S;
     |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
     |
-773 |     #[feature(x0600)] type T = S;
+754 |     #[feature(x0600)] type T = S;
     |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
     |
-777 |     #[feature(x0600)] impl S { }
+758 |     #[feature(x0600)] impl S { }
     |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
     |
-777 |     #[feature(x0600)] impl S { }
+758 |     #[feature(x0600)] impl S { }
     |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
     |
-757 | #[feature(x0600)]
+738 | #[feature(x0600)]
     | ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
     |
-757 | #[feature(x0600)]
+738 | #[feature(x0600)]
     | ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
     |
-787 |     mod inner { #![no_main="0400"] }
+768 |     mod inner { #![no_main="0400"] }
     |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
     |
-787 |     mod inner { #![no_main="0400"] }
+768 |     mod inner { #![no_main="0400"] }
     |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
     |
-791 |     #[no_main = "0400"] fn f() { }
+772 |     #[no_main = "0400"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
     |
-791 |     #[no_main = "0400"] fn f() { }
+772 |     #[no_main = "0400"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
     |
-795 |     #[no_main = "0400"] struct S;
+776 |     #[no_main = "0400"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
     |
-795 |     #[no_main = "0400"] struct S;
+776 |     #[no_main = "0400"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
     |
-799 |     #[no_main = "0400"] type T = S;
+780 |     #[no_main = "0400"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
     |
-799 |     #[no_main = "0400"] type T = S;
+780 |     #[no_main = "0400"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
     |
-803 |     #[no_main = "0400"] impl S { }
+784 |     #[no_main = "0400"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
     |
-803 |     #[no_main = "0400"] impl S { }
+784 |     #[no_main = "0400"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
     |
-783 | #[no_main = "0400"]
+764 | #[no_main = "0400"]
     | ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
     |
-783 | #[no_main = "0400"]
+764 | #[no_main = "0400"]
     | ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
     |
-825 |     mod inner { #![recursion_limit="0200"] }
+806 |     mod inner { #![recursion_limit="0200"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
     |
-825 |     mod inner { #![recursion_limit="0200"] }
+806 |     mod inner { #![recursion_limit="0200"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
     |
-829 |     #[recursion_limit="0200"] fn f() { }
+810 |     #[recursion_limit="0200"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
     |
-829 |     #[recursion_limit="0200"] fn f() { }
+810 |     #[recursion_limit="0200"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
     |
-833 |     #[recursion_limit="0200"] struct S;
+814 |     #[recursion_limit="0200"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
     |
-833 |     #[recursion_limit="0200"] struct S;
+814 |     #[recursion_limit="0200"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
     |
-837 |     #[recursion_limit="0200"] type T = S;
+818 |     #[recursion_limit="0200"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
     |
-837 |     #[recursion_limit="0200"] type T = S;
+818 |     #[recursion_limit="0200"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
     |
-841 |     #[recursion_limit="0200"] impl S { }
+822 |     #[recursion_limit="0200"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
     |
-841 |     #[recursion_limit="0200"] impl S { }
+822 |     #[recursion_limit="0200"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
     |
-821 | #[recursion_limit="0200"]
+802 | #[recursion_limit="0200"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
     |
-821 | #[recursion_limit="0200"]
+802 | #[recursion_limit="0200"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
     |
-850 |     mod inner { #![type_length_limit="0100"] }
+831 |     mod inner { #![type_length_limit="0100"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
     |
-850 |     mod inner { #![type_length_limit="0100"] }
+831 |     mod inner { #![type_length_limit="0100"] }
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
     |
-854 |     #[type_length_limit="0100"] fn f() { }
+835 |     #[type_length_limit="0100"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
     |
-854 |     #[type_length_limit="0100"] fn f() { }
+835 |     #[type_length_limit="0100"] fn f() { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
     |
-858 |     #[type_length_limit="0100"] struct S;
+839 |     #[type_length_limit="0100"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
     |
-858 |     #[type_length_limit="0100"] struct S;
+839 |     #[type_length_limit="0100"] struct S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
     |
-862 |     #[type_length_limit="0100"] type T = S;
+843 |     #[type_length_limit="0100"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
     |
-862 |     #[type_length_limit="0100"] type T = S;
+843 |     #[type_length_limit="0100"] type T = S;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
     |
-866 |     #[type_length_limit="0100"] impl S { }
+847 |     #[type_length_limit="0100"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
     |
-866 |     #[type_length_limit="0100"] impl S { }
+847 |     #[type_length_limit="0100"] impl S { }
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
     |
-846 | #[type_length_limit="0100"]
+827 | #[type_length_limit="0100"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
     |
-846 | #[type_length_limit="0100"]
+827 | #[type_length_limit="0100"]
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
@@ -1293,62 +1263,56 @@
 warning: unused attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1
    |
-63 | #![simd                       = "4000"] //~ WARN unused attribute
+63 | #![repr                       = "3900"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
    |
-64 | #![repr                       = "3900"] //~ WARN unused attribute
+64 | #![path                       = "3800"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
    |
-65 | #![path                       = "3800"] //~ WARN unused attribute
+65 | #![abi                        = "3700"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
    |
-66 | #![abi                        = "3700"] //~ WARN unused attribute
+66 | #![automatically_derived      = "3600"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1
    |
-67 | #![automatically_derived      = "3600"] //~ WARN unused attribute
+68 | #![no_link                    = "3400"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
    |
-69 | #![no_link                    = "3400"] //~ WARN unused attribute
+70 | #![should_panic               = "3200"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1
    |
-71 | #![should_panic               = "3200"] //~ WARN unused attribute
+71 | #![ignore                     = "3100"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:77:1
    |
-72 | #![ignore                     = "3100"] //~ WARN unused attribute
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:78:1
-   |
-78 | #![proc_macro_derive          = "2500"] //~ WARN unused attribute
+77 | #![proc_macro_derive          = "2500"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: compilation successful
-   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:1
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:1
     |
-877 | / fn main() { //~ ERROR compilation successful
-878 | |     println!("Hello World");
-879 | | }
+858 | / fn main() { //~ ERROR compilation successful
+859 | |     println!("Hello World");
+860 | | }
     | |_^
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
index 92bda4d..444c417 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
@@ -1,3 +1,5 @@
+error[E0601]: main function not found
+
 error[E0518]: attribute should be applied to function
   --> $DIR/issue-43106-gating-of-inline.rs:21:1
    |
@@ -37,7 +39,5 @@
 35 |     #[inline = "2100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^ ---------- not a function
 
-error[E0601]: main function not found
-
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
index 6f6f587..5de3204 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
@@ -42,5 +42,5 @@
 35 |     #[rustc_deprecated = "1500"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
index 59f0431..eace1dc 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
@@ -42,5 +42,5 @@
 35 |     #[stable = "1300"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
index 00cbc62..5906827 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
@@ -42,5 +42,5 @@
 35 |     #[unstable = "1200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr
index 9e0e563..4ec5c9e 100644
--- a/src/test/ui/fmt/send-sync.stderr
+++ b/src/test/ui/fmt/send-sync.stderr
@@ -12,7 +12,11 @@
    = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]`
    = note: required because it appears within the type `std::fmt::Arguments<'_>`
-   = note: required by `send`
+note: required by `send`
+  --> $DIR/send-sync.rs:11:1
+   |
+11 | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `*mut std::ops::Fn() + 'static: std::marker::Sync` is not satisfied in `std::fmt::Arguments<'_>`
   --> $DIR/send-sync.rs:19:5
@@ -28,7 +32,11 @@
    = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
    = note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]`
    = note: required because it appears within the type `std::fmt::Arguments<'_>`
-   = note: required by `sync`
+note: required by `sync`
+  --> $DIR/send-sync.rs:12:1
+   |
+12 | fn sync<T: Sync>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs
new file mode 100644
index 0000000..ac2a414
--- /dev/null
+++ b/src/test/ui/generator/auto-trait-regions.rs
@@ -0,0 +1,58 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators)]
+#![feature(optin_builtin_traits)]
+
+auto trait Foo {}
+
+struct No;
+
+impl !Foo for No {}
+
+struct A<'a, 'b>(&'a mut bool, &'b mut bool, No);
+
+impl<'a, 'b: 'a> Foo for A<'a, 'b> {}
+
+struct OnlyFooIfStaticRef(No);
+impl Foo for &'static OnlyFooIfStaticRef {}
+
+struct OnlyFooIfRef(No);
+impl<'a> Foo for &'a OnlyFooIfRef {}
+
+fn assert_foo<T: Foo>(f: T) {}
+
+fn main() {
+    // Make sure 'static is erased for generator interiors so we can't match it in trait selection
+    let x: &'static _ = &OnlyFooIfStaticRef(No);
+    let gen = || {
+        let x = x;
+        yield;
+        assert_foo(x);
+    };
+    assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied
+
+    // Allow impls which matches any lifetime
+    let x = &OnlyFooIfRef(No);
+    let gen = || {
+        let x = x;
+        yield;
+        assert_foo(x);
+    };
+    assert_foo(gen); // ok
+
+    // Disallow impls which relates lifetimes in the generator interior
+    let gen = || {
+        let a = A(&mut true, &mut true, No);
+        yield;
+        assert_foo(a);
+    };
+    assert_foo(gen); //~ ERROR the requirement `for<'r, 's> 'r : 's` is not satisfied
+}
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
new file mode 100644
index 0000000..37241e6
--- /dev/null
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+  --> $DIR/auto-trait-regions.rs:40:5
+   |
+40 |     assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied
+   |     ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
+   |
+   = help: the following implementations were found:
+             <No as Foo>
+   = note: required because it appears within the type `OnlyFooIfStaticRef`
+   = note: required because it appears within the type `&OnlyFooIfStaticRef`
+   = note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}`
+   = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+note: required by `assert_foo`
+  --> $DIR/auto-trait-regions.rs:30:1
+   |
+30 | fn assert_foo<T: Foo>(f: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0279]: the requirement `for<'r, 's> 'r : 's` is not satisfied (`expected bound lifetime parameter, found concrete lifetime`)
+  --> $DIR/auto-trait-regions.rs:57:5
+   |
+57 |     assert_foo(gen); //~ ERROR the requirement `for<'r, 's> 'r : 's` is not satisfied
+   |     ^^^^^^^^^^
+   |
+   = note: required because of the requirements on the impl of `for<'r, 's> Foo` for `A<'_, '_>`
+   = note: required because it appears within the type `for<'r, 's> {A<'r, 's>, ()}`
+   = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:52:15: 56:6 for<'r, 's> {A<'r, 's>, ()}]`
+note: required by `assert_foo`
+  --> $DIR/auto-trait-regions.rs:30:1
+   |
+30 | fn assert_foo<T: Foo>(f: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs
new file mode 100644
index 0000000..0b143d7
--- /dev/null
+++ b/src/test/ui/generator/dropck.rs
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators, generator_trait, box_leak)]
+
+use std::cell::RefCell;
+use std::ops::Generator;
+
+fn main() {
+    let (cell, mut gen);
+    cell = Box::new(RefCell::new(0));
+    let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
+    // the upvar is the non-dropck `&mut Option<Ref<'a, i32>>`.
+    gen = || {
+        // but the generator can use it to drop a `Ref<'a, i32>`.
+        let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
+        yield;
+    };
+    gen.resume();
+    // drops the RefCell and then the Ref, leading to use-after-free
+}
diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr
new file mode 100644
index 0000000..deaf00f
--- /dev/null
+++ b/src/test/ui/generator/dropck.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `ref_` does not live long enough
+  --> $DIR/dropck.rs:23:18
+   |
+21 |     gen = || {
+   |           -- capture occurs here
+22 |         // but the generator can use it to drop a `Ref<'a, i32>`.
+23 |         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
+   |                  ^^^^ borrowed value does not live long enough
+...
+28 | }
+   | - borrowed value dropped before borrower
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generator/generator-with-nll.rs b/src/test/ui/generator/generator-with-nll.rs
new file mode 100644
index 0000000..3223ff4
--- /dev/null
+++ b/src/test/ui/generator/generator-with-nll.rs
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z borrowck=compare
+
+#![feature(generators)]
+#![feature(nll)]
+
+fn main() {
+    || {
+        // The reference in `_a` is a Legal with NLL since it ends before the yield
+        let _a = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+        let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+        //~^ borrow may still be in use when generator yields (Mir)
+        yield ();
+        println!("{}", b);
+    };
+}
diff --git a/src/test/ui/generator/generator-with-nll.stderr b/src/test/ui/generator/generator-with-nll.stderr
new file mode 100644
index 0000000..0a52a92
--- /dev/null
+++ b/src/test/ui/generator/generator-with-nll.stderr
@@ -0,0 +1,29 @@
+error[E0626]: borrow may still be in use when generator yields (Mir)
+  --> $DIR/generator-with-nll.rs:20:17
+   |
+20 |         let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+   |                 ^^^^^^^^^
+21 |         //~^ borrow may still be in use when generator yields (Mir)
+22 |         yield ();
+   |         -------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Ast)
+  --> $DIR/generator-with-nll.rs:19:23
+   |
+19 |         let _a = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+   |                       ^^^^
+...
+22 |         yield ();
+   |         -------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Ast)
+  --> $DIR/generator-with-nll.rs:20:22
+   |
+20 |         let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+   |                      ^^^^
+21 |         //~^ borrow may still be in use when generator yields (Mir)
+22 |         yield ();
+   |         -------- possible yield occurs here
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
index a1f110a..e65c8f1 100644
--- a/src/test/ui/generator/not-send-sync.stderr
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -7,18 +7,26 @@
    = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell<i32>`
    = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:26:17: 30:6 a:&std::cell::Cell<i32> _]`
-   = note: required by `main::assert_send`
+note: required by `main::assert_send`
+  --> $DIR/not-send-sync.rs:17:5
+   |
+17 |     fn assert_send<T: Send>(_: T) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `std::cell::Cell<i32>: std::marker::Sync` is not satisfied in `[generator@$DIR/not-send-sync.rs:19:17: 23:6 (std::cell::Cell<i32>, ())]`
+error[E0277]: the trait bound `std::cell::Cell<i32>: std::marker::Sync` is not satisfied in `[generator@$DIR/not-send-sync.rs:19:17: 23:6 {std::cell::Cell<i32>, ()}]`
   --> $DIR/not-send-sync.rs:19:5
    |
 19 |     assert_sync(|| {
    |     ^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
    |
-   = help: within `[generator@$DIR/not-send-sync.rs:19:17: 23:6 (std::cell::Cell<i32>, ())]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
-   = note: required because it appears within the type `(std::cell::Cell<i32>, ())`
-   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:19:17: 23:6 (std::cell::Cell<i32>, ())]`
-   = note: required by `main::assert_sync`
+   = help: within `[generator@$DIR/not-send-sync.rs:19:17: 23:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
+   = note: required because it appears within the type `{std::cell::Cell<i32>, ()}`
+   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:19:17: 23:6 {std::cell::Cell<i32>, ()}]`
+note: required by `main::assert_sync`
+  --> $DIR/not-send-sync.rs:16:5
+   |
+16 |     fn assert_sync<T: Sync>(_: T) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/ui/generator/unsafe-immovable.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/ui/generator/unsafe-immovable.rs
index 5c32a75..45acbf5 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/ui/generator/unsafe-immovable.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(generators)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+fn main() {
+    static || { //~ ERROR: construction of immovable generator requires unsafe
+        yield;
+    };
+}
diff --git a/src/test/ui/generator/unsafe-immovable.stderr b/src/test/ui/generator/unsafe-immovable.stderr
new file mode 100644
index 0000000..06e43bf
--- /dev/null
+++ b/src/test/ui/generator/unsafe-immovable.stderr
@@ -0,0 +1,10 @@
+error[E0133]: construction of immovable generator requires unsafe function or block
+  --> $DIR/unsafe-immovable.rs:14:5
+   |
+14 | /     static || { //~ ERROR: construction of immovable generator requires unsafe
+15 | |         yield;
+16 | |     };
+   | |_____^ construction of immovable generator
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generator/yield-while-local-borrowed.rs b/src/test/ui/generator/yield-while-local-borrowed.rs
index 504f3e8..11bd4ed 100644
--- a/src/test/ui/generator/yield-while-local-borrowed.rs
+++ b/src/test/ui/generator/yield-while-local-borrowed.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -Z borrowck=compare
+
 #![feature(generators, generator_trait)]
 
 use std::ops::{GeneratorState, Generator};
@@ -19,7 +21,9 @@
     // (This error occurs because the region shows up in the type of
     // `b` and gets extended by region inference.)
     let mut b = move || {
-        let a = &3;
+        let a = &mut 3;
+        //~^ ERROR borrow may still be in use when generator yields (Ast)
+        //~| ERROR borrow may still be in use when generator yields (Mir)
         yield();
         println!("{}", a);
     };
@@ -30,7 +34,7 @@
     // No error here -- `a` is not in scope at the point of `yield`.
     let mut b = move || {
         {
-            let a = &3;
+            let a = &mut 3;
         }
         yield();
     };
@@ -45,7 +49,9 @@
     let mut b = move || {
         let a = 3;
         {
-            let b = &a; //~ ERROR
+            let b = &a;
+            //~^ ERROR borrow may still be in use when generator yields (Ast)
+            //~| ERROR borrow may still be in use when generator yields (Mir)
             yield();
             println!("{}", b);
         }
diff --git a/src/test/ui/generator/yield-while-local-borrowed.stderr b/src/test/ui/generator/yield-while-local-borrowed.stderr
index 2fe6c68..7961dd9 100644
--- a/src/test/ui/generator/yield-while-local-borrowed.stderr
+++ b/src/test/ui/generator/yield-while-local-borrowed.stderr
@@ -1,10 +1,38 @@
-error[E0626]: borrow may still be in use when generator yields
-  --> $DIR/yield-while-local-borrowed.rs:48:22
+error[E0626]: borrow may still be in use when generator yields (Mir)
+  --> $DIR/yield-while-local-borrowed.rs:24:17
    |
-48 |             let b = &a; //~ ERROR
+24 |         let a = &mut 3;
+   |                 ^^^^^^
+...
+27 |         yield();
+   |         ------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Ast)
+  --> $DIR/yield-while-local-borrowed.rs:24:22
+   |
+24 |         let a = &mut 3;
    |                      ^
-49 |             yield();
+...
+27 |         yield();
+   |         ------- possible yield occurs here
+
+error[E0626]: borrow may still be in use when generator yields (Ast)
+  --> $DIR/yield-while-local-borrowed.rs:52:22
+   |
+52 |             let b = &a;
+   |                      ^
+...
+55 |             yield();
    |             ------- possible yield occurs here
 
-error: aborting due to previous error
+error[E0626]: borrow may still be in use when generator yields (Mir)
+  --> $DIR/yield-while-local-borrowed.rs:52:21
+   |
+52 |             let b = &a;
+   |                     ^^
+...
+55 |             yield();
+   |             ------- possible yield occurs here
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index ffd6a3f..838a300 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -7,7 +7,11 @@
    = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
    = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:21:5: 21:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
    = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
-   = note: required by `send`
+note: required by `send`
+  --> $DIR/auto-trait-leak.rs:24:1
+   |
+24 | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
   --> $DIR/auto-trait-leak.rs:30:5
@@ -18,7 +22,11 @@
    = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
    = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:38:5: 38:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
    = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
-   = note: required by `send`
+note: required by `send`
+  --> $DIR/auto-trait-leak.rs:24:1
+   |
+24 | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0391]: unsupported cyclic reference between types/traits detected
   --> $DIR/auto-trait-leak.rs:44:1
diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr
index 30f2f51..a744013 100644
--- a/src/test/ui/imports/duplicate.stderr
+++ b/src/test/ui/imports/duplicate.stderr
@@ -12,7 +12,7 @@
 25 |     use a::foo as Otherfoo; //~ ERROR the name `foo` is defined multiple times
    |         ^^^^^^^^^^^^^^^^^^
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:56:9
    |
 56 |     use self::foo::bar; //~ ERROR `foo` is ambiguous
@@ -30,7 +30,7 @@
    |         ^^^^^^^^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:45:5
    |
 45 |     f::foo(); //~ ERROR `foo` is ambiguous
@@ -48,7 +48,7 @@
    |             ^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:46:5
    |
 46 |     g::foo(); //~ ERROR `foo` is ambiguous
@@ -66,7 +66,7 @@
    |             ^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:59:9
    |
 59 |         foo::bar(); //~ ERROR `foo` is ambiguous
diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr
index 91b0b97..32d7866 100644
--- a/src/test/ui/imports/macro-paths.stderr
+++ b/src/test/ui/imports/macro-paths.stderr
@@ -1,4 +1,4 @@
-error: `bar` is ambiguous
+error[E0659]: `bar` is ambiguous
   --> $DIR/macro-paths.rs:25:5
    |
 25 |     bar::m! { //~ ERROR ambiguous
@@ -16,7 +16,7 @@
    |         ^^^^^^
    = note: macro-expanded items do not shadow when used in a macro invocation path
 
-error: `baz` is ambiguous
+error[E0659]: `baz` is ambiguous
   --> $DIR/macro-paths.rs:35:5
    |
 35 |     baz::m! { //~ ERROR ambiguous
diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr
index 0b67613..75294f7 100644
--- a/src/test/ui/imports/macros.stderr
+++ b/src/test/ui/imports/macros.stderr
@@ -15,7 +15,7 @@
 49 |     use two_macros::m;
    |         ^^^^^^^^^^^^^
 
-error: `m` is ambiguous
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:28:5
    |
 28 |     m! { //~ ERROR ambiguous
@@ -33,7 +33,7 @@
    |         ^^^^^^^^^^^^^
    = note: macro-expanded macro imports do not shadow
 
-error: `m` is ambiguous
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:41:9
    |
 41 |         m! { //~ ERROR ambiguous
diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr
index 853ed98..8f4325f 100644
--- a/src/test/ui/imports/shadow_builtin_macros.stderr
+++ b/src/test/ui/imports/shadow_builtin_macros.stderr
@@ -9,7 +9,7 @@
    |
    = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
 
-error: `panic` is ambiguous
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:27:14
    |
 27 |     fn f() { panic!(); } //~ ERROR ambiguous
@@ -23,7 +23,7 @@
    = note: `panic` is also a builtin macro
    = note: consider adding an explicit import of `panic` to disambiguate
 
-error: `panic` is ambiguous
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:32:14
    |
 32 |     fn f() { panic!(); } //~ ERROR ambiguous
@@ -37,7 +37,7 @@
    = note: `panic` is also a builtin macro
    = note: macro-expanded macro imports do not shadow
 
-error: `n` is ambiguous
+error[E0659]: `n` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:61:5
    |
 61 |     n!(); //~ ERROR ambiguous
diff --git a/src/test/ui/in-band-lifetimes/single_use_lifetimes-4.rs b/src/test/ui/in-band-lifetimes/single_use_lifetimes-4.rs
index ead987a..4ac8f8c 100644
--- a/src/test/ui/in-band-lifetimes/single_use_lifetimes-4.rs
+++ b/src/test/ui/in-band-lifetimes/single_use_lifetimes-4.rs
@@ -17,4 +17,4 @@
     Variant(&'x u32)
 }
 
-fn main() { }
\ No newline at end of file
+fn main() { }
diff --git a/src/test/ui/in-band-lifetimes/single_use_lifetimes.rs b/src/test/ui/in-band-lifetimes/single_use_lifetimes.rs
index 96aaf89..a97056b 100644
--- a/src/test/ui/in-band-lifetimes/single_use_lifetimes.rs
+++ b/src/test/ui/in-band-lifetimes/single_use_lifetimes.rs
@@ -13,4 +13,4 @@
     *v
 }
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/ui/inference-variable-behind-raw-pointer.stderr b/src/test/ui/inference-variable-behind-raw-pointer.stderr
index a8874c9..d0ee55c 100644
--- a/src/test/ui/inference-variable-behind-raw-pointer.stderr
+++ b/src/test/ui/inference-variable-behind-raw-pointer.stderr
@@ -1,8 +1,10 @@
-warning[E0619]: the type of this value must be known in this context
+warning: the type of this value must be known in this context
   --> $DIR/inference-variable-behind-raw-pointer.rs:18:13
    |
 18 |     if data.is_null() {}
    |             ^^^^^^^
    |
-   = note: this will be made into a hard error in a future version of the compiler
+   = note: #[warn(tyvar_behind_raw_pointer)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
 
diff --git a/src/test/ui/issue-10969.stderr b/src/test/ui/issue-10969.stderr
index 8aea63e..68127b2 100644
--- a/src/test/ui/issue-10969.stderr
+++ b/src/test/ui/issue-10969.stderr
@@ -1,26 +1,18 @@
 error[E0618]: expected function, found `i32`
   --> $DIR/issue-10969.rs:12:5
    |
-12 |     i(); //~ERROR expected function, found `i32`
-   |     ^^^
-   |
-note: defined here
-  --> $DIR/issue-10969.rs:11:9
-   |
 11 | fn func(i: i32) {
-   |         ^
+   |         - `i32` defined here
+12 |     i(); //~ERROR expected function, found `i32`
+   |     ^^^ not a function
 
 error[E0618]: expected function, found `i32`
   --> $DIR/issue-10969.rs:16:5
    |
-16 |     i(); //~ERROR expected function, found `i32`
-   |     ^^^
-   |
-note: defined here
-  --> $DIR/issue-10969.rs:15:9
-   |
 15 |     let i = 0i32;
-   |         ^
+   |         - `i32` defined here
+16 |     i(); //~ERROR expected function, found `i32`
+   |     ^^^ not a function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-11319.stderr b/src/test/ui/issue-11319.stderr
index b5db112..20103d3 100644
--- a/src/test/ui/issue-11319.stderr
+++ b/src/test/ui/issue-11319.stderr
@@ -6,17 +6,14 @@
 14 | |     //~| expected type `bool`
 15 | |     //~| found type `()`
 ...  |
+19 | |         None    => (),
+   | |                    -- match arm with an incompatible type
 20 | |         _       => true
 21 | |     }
    | |_____^ expected bool, found ()
    |
    = note: expected type `bool`
               found type `()`
-note: match arm with an incompatible type
-  --> $DIR/issue-11319.rs:19:20
-   |
-19 |         None    => (),
-   |                    ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-1962.stderr b/src/test/ui/issue-1962.stderr
index 4e34898..5f92031 100644
--- a/src/test/ui/issue-1962.stderr
+++ b/src/test/ui/issue-1962.stderr
@@ -1,15 +1,8 @@
 error: denote infinite loops with `loop { ... }`
   --> $DIR/issue-1962.rs:14:3
    |
-14 |     while true  { //~ ERROR denote infinite loops with `loop
-   |     ^---------
-   |     |
-   |  ___help: use `loop`
-   | |
-15 | |     i += 1;
-16 | |     if i == 5 { break; }
-17 | |   }
-   | |___^
+14 |   while true  { //~ ERROR denote infinite loops with `loop
+   |   ^^^^^^^^^^ help: use `loop`
    |
    = note: requested on the command line with `-D while-true`
 
diff --git a/src/test/ui/issue-24036.stderr b/src/test/ui/issue-24036.stderr
index 1a70e90..c89f724 100644
--- a/src/test/ui/issue-24036.stderr
+++ b/src/test/ui/issue-24036.stderr
@@ -6,16 +6,8 @@
    |
    = note: expected type `[closure@$DIR/issue-24036.rs:12:17: 12:26]`
               found type `[closure@$DIR/issue-24036.rs:13:9: 13:18]`
-note: no two closures, even if identical, have the same type
-  --> $DIR/issue-24036.rs:13:9
-   |
-13 |     x = |c| c + 1;
-   |         ^^^^^^^^^
-help: consider boxing your closure and/or using it as a trait object
-  --> $DIR/issue-24036.rs:13:9
-   |
-13 |     x = |c| c + 1;
-   |         ^^^^^^^^^
+   = note: no two closures, even if identical, have the same type
+   = help: consider boxing your closure and/or using it as a trait object
 
 error[E0308]: match arms have incompatible types
   --> $DIR/issue-24036.rs:18:13
@@ -25,39 +17,15 @@
 19 | |     //~^ ERROR match arms have incompatible types
 20 | |         1 => |c| c + 1,
 21 | |         2 => |c| c - 1,
+   | |              --------- match arm with an incompatible type
 22 | |         _ => |c| c - 1
 23 | |     };
    | |_____^ expected closure, found a different closure
    |
    = note: expected type `[closure@$DIR/issue-24036.rs:20:14: 20:23]`
               found type `[closure@$DIR/issue-24036.rs:21:14: 21:23]`
-note: no two closures, even if identical, have the same type
-  --> $DIR/issue-24036.rs:18:13
-   |
-18 |       let x = match 1usize {
-   |  _____________^
-19 | |     //~^ ERROR match arms have incompatible types
-20 | |         1 => |c| c + 1,
-21 | |         2 => |c| c - 1,
-22 | |         _ => |c| c - 1
-23 | |     };
-   | |_____^
-help: consider boxing your closure and/or using it as a trait object
-  --> $DIR/issue-24036.rs:18:13
-   |
-18 |       let x = match 1usize {
-   |  _____________^
-19 | |     //~^ ERROR match arms have incompatible types
-20 | |         1 => |c| c + 1,
-21 | |         2 => |c| c - 1,
-22 | |         _ => |c| c - 1
-23 | |     };
-   | |_____^
-note: match arm with an incompatible type
-  --> $DIR/issue-24036.rs:21:14
-   |
-21 |         2 => |c| c - 1,
-   |              ^^^^^^^^^
+   = note: no two closures, even if identical, have the same type
+   = help: consider boxing your closure and/or using it as a trait object
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-24424.stderr b/src/test/ui/issue-24424.stderr
index acdf348..55af26d 100644
--- a/src/test/ui/issue-24424.stderr
+++ b/src/test/ui/issue-24424.stderr
@@ -4,7 +4,11 @@
 14 | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: required by `Trait0`
+note: required by `Trait0`
+  --> $DIR/issue-24424.rs:12:1
+   |
+12 | trait Trait0<'l0>  {}
+   | ^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-29723.rs b/src/test/ui/issue-29723.rs
new file mode 100644
index 0000000..f31e965
--- /dev/null
+++ b/src/test/ui/issue-29723.rs
@@ -0,0 +1,26 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+// test for https://github.com/rust-lang/rust/issues/29723
+
+fn main() {
+    let s = String::new();
+    let _s = match 0 {
+        0 if { drop(s); false } => String::from("oops"),
+        _ => {
+            // This should trigger an error,
+            // s could have been moved from.
+            s
+            //~^ ERROR use of moved value: `s`
+        }
+    };
+}
diff --git a/src/test/ui/issue-29723.stderr b/src/test/ui/issue-29723.stderr
new file mode 100644
index 0000000..061c3d4
--- /dev/null
+++ b/src/test/ui/issue-29723.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `s`
+  --> $DIR/issue-29723.rs:22:13
+   |
+18 |         0 if { drop(s); false } => String::from("oops"),
+   |                     - value moved here
+...
+22 |             s
+   |             ^ value used here after move
+   |
+   = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-30302.stderr b/src/test/ui/issue-30302.stderr
index e86b588..66e43d0 100644
--- a/src/test/ui/issue-30302.stderr
+++ b/src/test/ui/issue-30302.stderr
@@ -9,19 +9,17 @@
 error: unreachable pattern
   --> $DIR/issue-30302.rs:25:9
    |
+23 |         Nil => true,
+   |         --- matches any value
+24 | //~^ WARN pattern binding `Nil` is named the same as one of the variants of the type `Stack`
 25 |         _ => false
-   |         ^ this is an unreachable pattern
+   |         ^ unreachable pattern
    |
 note: lint level defined here
   --> $DIR/issue-30302.rs:14:9
    |
 14 | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
-note: this pattern matches any value
-  --> $DIR/issue-30302.rs:23:9
-   |
-23 |         Nil => true,
-   |         ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-31221.stderr b/src/test/ui/issue-31221.stderr
index ccc1df0..1db4834 100644
--- a/src/test/ui/issue-31221.stderr
+++ b/src/test/ui/issue-31221.stderr
@@ -1,43 +1,32 @@
 error: unreachable pattern
   --> $DIR/issue-31221.rs:28:9
    |
+27 |         Var3 => (),
+   |         ---- matches any value
 28 |         Var2 => (),
-   |         ^^^^ this is an unreachable pattern
+   |         ^^^^ unreachable pattern
    |
 note: lint level defined here
   --> $DIR/issue-31221.rs:14:9
    |
 14 | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
-note: this pattern matches any value
-  --> $DIR/issue-31221.rs:27:9
-   |
-27 |         Var3 => (),
-   |         ^^^^
 
 error: unreachable pattern
   --> $DIR/issue-31221.rs:34:9
    |
-34 |         &Var2 => (),
-   |         ^^^^^ this is an unreachable pattern
-   |
-note: this pattern matches any value
-  --> $DIR/issue-31221.rs:33:9
-   |
 33 |         &Var3 => (),
-   |         ^^^^^
+   |         ----- matches any value
+34 |         &Var2 => (),
+   |         ^^^^^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/issue-31221.rs:41:9
    |
-41 |         anything => ()
-   |         ^^^^^^^^ this is an unreachable pattern
-   |
-note: this pattern matches any value
-  --> $DIR/issue-31221.rs:40:9
-   |
 40 |         (c, d) => (),
-   |         ^^^^^^
+   |         ------ matches any value
+41 |         anything => ()
+   |         ^^^^^^^^ unreachable pattern
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issue-41652/issue_41652.rs b/src/test/ui/issue-41652/issue_41652.rs
index f38c682..a4e9282 100644
--- a/src/test/ui/issue-41652/issue_41652.rs
+++ b/src/test/ui/issue-41652/issue_41652.rs
@@ -17,7 +17,7 @@
 impl issue_41652_b::Tr for S {
     fn f() {
         3.f()
-        //~^ ERROR no method named `f` found for type `{integer}` in the current scope
+        //~^ ERROR can't call method `f` on ambiguous numeric type `{integer}`
     }
 }
 
diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr
index 5d14369..373dff2 100644
--- a/src/test/ui/issue-41652/issue_41652.stderr
+++ b/src/test/ui/issue-41652/issue_41652.stderr
@@ -1,18 +1,12 @@
-error[E0599]: no method named `f` found for type `{integer}` in the current scope
+error[E0689]: can't call method `f` on ambiguous numeric type `{integer}`
   --> $DIR/issue_41652.rs:19:11
    |
 19 |         3.f()
    |           ^
+help: you must specify a concrete type for this numeric value, like `i32`
    |
-   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
-   = help: try with `{integer}::f`
-note: candidate #1 is defined in the trait `issue_41652_b::Tr`
-  --> $DIR/auxiliary/issue_41652_b.rs:14:5
-   |
-14 | /     fn f()
-15 | |         where Self: Sized;
-   | |__________________________^
-   = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead
+19 |         3_i32.f()
+   |         ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-42106.stderr b/src/test/ui/issue-42106.stderr
index 0f96377..138f769 100644
--- a/src/test/ui/issue-42106.stderr
+++ b/src/test/ui/issue-42106.stderr
@@ -8,5 +8,5 @@
 14 | }
    | - immutable borrow ends here
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr
index dd6435a..32deabd 100644
--- a/src/test/ui/issue-44406.stderr
+++ b/src/test/ui/issue-44406.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-44406.rs:18:10
    |
 18 |     foo!(true); //~ ERROR expected type, found keyword
-   |          ^^^^
+   |          ^^^^ expected identifier, found keyword
 
 error: expected type, found keyword `true`
   --> $DIR/issue-44406.rs:18:10
diff --git a/src/test/ui/issue-46112.rs b/src/test/ui/issue-46112.rs
index c292f73..698005b 100644
--- a/src/test/ui/issue-46112.rs
+++ b/src/test/ui/issue-46112.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Issue 46112: An extern crate pub reexporting libcore was causing
+// Issue 46112: An extern crate pub re-exporting libcore was causing
 // paths rooted from `std` to be misrendered in the diagnostic output.
 
 // ignore-windows
diff --git a/src/test/ui/issue-46576.rs b/src/test/ui/issue-46576.rs
new file mode 100644
index 0000000..636a1e9
--- /dev/null
+++ b/src/test/ui/issue-46576.rs
@@ -0,0 +1,33 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-cloudabi no std::fs support
+
+#![allow(dead_code)]
+#![deny(unused_imports)]
+
+use std::fs::File;
+use std::io::{BufRead, BufReader, Read};
+//~^ ERROR unused import: `BufRead`
+
+pub fn read_from_file(path: &str) {
+    let file = File::open(&path).unwrap();
+    let mut reader = BufReader::new(file);
+    let mut s = String::new();
+    reader.read_to_string(&mut s).unwrap();
+}
+
+pub fn read_lines(s: &str) {
+    for _line in s.lines() {
+
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-46576.stderr b/src/test/ui/issue-46576.stderr
new file mode 100644
index 0000000..e0be6b4
--- /dev/null
+++ b/src/test/ui/issue-46576.stderr
@@ -0,0 +1,14 @@
+error: unused import: `BufRead`
+  --> $DIR/issue-46576.rs:17:15
+   |
+17 | use std::io::{BufRead, BufReader, Read};
+   |               ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-46576.rs:14:9
+   |
+14 | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/ui/issue-46983.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/ui/issue-46983.rs
index 5c32a75..ebbd474 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/ui/issue-46983.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(nll)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+fn foo(x: &u32) -> &'static u32 {
+    &*x
+    //~^ ERROR explicit lifetime required in the type of `x` [E0621]
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-46983.stderr b/src/test/ui/issue-46983.stderr
new file mode 100644
index 0000000..ac8417a
--- /dev/null
+++ b/src/test/ui/issue-46983.stderr
@@ -0,0 +1,10 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/issue-46983.rs:14:5
+   |
+13 | fn foo(x: &u32) -> &'static u32 {
+   |        - consider changing the type of `x` to `&'static u32`
+14 |     &*x
+   |     ^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs
new file mode 100644
index 0000000..e339716
--- /dev/null
+++ b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs
@@ -0,0 +1,22 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+type Guilty = bool;
+type FineDollars = u32;
+
+struct Verdict(Guilty, Option<FineDollars>);
+
+fn main() {
+    let justice = Verdict(true, Some(2718));
+    let _condemned = justice.00;
+    //~^ ERROR invalid tuple or struct index
+    let _punishment = justice.001;
+    //~^ ERROR invalid tuple or struct index
+}
diff --git a/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr
new file mode 100644
index 0000000..24b3c26
--- /dev/null
+++ b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr
@@ -0,0 +1,14 @@
+error: invalid tuple or struct index
+  --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:18:30
+   |
+18 |     let _condemned = justice.00;
+   |                              ^^ help: try simplifying the index: `0`
+
+error: invalid tuple or struct index
+  --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:20:31
+   |
+20 |     let _punishment = justice.001;
+   |                               ^^^ help: try simplifying the index: `1`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs b/src/test/ui/issue-47094.rs
similarity index 68%
copy from src/test/compile-fail/directory_ownership/backcompat-warnings.rs
copy to src/test/ui/issue-47094.rs
index 2da07a2..3ab9d4e 100644
--- a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs
+++ b/src/test/ui/issue-47094.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: mod statements in non-mod.rs files are unstable
+// must-compile-successfully
 
-#[path="mod_file_not_owning_aux3.rs"]
-mod foo;
+#[repr(C,u8)]
+enum Foo {
+    A,
+    B,
+}
+
+#[repr(C)]
+#[repr(u8)]
+enum Bar {
+    A,
+    B,
+}
 
 fn main() {}
diff --git a/src/test/ui/issue-47094.stderr b/src/test/ui/issue-47094.stderr
new file mode 100644
index 0000000..5276b88
--- /dev/null
+++ b/src/test/ui/issue-47094.stderr
@@ -0,0 +1,14 @@
+warning[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:13:8
+   |
+13 | #[repr(C,u8)]
+   |        ^ ^^
+
+warning[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:19:8
+   |
+19 | #[repr(C)]
+   |        ^
+20 | #[repr(u8)]
+   |        ^^
+
diff --git a/src/test/compile-fail/E0580.rs b/src/test/ui/issue-47377.rs
similarity index 70%
copy from src/test/compile-fail/E0580.rs
copy to src/test/ui/issue-47377.rs
index a2ef7da..f294008 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/ui/issue-47377.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -7,5 +7,9 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
-fn main() -> i32 { 0 } //~ ERROR E0580
+// ignore-tidy-tab
+fn main() {
+ 	let b = "hello";
+ 	let _a = b + ", World!";
+ 	//~^ ERROR E0369
+}
diff --git a/src/test/ui/issue-47377.stderr b/src/test/ui/issue-47377.stderr
new file mode 100644
index 0000000..13b3ff5
--- /dev/null
+++ b/src/test/ui/issue-47377.stderr
@@ -0,0 +1,12 @@
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-47377.rs:13:12
+   |
+13 |      let _a = b + ", World!";
+   |               ^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+   |
+13 |      let _a = b.to_owned() + ", World!";
+   |               ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/E0580.rs b/src/test/ui/issue-47380.rs
similarity index 68%
copy from src/test/compile-fail/E0580.rs
copy to src/test/ui/issue-47380.rs
index a2ef7da..e43a967 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/ui/issue-47380.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -7,5 +7,8 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
-fn main() -> i32 { 0 } //~ ERROR E0580
+fn main() {
+    let b = "hello";
+    println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
+    //~^ ERROR E0369
+}
diff --git a/src/test/ui/issue-47380.stderr b/src/test/ui/issue-47380.stderr
new file mode 100644
index 0000000..6c9f79b
--- /dev/null
+++ b/src/test/ui/issue-47380.stderr
@@ -0,0 +1,12 @@
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-47380.rs:12:33
+   |
+12 |     println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
+   |                                      ^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+   |
+12 |     println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!";
+   |                                      ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/E0580.rs b/src/test/ui/issue-47623.rs
similarity index 72%
copy from src/test/compile-fail/E0580.rs
copy to src/test/ui/issue-47623.rs
index a2ef7da..0c886fd 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/ui/issue-47623.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+use self; //~ERROR `self` imports are only allowed within a { } list
+
+fn main() {}
diff --git a/src/test/ui/issue-47623.stderr b/src/test/ui/issue-47623.stderr
new file mode 100644
index 0000000..c5a42d4
--- /dev/null
+++ b/src/test/ui/issue-47623.stderr
@@ -0,0 +1,8 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/issue-47623.rs:11:5
+   |
+11 | use self; //~ERROR `self` imports are only allowed within a { } list
+   |     ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint-output-format-2.stderr b/src/test/ui/lint-output-format-2.stderr
index d8c67c7..75e7e1f 100644
--- a/src/test/ui/lint-output-format-2.stderr
+++ b/src/test/ui/lint-output-format-2.stderr
@@ -1,8 +1,8 @@
 warning: use of deprecated item 'lint_output_format::foo': text
-  --> $DIR/lint-output-format-2.rs:20:5
+  --> $DIR/lint-output-format-2.rs:20:26
    |
 20 | use lint_output_format::{foo, bar};
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                          ^^^
    |
    = note: #[warn(deprecated)] on by default
 
diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs
index 3789b6d..dfcaede 100644
--- a/src/test/ui/lint/suggestions.rs
+++ b/src/test/ui/lint/suggestions.rs
@@ -24,6 +24,16 @@
 fn rio_grande() {} // should suggest `pub`
 //~^ WARN function is marked
 
+mod badlands {
+    // The private-no-mangle lints shouldn't suggest inserting `pub` when the
+    // item is already `pub` (but triggered the lint because, e.g., it's in a
+    // private module). (Issue #47383)
+    #[no_mangle] pub static DAUNTLESS: bool = true;
+    //~^ WARN static is marked
+    #[no_mangle] pub fn val_jean() {}
+    //~^ WARN function is marked
+}
+
 struct Equinox {
     warp_factor: f32,
 }
diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr
index 44cfb1a..8b30f55 100644
--- a/src/test/ui/lint/suggestions.stderr
+++ b/src/test/ui/lint/suggestions.stderr
@@ -1,7 +1,7 @@
 warning: unnecessary parentheses around assigned value
-  --> $DIR/suggestions.rs:36:21
+  --> $DIR/suggestions.rs:46:21
    |
-36 |         let mut a = (1); // should suggest no `mut`, no parens
+46 |         let mut a = (1); // should suggest no `mut`, no parens
    |                     ^^^ help: remove these parentheses
    |
 note: lint level defined here
@@ -11,17 +11,17 @@
    |                     ^^^^^^^^^^^^^
 
 warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
-  --> $DIR/suggestions.rs:31:1
+  --> $DIR/suggestions.rs:41:1
    |
-31 | #[no_debug] // should suggest removal of deprecated attribute
+41 | #[no_debug] // should suggest removal of deprecated attribute
    | ^^^^^^^^^^^ help: remove this attribute
    |
    = note: #[warn(deprecated)] on by default
 
 warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:36:13
+  --> $DIR/suggestions.rs:46:13
    |
-36 |         let mut a = (1); // should suggest no `mut`, no parens
+46 |         let mut a = (1); // should suggest no `mut`, no parens
    |             ---^^
    |             |
    |             help: remove this `mut`
@@ -72,28 +72,30 @@
    |
    = note: #[warn(private_no_mangle_fns)] on by default
 
-warning: denote infinite loops with `loop { ... }`
-  --> $DIR/suggestions.rs:34:5
+warning: static is marked #[no_mangle], but not exported
+  --> $DIR/suggestions.rs:31:18
    |
-34 |       while true { // should suggest `loop`
-   |       ^---------
-   |       |
-   |  _____help: use `loop`
-   | |
-35 | |     //~^ WARN denote infinite loops
-36 | |         let mut a = (1); // should suggest no `mut`, no parens
-37 | |         //~^ WARN does not need to be mutable
-...  |
-44 | |         println!("{}", a);
-45 | |     }
-   | |_____^
+31 |     #[no_mangle] pub static DAUNTLESS: bool = true;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: function is marked #[no_mangle], but not exported
+  --> $DIR/suggestions.rs:33:18
+   |
+33 |     #[no_mangle] pub fn val_jean() {}
+   |                  ^^^^^^^^^^^^^^^^^^^^
+
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/suggestions.rs:44:5
+   |
+44 |     while true { // should suggest `loop`
+   |     ^^^^^^^^^^ help: use `loop`
    |
    = note: #[warn(while_true)] on by default
 
 warning: the `warp_factor:` in this pattern is redundant
-  --> $DIR/suggestions.rs:41:23
+  --> $DIR/suggestions.rs:51:23
    |
-41 |             Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
+51 |             Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
    |                       ------------^^^^^^^^^^^^
    |                       |
    |                       help: remove this
diff --git a/src/test/ui/lint/use_suggestion_json.rs b/src/test/ui/lint/use_suggestion_json.rs
index 27232c4..c097a8f 100644
--- a/src/test/ui/lint/use_suggestion_json.rs
+++ b/src/test/ui/lint/use_suggestion_json.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi
 // compile-flags: --error-format pretty-json -Zunstable-options
 
 // The output for humans should just highlight the whole span without showing
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index 846d7df..86c2ad4 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -73,10 +73,10 @@
   "spans": [
     {
       "file_name": "$DIR/use_suggestion_json.rs",
-      "byte_start": 888,
-      "byte_end": 892,
-      "line_start": 20,
-      "line_end": 20,
+      "byte_start": 907,
+      "byte_end": 911,
+      "line_start": 21,
+      "line_end": 21,
       "column_start": 12,
       "column_end": 16,
       "is_primary": true,
@@ -100,10 +100,10 @@
       "spans": [
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -122,10 +122,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -144,10 +144,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -166,10 +166,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -188,10 +188,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -210,10 +210,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -232,10 +232,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -254,10 +254,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -276,10 +276,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -298,10 +298,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -320,10 +320,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -342,10 +342,10 @@
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 865,
-          "byte_end": 865,
-          "line_start": 19,
-          "line_end": 19,
+          "byte_start": 884,
+          "byte_end": 884,
+          "line_start": 20,
+          "line_end": 20,
           "column_start": 1,
           "column_end": 1,
           "is_primary": true,
@@ -368,19 +368,19 @@
     }
   ],
   "rendered": "error[E0412]: cannot find type `Iter` in this scope
-  --> $DIR/use_suggestion_json.rs:20:12
+  --> $DIR/use_suggestion_json.rs:21:12
    |
-20 |     let x: Iter;
+21 |     let x: Iter;
    |            ^^^^ not found in this scope
 help: possible candidates are found in other modules, you can import them into scope
    |
-19 | use std::collections::binary_heap::Iter;
+20 | use std::collections::binary_heap::Iter;
    |
-19 | use std::collections::btree_map::Iter;
+20 | use std::collections::btree_map::Iter;
    |
-19 | use std::collections::btree_set::Iter;
+20 | use std::collections::btree_set::Iter;
    |
-19 | use std::collections::hash_map::Iter;
+20 | use std::collections::hash_map::Iter;
    |
 and 8 other candidates
 
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr
index 72d9787..105de33 100644
--- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr
+++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr
@@ -5,6 +5,7 @@
    |  _____________^
 19 | |         0 => x,
 20 | |         _ => y,
+   | |              - match arm with an incompatible type
 21 | |     };
    | |_____^ expected bound lifetime parameter, found concrete lifetime
    |
@@ -12,11 +13,6 @@
               found type `for<'a> fn(&'a u8, &'a u8)`
    = note: this was previously accepted by the compiler but has been phased out
    = note: for more information, see https://github.com/rust-lang/rust/issues/45852
-note: match arm with an incompatible type
-  --> $DIR/old-lub-glb-hr.rs:20:14
-   |
-20 |         _ => y,
-   |              ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr
index 852f74b..3550314 100644
--- a/src/test/ui/lub-glb/old-lub-glb-object.stderr
+++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr
@@ -5,6 +5,7 @@
    |  _____________^
 21 | |         0 => x,
 22 | |         _ => y,
+   | |              - match arm with an incompatible type
 23 | |     };
    | |_____^ expected bound lifetime parameter 'a, found concrete lifetime
    |
@@ -12,11 +13,6 @@
               found type `&for<'a> Foo<&'a u8, &'a u8>`
    = note: this was previously accepted by the compiler but has been phased out
    = note: for more information, see https://github.com/rust-lang/rust/issues/45852
-note: match arm with an incompatible type
-  --> $DIR/old-lub-glb-object.rs:22:14
-   |
-22 |         _ => y,
-   |              ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/format-foreign.rs b/src/test/ui/macros/format-foreign.rs
index 91ca8f5..ec0eaed 100644
--- a/src/test/ui/macros/format-foreign.rs
+++ b/src/test/ui/macros/format-foreign.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    println!("%.*3$s %s!\n", "Hello,", "World", 4);
+    println!("%.*3$s %s!\n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
     println!("%1$*2$.*3$f", 123.456); //~ ERROR never used
 
     // This should *not* produce hints, on the basis that there's equally as
diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr
index d022995..f9852c5 100644
--- a/src/test/ui/macros/format-foreign.stderr
+++ b/src/test/ui/macros/format-foreign.stderr
@@ -1,12 +1,8 @@
 error: multiple unused formatting arguments
-  --> $DIR/format-foreign.rs:12:5
+  --> $DIR/format-foreign.rs:12:30
    |
-12 |     println!("%.*3$s %s!/n", "Hello,", "World", 4);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^--------^^-------^^-^^
-   |                              |         |        |
-   |                              |         |        unused
-   |                              |         unused
-   |                              unused
+12 |     println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
+   |     -------------------------^^^^^^^^--^^^^^^^--^-- multiple unused arguments in this statement
    |
    = help: `%.*3$s` should be written as `{:.2$}`
    = help: `%s` should be written as `{}`
diff --git a/src/test/ui/macros/format-unused-lables.rs b/src/test/ui/macros/format-unused-lables.rs
index 7a32d93..3347a12 100644
--- a/src/test/ui/macros/format-unused-lables.rs
+++ b/src/test/ui/macros/format-unused-lables.rs
@@ -10,9 +10,10 @@
 
 fn main() {
     println!("Test", 123, 456, 789);
+    //~^ ERROR multiple unused formatting arguments
 
     println!("Test2",
-        123,
+        123,  //~ ERROR multiple unused formatting arguments
         456,
         789
     );
@@ -20,7 +21,7 @@
     println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
 
     println!("Some more $STUFF",
-        "woo!",
+        "woo!",  //~ ERROR multiple unused formatting arguments
             STUFF=
        "things"
              , UNUSED="args");
diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr
index 9efdca1..64ea562 100644
--- a/src/test/ui/macros/format-unused-lables.stderr
+++ b/src/test/ui/macros/format-unused-lables.stderr
@@ -1,49 +1,43 @@
 error: multiple unused formatting arguments
-  --> $DIR/format-unused-lables.rs:12:5
+  --> $DIR/format-unused-lables.rs:12:22
    |
 12 |     println!("Test", 123, 456, 789);
-   |     ^^^^^^^^^^^^^^^^^---^^---^^---^^
-   |                      |    |    |
-   |                      |    |    unused
-   |                      |    unused
-   |                      unused
+   |     -----------------^^^--^^^--^^^-- multiple unused arguments in this statement
    |
    = 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: multiple unused formatting arguments
-  --> $DIR/format-unused-lables.rs:14:5
+  --> $DIR/format-unused-lables.rs:16:9
    |
-14 | /     println!("Test2",
-15 | |         123,
-   | |         --- unused
-16 | |         456,
-   | |         --- unused
-17 | |         789
-   | |         --- unused
-18 | |     );
-   | |______^
+15 | /     println!("Test2",
+16 | |         123,  //~ ERROR multiple unused formatting arguments
+   | |         ^^^
+17 | |         456,
+   | |         ^^^
+18 | |         789
+   | |         ^^^
+19 | |     );
+   | |______- multiple unused arguments in this statement
    |
    = 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: named argument never used
-  --> $DIR/format-unused-lables.rs:20:35
+  --> $DIR/format-unused-lables.rs:21:35
    |
-20 |     println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
+21 |     println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
    |                                   ^^^^^^
 
 error: multiple unused formatting arguments
-  --> $DIR/format-unused-lables.rs:22:5
+  --> $DIR/format-unused-lables.rs:24:9
    |
-22 | /     println!("Some more $STUFF",
-23 | |         "woo!",
-   | |         ------ unused
-24 | |             STUFF=
-25 | |        "things"
-   | |        -------- unused
-26 | |              , UNUSED="args");
-   | |_______________________------_^
-   |                         |
-   |                         unused
+23 | /     println!("Some more $STUFF",
+24 | |         "woo!",  //~ ERROR multiple unused formatting arguments
+   | |         ^^^^^^
+25 | |             STUFF=
+26 | |        "things"
+   | |        ^^^^^^^^
+27 | |              , UNUSED="args");
+   | |_______________________^^^^^^_- multiple unused arguments in this statement
    |
    = help: `$STUFF` should be written as `{STUFF}`
    = note: shell formatting not supported; see the documentation for `std::fmt`
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.rs b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
index 037f0d8..58a30e8 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.rs
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
@@ -46,12 +46,26 @@
      }
 }
 
+macro_rules! real_method_stmt {
+     () => {
+          2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+     }
+}
+
+macro_rules! real_method_expr {
+     () => {
+          2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+     }
+}
+
 fn main() {
     fake_method_stmt!();
     fake_field_stmt!();
     fake_anon_field_stmt!();
+    real_method_stmt!();
 
     let _ = fake_method_expr!();
     let _ = fake_field_expr!();
     let _ = fake_anon_field_expr!();
+    let _ = real_method_expr!();
 }
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
index 42144f6..b9cad7e 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
@@ -4,7 +4,7 @@
 15 |           1.fake() //~ ERROR no method
    |             ^^^^
 ...
-50 |     fake_method_stmt!();
+62 |     fake_method_stmt!();
    |     -------------------- in this macro invocation
 
 error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
@@ -13,7 +13,7 @@
 21 |           1.fake //~ ERROR doesn't have fields
    |             ^^^^
 ...
-51 |     fake_field_stmt!();
+63 |     fake_field_stmt!();
    |     ------------------- in this macro invocation
 
 error[E0609]: no field `0` on type `{integer}`
@@ -22,16 +22,29 @@
 27 |           (1).0 //~ ERROR no field
    |           ^^^^^
 ...
-52 |     fake_anon_field_stmt!();
+64 |     fake_anon_field_stmt!();
    |     ------------------------ in this macro invocation
 
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+  --> $DIR/macro-backtrace-invalid-internals.rs:51:15
+   |
+51 |           2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+   |               ^^^^
+...
+65 |     real_method_stmt!();
+   |     -------------------- in this macro invocation
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+51 |           2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+   |           ^^^^^^^
+
 error[E0599]: no method named `fake` found for type `{integer}` in the current scope
   --> $DIR/macro-backtrace-invalid-internals.rs:33:13
    |
 33 |           1.fake() //~ ERROR no method
    |             ^^^^
 ...
-54 |     let _ = fake_method_expr!();
+67 |     let _ = fake_method_expr!();
    |             ------------------- in this macro invocation
 
 error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
@@ -40,7 +53,7 @@
 39 |           1.fake //~ ERROR doesn't have fields
    |             ^^^^
 ...
-55 |     let _ = fake_field_expr!();
+68 |     let _ = fake_field_expr!();
    |             ------------------ in this macro invocation
 
 error[E0609]: no field `0` on type `{integer}`
@@ -49,8 +62,21 @@
 45 |           (1).0 //~ ERROR no field
    |           ^^^^^
 ...
-56 |     let _ = fake_anon_field_expr!();
+69 |     let _ = fake_anon_field_expr!();
    |             ----------------------- in this macro invocation
 
-error: aborting due to 6 previous errors
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+  --> $DIR/macro-backtrace-invalid-internals.rs:57:15
+   |
+57 |           2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+   |               ^^^^
+...
+70 |     let _ = real_method_expr!();
+   |             ------------------- in this macro invocation
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+57 |           2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+   |           ^^^^^^^
+
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
index 8485174..ebe9535 100644
--- a/src/test/ui/macros/macro-name-typo.stderr
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -2,7 +2,7 @@
   --> $DIR/macro-name-typo.rs:12:5
    |
 12 |     printlx!("oh noes!"); //~ ERROR cannot find
-   |     ^^^^^^^ help: you could try the macro: `println!`
+   |     ^^^^^^^ help: you could try the macro: `println`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr
index 6cfb05e..8d6da6a 100644
--- a/src/test/ui/macros/macro_undefined.stderr
+++ b/src/test/ui/macros/macro_undefined.stderr
@@ -10,7 +10,7 @@
   --> $DIR/macro_undefined.rs:21:5
    |
 21 |     k!(); //~ ERROR cannot find
-   |     ^ help: you could try the macro: `kl!`
+   |     ^ help: you could try the macro: `kl`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
index 442900e..53f2f54 100644
--- a/src/test/ui/mismatched_types/E0631.stderr
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -6,7 +6,11 @@
    |     |
    |     expected signature of `fn(usize) -> _`
    |
-   = note: required by `foo`
+note: required by `foo`
+  --> $DIR/E0631.rs:13:1
+   |
+13 | fn foo<F: Fn(usize)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/E0631.rs:18:5
@@ -16,7 +20,11 @@
    |     |
    |     expected signature of `fn(usize) -> _`
    |
-   = note: required by `bar`
+note: required by `bar`
+  --> $DIR/E0631.rs:14:1
+   |
+14 | fn bar<F: Fn<usize>>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/E0631.rs:19:5
@@ -27,7 +35,11 @@
 19 |     foo(f); //~ ERROR type mismatch
    |     ^^^ expected signature of `fn(usize) -> _`
    |
-   = note: required by `foo`
+note: required by `foo`
+  --> $DIR/E0631.rs:13:1
+   |
+13 | fn foo<F: Fn(usize)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/E0631.rs:20:5
@@ -38,7 +50,11 @@
 20 |     bar(f); //~ ERROR type mismatch
    |     ^^^ expected signature of `fn(usize) -> _`
    |
-   = note: required by `bar`
+note: required by `bar`
+  --> $DIR/E0631.rs:14:1
+   |
+14 | fn bar<F: Fn<usize>>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs
index 1ee24e3..96e5201 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.rs
+++ b/src/test/ui/mismatched_types/closure-arg-count.rs
@@ -18,6 +18,8 @@
     //~^ ERROR closure is expected to take
     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
     //~^ ERROR closure is expected to take
+    [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
+    //~^ ERROR closure is expected to take
     f(|| panic!());
     //~^ ERROR closure is expected to take
 
@@ -32,6 +34,9 @@
     let bar = |i, x, y| i;
     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
     //~^ ERROR closure is expected to take
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
+    //~^ ERROR function is expected to take
 }
 
 fn foo() {}
+fn qux(x: usize, y: usize) {}
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index 216f39b..be00ee4 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -14,64 +14,101 @@
    |               |
    |               expected closure that takes 2 arguments
 
-error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
+error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
   --> $DIR/closure-arg-count.rs:19:15
    |
 19 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
-   |               ^^^^^^^ ----------------- takes 1 argument
+   |               ^^^^^^^ ----------------- takes a single 2-tuple as argument
    |               |
-   |               expected closure that takes 2 arguments
+   |               expected closure that takes 2 distinct arguments
+help: change the closure to take multiple arguments instead of a single tuple
+   |
+19 |     [1, 2, 3].sort_by(|tuple, tuple2| panic!());
+   |                       ^^^^^^^^^^^^^^^
+
+error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
+  --> $DIR/closure-arg-count.rs:21:15
+   |
+21 |     [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
+   |               ^^^^^^^ ----------------------------- takes a single 2-tuple as argument
+   |               |
+   |               expected closure that takes 2 distinct arguments
+help: change the closure to take multiple arguments instead of a single tuple
+   |
+21 |     [1, 2, 3].sort_by(|tuple, tuple2| panic!());
+   |                       ^^^^^^^^^^^^^^^
 
 error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
-  --> $DIR/closure-arg-count.rs:21:5
+  --> $DIR/closure-arg-count.rs:23:5
    |
-21 |     f(|| panic!());
+23 |     f(|| panic!());
    |     ^ -- takes 0 arguments
    |     |
    |     expected closure that takes 1 argument
    |
-   = note: required by `f`
-
-error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments
-  --> $DIR/closure-arg-count.rs:24:53
+note: required by `f`
+  --> $DIR/closure-arg-count.rs:13:1
    |
-24 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
-   |                                                     ^^^ ------ help: consider changing the closure to accept a tuple: `|(i, x)|`
-   |                                                     |
-   |                                                     expected closure that takes a single tuple as argument
+13 | fn f<F: Fn<usize>>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
   --> $DIR/closure-arg-count.rs:26:53
    |
-26 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
-   |                                                     ^^^ ------------- help: consider changing the closure to accept a tuple: `|(i, x): (usize, _)|`
+26 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
+   |                                                     ^^^ ------ takes 2 distinct arguments
    |                                                     |
-   |                                                     expected closure that takes a single tuple as argument
+   |                                                     expected closure that takes a single 2-tuple as argument
+help: change the closure to accept a tuple instead of individual arguments
+   |
+26 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
+   |                                                         ^^^^^^^^
 
-error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
   --> $DIR/closure-arg-count.rs:28:53
    |
-28 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
+28 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
+   |                                                     ^^^ ------------- takes 2 distinct arguments
+   |                                                     |
+   |                                                     expected closure that takes a single 2-tuple as argument
+help: change the closure to accept a tuple instead of individual arguments
+   |
+28 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
+   |                                                         ^^^^^^^^
+
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
+  --> $DIR/closure-arg-count.rs:30:53
+   |
+30 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
    |                                                     ^^^ --------- takes 3 distinct arguments
    |                                                     |
    |                                                     expected closure that takes a single 2-tuple as argument
 
 error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments
-  --> $DIR/closure-arg-count.rs:30:53
+  --> $DIR/closure-arg-count.rs:32:53
    |
-30 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
+32 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
    |                                                     ^^^ expected function that takes a single 2-tuple as argument
 ...
-37 | fn foo() {}
+41 | fn foo() {}
    | -------- takes 0 arguments
 
 error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
-  --> $DIR/closure-arg-count.rs:33:53
+  --> $DIR/closure-arg-count.rs:35:53
    |
-32 |     let bar = |i, x, y| i;
+34 |     let bar = |i, x, y| i;
    |               --------- takes 3 distinct arguments
-33 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
+35 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
    |                                                     ^^^ expected closure that takes a single 2-tuple as argument
 
-error: aborting due to 9 previous errors
+error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count.rs:37:53
+   |
+37 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
+   |                                                     ^^^ expected function that takes a single 2-tuple as argument
+...
+42 | fn qux(x: usize, y: usize) {}
+   | -------------------------- takes 2 distinct arguments
+
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 77d3a33..dfd02fe 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -31,7 +31,11 @@
    |     expected signature of `for<'r> fn(*mut &'r u32) -> _`
    |     found signature of `fn(*mut &'a u32) -> _`
    |
-   = note: required by `baz`
+note: required by `baz`
+  --> $DIR/closure-arg-type-mismatch.rs:18:1
+   |
+18 | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()`
   --> $DIR/closure-arg-type-mismatch.rs:20:5
@@ -39,7 +43,11 @@
 20 |     baz(f); //~ ERROR type mismatch
    |     ^^^ expected bound lifetime parameter, found concrete lifetime
    |
-   = note: required by `baz`
+note: required by `baz`
+  --> $DIR/closure-arg-type-mismatch.rs:18:1
+   |
+18 | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index 99767ba..01de7e0 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -5,7 +5,11 @@
    |     ^^^ expected bound lifetime parameter, found concrete lifetime
    |
    = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
-   = note: required by `baz`
+note: required by `baz`
+  --> $DIR/closure-mismatch.rs:15:1
+   |
+15 | fn baz<T: Foo>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-mismatch.rs:18:5
@@ -16,7 +20,11 @@
    |     expected signature of `for<'r> fn(&'r ()) -> _`
    |
    = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
-   = note: required by `baz`
+note: required by `baz`
+  --> $DIR/closure-mismatch.rs:15:1
+   |
+15 | fn baz<T: Foo>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index 2a27ffd..64c260c 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -7,7 +7,11 @@
 21 |     apply(&3, takes_mut);
    |     ^^^^^ expected signature of `fn(&{integer}) -> _`
    |
-   = note: required by `apply`
+note: required by `apply`
+  --> $DIR/fn-variance-1.rs:15:1
+   |
+15 | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/fn-variance-1.rs:25:5
@@ -18,7 +22,11 @@
 25 |     apply(&mut 3, takes_imm);
    |     ^^^^^ expected signature of `fn(&mut {integer}) -> _`
    |
-   = note: required by `apply`
+note: required by `apply`
+  --> $DIR/fn-variance-1.rs:15:1
+   |
+15 | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/recovered-block.rs b/src/test/ui/mismatched_types/recovered-block.rs
index f3e3579..8166254 100644
--- a/src/test/ui/mismatched_types/recovered-block.rs
+++ b/src/test/ui/mismatched_types/recovered-block.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::env support
+
 use std::env;
 
 pub struct Foo {
diff --git a/src/test/ui/mismatched_types/recovered-block.stderr b/src/test/ui/mismatched_types/recovered-block.stderr
index dcaf281..23c1a5b 100644
--- a/src/test/ui/mismatched_types/recovered-block.stderr
+++ b/src/test/ui/mismatched_types/recovered-block.stderr
@@ -1,17 +1,17 @@
 error: missing `struct` for struct definition
-  --> $DIR/recovered-block.rs:21:8
+  --> $DIR/recovered-block.rs:23:8
    |
-21 |     pub Foo { text }
+23 |     pub Foo { text }
    |        ^
 help: add `struct` here to parse `Foo` as a public struct
    |
-21 |     pub struct Foo { text }
+23 |     pub struct Foo { text }
    |         ^^^^^^
 
 error: expected one of `(` or `<`, found `{`
-  --> $DIR/recovered-block.rs:27:9
+  --> $DIR/recovered-block.rs:29:9
    |
-27 |     Foo { text: "".to_string() }
+29 |     Foo { text: "".to_string() }
    |         ^ expected one of `(` or `<` here
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
index 10f4b32..f2237e4 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
@@ -15,13 +15,15 @@
 fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
 
 fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
+//~^ NOTE required by `call_it`
     f(2, y)
 }
 
 pub fn main() {
     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
+    //~^ NOTE found signature of `fn(usize, isize) -> _`
     let z = call_it(3, f);
     //~^ ERROR type mismatch
-    //~| required by `call_it`
+    //~| NOTE expected signature of `fn(isize, isize) -> _`
     println!("{}", z);
 }
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index 8539c88..9c9bbd1 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -1,12 +1,17 @@
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/unboxed-closures-vtable-mismatch.rs:23:13
+  --> $DIR/unboxed-closures-vtable-mismatch.rs:25:13
    |
-22 |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
+23 |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
    |                       ----------------------------- found signature of `fn(usize, isize) -> _`
-23 |     let z = call_it(3, f);
+24 |     //~^ NOTE found signature of `fn(usize, isize) -> _`
+25 |     let z = call_it(3, f);
    |             ^^^^^^^ expected signature of `fn(isize, isize) -> _`
    |
-   = note: required by `call_it`
+note: required by `call_it`
+  --> $DIR/unboxed-closures-vtable-mismatch.rs:17:1
+   |
+17 | fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/compile-fail/moves-based-on-type-tuple.rs b/src/test/ui/moves-based-on-type-tuple.rs
similarity index 77%
rename from src/test/compile-fail/moves-based-on-type-tuple.rs
rename to src/test/ui/moves-based-on-type-tuple.rs
index a4d3e3e..27903fe 100644
--- a/src/test/compile-fail/moves-based-on-type-tuple.rs
+++ b/src/test/ui/moves-based-on-type-tuple.rs
@@ -10,9 +10,14 @@
 
 #![feature(box_syntax)]
 
+// compile-flags: -Z emit-end-regions -Z borrowck=compare
+
 fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
-    box (x, x) //~ ERROR use of moved value
+    box (x, x)
+    //~^ use of moved value: `x` (Ast) [E0382]
+    //~| use of moved value: `x` (Mir) [E0382]
 }
+
 fn main() {
     dup(box 3);
 }
diff --git a/src/test/ui/moves-based-on-type-tuple.stderr b/src/test/ui/moves-based-on-type-tuple.stderr
new file mode 100644
index 0000000..e166710
--- /dev/null
+++ b/src/test/ui/moves-based-on-type-tuple.stderr
@@ -0,0 +1,22 @@
+error[E0382]: use of moved value: `x` (Ast)
+  --> $DIR/moves-based-on-type-tuple.rs:16:13
+   |
+16 |     box (x, x)
+   |          -  ^ value used here after move
+   |          |
+   |          value moved here
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x` (Mir)
+  --> $DIR/moves-based-on-type-tuple.rs:16:13
+   |
+16 |     box (x, x)
+   |          -  ^ value used here after move
+   |          |
+   |          value moved here
+   |
+   = note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/ui/nll/borrow-use-issue-46875.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/ui/nll/borrow-use-issue-46875.rs
index 5c32a75..47d69fe 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/ui/nll/borrow-use-issue-46875.rs
@@ -8,9 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#![feature(nll)]
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+// run-pass
+
+fn vec() {
+    let mut _x = vec!['c'];
+    let _y = &_x;
+    _x = Vec::new();
+}
+
+fn int() {
+    let mut _x = 5;
+    let _y = &_x;
+    _x = 7;
+}
+
+fn main() {
+    vec();
+    int();
+}
diff --git a/src/test/ui/nll/borrowed-match-issue-45045.rs b/src/test/ui/nll/borrowed-match-issue-45045.rs
new file mode 100644
index 0000000..8688bfa
--- /dev/null
+++ b/src/test/ui/nll/borrowed-match-issue-45045.rs
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #45045
+
+#![feature(nll)]
+
+enum Xyz {
+    A,
+    B,
+}
+
+fn main() {
+    let mut e = Xyz::A;
+    let f = &mut e;
+    let g = f;
+    match e {
+        Xyz::A => println!("a"),
+        //~^ cannot use `e` because it was mutably borrowed [E0503]
+        Xyz::B => println!("b"),
+    };
+    *g = Xyz::B;
+}
diff --git a/src/test/ui/nll/borrowed-match-issue-45045.stderr b/src/test/ui/nll/borrowed-match-issue-45045.stderr
new file mode 100644
index 0000000..15ca300
--- /dev/null
+++ b/src/test/ui/nll/borrowed-match-issue-45045.stderr
@@ -0,0 +1,11 @@
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/borrowed-match-issue-45045.rs:25:9
+   |
+22 |     let f = &mut e;
+   |             ------ borrow of `e` occurs here
+...
+25 |         Xyz::A => println!("a"),
+   |         ^^^^^^ use of borrowed `e`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/borrowed-referent-issue-38899.rs b/src/test/ui/nll/borrowed-referent-issue-38899.rs
new file mode 100644
index 0000000..d7c1585
--- /dev/null
+++ b/src/test/ui/nll/borrowed-referent-issue-38899.rs
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #38899
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+pub struct Block<'a> {
+    current: &'a u8,
+    unrelated: &'a u8,
+}
+
+fn bump<'a>(mut block: &mut Block<'a>) {
+    let x = &mut block;
+    println!("{}", x.current);
+    let p: &'a u8 = &*block.current;
+    //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+    drop(x);
+    drop(p);
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/borrowed-referent-issue-38899.stderr b/src/test/ui/nll/borrowed-referent-issue-38899.stderr
new file mode 100644
index 0000000..3031fec
--- /dev/null
+++ b/src/test/ui/nll/borrowed-referent-issue-38899.stderr
@@ -0,0 +1,11 @@
+error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowed-referent-issue-38899.rs:24:21
+   |
+22 |     let x = &mut block;
+   |             ---------- mutable borrow occurs here
+23 |     println!("{}", x.current);
+24 |     let p: &'a u8 = &*block.current;
+   |                     ^^^^^^^^^^^^^^^ immutable borrow occurs here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
index 3f56dfe..ac21fe2 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
@@ -18,7 +18,7 @@
 fn foo(x: &u32) -> &'static u32 {
     &*x
         //~^ WARN not reporting region error due to -Znll
-        //~| ERROR does not outlive free region
+        //~| ERROR explicit lifetime required in the type of `x`
 }
 
 fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
index 6648e38..2a1122c 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
@@ -4,11 +4,13 @@
 19 |     &*x
    |     ^^^
 
-error: free region `ReFree(DefId(0/0:3 ~ region_lbr_anon_does_not_outlive_static[317d]::foo[0]), BrAnon(0))` does not outlive free region `ReStatic`
+error[E0621]: explicit lifetime required in the type of `x`
   --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
    |
+18 | fn foo(x: &u32) -> &'static u32 {
+   |        - consider changing the type of `x` to `&ReStatic u32`
 19 |     &*x
-   |     ^^^
+   |     ^^^ lifetime `ReStatic` required
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/generator-distinct-lifetime.rs b/src/test/ui/nll/generator-distinct-lifetime.rs
new file mode 100644
index 0000000..60f67b1
--- /dev/null
+++ b/src/test/ui/nll/generator-distinct-lifetime.rs
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators, nll)]
+
+// Test for issue #47189. Here, both `s` and `t` are live for the
+// generator's lifetime, but within the generator they have distinct
+// lifetimes. We accept this code -- even though the borrow extends
+// over a yield -- because the data that is borrowed (`*x`) is not
+// stored on the stack.
+
+// must-compile-successfully
+
+fn foo(x: &mut u32) {
+    move || {
+        let s = &mut *x;
+        yield;
+        *s += 1;
+
+        let t = &mut *x;
+        yield;
+        *t += 1;
+    };
+}
+
+fn main() {
+    foo(&mut 0);
+}
diff --git a/src/test/ui/nll/guarantor-issue-46974.rs b/src/test/ui/nll/guarantor-issue-46974.rs
new file mode 100644
index 0000000..09ce42ce
--- /dev/null
+++ b/src/test/ui/nll/guarantor-issue-46974.rs
@@ -0,0 +1,31 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that NLL analysis propagates lifetimes correctly through
+// field accesses, Box accesses, etc.
+
+#![feature(nll)]
+
+fn foo(s: &mut (i32,)) -> i32 {
+    let t = &mut *s; // this borrow should last for the entire function
+    let x = &t.0;
+    *s = (2,); //~ ERROR cannot assign to `*s`
+    *x
+}
+
+fn bar(s: &Box<(i32,)>) -> &'static i32 {
+    // FIXME(#46983): error message should be better
+    &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
+}
+
+fn main() {
+    foo(&mut (0,));
+    bar(&Box::new((1,)));
+}
diff --git a/src/test/ui/nll/guarantor-issue-46974.stderr b/src/test/ui/nll/guarantor-issue-46974.stderr
new file mode 100644
index 0000000..4f0bd88
--- /dev/null
+++ b/src/test/ui/nll/guarantor-issue-46974.stderr
@@ -0,0 +1,20 @@
+error[E0506]: cannot assign to `*s` because it is borrowed
+  --> $DIR/guarantor-issue-46974.rs:19:5
+   |
+17 |     let t = &mut *s; // this borrow should last for the entire function
+   |             ------- borrow of `*s` occurs here
+18 |     let x = &t.0;
+19 |     *s = (2,); //~ ERROR cannot assign to `*s`
+   |     ^^^^^^^^^ assignment to borrowed `*s` occurs here
+
+error[E0621]: explicit lifetime required in the type of `s`
+  --> $DIR/guarantor-issue-46974.rs:25:5
+   |
+23 | fn bar(s: &Box<(i32,)>) -> &'static i32 {
+   |        - consider changing the type of `s` to `&'static std::boxed::Box<(i32,)>`
+24 |     // FIXME(#46983): error message should be better
+25 |     &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
+   |     ^^^^ lifetime `'static` required
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/issue-47022.rs b/src/test/ui/nll/issue-47022.rs
new file mode 100644
index 0000000..a7362c3
--- /dev/null
+++ b/src/test/ui/nll/issue-47022.rs
@@ -0,0 +1,47 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// must-compile-successfully
+
+#![allow(warnings)]
+#![feature(nll)]
+
+struct LoadedObject {
+    bodies: Vec<Body>,
+    color: Color,
+}
+
+struct Body;
+
+#[derive(Clone)]
+struct Color;
+
+struct Graphic {
+    color: Color,
+}
+
+fn convert(objects: Vec<LoadedObject>) -> (Vec<Body>, Vec<Graphic>) {
+    objects
+        .into_iter()
+        .flat_map(|LoadedObject { bodies, color, .. }| {
+            bodies.into_iter().map(move |body| {
+                (
+                    body,
+                    Graphic {
+                        color: color.clone(),
+                    },
+                )
+            })
+        })
+        .unzip()
+}
+
+fn main() {}
+
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.rs b/src/test/ui/nll/return-ref-mut-issue-46557.rs
new file mode 100644
index 0000000..79150f3
--- /dev/null
+++ b/src/test/ui/nll/return-ref-mut-issue-46557.rs
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #46557
+
+#![feature(nll)]
+#![allow(dead_code)]
+
+fn gimme_static_mut() -> &'static mut u32 {
+    let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.stderr
new file mode 100644
index 0000000..763e2bf
--- /dev/null
+++ b/src/test/ui/nll/return-ref-mut-issue-46557.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/return-ref-mut-issue-46557.rs:17:21
+   |
+17 |     let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
+   |                     ^^^^^^^ temporary value does not live long enough
+18 |     x
+19 | }
+   |  - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for lifetime '_#2r...
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/non_modrs_mods/non_modrs_mods.stderr b/src/test/ui/non_modrs_mods/non_modrs_mods.stderr
index b4b5247..f60d2e9 100644
--- a/src/test/ui/non_modrs_mods/non_modrs_mods.stderr
+++ b/src/test/ui/non_modrs_mods/non_modrs_mods.stderr
@@ -1,4 +1,4 @@
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
   --> $DIR/modrs_mod/inner_foors_mod.rs:11:9
    |
 11 | pub mod innest;
@@ -7,7 +7,7 @@
    = help: add #![feature(non_modrs_mods)] to the crate attributes to enable
    = help: on stable builds, rename this file to inner_foors_mod/mod.rs
 
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
   --> $DIR/foors_mod.rs:13:9
    |
 13 | pub mod inner_modrs_mod;
@@ -16,7 +16,7 @@
    = help: add #![feature(non_modrs_mods)] to the crate attributes to enable
    = help: on stable builds, rename this file to foors_mod/mod.rs
 
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
   --> $DIR/foors_mod.rs:14:9
    |
 14 | pub mod inner_foors_mod;
@@ -25,7 +25,7 @@
    = help: add #![feature(non_modrs_mods)] to the crate attributes to enable
    = help: on stable builds, rename this file to foors_mod/mod.rs
 
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
+error[E0658]: mod statements in non-mod.rs files are unstable (see issue #44660)
   --> $DIR/foors_mod/inner_foors_mod.rs:11:9
    |
 11 | pub mod innest;
@@ -34,14 +34,5 @@
    = help: add #![feature(non_modrs_mods)] to the crate attributes to enable
    = help: on stable builds, rename this file to inner_foors_mod/mod.rs
 
-error: mod statements in non-mod.rs files are unstable (see issue #44660)
-  --> $DIR/some_crazy_attr_mod_dir/arbitrary_name.rs:11:9
-   |
-11 | pub mod inner_modrs_mod;
-   |         ^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(non_modrs_mods)] to the crate attributes to enable
-   = help: on stable builds, rename this file to attr_mod/mod.rs
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/innest.rs b/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs
similarity index 100%
rename from src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/innest.rs
rename to src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs
diff --git a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/mod.rs b/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs
similarity index 100%
rename from src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/attr_mod/inner_modrs_mod/mod.rs
rename to src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/ui/obsolete-syntax-impl-for-dotdot.rs
similarity index 68%
copy from src/test/compile-fail/auto-impl-future-compat.rs
copy to src/test/ui/obsolete-syntax-impl-for-dotdot.rs
index 5c32a75..914621a 100644
--- a/src/test/compile-fail/auto-impl-future-compat.rs
+++ b/src/test/ui/obsolete-syntax-impl-for-dotdot.rs
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+trait Trait1 {}
+trait Trait2 {}
 
-trait Foo {}
-impl Foo for .. {}
-//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
-//~^^ WARN this was previously accepted by the compiler
+#[cfg(not_enabled)]
+impl Trait1 for .. {}
+
+impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax
+
+fn main() {}
diff --git a/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr b/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr
new file mode 100644
index 0000000..aa0af84
--- /dev/null
+++ b/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr
@@ -0,0 +1,10 @@
+error: `impl Trait for .. {}` is an obsolete syntax
+  --> $DIR/obsolete-syntax-impl-for-dotdot.rs:17:1
+   |
+17 | impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `auto trait Trait {}` instead
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr
index 1f71be4..cfac398 100644
--- a/src/test/ui/on-unimplemented/multiple-impls.stderr
+++ b/src/test/ui/on-unimplemented/multiple-impls.stderr
@@ -5,7 +5,11 @@
    |     ^^^^^^^^^^^^ trait message
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
-   = note: required by `Index::index`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:22:5
+   |
+22 |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:43:5
@@ -22,7 +26,11 @@
    |     ^^^^^^^^^^^^ on impl for Foo
    |
    = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
-   = note: required by `Index::index`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:22:5
+   |
+22 |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:46:5
@@ -39,7 +47,11 @@
    |     ^^^^^^^^^^^^ on impl for Bar
    |
    = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
-   = note: required by `Index::index`
+note: required by `Index::index`
+  --> $DIR/multiple-impls.rs:22:5
+   |
+22 |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:49:5
diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr
index c8c06bf..ed2da68 100644
--- a/src/test/ui/on-unimplemented/on-impl.stderr
+++ b/src/test/ui/on-unimplemented/on-impl.stderr
@@ -5,7 +5,11 @@
    |     ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
-   = note: required by `Index::index`
+note: required by `Index::index`
+  --> $DIR/on-impl.rs:19:5
+   |
+19 |     fn index(&self, index: Idx) -> &Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:32:5
diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr
index cde5602..028200a 100644
--- a/src/test/ui/on-unimplemented/on-trait.stderr
+++ b/src/test/ui/on-unimplemented/on-trait.stderr
@@ -5,7 +5,11 @@
    |                              ^^^^^^^ a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
    |
    = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
-   = note: required by `collect`
+note: required by `collect`
+  --> $DIR/on-trait.rs:31:1
+   |
+31 | fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::string::String: Bar::Foo<u8, _, u32>` is not satisfied
   --> $DIR/on-trait.rs:40:21
@@ -14,7 +18,11 @@
    |                     ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo`
    |
    = help: the trait `Bar::Foo<u8, _, u32>` is not implemented for `std::string::String`
-   = note: required by `foobar`
+note: required by `foobar`
+  --> $DIR/on-trait.rs:21:1
+   |
+21 | fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/pat-slice-old-style.stderr b/src/test/ui/pat-slice-old-style.stderr
index 5e7cd10..29c41c4 100644
--- a/src/test/ui/pat-slice-old-style.stderr
+++ b/src/test/ui/pat-slice-old-style.stderr
@@ -1,4 +1,4 @@
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
   --> $DIR/pat-slice-old-style.rs:19:9
    |
 19 |         [a, b..] => {},
diff --git a/src/test/ui/print_type_sizes/anonymous.rs b/src/test/ui/print_type_sizes/anonymous.rs
index cf0bede..56c05f5 100644
--- a/src/test/ui/print_type_sizes/anonymous.rs
+++ b/src/test/ui/print_type_sizes/anonymous.rs
@@ -15,7 +15,10 @@
 // that one cannot control the sizes of these types with the same sort
 // of enum-variant manipulation tricks.
 
-pub fn main() {
+#![feature(start)]
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _byte: u8 = 0;
     let _word: usize = 0;
     let _tuple: (u8, usize)= (0, 0);
@@ -25,4 +28,6 @@
 
     fn id(x: u8) -> u8 { x };
     fn bye(_: u8) -> ! { loop { } }
+
+    0
 }
diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs
index 7bc4822..d0e5bd1 100644
--- a/src/test/ui/print_type_sizes/generics.rs
+++ b/src/test/ui/print_type_sizes/generics.rs
@@ -15,6 +15,8 @@
 // monomorphized, in the MIR of the original function in which they
 // occur, to have their size reported.
 
+#![feature(start)]
+
 // In an ad-hoc attempt to avoid the injection of unwinding code
 // (which clutters the output of `-Z print-type-sizes` with types from
 // `unwind::libunwind`):
@@ -66,9 +68,11 @@
         Pair::new(FiftyBytes::new(), FiftyBytes::new());
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _b: Pair<u8> = Pair::new(0, 0);
     let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
     let _z: ZeroSized = ZeroSized;
     f1::<SevenBytes>(SevenBytes::new());
+    0
 }
diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs
index a9f2944..a50b28f 100644
--- a/src/test/ui/print_type_sizes/multiple_types.rs
+++ b/src/test/ui/print_type_sizes/multiple_types.rs
@@ -14,6 +14,8 @@
 // This file illustrates that when multiple structural types occur in
 // a function, every one of them is included in the output.
 
+#![feature(start)]
+
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -22,8 +24,10 @@
     Large(FiftyBytes),
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _e: Enum;
     let _f: FiftyBytes;
     let _s: SevenBytes;
+    0
 }
diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs
index 08b5870..7f234e2 100644
--- a/src/test/ui/print_type_sizes/niche-filling.rs
+++ b/src/test/ui/print_type_sizes/niche-filling.rs
@@ -21,6 +21,7 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
+#![feature(start)]
 #![feature(nonzero)]
 #![allow(dead_code)]
 
@@ -76,7 +77,8 @@
     Four(D)
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _x: MyOption<NonZero<u32>> = Default::default();
     let _y: EmbeddedDiscr = Default::default();
     let _z: MyOption<IndirectNonZero<u32>> = Default::default();
@@ -87,4 +89,5 @@
     let _e: Enum4<(), char, (), ()> = Enum4::One(());
     let _f: Enum4<(), (), bool, ()> = Enum4::One(());
     let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
+    0
 }
diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs
index 40c41aa..d9b9026 100644
--- a/src/test/ui/print_type_sizes/no_duplicates.rs
+++ b/src/test/ui/print_type_sizes/no_duplicates.rs
@@ -15,12 +15,16 @@
 // (even if multiple functions), it is only printed once in the
 // print-type-sizes output.
 
+#![feature(start)]
+
 pub struct SevenBytes([u8; 7]);
 
 pub fn f1() {
     let _s: SevenBytes = SevenBytes([0; 7]);
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _s: SevenBytes = SevenBytes([0; 7]);
+    0
 }
diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs
index 1ee6395..a4288f6 100644
--- a/src/test/ui/print_type_sizes/packed.rs
+++ b/src/test/ui/print_type_sizes/packed.rs
@@ -20,6 +20,7 @@
 // padding and overall computed sizes can be quite different.
 
 #![allow(dead_code)]
+#![feature(start)]
 
 #[derive(Default)]
 #[repr(packed)]
@@ -42,7 +43,9 @@
     d: u8,
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _c: Packed = Default::default();
     let _d: Padded = Default::default();
+    0
 }
diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs
index b3cd213..b4661ef 100644
--- a/src/test/ui/print_type_sizes/padding.rs
+++ b/src/test/ui/print_type_sizes/padding.rs
@@ -19,6 +19,7 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
+#![feature(start)]
 #![allow(dead_code)]
 
 struct S {
@@ -37,4 +38,7 @@
     B(S),
 }
 
-fn main() { }
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    0
+}
diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs
index 1bf76da..108b8db 100644
--- a/src/test/ui/print_type_sizes/repr-align.rs
+++ b/src/test/ui/print_type_sizes/repr-align.rs
@@ -20,6 +20,7 @@
 // padding and overall computed sizes can be quite different.
 #![feature(attr_literals)]
 #![feature(repr_align)]
+#![feature(start)]
 #![allow(dead_code)]
 
 #[repr(align(16))]
@@ -39,6 +40,8 @@
     d: i8,
 }
 
-fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _s: S = Default::default();
+    0
 }
diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs
index fae6cd4..4d03969 100644
--- a/src/test/ui/print_type_sizes/uninhabited.rs
+++ b/src/test/ui/print_type_sizes/uninhabited.rs
@@ -12,8 +12,11 @@
 // must-compile-successfully
 
 #![feature(never_type)]
+#![feature(start)]
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _x: Option<!> = None;
     let _y: Result<u32, !> = Ok(42);
+    0
 }
diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs
index 2725bb0..e4d5416 100644
--- a/src/test/ui/print_type_sizes/variants.rs
+++ b/src/test/ui/print_type_sizes/variants.rs
@@ -19,6 +19,8 @@
 // 2. For an enum, the print-type-sizes output will also include the
 //    size of each variant.
 
+#![feature(start)]
+
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -27,6 +29,8 @@
     Large(FiftyBytes),
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _e: Enum;
+    0
 }
diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr
index cbf206e..1bdb47d 100644
--- a/src/test/ui/pub/pub-restricted-error.stderr
+++ b/src/test/ui/pub/pub-restricted-error.stderr
@@ -2,7 +2,7 @@
   --> $DIR/pub-restricted-error.rs:16:16
    |
 16 |     pub(crate) () foo: usize, //~ ERROR expected identifier
-   |                ^
+   |                ^ expected identifier
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pub/pub-restricted-non-path.stderr b/src/test/ui/pub/pub-restricted-non-path.stderr
index b76e878..e5b1321 100644
--- a/src/test/ui/pub/pub-restricted-non-path.stderr
+++ b/src/test/ui/pub/pub-restricted-non-path.stderr
@@ -2,7 +2,7 @@
   --> $DIR/pub-restricted-non-path.rs:13:6
    |
 13 | pub (.) fn afn() {} //~ ERROR expected identifier
-   |      ^
+   |      ^ expected identifier
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/privacy-enum-ctor.rs b/src/test/ui/resolve/privacy-enum-ctor.rs
new file mode 100644
index 0000000..08480a0
--- /dev/null
+++ b/src/test/ui/resolve/privacy-enum-ctor.rs
@@ -0,0 +1,81 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod m {
+    pub enum E {
+        Fn(u8),
+        Struct {
+            s: u8,
+        },
+        Unit,
+    }
+
+    pub mod n {
+        pub(in m) enum Z {
+            Fn(u8),
+            Struct {
+                s: u8,
+            },
+            Unit,
+        }
+    }
+
+    use m::n::Z; // OK, only the type is imported
+
+    fn f() {
+        n::Z;
+        //~^ ERROR expected value, found enum `n::Z`
+        Z;
+        //~^ ERROR expected value, found enum `Z`
+        let _: Z = Z::Fn;
+        //~^ ERROR mismatched types
+        let _: Z = Z::Struct;
+        //~^ ERROR expected value, found struct variant `Z::Struct`
+        let _ = Z::Unit();
+        //~^ ERROR expected function, found enum variant `Z::Unit`
+        let _ = Z::Unit {};
+        // This is ok, it is equivalent to not having braces
+    }
+}
+
+use m::E; // OK, only the type is imported
+
+fn main() {
+    let _: E = m::E;
+    //~^ ERROR expected value, found enum `m::E`
+    let _: E = m::E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = m::E::Struct;
+    //~^ ERROR expected value, found struct variant `m::E::Struct`
+    let _: E = m::E::Unit();
+    //~^ ERROR expected function, found enum variant `m::E::Unit`
+    let _: E = E;
+    //~^ ERROR expected value, found enum `E`
+    let _: E = E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = E::Struct;
+    //~^ ERROR expected value, found struct variant `E::Struct`
+    let _: E = E::Unit();
+    //~^ ERROR expected function, found enum variant `E::Unit`
+    let _: Z = m::n::Z;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found enum `m::n::Z`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Fn;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Struct;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found struct variant `m::n::Z::Struct`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Unit {};
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+}
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
new file mode 100644
index 0000000..c4f6d1f
--- /dev/null
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -0,0 +1,225 @@
+error[E0423]: expected value, found enum `n::Z`
+  --> $DIR/privacy-enum-ctor.rs:33:9
+   |
+33 |         n::Z;
+   |         ^^^^
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0423]: expected value, found enum `Z`
+  --> $DIR/privacy-enum-ctor.rs:35:9
+   |
+35 |         Z;
+   |         ^ did you mean `f`?
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0423]: expected value, found struct variant `Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:39:20
+   |
+39 |         let _: Z = Z::Struct;
+   |                    ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `m::E`
+  --> $DIR/privacy-enum-ctor.rs:51:16
+   |
+51 |     let _: E = m::E;
+   |                ^^^-
+   |                   |
+   |                   did you mean `f`?
+   |
+   = note: did you mean to use one of the following variants?
+           - `E::Fn`
+           - `E::Struct`
+           - `E::Unit`
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+48 | use std::f32::consts::E;
+   |
+48 | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `m::E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:55:16
+   |
+55 |     let _: E = m::E::Struct;
+   |                ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `E`
+  --> $DIR/privacy-enum-ctor.rs:59:16
+   |
+59 |     let _: E = E;
+   |                ^
+   |
+   = note: did you mean to use one of the following variants?
+           - `E::Fn`
+           - `E::Struct`
+           - `E::Unit`
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+48 | use std::f32::consts::E;
+   |
+48 | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:63:16
+   |
+63 |     let _: E = E::Struct;
+   |                ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:67:12
+   |
+67 |     let _: Z = m::n::Z;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0423]: expected value, found enum `m::n::Z`
+  --> $DIR/privacy-enum-ctor.rs:67:16
+   |
+67 |     let _: Z = m::n::Z;
+   |                ^^^^^^^
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:71:12
+   |
+71 |     let _: Z = m::n::Z::Fn;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:74:12
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0423]: expected value, found struct variant `m::n::Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:74:16
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:78:12
+   |
+78 |     let _: Z = m::n::Z::Unit {};
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:67:16
+   |
+67 |     let _: Z = m::n::Z;
+   |                ^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:71:16
+   |
+71 |     let _: Z = m::n::Z::Fn;
+   |                ^^^^^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:74:16
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:78:16
+   |
+78 |     let _: Z = m::n::Z::Unit {};
+   |                ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:37:20
+   |
+37 |         let _: Z = Z::Fn;
+   |                    ^^^^^ expected enum `m::n::Z`, found fn item
+   |
+   = note: expected type `m::n::Z`
+              found type `fn(u8) -> m::n::Z {m::n::Z::Fn}`
+
+error[E0618]: expected function, found enum variant `Z::Unit`
+  --> $DIR/privacy-enum-ctor.rs:41:17
+   |
+26 |             Unit,
+   |             ---- `Z::Unit` defined here
+...
+41 |         let _ = Z::Unit();
+   |                 ^^^^^^^^^ not a function
+help: `Z::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+41 |         let _ = Z::Unit;
+   |                 ^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:53:16
+   |
+53 |     let _: E = m::E::Fn;
+   |                ^^^^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `m::E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:57:16
+   |
+17 |         Unit,
+   |         ---- `m::E::Unit` defined here
+...
+57 |     let _: E = m::E::Unit();
+   |                ^^^^^^^^^^^^ not a function
+help: `m::E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+57 |     let _: E = m::E::Unit;
+   |                ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:61:16
+   |
+61 |     let _: E = E::Fn;
+   |                ^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:65:16
+   |
+17 |         Unit,
+   |         ---- `E::Unit` defined here
+...
+65 |     let _: E = E::Unit();
+   |                ^^^^^^^^^ not a function
+help: `E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+65 |     let _: E = E::Unit;
+   |                ^^^^^^^
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs
index eb6edae..9029eeb 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.rs
+++ b/src/test/ui/resolve/privacy-struct-ctor.rs
@@ -14,6 +14,9 @@
 
 mod m {
     pub struct S(u8);
+    pub struct S2 {
+        s: u8
+    }
 
     pub mod n {
         pub(in m) struct Z(pub(in m::n) u8);
@@ -22,22 +25,33 @@
     use m::n::Z; // OK, only the type is imported
 
     fn f() {
-        n::Z; //~ ERROR tuple struct `Z` is private
+        n::Z;
+        //~^ ERROR tuple struct `Z` is private
         Z;
         //~^ ERROR expected value, found struct `Z`
     }
 }
 
 use m::S; // OK, only the type is imported
+use m::S2; // OK, only the type is imported
 
 fn main() {
-    m::S; //~ ERROR tuple struct `S` is private
+    m::S;
+    //~^ ERROR tuple struct `S` is private
+    let _: S = m::S(2);
+    //~^ ERROR tuple struct `S` is private
     S;
     //~^ ERROR expected value, found struct `S`
-    m::n::Z; //~ ERROR tuple struct `Z` is private
+    m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
 
-    xcrate::m::S; //~ ERROR tuple struct `S` is private
+    S2;
+    //~^ ERROR expected value, found struct `S2`
+
+    xcrate::m::S;
+    //~^ ERROR tuple struct `S` is private
     xcrate::S;
     //~^ ERROR expected value, found struct `xcrate::S`
-    xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+    xcrate::m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
 }
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index 39bedf5..e97a4e4 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -1,72 +1,77 @@
 error[E0423]: expected value, found struct `Z`
-  --> $DIR/privacy-struct-ctor.rs:26:9
+  --> $DIR/privacy-struct-ctor.rs:30:9
    |
-26 |         Z;
+30 |         Z;
    |         ^
    |         |
    |         did you mean `S`?
    |         constructor is not visible here due to private fields
-   |         did you mean `Z { /* fields */ }`?
 help: possible better candidate is found in another module, you can import it into scope
    |
-22 |     use m::n::Z;
+25 |     use m::n::Z;
    |
 
 error[E0423]: expected value, found struct `S`
-  --> $DIR/privacy-struct-ctor.rs:35:5
+  --> $DIR/privacy-struct-ctor.rs:43:5
    |
-35 |     S;
-   |     ^
-   |     |
-   |     constructor is not visible here due to private fields
-   |     did you mean `S { /* fields */ }`?
+43 |     S;
+   |     ^ constructor is not visible here due to private fields
 help: possible better candidate is found in another module, you can import it into scope
    |
-31 | use m::S;
+35 | use m::S;
    |
 
+error[E0423]: expected value, found struct `S2`
+  --> $DIR/privacy-struct-ctor.rs:48:5
+   |
+48 |     S2;
+   |     ^^ did you mean `S2 { /* fields */ }`?
+
 error[E0423]: expected value, found struct `xcrate::S`
-  --> $DIR/privacy-struct-ctor.rs:40:5
+  --> $DIR/privacy-struct-ctor.rs:53:5
    |
-40 |     xcrate::S;
-   |     ^^^^^^^^^
-   |     |
-   |     constructor is not visible here due to private fields
-   |     did you mean `xcrate::S { /* fields */ }`?
+53 |     xcrate::S;
+   |     ^^^^^^^^^ constructor is not visible here due to private fields
 help: possible better candidate is found in another module, you can import it into scope
    |
-31 | use m::S;
+35 | use m::S;
    |
 
 error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:25:9
+  --> $DIR/privacy-struct-ctor.rs:28:9
    |
-25 |         n::Z; //~ ERROR tuple struct `Z` is private
+28 |         n::Z;
    |         ^^^^
 
 error[E0603]: tuple struct `S` is private
-  --> $DIR/privacy-struct-ctor.rs:34:5
-   |
-34 |     m::S; //~ ERROR tuple struct `S` is private
-   |     ^^^^
-
-error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:37:5
-   |
-37 |     m::n::Z; //~ ERROR tuple struct `Z` is private
-   |     ^^^^^^^
-
-error[E0603]: tuple struct `S` is private
   --> $DIR/privacy-struct-ctor.rs:39:5
    |
-39 |     xcrate::m::S; //~ ERROR tuple struct `S` is private
+39 |     m::S;
+   |     ^^^^
+
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:41:16
+   |
+41 |     let _: S = m::S(2);
+   |                ^^^^
+
+error[E0603]: tuple struct `Z` is private
+  --> $DIR/privacy-struct-ctor.rs:45:5
+   |
+45 |     m::n::Z;
+   |     ^^^^^^^
+
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:51:5
+   |
+51 |     xcrate::m::S;
    |     ^^^^^^^^^^^^
 
 error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:42:5
+  --> $DIR/privacy-struct-ctor.rs:55:5
    |
-42 |     xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+55 |     xcrate::m::n::Z;
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs
index 6d21617..8881b96 100644
--- a/src/test/ui/resolve/token-error-correct-3.rs
+++ b/src/test/ui/resolve/token-error-correct-3.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::fs support
+
 // Test that we do some basic error correcton in the tokeniser (and don't spew
 // too many bogus errors).
 
diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr
index f2281a2..33cf1d8 100644
--- a/src/test/ui/resolve/token-error-correct-3.stderr
+++ b/src/test/ui/resolve/token-error-correct-3.stderr
@@ -1,40 +1,40 @@
 error: incorrect close delimiter: `}`
-  --> $DIR/token-error-correct-3.rs:28:9
+  --> $DIR/token-error-correct-3.rs:30:9
    |
-28 |         } else { //~ ERROR: incorrect close delimiter: `}`
+30 |         } else { //~ ERROR: incorrect close delimiter: `}`
    |         ^
    |
 note: unclosed delimiter
-  --> $DIR/token-error-correct-3.rs:22:21
+  --> $DIR/token-error-correct-3.rs:24:21
    |
-22 |             callback(path.as_ref(); //~ ERROR expected one of
+24 |             callback(path.as_ref(); //~ ERROR expected one of
    |                     ^
 
 error: expected one of `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/token-error-correct-3.rs:22:35
+  --> $DIR/token-error-correct-3.rs:24:35
    |
-22 |             callback(path.as_ref(); //~ ERROR expected one of
+24 |             callback(path.as_ref(); //~ ERROR expected one of
    |                                   ^ expected one of `,`, `.`, `?`, or an operator here
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
-  --> $DIR/token-error-correct-3.rs:28:9
+  --> $DIR/token-error-correct-3.rs:30:9
    |
-23 |             fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
+25 |             fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
    |                                                             - expected one of `.`, `;`, `?`, `}`, or an operator here
 ...
-28 |         } else { //~ ERROR: incorrect close delimiter: `}`
+30 |         } else { //~ ERROR: incorrect close delimiter: `}`
    |         ^ unexpected token
 
 error[E0425]: cannot find function `is_directory` in this scope
-  --> $DIR/token-error-correct-3.rs:21:13
+  --> $DIR/token-error-correct-3.rs:23:13
    |
-21 |         if !is_directory(path.as_ref()) { //~ ERROR: cannot find function `is_directory`
+23 |         if !is_directory(path.as_ref()) { //~ ERROR: cannot find function `is_directory`
    |             ^^^^^^^^^^^^ not found in this scope
 
 error[E0308]: mismatched types
-  --> $DIR/token-error-correct-3.rs:23:13
+  --> $DIR/token-error-correct-3.rs:25:13
    |
-23 |             fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
+25 |             fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
    |             |
    |             expected (), found enum `std::result::Result`
diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr
index aea9fc3..843d7c2 100644
--- a/src/test/ui/resolve/tuple-struct-alias.stderr
+++ b/src/test/ui/resolve/tuple-struct-alias.stderr
@@ -2,31 +2,33 @@
   --> $DIR/tuple-struct-alias.rs:16:17
    |
 16 |         let s = Self(0, 1); //~ ERROR expected function
-   |                 ^^^^ did you mean `Self { /* fields */ }`?
+   |                 ^^^^ not a function
+   |
+   = note: can't use `Self` as a constructor, you must use the implemented struct
 
 error[E0532]: expected tuple struct/variant, found self type `Self`
   --> $DIR/tuple-struct-alias.rs:18:13
    |
 18 |             Self(..) => {} //~ ERROR expected tuple struct/variant
-   |             ^^^^ did you mean `Self { /* fields */ }`?
+   |             ^^^^ not a tuple struct/variant
+   |
+   = note: can't use `Self` as a constructor, you must use the implemented struct
 
 error[E0423]: expected function, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:24:13
    |
 24 |     let s = A(0, 1); //~ ERROR expected function
-   |             ^
-   |             |
-   |             did you mean `S`?
-   |             did you mean `A { /* fields */ }`?
+   |             ^ did you mean `S`?
+   |
+   = note: can't use a type alias as a constructor
 
 error[E0532]: expected tuple struct/variant, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:26:9
    |
 26 |         A(..) => {} //~ ERROR expected tuple struct/variant
-   |         ^
-   |         |
-   |         did you mean `S`?
-   |         did you mean `A { /* fields */ }`?
+   |         ^ did you mean `S`?
+   |
+   = note: can't use a type alias as a constructor
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/resolve/use_suggestion_placement.rs b/src/test/ui/resolve/use_suggestion_placement.rs
index 87f38df..835c42e 100644
--- a/src/test/ui/resolve/use_suggestion_placement.rs
+++ b/src/test/ui/resolve/use_suggestion_placement.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::path support
+
 macro_rules! y {
     () => {}
 }
diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr
index 1cc2d06..3607aa5 100644
--- a/src/test/ui/resolve/use_suggestion_placement.stderr
+++ b/src/test/ui/resolve/use_suggestion_placement.stderr
@@ -1,33 +1,33 @@
 error[E0412]: cannot find type `Path` in this scope
-  --> $DIR/use_suggestion_placement.rs:25:16
+  --> $DIR/use_suggestion_placement.rs:27:16
    |
-25 |     type Bar = Path; //~ ERROR cannot find
+27 |     type Bar = Path; //~ ERROR cannot find
    |                ^^^^ not found in this scope
 help: possible candidate is found in another module, you can import it into scope
    |
-21 |     use std::path::Path;
+23 |     use std::path::Path;
    |
 
 error[E0425]: cannot find value `A` in this scope
-  --> $DIR/use_suggestion_placement.rs:30:13
+  --> $DIR/use_suggestion_placement.rs:32:13
    |
-30 |     let _ = A; //~ ERROR cannot find
+32 |     let _ = A; //~ ERROR cannot find
    |             ^ not found in this scope
 help: possible candidate is found in another module, you can import it into scope
    |
-11 | use m::A;
+13 | use m::A;
    |
 
 error[E0412]: cannot find type `HashMap` in this scope
-  --> $DIR/use_suggestion_placement.rs:35:23
+  --> $DIR/use_suggestion_placement.rs:37:23
    |
-35 |     type Dict<K, V> = HashMap<K, V>; //~ ERROR cannot find
+37 |     type Dict<K, V> = HashMap<K, V>; //~ ERROR cannot find
    |                       ^^^^^^^ not found in this scope
 help: possible candidates are found in other modules, you can import them into scope
    |
-11 | use std::collections::HashMap;
+13 | use std::collections::HashMap;
    |
-11 | use std::collections::hash_map::HashMap;
+13 | use std::collections::hash_map::HashMap;
    |
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr b/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr
index ebf9e49..8aa17ad 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr
@@ -1,4 +1,4 @@
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
   --> $DIR/suggestion.rs:12:12
    |
 12 |     if let Some(y) = &Some(22) { //~ ERROR non-reference pattern
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
index 66673c1..8e03c30 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
@@ -42,7 +42,7 @@
 
 fn test4(f: &Test) {
     f.f.call_mut(())
-    //~^ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
+    //~^ ERROR: cannot borrow `Box` content `*f.f` of immutable binding as mutable
 }
 
 fn test5(f: &mut Test) {
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
index 542ee99..581b366 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
@@ -19,7 +19,7 @@
 35 |     (*f)();
    |     ^^^^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable `Box` content `*f.f` as mutable
+error[E0596]: cannot borrow `Box` content `*f.f` of immutable binding as mutable
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
    |
 43 | fn test4(f: &Test) {
diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr
index 0785261..06f0e6e 100644
--- a/src/test/ui/span/coerce-suggestions.stderr
+++ b/src/test/ui/span/coerce-suggestions.stderr
@@ -6,9 +6,6 @@
    |
    = note: expected type `usize`
               found type `std::string::String`
-   = help: here are some functions which might fulfill your needs:
-           - .capacity()
-           - .len()
 
 error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:19:19
@@ -44,7 +41,10 @@
   --> $DIR/coerce-suggestions.rs:27:9
    |
 27 |     f = box f;
-   |         ^^^^^ cyclic type of infinite size
+   |         ^^^^^
+   |         |
+   |         cyclic type of infinite size
+   |         help: try using a conversion method: `box f.to_string()`
 
 error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:31:9
diff --git a/src/test/ui/span/gated-features-attr-spans.stderr b/src/test/ui/span/gated-features-attr-spans.stderr
index d067470..74a2c1d 100644
--- a/src/test/ui/span/gated-features-attr-spans.stderr
+++ b/src/test/ui/span/gated-features-attr-spans.stderr
@@ -1,4 +1,4 @@
-error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
+error[E0658]: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
   --> $DIR/gated-features-attr-spans.rs:13:1
    |
 13 | #[repr(align(16))] //~ ERROR is experimental
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(repr_align)] to the crate attributes to enable
 
-error: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
   --> $DIR/gated-features-attr-spans.rs:20:1
    |
 20 | #[repr(simd)] //~ ERROR are experimental
diff --git a/src/test/ui/span/impl-parsing.rs b/src/test/ui/span/impl-parsing.rs
new file mode 100644
index 0000000..064e3c3
--- /dev/null
+++ b/src/test/ui/span/impl-parsing.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only -Z continue-parse-after-error
+
+impl ! {} // OK
+impl ! where u8: Copy {} // OK
+
+impl Trait Type {} //~ ERROR missing `for` in a trait impl
+impl Trait .. {} //~ ERROR missing `for` in a trait impl
+impl ?Sized for Type {} //~ ERROR expected a trait, found type
+impl ?Sized for .. {} //~ ERROR expected a trait, found type
+
+default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
diff --git a/src/test/ui/span/impl-parsing.stderr b/src/test/ui/span/impl-parsing.stderr
new file mode 100644
index 0000000..9126384
--- /dev/null
+++ b/src/test/ui/span/impl-parsing.stderr
@@ -0,0 +1,32 @@
+error: missing `for` in a trait impl
+  --> $DIR/impl-parsing.rs:16:11
+   |
+16 | impl Trait Type {} //~ ERROR missing `for` in a trait impl
+   |           ^
+
+error: missing `for` in a trait impl
+  --> $DIR/impl-parsing.rs:17:11
+   |
+17 | impl Trait .. {} //~ ERROR missing `for` in a trait impl
+   |           ^
+
+error: expected a trait, found type
+  --> $DIR/impl-parsing.rs:18:6
+   |
+18 | impl ?Sized for Type {} //~ ERROR expected a trait, found type
+   |      ^^^^^^
+
+error: expected a trait, found type
+  --> $DIR/impl-parsing.rs:19:6
+   |
+19 | impl ?Sized for .. {} //~ ERROR expected a trait, found type
+   |      ^^^^^^
+
+error: expected `impl`, found `FAIL`
+  --> $DIR/impl-parsing.rs:21:16
+   |
+21 | default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
+   |                ^^^^ expected `impl` here
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr
index 81ba005..9046b90 100644
--- a/src/test/ui/span/issue-29595.stderr
+++ b/src/test/ui/span/issue-29595.stderr
@@ -4,7 +4,11 @@
 17 |     let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied
    |                 ^^^^^ the trait `Tr` is not implemented for `u8`
    |
-   = note: required by `Tr::C`
+note: required by `Tr::C`
+  --> $DIR/issue-29595.rs:13:5
+   |
+13 |     const C: Self;
+   |     ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-33884.rs b/src/test/ui/span/issue-33884.rs
index 93aa502..d0f23ca 100644
--- a/src/test/ui/span/issue-33884.rs
+++ b/src/test/ui/span/issue-33884.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::net support
+
 use std::net::TcpListener;
 use std::net::TcpStream;
 use std::io::{self, Read, Write};
diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr
index cf5190b..5a9c205 100644
--- a/src/test/ui/span/issue-33884.stderr
+++ b/src/test/ui/span/issue-33884.stderr
@@ -1,7 +1,7 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-33884.rs:16:22
+  --> $DIR/issue-33884.rs:18:22
    |
-16 |     stream.write_fmt(format!("message received"))
+18 |     stream.write_fmt(format!("message received"))
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::fmt::Arguments`, found struct `std::string::String`
    |
    = note: expected type `std::fmt::Arguments<'_>`
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index 3794d6b..18860a7 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -33,8 +33,6 @@
    |
    = note: expected type `usize`
               found type `&'static str`
-   = help: here are some functions which might fulfill your needs:
-           - .len()
 
 error[E0061]: this function takes 2 parameters but 3 parameters were supplied
   --> $DIR/issue-34264.rs:20:5
diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr
index 50908b2..7f39210 100644
--- a/src/test/ui/span/issue-36530.stderr
+++ b/src/test/ui/span/issue-36530.stderr
@@ -1,4 +1,4 @@
-error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/issue-36530.rs:11:1
    |
 11 | #[foo] //~ ERROR is currently unknown to the compiler
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
   --> $DIR/issue-36530.rs:13:5
    |
 13 |     #![foo] //~ ERROR is currently unknown to the compiler
diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr
index e3e9334..2ac132f 100644
--- a/src/test/ui/span/macro-ty-params.stderr
+++ b/src/test/ui/span/macro-ty-params.stderr
@@ -22,5 +22,5 @@
 20 |     m!(MyTrait<>); //~ ERROR generic arguments in macro path
    |               ^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/specialization-feature-gate-default.stderr b/src/test/ui/specialization-feature-gate-default.stderr
index e17d130..96e0fe1 100644
--- a/src/test/ui/specialization-feature-gate-default.stderr
+++ b/src/test/ui/specialization-feature-gate-default.stderr
@@ -1,4 +1,4 @@
-error: specialization is unstable (see issue #31844)
+error[E0658]: specialization is unstable (see issue #31844)
   --> $DIR/specialization-feature-gate-default.rs:20:5
    |
 20 |     default fn foo(&self) {} //~ ERROR specialization is unstable
diff --git a/src/test/ui/suggestions/conversion-methods.rs b/src/test/ui/suggestions/conversion-methods.rs
new file mode 100644
index 0000000..8a53bc3
--- /dev/null
+++ b/src/test/ui/suggestions/conversion-methods.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::path::{Path, PathBuf};
+
+
+fn main() {
+    let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+    let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+    //~^ ERROR mismatched types
+
+    let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+    //~^ ERROR mismatched types
+
+    let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/conversion-methods.stderr b/src/test/ui/suggestions/conversion-methods.stderr
new file mode 100644
index 0000000..96fdc29
--- /dev/null
+++ b/src/test/ui/suggestions/conversion-methods.stderr
@@ -0,0 +1,50 @@
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:15:41
+   |
+15 |     let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types
+   |                                         ^^^^^^^^^^^^^^^^^^^^^
+   |                                         |
+   |                                         expected struct `std::string::String`, found reference
+   |                                         help: try using a conversion method: `"'Tis a fond Ambush—".to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:16:40
+   |
+16 |     let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                        |
+   |                                        expected struct `std::path::PathBuf`, found reference
+   |                                        help: try using a conversion method: `Path::new("/ern/her/own/surprise").to_path_buf()`
+   |
+   = note: expected type `std::path::PathBuf`
+              found type `&std::path::Path`
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:19:40
+   |
+19 |     let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
+   |                                        ^
+   |                                        |
+   |                                        expected struct `std::string::String`, found integral variable
+   |                                        help: try using a conversion method: `2.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/conversion-methods.rs:22:47
+   |
+22 |     let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3]; //~ ERROR mismatched types
+   |                                               ^^^^^^^^^^
+   |                                               |
+   |                                               expected struct `std::vec::Vec`, found reference
+   |                                               help: try using a conversion method: `&[1, 2, 3].to_vec()`
+   |
+   = note: expected type `std::vec::Vec<usize>`
+              found type `&[{integer}; 3]`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/suggestions/dont-suggest-dereference-on-arg.stderr b/src/test/ui/suggestions/dont-suggest-dereference-on-arg.stderr
index 799d908..5413dcd 100644
--- a/src/test/ui/suggestions/dont-suggest-dereference-on-arg.stderr
+++ b/src/test/ui/suggestions/dont-suggest-dereference-on-arg.stderr
@@ -1,4 +1,4 @@
-error: non-reference pattern used to match a reference (see issue #42640)
+error[E0658]: non-reference pattern used to match a reference (see issue #42640)
   --> $DIR/dont-suggest-dereference-on-arg.rs:16:18
    |
 16 |         .filter(|&(ref a, _)| foo(a))
diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.rs b/src/test/ui/suggestions/fn-closure-mutable-capture.rs
new file mode 100644
index 0000000..385efeb
--- /dev/null
+++ b/src/test/ui/suggestions/fn-closure-mutable-capture.rs
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn bar<F: Fn()>(_f: F) {}
+
+pub fn foo() {
+    let mut x = 0;
+    bar(move || x = 1);
+    //~^ ERROR cannot assign to captured outer variable in an `Fn` closure
+    //~| NOTE `Fn` closures cannot capture their enclosing environment for modifications
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.stderr b/src/test/ui/suggestions/fn-closure-mutable-capture.stderr
new file mode 100644
index 0000000..6c79e44
--- /dev/null
+++ b/src/test/ui/suggestions/fn-closure-mutable-capture.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/fn-closure-mutable-capture.rs:15:17
+   |
+15 |     bar(move || x = 1);
+   |                 ^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/fn-closure-mutable-capture.rs:15:9
+   |
+15 |     bar(move || x = 1);
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/typeck-default-trait-impl-outside-crate.rs b/src/test/ui/suggestions/issue-45562.rs
similarity index 72%
copy from src/test/ui/typeck-default-trait-impl-outside-crate.rs
copy to src/test/ui/suggestions/issue-45562.rs
index ff0446e..f493df5 100644
--- a/src/test/ui/typeck-default-trait-impl-outside-crate.rs
+++ b/src/test/ui/suggestions/issue-45562.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(optin_builtin_traits)]
+#[no_mangle] pub const RAH: usize = 5;
+//~^ ERROR const items should never be #[no_mangle]
 
-#[allow(auto_impl)]
-impl Copy for .. {} //~ ERROR E0318
 fn main() {}
diff --git a/src/test/ui/suggestions/issue-45562.stderr b/src/test/ui/suggestions/issue-45562.stderr
new file mode 100644
index 0000000..2f8c4cd
--- /dev/null
+++ b/src/test/ui/suggestions/issue-45562.stderr
@@ -0,0 +1,12 @@
+error: const items should never be #[no_mangle]
+  --> $DIR/issue-45562.rs:11:14
+   |
+11 | #[no_mangle] pub const RAH: usize = 5;
+   |              ---------^^^^^^^^^^^^^^^^
+   |              |
+   |              help: try a static value: `pub static`
+   |
+   = note: #[deny(no_mangle_const_items)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
new file mode 100644
index 0000000..fa5bafa
--- /dev/null
+++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = 2.0.powi(2);
+    //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+    let y = 2.0;
+    let x = y.powi(2);
+    //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
new file mode 100644
index 0000000..c2b292c
--- /dev/null
+++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
@@ -0,0 +1,22 @@
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
+   |
+12 |     let x = 2.0.powi(2);
+   |                 ^^^^
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+12 |     let x = 2.0_f32.powi(2);
+   |             ^^^^^^^
+
+error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:15:15
+   |
+15 |     let x = y.powi(2);
+   |               ^^^^
+help: you must specify a type for this binding, like `f32`
+   |
+14 |     let y: f32 = 2.0;
+   |         ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/ui/suggestions/numeric-cast-2.rs
similarity index 61%
copy from src/test/compile-fail/regions-escape-unboxed-closure.rs
copy to src/test/ui/suggestions/numeric-cast-2.rs
index cf41fad..2092b6b 100644
--- a/src/test/compile-fail/regions-escape-unboxed-closure.rs
+++ b/src/test/ui/suggestions/numeric-cast-2.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,10 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: &mut FnMut(&isize)) {
+fn foo() -> i32 {
+    4
 }
-
 fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
+    let x: u16 = foo();
+    //~^ ERROR mismatched types
+    let y: i64 = x + x;
+    //~^ ERROR mismatched types
+    let z: i32 = x + x;
+    //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/suggestions/numeric-cast-2.stderr b/src/test/ui/suggestions/numeric-cast-2.stderr
new file mode 100644
index 0000000..90086d2
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast-2.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:15:18
+   |
+15 |     let x: u16 = foo();
+   |                  ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:17:18
+   |
+17 |     let y: i64 = x + x;
+   |                  ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:19:18
+   |
+19 |     let z: i32 = x + x;
+   |                  ^^^^^ expected i32, found u16
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/suggestions/numeric-cast.rs b/src/test/ui/suggestions/numeric-cast.rs
new file mode 100644
index 0000000..6e14403
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast.rs
@@ -0,0 +1,315 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+fn foo<N>(_x: N) {}
+
+fn main() {
+    let x_usize: usize = 1;
+    let x_u64: u64 = 2;
+    let x_u32: u32 = 3;
+    let x_u16: u16 = 4;
+    let x_u8: u8 = 5;
+    let x_isize: isize = 6;
+    let x_i64: i64 = 7;
+    let x_i32: i32 = 8;
+    let x_i16: i16 = 9;
+    let x_i8: i8 = 10;
+    let x_f64: f64 = 11.0;
+    let x_f32: f32 = 12.0;
+
+    foo::<usize>(x_usize);
+    foo::<usize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<isize>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_isize);
+    foo::<isize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u64);
+    foo::<u64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i64);
+    foo::<i64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u32);
+    foo::<u32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i32);
+    foo::<i32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u16);
+    foo::<u16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i16);
+    foo::<i16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u8);
+    foo::<u8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i8);
+    foo::<i8>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<f64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_f64);
+    foo::<f64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<f32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_f32);
+}
diff --git a/src/test/ui/suggestions/numeric-cast.stderr b/src/test/ui/suggestions/numeric-cast.stderr
new file mode 100644
index 0000000..0ce3d08
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast.stderr
@@ -0,0 +1,886 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:29:18
+   |
+29 |     foo::<usize>(x_u64);
+   |                  ^^^^^ expected usize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:31:18
+   |
+31 |     foo::<usize>(x_u32);
+   |                  ^^^^^ expected usize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:33:18
+   |
+33 |     foo::<usize>(x_u16);
+   |                  ^^^^^ expected usize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:35:18
+   |
+35 |     foo::<usize>(x_u8);
+   |                  ^^^^ expected usize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:37:18
+   |
+37 |     foo::<usize>(x_isize);
+   |                  ^^^^^^^ expected usize, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:39:18
+   |
+39 |     foo::<usize>(x_i64);
+   |                  ^^^^^ expected usize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:41:18
+   |
+41 |     foo::<usize>(x_i32);
+   |                  ^^^^^ expected usize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:43:18
+   |
+43 |     foo::<usize>(x_i16);
+   |                  ^^^^^ expected usize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:45:18
+   |
+45 |     foo::<usize>(x_i8);
+   |                  ^^^^ expected usize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:47:18
+   |
+47 |     foo::<usize>(x_f64);
+   |                  ^^^^^ expected usize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:49:18
+   |
+49 |     foo::<usize>(x_f32);
+   |                  ^^^^^ expected usize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:52:18
+   |
+52 |     foo::<isize>(x_usize);
+   |                  ^^^^^^^ expected isize, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:54:18
+   |
+54 |     foo::<isize>(x_u64);
+   |                  ^^^^^ expected isize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:56:18
+   |
+56 |     foo::<isize>(x_u32);
+   |                  ^^^^^ expected isize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:58:18
+   |
+58 |     foo::<isize>(x_u16);
+   |                  ^^^^^ expected isize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:60:18
+   |
+60 |     foo::<isize>(x_u8);
+   |                  ^^^^ expected isize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:63:18
+   |
+63 |     foo::<isize>(x_i64);
+   |                  ^^^^^ expected isize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:65:18
+   |
+65 |     foo::<isize>(x_i32);
+   |                  ^^^^^ expected isize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:67:18
+   |
+67 |     foo::<isize>(x_i16);
+   |                  ^^^^^ expected isize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:69:18
+   |
+69 |     foo::<isize>(x_i8);
+   |                  ^^^^ expected isize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:71:18
+   |
+71 |     foo::<isize>(x_f64);
+   |                  ^^^^^ expected isize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:73:18
+   |
+73 |     foo::<isize>(x_f32);
+   |                  ^^^^^ expected isize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:76:16
+   |
+76 |     foo::<u64>(x_usize);
+   |                ^^^^^^^ expected u64, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:79:16
+   |
+79 |     foo::<u64>(x_u32);
+   |                ^^^^^ expected u64, found u32
+help: you can cast an `u32` to `u64`, which will zero-extend the source value
+   |
+79 |     foo::<u64>(x_u32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:81:16
+   |
+81 |     foo::<u64>(x_u16);
+   |                ^^^^^ expected u64, found u16
+help: you can cast an `u16` to `u64`, which will zero-extend the source value
+   |
+81 |     foo::<u64>(x_u16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:83:16
+   |
+83 |     foo::<u64>(x_u8);
+   |                ^^^^ expected u64, found u8
+help: you can cast an `u8` to `u64`, which will zero-extend the source value
+   |
+83 |     foo::<u64>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:85:16
+   |
+85 |     foo::<u64>(x_isize);
+   |                ^^^^^^^ expected u64, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:87:16
+   |
+87 |     foo::<u64>(x_i64);
+   |                ^^^^^ expected u64, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:89:16
+   |
+89 |     foo::<u64>(x_i32);
+   |                ^^^^^ expected u64, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:91:16
+   |
+91 |     foo::<u64>(x_i16);
+   |                ^^^^^ expected u64, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:93:16
+   |
+93 |     foo::<u64>(x_i8);
+   |                ^^^^ expected u64, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:95:16
+   |
+95 |     foo::<u64>(x_f64);
+   |                ^^^^^ expected u64, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:97:16
+   |
+97 |     foo::<u64>(x_f32);
+   |                ^^^^^ expected u64, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:100:16
+    |
+100 |     foo::<i64>(x_usize);
+    |                ^^^^^^^ expected i64, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:102:16
+    |
+102 |     foo::<i64>(x_u64);
+    |                ^^^^^ expected i64, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:104:16
+    |
+104 |     foo::<i64>(x_u32);
+    |                ^^^^^ expected i64, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:106:16
+    |
+106 |     foo::<i64>(x_u16);
+    |                ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:108:16
+    |
+108 |     foo::<i64>(x_u8);
+    |                ^^^^ expected i64, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:110:16
+    |
+110 |     foo::<i64>(x_isize);
+    |                ^^^^^^^ expected i64, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:113:16
+    |
+113 |     foo::<i64>(x_i32);
+    |                ^^^^^ expected i64, found i32
+help: you can cast an `i32` to `i64`, which will sign-extend the source value
+    |
+113 |     foo::<i64>(x_i32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:115:16
+    |
+115 |     foo::<i64>(x_i16);
+    |                ^^^^^ expected i64, found i16
+help: you can cast an `i16` to `i64`, which will sign-extend the source value
+    |
+115 |     foo::<i64>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:117:16
+    |
+117 |     foo::<i64>(x_i8);
+    |                ^^^^ expected i64, found i8
+help: you can cast an `i8` to `i64`, which will sign-extend the source value
+    |
+117 |     foo::<i64>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:119:16
+    |
+119 |     foo::<i64>(x_f64);
+    |                ^^^^^ expected i64, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:121:16
+    |
+121 |     foo::<i64>(x_f32);
+    |                ^^^^^ expected i64, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:124:16
+    |
+124 |     foo::<u32>(x_usize);
+    |                ^^^^^^^ expected u32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:126:16
+    |
+126 |     foo::<u32>(x_u64);
+    |                ^^^^^ expected u32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:129:16
+    |
+129 |     foo::<u32>(x_u16);
+    |                ^^^^^ expected u32, found u16
+help: you can cast an `u16` to `u32`, which will zero-extend the source value
+    |
+129 |     foo::<u32>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:131:16
+    |
+131 |     foo::<u32>(x_u8);
+    |                ^^^^ expected u32, found u8
+help: you can cast an `u8` to `u32`, which will zero-extend the source value
+    |
+131 |     foo::<u32>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:133:16
+    |
+133 |     foo::<u32>(x_isize);
+    |                ^^^^^^^ expected u32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:135:16
+    |
+135 |     foo::<u32>(x_i64);
+    |                ^^^^^ expected u32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:137:16
+    |
+137 |     foo::<u32>(x_i32);
+    |                ^^^^^ expected u32, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:139:16
+    |
+139 |     foo::<u32>(x_i16);
+    |                ^^^^^ expected u32, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:141:16
+    |
+141 |     foo::<u32>(x_i8);
+    |                ^^^^ expected u32, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:143:16
+    |
+143 |     foo::<u32>(x_f64);
+    |                ^^^^^ expected u32, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:145:16
+    |
+145 |     foo::<u32>(x_f32);
+    |                ^^^^^ expected u32, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:148:16
+    |
+148 |     foo::<i32>(x_usize);
+    |                ^^^^^^^ expected i32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:150:16
+    |
+150 |     foo::<i32>(x_u64);
+    |                ^^^^^ expected i32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:152:16
+    |
+152 |     foo::<i32>(x_u32);
+    |                ^^^^^ expected i32, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:154:16
+    |
+154 |     foo::<i32>(x_u16);
+    |                ^^^^^ expected i32, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:156:16
+    |
+156 |     foo::<i32>(x_u8);
+    |                ^^^^ expected i32, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:158:16
+    |
+158 |     foo::<i32>(x_isize);
+    |                ^^^^^^^ expected i32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:160:16
+    |
+160 |     foo::<i32>(x_i64);
+    |                ^^^^^ expected i32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:163:16
+    |
+163 |     foo::<i32>(x_i16);
+    |                ^^^^^ expected i32, found i16
+help: you can cast an `i16` to `i32`, which will sign-extend the source value
+    |
+163 |     foo::<i32>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:165:16
+    |
+165 |     foo::<i32>(x_i8);
+    |                ^^^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+    |
+165 |     foo::<i32>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:167:16
+    |
+167 |     foo::<i32>(x_f64);
+    |                ^^^^^ expected i32, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:169:16
+    |
+169 |     foo::<i32>(x_f32);
+    |                ^^^^^ expected i32, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:172:16
+    |
+172 |     foo::<u16>(x_usize);
+    |                ^^^^^^^ expected u16, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:174:16
+    |
+174 |     foo::<u16>(x_u64);
+    |                ^^^^^ expected u16, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:176:16
+    |
+176 |     foo::<u16>(x_u32);
+    |                ^^^^^ expected u16, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:179:16
+    |
+179 |     foo::<u16>(x_u8);
+    |                ^^^^ expected u16, found u8
+help: you can cast an `u8` to `u16`, which will zero-extend the source value
+    |
+179 |     foo::<u16>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:181:16
+    |
+181 |     foo::<u16>(x_isize);
+    |                ^^^^^^^ expected u16, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:183:16
+    |
+183 |     foo::<u16>(x_i64);
+    |                ^^^^^ expected u16, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:185:16
+    |
+185 |     foo::<u16>(x_i32);
+    |                ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:187:16
+    |
+187 |     foo::<u16>(x_i16);
+    |                ^^^^^ expected u16, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:189:16
+    |
+189 |     foo::<u16>(x_i8);
+    |                ^^^^ expected u16, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:191:16
+    |
+191 |     foo::<u16>(x_f64);
+    |                ^^^^^ expected u16, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:193:16
+    |
+193 |     foo::<u16>(x_f32);
+    |                ^^^^^ expected u16, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:196:16
+    |
+196 |     foo::<i16>(x_usize);
+    |                ^^^^^^^ expected i16, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:198:16
+    |
+198 |     foo::<i16>(x_u64);
+    |                ^^^^^ expected i16, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:200:16
+    |
+200 |     foo::<i16>(x_u32);
+    |                ^^^^^ expected i16, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:202:16
+    |
+202 |     foo::<i16>(x_u16);
+    |                ^^^^^ expected i16, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:204:16
+    |
+204 |     foo::<i16>(x_u8);
+    |                ^^^^ expected i16, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:206:16
+    |
+206 |     foo::<i16>(x_isize);
+    |                ^^^^^^^ expected i16, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:208:16
+    |
+208 |     foo::<i16>(x_i64);
+    |                ^^^^^ expected i16, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:210:16
+    |
+210 |     foo::<i16>(x_i32);
+    |                ^^^^^ expected i16, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:213:16
+    |
+213 |     foo::<i16>(x_i8);
+    |                ^^^^ expected i16, found i8
+help: you can cast an `i8` to `i16`, which will sign-extend the source value
+    |
+213 |     foo::<i16>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:215:16
+    |
+215 |     foo::<i16>(x_f64);
+    |                ^^^^^ expected i16, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:217:16
+    |
+217 |     foo::<i16>(x_f32);
+    |                ^^^^^ expected i16, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:220:15
+    |
+220 |     foo::<u8>(x_usize);
+    |               ^^^^^^^ expected u8, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:222:15
+    |
+222 |     foo::<u8>(x_u64);
+    |               ^^^^^ expected u8, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:224:15
+    |
+224 |     foo::<u8>(x_u32);
+    |               ^^^^^ expected u8, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:226:15
+    |
+226 |     foo::<u8>(x_u16);
+    |               ^^^^^ expected u8, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:229:15
+    |
+229 |     foo::<u8>(x_isize);
+    |               ^^^^^^^ expected u8, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:231:15
+    |
+231 |     foo::<u8>(x_i64);
+    |               ^^^^^ expected u8, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:233:15
+    |
+233 |     foo::<u8>(x_i32);
+    |               ^^^^^ expected u8, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:235:15
+    |
+235 |     foo::<u8>(x_i16);
+    |               ^^^^^ expected u8, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:237:15
+    |
+237 |     foo::<u8>(x_i8);
+    |               ^^^^ expected u8, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:239:15
+    |
+239 |     foo::<u8>(x_f64);
+    |               ^^^^^ expected u8, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:241:15
+    |
+241 |     foo::<u8>(x_f32);
+    |               ^^^^^ expected u8, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:244:15
+    |
+244 |     foo::<i8>(x_usize);
+    |               ^^^^^^^ expected i8, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:246:15
+    |
+246 |     foo::<i8>(x_u64);
+    |               ^^^^^ expected i8, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:248:15
+    |
+248 |     foo::<i8>(x_u32);
+    |               ^^^^^ expected i8, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:250:15
+    |
+250 |     foo::<i8>(x_u16);
+    |               ^^^^^ expected i8, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:252:15
+    |
+252 |     foo::<i8>(x_u8);
+    |               ^^^^ expected i8, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:254:15
+    |
+254 |     foo::<i8>(x_isize);
+    |               ^^^^^^^ expected i8, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:256:15
+    |
+256 |     foo::<i8>(x_i64);
+    |               ^^^^^ expected i8, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:258:15
+    |
+258 |     foo::<i8>(x_i32);
+    |               ^^^^^ expected i8, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:260:15
+    |
+260 |     foo::<i8>(x_i16);
+    |               ^^^^^ expected i8, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:263:15
+    |
+263 |     foo::<i8>(x_f64);
+    |               ^^^^^ expected i8, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:265:15
+    |
+265 |     foo::<i8>(x_f32);
+    |               ^^^^^ expected i8, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:268:16
+    |
+268 |     foo::<f64>(x_usize);
+    |                ^^^^^^^ expected f64, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:270:16
+    |
+270 |     foo::<f64>(x_u64);
+    |                ^^^^^ expected f64, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:272:16
+    |
+272 |     foo::<f64>(x_u32);
+    |                ^^^^^ expected f64, found u32
+help: you can cast an `u32` to `f64`, producing the floating point representation of the integer
+    |
+272 |     foo::<f64>(x_u32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:274:16
+    |
+274 |     foo::<f64>(x_u16);
+    |                ^^^^^ expected f64, found u16
+help: you can cast an `u16` to `f64`, producing the floating point representation of the integer
+    |
+274 |     foo::<f64>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:276:16
+    |
+276 |     foo::<f64>(x_u8);
+    |                ^^^^ expected f64, found u8
+help: you can cast an `u8` to `f64`, producing the floating point representation of the integer
+    |
+276 |     foo::<f64>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:278:16
+    |
+278 |     foo::<f64>(x_isize);
+    |                ^^^^^^^ expected f64, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:280:16
+    |
+280 |     foo::<f64>(x_i64);
+    |                ^^^^^ expected f64, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:282:16
+    |
+282 |     foo::<f64>(x_i32);
+    |                ^^^^^ expected f64, found i32
+help: you can cast an `i32` to `f64`, producing the floating point representation of the integer
+    |
+282 |     foo::<f64>(x_i32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:284:16
+    |
+284 |     foo::<f64>(x_i16);
+    |                ^^^^^ expected f64, found i16
+help: you can cast an `i16` to `f64`, producing the floating point representation of the integer
+    |
+284 |     foo::<f64>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:286:16
+    |
+286 |     foo::<f64>(x_i8);
+    |                ^^^^ expected f64, found i8
+help: you can cast an `i8` to `f64`, producing the floating point representation of the integer
+    |
+286 |     foo::<f64>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:289:16
+    |
+289 |     foo::<f64>(x_f32);
+    |                ^^^^^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+    |
+289 |     foo::<f64>(x_f32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:292:16
+    |
+292 |     foo::<f32>(x_usize);
+    |                ^^^^^^^ expected f32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:294:16
+    |
+294 |     foo::<f32>(x_u64);
+    |                ^^^^^ expected f32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:296:16
+    |
+296 |     foo::<f32>(x_u32);
+    |                ^^^^^ expected f32, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:298:16
+    |
+298 |     foo::<f32>(x_u16);
+    |                ^^^^^ expected f32, found u16
+help: you can cast an `u16` to `f32`, producing the floating point representation of the integer
+    |
+298 |     foo::<f32>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:300:16
+    |
+300 |     foo::<f32>(x_u8);
+    |                ^^^^ expected f32, found u8
+help: you can cast an `u8` to `f32`, producing the floating point representation of the integer
+    |
+300 |     foo::<f32>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:302:16
+    |
+302 |     foo::<f32>(x_isize);
+    |                ^^^^^^^ expected f32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:304:16
+    |
+304 |     foo::<f32>(x_i64);
+    |                ^^^^^ expected f32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:306:16
+    |
+306 |     foo::<f32>(x_i32);
+    |                ^^^^^ expected f32, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:308:16
+    |
+308 |     foo::<f32>(x_i16);
+    |                ^^^^^ expected f32, found i16
+help: you can cast an `i16` to `f32`, producing the floating point representation of the integer
+    |
+308 |     foo::<f32>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:310:16
+    |
+310 |     foo::<f32>(x_i8);
+    |                ^^^^ expected f32, found i8
+help: you can cast an `i8` to `f32`, producing the floating point representation of the integer
+    |
+310 |     foo::<f32>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:312:16
+    |
+312 |     foo::<f32>(x_f64);
+    |                ^^^^^ expected f32, found f64
+
+error: aborting due to 132 previous errors
+
diff --git a/src/test/ui/suggestions/try-operator-on-main.rs b/src/test/ui/suggestions/try-operator-on-main.rs
index e9d2859..e52ef45 100644
--- a/src/test/ui/suggestions/try-operator-on-main.rs
+++ b/src/test/ui/suggestions/try-operator-on-main.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-cloudabi no std::fs support
+
 #![feature(try_trait)]
 
 use std::ops::Try;
diff --git a/src/test/ui/suggestions/try-operator-on-main.stderr b/src/test/ui/suggestions/try-operator-on-main.stderr
index 8b17e06..3b32b4a 100644
--- a/src/test/ui/suggestions/try-operator-on-main.stderr
+++ b/src/test/ui/suggestions/try-operator-on-main.stderr
@@ -1,7 +1,7 @@
 error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
-  --> $DIR/try-operator-on-main.rs:17:5
+  --> $DIR/try-operator-on-main.rs:19:5
    |
-17 |     std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
+19 |     std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
    |     ---------------------------
    |     |
    |     cannot use the `?` operator in a function that returns `()`
@@ -11,9 +11,9 @@
    = note: required by `std::ops::Try::from_error`
 
 error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
-  --> $DIR/try-operator-on-main.rs:20:5
+  --> $DIR/try-operator-on-main.rs:22:5
    |
-20 |     ()?; //~ ERROR the `?` operator can only
+22 |     ()?; //~ ERROR the `?` operator can only
    |     ---
    |     |
    |     the `?` operator cannot be applied to type `()`
@@ -23,17 +23,21 @@
    = note: required by `std::ops::Try::into_result`
 
 error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
-  --> $DIR/try-operator-on-main.rs:23:5
+  --> $DIR/try-operator-on-main.rs:25:5
    |
-23 |     try_trait_generic::<()>(); //~ ERROR the trait bound
+25 |     try_trait_generic::<()>(); //~ ERROR the trait bound
    |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()`
    |
-   = note: required by `try_trait_generic`
+note: required by `try_trait_generic`
+  --> $DIR/try-operator-on-main.rs:30:1
+   |
+30 | fn try_trait_generic<T: Try>() -> T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
-  --> $DIR/try-operator-on-main.rs:30:5
+  --> $DIR/try-operator-on-main.rs:32:5
    |
-30 |     ()?; //~ ERROR the `?` operator can only
+32 |     ()?; //~ ERROR the `?` operator can only
    |     ---
    |     |
    |     the `?` operator cannot be applied to type `()`
diff --git a/src/test/ui/target-feature-wrong.rs b/src/test/ui/target-feature-wrong.rs
new file mode 100644
index 0000000..e70d549
--- /dev/null
+++ b/src/test/ui/target-feature-wrong.rs
@@ -0,0 +1,37 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-arm
+// ignore-aarch64
+// ignore-wasm
+// ignore-emscripten
+
+#![feature(target_feature)]
+
+#[target_feature = "+sse2"]
+//~^ WARN: deprecated
+#[target_feature(enable = "foo")]
+//~^ ERROR: not valid for this target
+#[target_feature(bar)]
+//~^ ERROR: only accepts sub-keys
+#[target_feature(disable = "baz")]
+//~^ ERROR: only accepts sub-keys
+unsafe fn foo() {}
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR: can only be applied to `unsafe` function
+fn bar() {}
+
+fn main() {
+    unsafe {
+        foo();
+        bar();
+    }
+}
diff --git a/src/test/ui/target-feature-wrong.stderr b/src/test/ui/target-feature-wrong.stderr
new file mode 100644
index 0000000..c5534bf
--- /dev/null
+++ b/src/test/ui/target-feature-wrong.stderr
@@ -0,0 +1,32 @@
+warning: #[target_feature = ".."] is deprecated and will eventually be removed, use #[target_feature(enable = "..")] instead
+  --> $DIR/target-feature-wrong.rs:18:1
+   |
+18 | #[target_feature = "+sse2"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the feature named `foo` is not valid for this target
+  --> $DIR/target-feature-wrong.rs:20:18
+   |
+20 | #[target_feature(enable = "foo")]
+   |                  ^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+  --> $DIR/target-feature-wrong.rs:22:18
+   |
+22 | #[target_feature(bar)]
+   |                  ^^^
+
+error: #[target_feature(..)] only accepts sub-keys of `enable` currently
+  --> $DIR/target-feature-wrong.rs:24:18
+   |
+24 | #[target_feature(disable = "baz")]
+   |                  ^^^^^^^^^^^^^^^
+
+error: #[target_feature(..)] can only be applied to `unsafe` function
+  --> $DIR/target-feature-wrong.rs:28:1
+   |
+28 | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/token/issue-15980.rs b/src/test/ui/token/issue-15980.rs
new file mode 100644
index 0000000..e1b134c
--- /dev/null
+++ b/src/test/ui/token/issue-15980.rs
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::io;
+
+fn main(){
+    let x: io::IoResult<()> = Ok(());
+    //~^ ERROR cannot find type `IoResult` in module `io`
+    //~| NOTE did you mean `Result`?
+    match x {
+        Err(ref e) if e.kind == io::EndOfFile {
+            //~^ NOTE while parsing this struct
+            return
+            //~^ ERROR expected identifier, found keyword `return`
+            //~| NOTE expected identifier, found keyword
+        }
+        //~^ NOTE expected one of `.`, `=>`, `?`, or an operator here
+        _ => {}
+        //~^ ERROR expected one of `.`, `=>`, `?`, or an operator, found `_`
+        //~| NOTE unexpected token
+    }
+}
diff --git a/src/test/ui/token/issue-15980.stderr b/src/test/ui/token/issue-15980.stderr
new file mode 100644
index 0000000..71cd4b2
--- /dev/null
+++ b/src/test/ui/token/issue-15980.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `return`
+  --> $DIR/issue-15980.rs:20:13
+   |
+18 |         Err(ref e) if e.kind == io::EndOfFile {
+   |                                 ------------- while parsing this struct
+19 |             //~^ NOTE while parsing this struct
+20 |             return
+   |             ^^^^^^ expected identifier, found keyword
+
+error: expected one of `.`, `=>`, `?`, or an operator, found `_`
+  --> $DIR/issue-15980.rs:25:9
+   |
+23 |         }
+   |          - expected one of `.`, `=>`, `?`, or an operator here
+24 |         //~^ NOTE expected one of `.`, `=>`, `?`, or an operator here
+25 |         _ => {}
+   |         ^ unexpected token
+
+error[E0412]: cannot find type `IoResult` in module `io`
+  --> $DIR/issue-15980.rs:14:16
+   |
+14 |     let x: io::IoResult<()> = Ok(());
+   |                ^^^^^^^^ did you mean `Result`?
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/E0580.rs b/src/test/ui/type-annotation-needed.rs
similarity index 67%
copy from src/test/compile-fail/E0580.rs
copy to src/test/ui/type-annotation-needed.rs
index a2ef7da..3ed6e5d 100644
--- a/src/test/compile-fail/E0580.rs
+++ b/src/test/ui/type-annotation-needed.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,4 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { 0 } //~ ERROR E0580
+fn foo<T: Into<String>>(x: i32) {}
+//~^ NOTE required by
+
+fn main() {
+    foo(42);
+    //~^ ERROR type annotations required
+}
diff --git a/src/test/ui/type-annotation-needed.stderr b/src/test/ui/type-annotation-needed.stderr
new file mode 100644
index 0000000..7d49afb
--- /dev/null
+++ b/src/test/ui/type-annotation-needed.stderr
@@ -0,0 +1,14 @@
+error[E0283]: type annotations required: cannot resolve `_: std::convert::Into<std::string::String>`
+  --> $DIR/type-annotation-needed.rs:15:5
+   |
+15 |     foo(42);
+   |     ^^^
+   |
+note: required by `foo`
+  --> $DIR/type-annotation-needed.rs:11:1
+   |
+11 | fn foo<T: Into<String>>(x: i32) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr
index 2ca97aa..cf270af 100644
--- a/src/test/ui/type-check/issue-40294.stderr
+++ b/src/test/ui/type-check/issue-40294.stderr
@@ -10,7 +10,11 @@
 21 | | }
    | |_^
    |
-   = note: required by `Foo`
+note: required by `Foo`
+  --> $DIR/issue-40294.rs:11:1
+   |
+11 | trait Foo: Sized {
+   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck-default-trait-impl-outside-crate.stderr b/src/test/ui/typeck-default-trait-impl-outside-crate.stderr
deleted file mode 100644
index 6b50fde..0000000
--- a/src/test/ui/typeck-default-trait-impl-outside-crate.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error[E0318]: cannot create default implementations for traits outside the crate they're defined in; define a new trait instead
-  --> $DIR/typeck-default-trait-impl-outside-crate.rs:14:6
-   |
-14 | impl Copy for .. {} //~ ERROR E0318
-   |      ^^^^ `Copy` trait not defined in this crate
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/update-references.sh b/src/test/ui/update-references.sh
index b9ded7d..c2c842f 100755
--- a/src/test/ui/update-references.sh
+++ b/src/test/ui/update-references.sh
@@ -46,5 +46,3 @@
         cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME
     fi
 done
-
-
diff --git a/src/test/ui/use-mod.rs b/src/test/ui/use-mod.rs
index 2eb7169..37495cd 100644
--- a/src/test/ui/use-mod.rs
+++ b/src/test/ui/use-mod.rs
@@ -10,7 +10,7 @@
 
 use foo::bar::{
     self,
-//~^ ERROR `self` import can only appear once in the list
+//~^ ERROR `self` import can only appear once in an import list
     Bar,
     self
 //~^ ERROR the name `bar` is defined multiple times
diff --git a/src/test/ui/use-mod.stderr b/src/test/ui/use-mod.stderr
index abc7e2b..bb64909 100644
--- a/src/test/ui/use-mod.stderr
+++ b/src/test/ui/use-mod.stderr
@@ -1,20 +1,17 @@
-error[E0430]: `self` import can only appear once in the list
+error[E0430]: `self` import can only appear once in an import list
   --> $DIR/use-mod.rs:12:5
    |
 12 |     self,
-   |     ^^^^
-   |
-note: another `self` import appears here
-  --> $DIR/use-mod.rs:15:5
-   |
+   |     ^^^^ can only appear once in an import list
+...
 15 |     self
-   |     ^^^^
+   |     ---- another `self` import appears here
 
 error[E0431]: `self` import can only appear in an import list with a non-empty prefix
   --> $DIR/use-mod.rs:19:6
    |
 19 | use {self};
-   |      ^^^^
+   |      ^^^^ can only appear in an import list with a non-empty prefix
 
 error[E0252]: the name `bar` is defined multiple times
   --> $DIR/use-mod.rs:15:5
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 371bbd1..4113f8f 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -46,8 +46,9 @@
 
 static TARGETS: &'static [&'static str] = &[
     "aarch64-apple-ios",
-    "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
+    "aarch64-unknown-cloudabi",
+    "aarch64-unknown-fuchsia",
     "aarch64-unknown-linux-gnu",
     "aarch64-unknown-linux-musl",
     "arm-linux-androideabi",
@@ -58,6 +59,7 @@
     "armv5te-unknown-linux-gnueabi",
     "armv7-apple-ios",
     "armv7-linux-androideabi",
+    "armv7-unknown-cloudabi-eabihf",
     "armv7-unknown-linux-gnueabihf",
     "armv7-unknown-linux-musleabihf",
     "armv7s-apple-ios",
@@ -65,10 +67,12 @@
     "i386-apple-ios",
     "i586-pc-windows-msvc",
     "i586-unknown-linux-gnu",
+    "i586-unknown-linux-musl",
     "i686-apple-darwin",
     "i686-linux-android",
     "i686-pc-windows-gnu",
     "i686-pc-windows-msvc",
+    "i686-unknown-cloudabi",
     "i686-unknown-freebsd",
     "i686-unknown-linux-gnu",
     "i686-unknown-linux-musl",
@@ -86,13 +90,14 @@
     "sparcv9-sun-solaris",
     "wasm32-unknown-emscripten",
     "wasm32-unknown-unknown",
-    "x86_64-linux-android",
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
+    "x86_64-linux-android",
     "x86_64-pc-windows-gnu",
     "x86_64-pc-windows-msvc",
     "x86_64-rumprun-netbsd",
     "x86_64-sun-solaris",
+    "x86_64-unknown-cloudabi",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-fuchsia",
     "x86_64-unknown-linux-gnu",
diff --git a/src/tools/cargo b/src/tools/cargo
index 930f9d9..6a8eb71 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 930f9d949b384fde9b0d7b9cc590515933f194c0
+Subproject commit 6a8eb71f6d226f9ac869dbacd5ff6aa76deef1c4
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 494c57b..725c8e7 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -8,7 +8,7 @@
 env_logger = { version = "0.4", default-features = false }
 filetime = "0.1"
 getopts = "0.2"
-log = "0.3"
+log = "0.4"
 regex = "0.2"
 rustc-serialize = "0.3"
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 48c3c5c..1d8cef0 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -13,7 +13,7 @@
 use std::str::FromStr;
 use std::path::PathBuf;
 
-use test::{ColorConfig, TestPaths};
+use test::ColorConfig;
 
 #[derive(Clone, Copy, PartialEq, Debug)]
 pub enum Mode {
@@ -222,6 +222,13 @@
     pub nodejs: Option<String>,
 }
 
+#[derive(Clone)]
+pub struct TestPaths {
+    pub file: PathBuf,         // e.g., compile-test/foo/bar/baz.rs
+    pub base: PathBuf,         // e.g., compile-test, auxiliary
+    pub relative_dir: PathBuf, // e.g., foo/bar
+}
+
 /// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
 pub fn expected_output_path(testpaths: &TestPaths, revision: Option<&str>, kind: &str) -> PathBuf {
     assert!(UI_EXTENSIONS.contains(&kind));
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 1f736e3..ff66273 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -41,9 +41,13 @@
         iter_header(testfile,
                     None,
                     &mut |ln| {
+            // we should check if any only-<platform> exists and if it exists
+            // and does not matches the current platform, skip the test
             props.ignore =
                 props.ignore ||
                 config.parse_cfg_name_directive(ln, "ignore") ||
+                (config.has_cfg_prefix(ln, "only") &&
+                !config.parse_cfg_name_directive(ln, "only")) ||
                 ignore_gdb(config, ln) ||
                 ignore_lldb(config, ln) ||
                 ignore_llvm(config, ln);
@@ -564,6 +568,13 @@
         }
     }
 
+    fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
+        // returns whether this line contains this prefix or not. For prefix
+        // "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
+        // "ignore-andorid" etc.
+        line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-')
+    }
+
     fn parse_name_directive(&self, line: &str, directive: &str) -> bool {
         // Ensure the directive is a whole word. Do not match "ignore-x86" when
         // the line says "ignore-x86_64".
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 80630b5..533aaf9 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -33,10 +33,10 @@
 use std::process::Command;
 use filetime::FileTime;
 use getopts::Options;
-use common::Config;
+use common::{Config, TestPaths};
 use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
 use common::{expected_output_path, UI_EXTENSIONS};
-use test::{ColorConfig, TestPaths};
+use test::ColorConfig;
 use util::logv;
 
 use self::header::EarlyProps;
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 3aee881..bf5fc00 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use common::Config;
+use common::{Config, TestPaths};
 use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
 use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
 use common::{Incremental, MirOpt, RunMake, Ui};
@@ -18,10 +18,10 @@
 use filetime::FileTime;
 use json;
 use header::TestProps;
-use test::TestPaths;
 use util::logv;
 use regex::Regex;
 
+use std::collections::VecDeque;
 use std::collections::HashMap;
 use std::collections::HashSet;
 use std::env;
@@ -49,6 +49,88 @@
     }
 }
 
+#[derive(Debug, PartialEq)]
+pub enum DiffLine {
+    Context(String),
+    Expected(String),
+    Resulting(String),
+}
+
+#[derive(Debug, PartialEq)]
+pub struct Mismatch {
+    pub line_number: u32,
+    pub lines: Vec<DiffLine>,
+}
+
+impl Mismatch {
+    fn new(line_number: u32) -> Mismatch {
+        Mismatch {
+            line_number: line_number,
+            lines: Vec::new(),
+        }
+    }
+}
+
+// Produces a diff between the expected output and actual output.
+pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
+    let mut line_number = 1;
+    let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
+    let mut lines_since_mismatch = context_size + 1;
+    let mut results = Vec::new();
+    let mut mismatch = Mismatch::new(0);
+
+    for result in diff::lines(actual, expected) {
+        match result {
+            diff::Result::Left(str) => {
+                if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
+                    results.push(mismatch);
+                    mismatch = Mismatch::new(line_number - context_queue.len() as u32);
+                }
+
+                while let Some(line) = context_queue.pop_front() {
+                    mismatch.lines.push(DiffLine::Context(line.to_owned()));
+                }
+
+                mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
+                lines_since_mismatch = 0;
+            }
+            diff::Result::Right(str) => {
+                if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
+                    results.push(mismatch);
+                    mismatch = Mismatch::new(line_number - context_queue.len() as u32);
+                }
+
+                while let Some(line) = context_queue.pop_front() {
+                    mismatch.lines.push(DiffLine::Context(line.to_owned()));
+                }
+
+                mismatch.lines.push(DiffLine::Expected(str.to_owned()));
+                line_number += 1;
+                lines_since_mismatch = 0;
+            }
+            diff::Result::Both(str, _) => {
+                if context_queue.len() >= context_size {
+                    let _ = context_queue.pop_front();
+                }
+
+                if lines_since_mismatch < context_size {
+                    mismatch.lines.push(DiffLine::Context(str.to_owned()));
+                } else if context_size > 0 {
+                    context_queue.push_back(str);
+                }
+
+                line_number += 1;
+                lines_since_mismatch += 1;
+            }
+        }
+    }
+
+    results.push(mismatch);
+    results.remove(0);
+
+    results
+}
+
 pub fn run(config: Config, testpaths: &TestPaths) {
     match &*config.target {
         "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
@@ -384,8 +466,7 @@
         let mut rustc = Command::new(&self.config.rustc_path);
         rustc
             .arg("-")
-            .arg("-Zunstable-options")
-            .args(&["--unpretty", &pretty_type])
+            .args(&["-Z", &format!("unpretty={}", pretty_type)])
             .args(&["--target", &self.config.target])
             .arg("-L")
             .arg(&aux_dir)
@@ -902,6 +983,13 @@
         for line in reader.lines() {
             match line {
                 Ok(line) => {
+                    let line =
+                        if line.starts_with("//") {
+                            line[2..].trim_left()
+                        } else {
+                            line.as_str()
+                        };
+
                     if line.contains("#break") {
                         breakpoint_lines.push(counter);
                     }
@@ -1369,9 +1457,10 @@
 
             let crate_type = if aux_props.no_prefer_dynamic {
                 None
-            } else if (self.config.target.contains("musl") && !aux_props.force_host)
-                || self.config.target.contains("wasm32")
+            } else if self.config.target.contains("cloudabi")
                 || self.config.target.contains("emscripten")
+                || (self.config.target.contains("musl") && !aux_props.force_host)
+                || self.config.target.contains("wasm32")
             {
                 // We primarily compile all auxiliary libraries as dynamic libraries
                 // to avoid code size bloat and large binaries as much as possible
@@ -1513,6 +1602,10 @@
             rustc.args(&["-Z", "incremental-queries"]);
         }
 
+        if self.config.mode == CodegenUnits {
+            rustc.args(&["-Z", "human_readable_cgu_names"]);
+        }
+
         match self.config.mode {
             CompileFail | ParseFail | Incremental => {
                 // If we are extracting and matching errors in the new
@@ -2709,15 +2802,29 @@
             return 0;
         }
 
-        println!("normalized {}:\n{}\n", kind, actual);
-        println!("expected {}:\n{}\n", kind, expected);
-        println!("diff of {}:\n", kind);
-
-        for diff in diff::lines(expected, actual) {
-            match diff {
-                diff::Result::Left(l) => println!("-{}", l),
-                diff::Result::Both(l, _) => println!(" {}", l),
-                diff::Result::Right(r) => println!("+{}", r),
+        if expected.is_empty() {
+            println!("normalized {}:\n{}\n", kind, actual);
+        } else {
+            println!("diff of {}:\n", kind);
+            let diff_results = make_diff(expected, actual, 3);
+            for result in diff_results {
+                let mut line_number = result.line_number;
+                for line in result.lines {
+                    match line {
+                        DiffLine::Expected(e) => {
+                            println!("-\t{}", e);
+                            line_number += 1;
+                        },
+                        DiffLine::Context(c) => {
+                            println!("{}\t{}", line_number, c);
+                            line_number += 1;
+                        },
+                        DiffLine::Resulting(r) => {
+                            println!("+\t{}", r);
+                        },
+                    }
+                }
+                println!("");
             }
         }
 
@@ -2856,7 +2963,7 @@
                     *skipped += data.len();
                     if data.len() <= TAIL_LEN {
                         tail[..data.len()].copy_from_slice(data);
-                        tail.rotate(data.len());
+                        tail.rotate_left(data.len());
                     } else {
                         tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]);
                     }
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index c00f28e..3c9dae9 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -15,6 +15,7 @@
 const OS_TABLE: &'static [(&'static str, &'static str)] = &[
     ("android", "android"),
     ("bitrig", "bitrig"),
+    ("cloudabi", "cloudabi"),
     ("darwin", "macos"),
     ("dragonfly", "dragonfly"),
     ("freebsd", "freebsd"),
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index ca383b5a..8454e71 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -100,7 +100,7 @@
 
         // Description rendered as markdown.
         match info.description {
-            Some(ref desc) => write!(output, "{}", Markdown(desc, RenderType::Hoedown))?,
+            Some(ref desc) => write!(output, "{}", Markdown(desc, &[], RenderType::Hoedown))?,
             None => write!(output, "<p>No description.</p>\n")?,
         }
 
@@ -109,7 +109,65 @@
     }
 
     fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
-        write!(output, "</body>\n</html>")?;
+        write!(output, r##"<script>
+function onEach(arr, func) {{
+    if (arr && arr.length > 0 && func) {{
+        for (var i = 0; i < arr.length; i++) {{
+            func(arr[i]);
+        }}
+    }}
+}}
+
+function hasClass(elem, className) {{
+    if (elem && className && elem.className) {{
+        var elemClass = elem.className;
+        var start = elemClass.indexOf(className);
+        if (start === -1) {{
+            return false;
+        }} else if (elemClass.length === className.length) {{
+            return true;
+        }} else {{
+            if (start > 0 && elemClass[start - 1] !== ' ') {{
+                return false;
+            }}
+            var end = start + className.length;
+            if (end < elemClass.length && elemClass[end] !== ' ') {{
+                return false;
+            }}
+            return true;
+        }}
+        if (start > 0 && elemClass[start - 1] !== ' ') {{
+            return false;
+        }}
+        var end = start + className.length;
+        if (end < elemClass.length && elemClass[end] !== ' ') {{
+            return false;
+        }}
+        return true;
+    }}
+    return false;
+}}
+
+onEach(document.getElementsByClassName('rust-example-rendered'), function(e) {{
+    if (hasClass(e, 'compile_fail')) {{
+        e.addEventListener("mouseover", function(event) {{
+            e.previousElementSibling.childNodes[0].style.color = '#f00';
+        }});
+        e.addEventListener("mouseout", function(event) {{
+            e.previousElementSibling.childNodes[0].style.color = '';
+        }});
+    }} else if (hasClass(e, 'ignore')) {{
+        e.addEventListener("mouseover", function(event) {{
+            e.previousElementSibling.childNodes[0].style.color = '#ff9200';
+        }});
+        e.addEventListener("mouseout", function(event) {{
+            e.previousElementSibling.childNodes[0].style.color = '';
+        }});
+    }}
+}});
+</script>
+</body>
+</html>"##)?;
         Ok(())
     }
 }
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 3b0925d..f6eaa09 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -132,7 +132,16 @@
     // Unfortunately we're not 100% full of valid links today to we need a few
     // whitelists to get this past `make check` today.
     // FIXME(#32129)
-    if file.ends_with("std/string/struct.String.html") {
+    if file.ends_with("std/string/struct.String.html") ||
+       file.ends_with("interpret/struct.ValTy.html") ||
+       file.ends_with("symbol/struct.InternedString.html") ||
+       file.ends_with("ast/struct.ThinVec.html") ||
+       file.ends_with("util/struct.ThinVec.html") ||
+       file.ends_with("util/struct.RcSlice.html") ||
+       file.ends_with("layout/struct.TyLayout.html") ||
+       file.ends_with("ty/struct.Slice.html") ||
+       file.ends_with("ty/enum.Attributes.html") ||
+       file.ends_with("ty/struct.SymbolName.html") {
         return None;
     }
     // FIXME(#32553)
@@ -144,7 +153,9 @@
        file.ends_with("struct.BTreeSet.html") ||
        file.ends_with("btree_map/struct.BTreeMap.html") ||
        file.ends_with("hash_map/struct.HashMap.html") ||
-       file.ends_with("hash_set/struct.HashSet.html") {
+       file.ends_with("hash_set/struct.HashSet.html") ||
+       file.ends_with("sync/struct.Lrc.html") ||
+       file.ends_with("sync/struct.RwLock.html") {
         return None;
     }
 
@@ -181,7 +192,17 @@
             for part in Path::new(base).join(url).components() {
                 match part {
                     Component::Prefix(_) |
-                    Component::RootDir => panic!(),
+                    Component::RootDir => {
+                        // Avoid absolute paths as they make the docs not
+                        // relocatable by making assumptions on where the docs
+                        // are hosted relative to the site root.
+                        *errors = true;
+                        println!("{}:{}: absolute path - {}",
+                                 pretty_file.display(),
+                                 i + 1,
+                                 Path::new(base).join(url).display());
+                        return;
+                    }
                     Component::CurDir => {}
                     Component::ParentDir => { path.pop(); }
                     Component::Normal(s) => { path.push(s); }
diff --git a/src/tools/miri b/src/tools/miri
index 2671cf3..919604e 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 2671cf34a58b11f995add8402e75c1cd94ed051e
+Subproject commit 919604e1ead8294c8ca14f101be4380ea1ea370c
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
new file mode 100755
index 0000000..b90947e
--- /dev/null
+++ b/src/tools/publish_toolstate.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+import sys
+import re
+import json
+import copy
+import datetime
+import collections
+
+# List of people to ping when the status of a tool changed.
+MAINTAINERS = {
+    'miri': '@oli-obk @RalfJung @eddyb',
+    'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk',
+    'rls': '@nrc',
+    'rustfmt': '@nrc',
+}
+
+
+def read_current_status(current_commit, path):
+    '''Reads build status of `current_commit` from content of `history/*.tsv`
+    '''
+    with open(path, 'rU') as f:
+        for line in f:
+            (commit, status) = line.split('\t', 1)
+            if commit == current_commit:
+                return json.loads(status)
+    return {}
+
+
+def update_latest(current_commit, relevant_pr_number, current_datetime):
+    '''Updates `_data/latest.json` to match build result of the given commit.
+    '''
+    with open('_data/latest.json', 'rb+') as f:
+        latest = json.load(f, object_pairs_hook=collections.OrderedDict)
+
+        current_status = {
+            os: read_current_status(current_commit, 'history/' + os + '.tsv')
+            for os in ['windows', 'linux']
+        }
+
+        slug = 'rust-lang/rust'
+        message = '📣 Toolstate changed by {}!\n\nTested on commit {}@{}.\n\n' \
+            .format(relevant_pr_number, slug, current_commit)
+        anything_changed = False
+        for status in latest:
+            tool = status['tool']
+            changed = False
+
+            for os, s in current_status.items():
+                old = status[os]
+                new = s.get(tool, old)
+                status[os] = new
+                if new > old:
+                    changed = True
+                    message += '🎉 {} on {}: {} → {}.\n' \
+                        .format(tool, os, old, new)
+                elif new < old:
+                    changed = True
+                    message += '💔 {} on {}: {} → {} (cc {}).\n' \
+                        .format(tool, os, old, new, MAINTAINERS[tool])
+
+            if changed:
+                status['commit'] = current_commit
+                status['datetime'] = current_datetime
+                anything_changed = True
+
+        if not anything_changed:
+            return ''
+
+        f.seek(0)
+        f.truncate(0)
+        json.dump(latest, f, indent=4, separators=(',', ': '))
+        return message
+
+
+if __name__ == '__main__':
+    cur_commit = sys.argv[1]
+    cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
+    cur_commit_msg = sys.argv[2]
+    save_message_to_path = sys.argv[3]
+
+    relevant_pr_match = re.search('#[0-9]+', cur_commit_msg)
+    if relevant_pr_match:
+        relevant_pr_number = 'rust-lang/rust' + relevant_pr_match.group(0)
+    else:
+        relevant_pr_number = '<unknown PR>'
+
+    message = update_latest(cur_commit, relevant_pr_number, cur_datetime)
+    if message:
+        print(message)
+        with open(save_message_to_path, 'w') as f:
+            f.write(message)
+    else:
+        print('<Nothing changed>')
diff --git a/src/tools/rls b/src/tools/rls
index 9782aa4..299a6a9 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 9782aa4c3c5b203732b9a1a4f3c9d7fbc912e437
+Subproject commit 299a6a91089af06b3b515450fece3c45a059dbbf
diff --git a/src/tools/rust-installer b/src/tools/rust-installer
index 0ddd53c..b55e0fc 160000
--- a/src/tools/rust-installer
+++ b/src/tools/rust-installer
@@ -1 +1 @@
-Subproject commit 0ddd53c4bc2a76df565a1c1fc0cc6f19f254b51e
+Subproject commit b55e0fc77590cf5d23a01dedeb2104d8cbb48efc
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 4aa0962..bc35cbe 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -8,5 +8,5 @@
 clap = "2.25.0"
 
 [dependencies.mdbook]
-version = "0.0.26"
+version = "0.0.28"
 default-features = false
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index a0c3e81..50f4364 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -52,12 +52,14 @@
 // Build command implementation
 pub fn build(args: &ArgMatches) -> Result<()> {
     let book_dir = get_book_dir(args);
-    let book = MDBook::new(&book_dir).read_config()?;
+    let mut book = MDBook::new(&book_dir).read_config()?;
 
-    let mut book = match args.value_of("dest-dir") {
-        Some(dest_dir) => book.with_destination(dest_dir),
-        None => book,
-    };
+    // Set this to allow us to catch bugs in advance.
+    book.config.build.create_missing = false;
+
+    if let Some(dest_dir) = args.value_of("dest-dir") {
+        book.config.build.build_dir = PathBuf::from(dest_dir);
+    }
 
     book.build()?;
 
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
new file mode 100644
index 0000000..7c9ee2a
--- /dev/null
+++ b/src/tools/rustdoc-js/tester.js
@@ -0,0 +1,210 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const fs = require('fs');
+
+const TEST_FOLDER = 'src/test/rustdoc-js/';
+
+// Stupid function extractor based on indent.
+function extractFunction(content, functionName) {
+    var x = content.split('\n');
+    var in_func = false;
+    var indent = 0;
+    var lines = [];
+
+    for (var i = 0; i < x.length; ++i) {
+        if (in_func === false) {
+            var splitter = "function " + functionName + "(";
+            if (x[i].trim().startsWith(splitter)) {
+                in_func = true;
+                indent = x[i].split(splitter)[0].length;
+                lines.push(x[i]);
+            }
+        } else {
+            lines.push(x[i]);
+            if (x[i].trim() === "}" && x[i].split("}")[0].length === indent) {
+                return lines.join("\n");
+            }
+        }
+    }
+    return null;
+}
+
+// Stupid function extractor for array.
+function extractArrayVariable(content, arrayName) {
+    var x = content.split('\n');
+    var found_var = false;
+    var lines = [];
+
+    for (var i = 0; i < x.length; ++i) {
+        if (found_var === false) {
+            var splitter = "var " + arrayName + " = [";
+            if (x[i].trim().startsWith(splitter)) {
+                found_var = true;
+                i -= 1;
+            }
+        } else {
+            lines.push(x[i]);
+            if (x[i].endsWith('];')) {
+                return lines.join("\n");
+            }
+        }
+    }
+    return null;
+}
+
+// Stupid function extractor for variable.
+function extractVariable(content, varName) {
+    var x = content.split('\n');
+    var found_var = false;
+    var lines = [];
+
+    for (var i = 0; i < x.length; ++i) {
+        if (found_var === false) {
+            var splitter = "var " + varName + " = ";
+            if (x[i].trim().startsWith(splitter)) {
+                found_var = true;
+                i -= 1;
+            }
+        } else {
+            lines.push(x[i]);
+            if (x[i].endsWith(';')) {
+                return lines.join("\n");
+            }
+        }
+    }
+    return null;
+}
+
+function loadContent(content) {
+    var Module = module.constructor;
+    var m = new Module();
+    m._compile(content, "tmp.js");
+    return m.exports;
+}
+
+function readFile(filePath) {
+    return fs.readFileSync(filePath, 'utf8');
+}
+
+function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) {
+    var content = '';
+    for (var i = 0; i < thingsToLoad.length; ++i) {
+        var tmp = funcToCall(fileContent, thingsToLoad[i]);
+        if (tmp === null) {
+            console.error('enable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"');
+            process.exit(1);
+        }
+        content += tmp;
+        content += 'exports.' + thingsToLoad[i] + ' = ' + thingsToLoad[i] + ';';
+    }
+    return content;
+}
+
+function lookForEntry(entry, data) {
+    for (var i = 0; i < data.length; ++i) {
+        var allGood = true;
+        for (var key in entry) {
+            if (!entry.hasOwnProperty(key)) {
+                continue;
+            }
+            var value = data[i][key];
+            // To make our life easier, if there is a "parent" type, we add it to the path.
+            if (key === 'path' && data[i]['parent'] !== undefined) {
+                if (value.length > 0) {
+                    value += '::' + data[i]['parent']['name'];
+                } else {
+                    value = data[i]['parent']['name'];
+                }
+            }
+            if (value !== entry[key]) {
+                allGood = false;
+                break;
+            }
+        }
+        if (allGood === true) {
+            return true;
+        }
+    }
+    return false;
+}
+
+function main(argv) {
+    if (argv.length !== 3) {
+        console.error("Expected toolchain to check as argument (for example 'x86_64-apple-darwin'");
+        return 1;
+    }
+    var toolchain = argv[2];
+
+    var mainJs = readFile("build/" + toolchain + "/doc/main.js");
+    var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n");
+    if (searchIndex[searchIndex.length - 1].length === 0) {
+        searchIndex.pop();
+    }
+    searchIndex.pop();
+    searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;');
+    finalJS = "";
+
+    var arraysToLoad = ["itemTypes"];
+    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "TY_PRIMITIVE", "levenshtein_row2"];
+    // execQuery first parameter is built in getQuery (which takes in the search input).
+    // execQuery last parameter is built in buildIndex.
+    // buildIndex requires the hashmap from search-index.
+    var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery"];
+
+    finalJS += 'window = { "currentCrate": "std" };\n';
+    finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs);
+    finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs);
+    finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs);
+
+    var loaded = loadContent(finalJS);
+    var index = loaded.buildIndex(searchIndex.searchIndex);
+
+    var errors = 0;
+
+    fs.readdirSync(TEST_FOLDER).forEach(function(file) {
+        var loadedFile = loadContent(readFile(TEST_FOLDER + file) +
+                               'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
+        const expected = loadedFile.EXPECTED;
+        const query = loadedFile.QUERY;
+        var results = loaded.execQuery(loaded.getQuery(query), index);
+        process.stdout.write('Checking "' + file + '" ... ');
+        var error_text = [];
+        for (var key in expected) {
+            if (!expected.hasOwnProperty(key)) {
+                continue;
+            }
+            if (!results.hasOwnProperty(key)) {
+                error_text.push('==> Unknown key "' + key + '"');
+                break;
+            }
+            var entry = expected[key];
+            var found = false;
+            for (var i = 0; i < entry.length; ++i) {
+                if (lookForEntry(entry[i], results[key]) === true) {
+                    found = true;
+                } else {
+                    error_text.push("==> Result not found in '" + key + "': '" +
+                                    JSON.stringify(entry[i]) + "'");
+                }
+            }
+        }
+        if (error_text.length !== 0) {
+            errors += 1;
+            console.error("FAILED");
+            console.error(error_text.join("\n"));
+        } else {
+            console.log("OK");
+        }
+    });
+    return errors;
+}
+
+process.exit(main(process.argv));
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
index 8db33ff..e0e3e22 160000
--- a/src/tools/rustfmt
+++ b/src/tools/rustfmt
@@ -1 +1 @@
-Subproject commit 8db33ff0f74c64bd4ddfbcb0eda0c8277ff9980a
+Subproject commit e0e3e22248cd14ebbe0253e9720261a0328bfc59
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 61d7198..eee2902 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -69,6 +69,7 @@
         "src/tools/miri",
         "src/librustc/mir/interpret",
         "src/librustc_mir/interpret",
+        "src/target",
     ];
     skip.iter().any(|p| path.ends_with(p))
 }
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index fdbcfd1..8071f07 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -168,8 +168,8 @@
         let prev_newline_idx = contents[..prev_newline_idx].rfind('\n');
         if let Some(nl) = prev_newline_idx {
             let prev_line = &contents[nl + 1 .. mod_tests_idx];
-            let emcc_cfg = "cfg(all(test, not(target_os";
-            if prev_line.contains(emcc_cfg) {
+            if prev_line.contains("cfg(all(test, not(target_os")
+                || prev_line.contains("cfg(all(test, not(any(target_os") {
                 nl
             } else {
                 mod_tests_idx
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 40d84b9..b784a0e 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -130,6 +130,7 @@
         let skip_tab = contents.contains("ignore-tidy-tab");
         let skip_length = contents.contains("ignore-tidy-linelength");
         let skip_end_whitespace = contents.contains("ignore-tidy-end-whitespace");
+        let mut trailing_new_lines = 0;
         for (i, line) in contents.split("\n").enumerate() {
             let mut err = |msg: &str| {
                 tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
@@ -161,10 +162,20 @@
             if filename.ends_with(".cpp") && line.contains("llvm_unreachable") {
                 err(LLVM_UNREACHABLE_INFO);
             }
+            if line.is_empty() {
+                trailing_new_lines += 1;
+            } else {
+                trailing_new_lines = 0;
+            }
         }
         if !licenseck(file, &contents) {
             tidy_error!(bad, "{}: incorrect license", file.display());
         }
+        match trailing_new_lines {
+            0 => tidy_error!(bad, "{}: missing trailing newline", file.display()),
+            1 | 2 => {}
+            n => tidy_error!(bad, "{}: too many trailing newlines ({})", file.display(), n),
+        };
     })
 }
 
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index ff032b1..6ffe78e 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -49,7 +49,7 @@
     features
         .iter()
         .filter(|&(_, ref f)| f.level == Status::Unstable)
-        .map(|(name, _)| name.to_owned())
+        .map(|(name, _)| name.replace('_', "-"))
         .collect()
 }
 
@@ -60,7 +60,7 @@
         .map(|entry| entry.expect("could not read directory entry"))
         .filter(dir_entry_is_file)
         .map(|entry| entry.file_name().into_string().unwrap())
-        .map(|n| n.trim_right_matches(".md").replace('-', "_"))
+        .map(|n| n.trim_right_matches(".md").to_owned())
         .collect()
 }
 
@@ -87,7 +87,9 @@
     // Library features
 
     let lang_features = collect_lang_features(path);
-    let lib_features = collect_lib_features(path);
+    let lib_features = collect_lib_features(path).into_iter().filter(|&(ref name, _)| {
+        !lang_features.contains_key(name)
+    }).collect();
 
     let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features);
     let unstable_book_lib_features_section_file_names =
diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml
deleted file mode 100644
index 6901343..0000000
--- a/src/tools/toolstate.toml
+++ /dev/null
@@ -1,36 +0,0 @@
-# This file reflects the current status of all tools which are allowed
-# to fail without failing the build.
-#
-# There are three states a tool can be in:
-# 1. Broken: The tool doesn't build
-# 2. Compiling: The tool builds but its tests are failing
-# 3. Testing: The tool builds and its tests are passing
-#
-# In the future there will be further states like "Distributing", which
-# configures whether the tool is included in the Rust distribution.
-#
-# If a tool was working before your PR but is broken now, consider
-# opening a PR against the tool so that it works with your changes.
-# If the tool stops compiling, change its state to `Broken`. If it
-# still builds, change it to `Compiling`.
-# How to do that is described in
-# "CONTRIBUTING.md#External Dependencies". If the effort required is not
-# warranted (e.g. due to the tool abusing some API that you changed, and
-# fixing the tool would mean a significant refactoring) remember to ping
-# the tool authors, so they can fix it, instead of being surprised by the
-# breakage.
-#
-# Each tool has a list of people to ping
-
-# ping @oli-obk @RalfJung @eddyb
-miri = "Broken"
-
-# ping @Manishearth @llogiq @mcarton @oli-obk
-clippy = "Broken"
-
-# ping @nrc
-rls = "Broken"
-
-# ping @nrc
-# when breaking rustfmt, always break rls as well
-rustfmt = "Broken"
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index 5c2bd1e..f66144f 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -53,9 +53,9 @@
     set
         .iter()
         .map(|ref n| format!("    - [{}]({}/{}.md)",
-                                      n,
+                                      n.replace('-', "_"),
                                       dir,
-                                      n.replace('_', "-")))
+                                      n))
         .fold("".to_owned(), |s, a| s + &a + "\n")
 }
 
@@ -96,14 +96,17 @@
     let unstable_section_file_names = collect_unstable_book_section_file_names(src);
     t!(fs::create_dir_all(&out));
     for feature_name in &unstable_features - &unstable_section_file_names {
-        let file_name = format!("{}.md", feature_name.replace('_', "-"));
+        let feature_name_underscore = feature_name.replace('-', "_");
+        let file_name = format!("{}.md", feature_name);
         let out_file_path = out.join(&file_name);
-        let feature = &features[&feature_name];
+        let feature = &features[&feature_name_underscore];
 
         if has_valid_tracking_issue(&feature) {
-            generate_stub_issue(&out_file_path, &feature_name, feature.tracking_issue.unwrap());
+            generate_stub_issue(&out_file_path,
+                                &feature_name_underscore,
+                                feature.tracking_issue.unwrap());
         } else {
-            generate_stub_no_issue(&out_file_path, &feature_name);
+            generate_stub_no_issue(&out_file_path, &feature_name_underscore);
         }
     }
 }
@@ -129,7 +132,9 @@
     let dest_path = Path::new(&dest_path_str).join("src");
 
     let lang_features = collect_lang_features(src_path);
-    let lib_features = collect_lib_features(src_path);
+    let lib_features = collect_lib_features(src_path).into_iter().filter(|&(ref name, _)| {
+        !lang_features.contains_key(name)
+    }).collect();
 
     let doc_src_path = src_path.join(PATH_STR);