Auto merge of #57704 - lenoil98:patch-2, r=alexcrichton

Update bootstrap.py

Add PowerPC64 support on FreeBSD
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 65cdfe6..9924055 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,9 +19,16 @@
 
 As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
 
+The [rustc-guide] is your friend! It describes how the compiler works and how
+to contribute to it in more detail than this document.
+
+If this is your first time contributing, the [walkthrough] chapter of the guide
+can give you a good example of how a typical contribution would go.
+
 [pound-rust-internals]: https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
 [internals]: https://internals.rust-lang.org
 [coc]: https://www.rust-lang.org/conduct.html
+[walkthrough]: https://rust-lang.github.io/rustc-guide/walkthrough.html
 
 ## Feature Requests
 [feature-requests]: #feature-requests
@@ -89,222 +96,14 @@
 ```
 
 ## The Build System
-[the-build-system]: #the-build-system
 
-Rust's build system allows you to bootstrap the compiler, run tests &
-benchmarks, generate documentation, install a fresh build of Rust, and more.
-It's your best friend when working on Rust, allowing you to compile & test
-your contributions before submission.
+For info on how to configure and build the compiler, please see [this
+chapter][rustcguidebuild] of the rustc-guide. This chapter contains info for
+contributions to the compiler and the standard library. It also lists some
+really useful commands to the build system (`./x.py`), which could save you a
+lot of time.
 
-The build system lives in [the `src/bootstrap` directory][bootstrap] in the
-project root. Our build system is itself written in Rust and is based on Cargo
-to actually build all the compiler's crates. If you have questions on the build
-system internals, try asking in [`#rust-internals`][pound-rust-internals].
-
-[bootstrap]: https://github.com/rust-lang/rust/tree/master/src/bootstrap/
-
-### Configuration
-[configuration]: #configuration
-
-Before you can start building the compiler you need to configure the build for
-your system. In most cases, that will just mean using the defaults provided
-for Rust.
-
-To change configuration, you must copy the file `config.toml.example`
-to `config.toml` in the directory from which you will be running the build, and
-change the settings provided.
-
-There are large number of options provided in this config file that will alter the
-configuration used in the build process. Some options to note:
-
-#### `[llvm]`:
-- `assertions = true` = This enables LLVM assertions, which makes LLVM misuse cause an assertion failure instead of weird misbehavior. This also slows down the compiler's runtime by ~20%.
-- `ccache = true` - Use ccache when building llvm
-
-#### `[build]`:
-- `compiler-docs = true` - Build compiler documentation
-
-#### `[rust]`:
-- `debuginfo = true` - Build a compiler with debuginfo. Makes building rustc slower, but then you can use a debugger to debug `rustc`.
-- `debuginfo-lines = true` - An alternative to `debuginfo = true` that doesn't let you use a debugger, but doesn't make building rustc slower and still gives you line numbers in backtraces.
-- `debuginfo-tools = true` - Build the extended tools with debuginfo.
-- `debug-assertions = true` - Makes the log output of `debug!` work.
-- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust, but makes the stage1 compiler x100 slower.
-
-For more options, the `config.toml` file contains commented out defaults, with
-descriptions of what each option will do.
-
-Note: Previously the `./configure` script was used to configure this
-project. It can still be used, but it's recommended to use a `config.toml`
-file. If you still have a `config.mk` file in your directory - from
-`./configure` - you may need to delete it for `config.toml` to work.
-
-### Building
-[building]: #building
-
-A default configuration requires around 3.5 GB of disk space, whereas building a debug configuration may require more than 30 GB.
-
-Dependencies
-- [build dependencies](README.md#building-from-source)
-- `gdb` 6.2.0 minimum, 7.1 or later recommended for test builds
-
-The build system uses the `x.py` script to control the build process. This script
-is used to build, test, and document various parts of the compiler. You can
-execute it as:
-
-```sh
-python x.py build
-```
-
-On some systems you can also use the shorter version:
-
-```sh
-./x.py build
-```
-
-To learn more about the driver and top-level targets, you can execute:
-
-```sh
-python x.py --help
-```
-
-The general format for the driver script is:
-
-```sh
-python x.py <command> [<directory>]
-```
-
-Some example commands are `build`, `test`, and `doc`. These will build, test,
-and document the specified directory. The second argument, `<directory>`, is
-optional and defaults to working over the entire compiler. If specified,
-however, only that specific directory will be built. For example:
-
-```sh
-# build the entire compiler
-python x.py build
-
-# build all documentation
-python x.py doc
-
-# run all test suites
-python x.py test
-
-# build only the standard library
-python x.py build src/libstd
-
-# test only one particular test suite
-python x.py test src/test/rustdoc
-
-# build only the stage0 libcore library
-python x.py build src/libcore --stage 0
-```
-
-You can explore the build system through the various `--help` pages for each
-subcommand. For example to learn more about a command you can run:
-
-```
-python x.py build --help
-```
-
-To learn about all possible rules you can execute, run:
-
-```
-python x.py build --help --verbose
-```
-
-Note: Previously `./configure` and `make` were used to build this project.
-They are still available, but `x.py` is the recommended build system.
-
-### Useful commands
-[useful-commands]: #useful-commands
-
-Some common invocations of `x.py` are:
-
-- `x.py build --help` - show the help message and explain the subcommand
-- `x.py build src/libtest --stage 1` - build up to (and including) the first
-  stage. For most cases we don't need to build the stage2 compiler, so we can
-  save time by not building it. The stage1 compiler is a fully functioning
-  compiler and (probably) will be enough to determine if your change works as
-  expected.
-- `x.py build src/rustc --stage 1` - This will build just rustc, without libstd.
-  This is the fastest way to recompile after you changed only rustc source code.
-  Note however that the resulting rustc binary won't have a stdlib to link
-  against by default. You can build libstd once with `x.py build src/libstd`,
-  but it is only guaranteed to work if recompiled, so if there are any issues
-  recompile it.
-- `x.py test` - build the full compiler & run all tests (takes a while). This
-  is what gets run by the continuous integration system against your pull
-  request. You should run this before submitting to make sure your tests pass
-  & everything builds in the correct manner.
-- `x.py test src/libstd --stage 1` - test the standard library without
-  recompiling stage 2.
-- `x.py test src/test/run-pass --test-args TESTNAME` - Run a matching set of
-  tests.
-  - `TESTNAME` should be a substring of the tests to match against e.g. it could
-    be the fully qualified test name, or just a part of it.
-    `TESTNAME=collections::hash::map::test_map::test_capacity_not_less_than_len`
-    or `TESTNAME=test_capacity_not_less_than_len`.
-- `x.py test src/test/run-pass --stage 1 --test-args <substring-of-test-name>` -
-  Run a single rpass test with the stage1 compiler (this will be quicker than
-  running the command above as we only build the stage1 compiler, not the entire
-  thing).  You can also leave off the directory argument to run all stage1 test
-  types.
-- `x.py test src/libcore --stage 1` - Run stage1 tests in `libcore`.
-- `x.py test src/tools/tidy` - Check that the source code is in compliance with
-  Rust's style guidelines. There is no official document describing Rust's full
-  guidelines as of yet, but basic rules like 4 spaces for indentation and no
-  more than 99 characters in a single line should be kept in mind when writing
-  code.
-
-### Using your local build
-[using-local-build]: #using-local-build
-
-If you use Rustup to manage your rust install, it has a feature called ["custom
-toolchains"][toolchain-link] that you can use to access your newly-built compiler
-without having to install it to your system or user PATH. If you've run `python
-x.py build`, then you can add your custom rustc to a new toolchain like this:
-
-[toolchain-link]: https://github.com/rust-lang-nursery/rustup.rs#working-with-custom-toolchains-and-local-builds
-
-```
-rustup toolchain link <name> build/<host-triple>/stage2
-```
-
-Where `<host-triple>` is the build triple for the host (the triple of your
-computer, by default), and `<name>` is the name for your custom toolchain. (If you
-added `--stage 1` to your build command, the compiler will be in the `stage1`
-folder instead.) You'll only need to do this once - it will automatically point
-to the latest build you've done.
-
-Once this is set up, you can use your custom toolchain just like any other. For
-example, if you've named your toolchain `local`, running `cargo +local build` will
-compile a project with your custom rustc, setting `rustup override set local` will
-override the toolchain for your current directory, and `cargo +local doc` will use
-your custom rustc and rustdoc to generate docs. (If you do this with a `--stage 1`
-build, you'll need to build rustdoc specially, since it's not normally built in
-stage 1. `python x.py build --stage 1 src/libstd src/tools/rustdoc` will build
-rustdoc and libstd, which will allow rustdoc to be run with that toolchain.)
-
-### Out-of-tree builds
-[out-of-tree-builds]: #out-of-tree-builds
-
-Rust's `x.py` script fully supports out-of-tree builds - it looks for
-the Rust source code from the directory `x.py` was found in, but it
-reads the `config.toml` configuration file from the directory it's
-run in, and places all build artifacts within a subdirectory named `build`.
-
-This means that if you want to do an out-of-tree build, you can just do it:
-```
-$ cd my/build/dir
-$ cp ~/my-config.toml config.toml # Or fill in config.toml otherwise
-$ path/to/rust/x.py build
-...
-$ # This will use the Rust source code in `path/to/rust`, but build
-$ # artifacts will now be in ./build
-```
-
-It's absolutely fine to have multiple build directories with different
-`config.toml` configurations using the same code.
+[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html
 
 ## Pull Requests
 [pull-requests]: #pull-requests
@@ -320,26 +119,13 @@
 
 Please make pull requests against the `master` branch.
 
-Compiling all of `./x.py test` can take a while. When testing your pull request,
-consider using one of the more specialized `./x.py` targets to cut down on the
-amount of time you have to wait. You need to have built the compiler at least
-once before running these will work, but that’s only one full build rather than
-one each time.
-
-    $ python x.py test --stage 1
-
-is one such example, which builds just `rustc`, and then runs the tests. If
-you’re adding something to the standard library, try
-
-    $ python x.py test src/libstd --stage 1
-
 Please make sure your pull request is in compliance with Rust's style
 guidelines by running
 
     $ python x.py test src/tools/tidy
 
 Make this check before every pull request (and every new commit in a pull
-request) ; you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
+request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
 before every push to make sure you never forget to make this check.
 
 All pull requests are reviewed by another person. We have a bot,
@@ -532,6 +318,12 @@
 reference to `doc/reference.html`. The CSS might be messed up, but you can
 verify that the HTML is right.
 
+Additionally, contributions to the [rustc-guide] are always welcome. Contributions
+can be made directly at [the
+rust-lang/rustc-guide](https://github.com/rust-lang/rustc-guide) repo. The issue
+tracker in that repo is also a great way to find things that need doing. There
+are issues for beginners and advanced compiler devs alike!
+
 ## Issue Triage
 [issue-triage]: #issue-triage
 
@@ -627,7 +419,7 @@
 more seasoned developers, some useful places to look for information
 are:
 
-* The [rustc guide] contains information about how various parts of the compiler work
+* The [rustc guide] contains information about how various parts of the compiler work and how to contribute to the compiler
 * [Rust Forge][rustforge] contains additional documentation, including write-ups of how to achieve common tasks
 * The [Rust Internals forum][rif], a place to ask questions and
   discuss Rust's internals
diff --git a/README.md b/README.md
index cb1f062..514e420 100644
--- a/README.md
+++ b/README.md
@@ -13,9 +13,13 @@
 ["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
 [The Book]: https://doc.rust-lang.org/book/index.html
 
-## Building from Source
+## Installing from Source
 [building-from-source]: #building-from-source
 
+_Note: If you wish to contribute to the compiler, you should read
+[this chapter](https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html)
+of the rustc-guide instead._
+
 ### Building on *nix
 1. Make sure you have installed the dependencies:
 
diff --git a/appveyor.yml b/appveyor.yml
index f043b8b..d70ad54 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,12 +5,6 @@
   # server goes down presumably. See #43333 for more info
   CARGO_HTTP_CHECK_REVOKE: false
 
-  # Recommended by AppVeyor this moves our builds to GCE which incurs a 3-4
-  # minute startup overhead, but that's paltry compared to our overall build
-  # times so we're will to eat the cost. This is intended to give us better
-  # performance I believe!
-  appveyor_build_worker_cloud: gce
-
   matrix:
   # 32/64 bit MSVC tests
   - MSYS_BITS: 64
diff --git a/config.toml.example b/config.toml.example
index 23943d3..24293fc 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -90,6 +90,11 @@
 # with clang-cl, so this is special in that it only compiles LLVM with clang-cl
 #clang-cl = '/path/to/clang-cl.exe'
 
+# Pass extra compiler and linker flags to the LLVM CMake build.
+#cflags = "-fextra-flag"
+#cxxflags = "-fextra-flag"
+#ldflags = "-Wl,extra-flag"
+
 # Use libc++ when building LLVM instead of libstdc++. This is the default on
 # platforms already use libc++ as the default C++ library, but this option
 # allows you to use libc++ even on platforms when it's not. You need to ensure
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 9c58f5b..31adab6 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -660,6 +660,15 @@
         }
     }
 
+    /// Get the paths to all of the compiler's codegen backends.
+    fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
+        fs::read_dir(self.sysroot_codegen_backends(compiler))
+            .into_iter()
+            .flatten()
+            .filter_map(Result::ok)
+            .map(|entry| entry.path())
+    }
+
     pub fn rustdoc(&self, host: Interned<String>) -> PathBuf {
         self.ensure(tool::Rustdoc { host })
     }
@@ -750,6 +759,9 @@
             match mode {
                 Mode::Std => {
                     self.clear_if_dirty(&my_out, &self.rustc(compiler));
+                    for backend in self.codegen_backends(compiler) {
+                        self.clear_if_dirty(&my_out, &backend);
+                    }
                 },
                 Mode::Test => {
                     self.clear_if_dirty(&my_out, &libstd_stamp);
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 9421817..a2989f0 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -82,6 +82,9 @@
     pub lldb_enabled: bool,
     pub llvm_tools_enabled: bool,
 
+    pub llvm_cflags: Option<String>,
+    pub llvm_cxxflags: Option<String>,
+    pub llvm_ldflags: Option<String>,
     pub llvm_use_libcxx: bool,
 
     // rust codegen options
@@ -254,6 +257,9 @@
     link_shared: Option<bool>,
     version_suffix: Option<String>,
     clang_cl: Option<String>,
+    cflags: Option<String>,
+    cxxflags: Option<String>,
+    ldflags: Option<String>,
     use_libcxx: Option<bool>,
 }
 
@@ -516,6 +522,10 @@
             config.llvm_link_jobs = llvm.link_jobs;
             config.llvm_version_suffix = llvm.version_suffix.clone();
             config.llvm_clang_cl = llvm.clang_cl.clone();
+
+            config.llvm_cflags = llvm.cflags.clone();
+            config.llvm_cxxflags = llvm.cxxflags.clone();
+            config.llvm_ldflags = llvm.ldflags.clone();
             set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
         }
 
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index b0c3c970..7b70236 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -64,6 +64,10 @@
 o("missing-tools", "dist.missing-tools", "allow failures when building tools")
 o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++")
 
+o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
+o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
+o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags")
+
 # Optimization and debugging options. These may be overridden by the release
 # channel, etc.
 o("optimize", "rust.optimize", "build optimized rust code")
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index cb9c86d..f5bacd6 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -358,7 +358,11 @@
     }
 
     cfg.build_arg("-j").build_arg(builder.jobs().to_string());
-    cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" "));
+    let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" ");
+    if let Some(ref s) = builder.config.llvm_cxxflags {
+        cflags.push_str(&format!(" {}", s));
+    }
+    cfg.define("CMAKE_C_FLAGS", cflags);
     let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" ");
     if builder.config.llvm_static_stdcpp &&
         !target.contains("windows") &&
@@ -366,6 +370,9 @@
     {
         cxxflags.push_str(" -static-libstdc++");
     }
+    if let Some(ref s) = builder.config.llvm_cxxflags {
+        cxxflags.push_str(&format!(" {}", s));
+    }
     cfg.define("CMAKE_CXX_FLAGS", cxxflags);
     if let Some(ar) = builder.ar(target) {
         if ar.is_absolute() {
@@ -383,6 +390,12 @@
         }
     }
 
+    if let Some(ref s) = builder.config.llvm_ldflags {
+        cfg.define("CMAKE_SHARED_LINKER_FLAGS", s);
+        cfg.define("CMAKE_MODULE_LINKER_FLAGS", s);
+        cfg.define("CMAKE_EXE_LINKER_FLAGS", s);
+    }
+
     if env::var_os("SCCACHE_ERROR_LOG").is_some() {
         cfg.env("RUST_LOG", "sccache=warn");
     }
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 94f2104..a616409 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -187,7 +187,7 @@
 
 This flag lets you control the optimization level.
 
-* `0`: no optimizations
+* `0`: no optimizations, also turn on `cfg(debug_assertions)`.
 * `1`: basic optimizations
 * `2`: some optimizations
 * `3`: all optimizations
diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
index 3a1cafe..25a5c97 100644
--- a/src/doc/rustc/src/contributing.md
+++ b/src/doc/rustc/src/contributing.md
@@ -1,6 +1,12 @@
 # Contributing to rustc
 
 We'd love to have your help improving `rustc`! To that end, we've written [a
-whole book](https://rust-lang.github.io/rustc-guide/) on its
+whole book][rustc_guide] on its
 internals, how it works, and how to get started working on it. To learn
 more, you'll want to check that out.
+
+If you would like to contribute to _this_ book, you can find its source in the
+rustc source at [src/doc/rustc][rustc_book].
+
+[rustc_guide]: https://rust-lang.github.io/rustc-guide/
+[rustc_book]: https://github.com/rust-lang/rust/tree/master/src/doc/rustc
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 905b064..d3eb8cb 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -417,3 +417,15 @@
 (grouping of crate docs generated into the same output directory, like with `cargo doc`). Per-crate
 files like the search index will still load from the documentation root, but anything that gets
 renamed with `--resource-suffix` will load from the given path.
+
+### `--persist-doctests`: persist doctest executables after running
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs --test -Z unstable-options --persist-doctests target/rustdoctest
+```
+
+This flag allows you to keep doctest executables around after they're compiled or run.
+Usually, rustdoc will immediately discard a compiled doctest after it's been tested, but
+with this option, you can keep those binaries around for farther testing.
\ No newline at end of file
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 86f28a9..d43a5c1 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -91,6 +91,8 @@
 /// For example, let's tweak our previous code a bit:
 ///
 /// ```
+/// // The derive implements <BookFormat> == <BookFormat> comparisons
+/// #[derive(PartialEq)]
 /// enum BookFormat {
 ///     Paperback,
 ///     Hardback,
@@ -102,31 +104,34 @@
 ///     format: BookFormat,
 /// }
 ///
+/// // Implement <Book> == <BookFormat> comparisons
 /// impl PartialEq<BookFormat> for Book {
 ///     fn eq(&self, other: &BookFormat) -> bool {
-///         match (&self.format, other) {
-///            (BookFormat::Paperback, BookFormat::Paperback) => true,
-///            (BookFormat::Hardback,  BookFormat::Hardback)  => true,
-///            (BookFormat::Ebook,     BookFormat::Ebook)     => true,
-///            (_, _) => false,
-///         }
+///         self.format == *other
+///     }
+/// }
+///
+/// // Implement <BookFormat> == <Book> comparisons
+/// impl PartialEq<Book> for BookFormat {
+///     fn eq(&self, other: &Book) -> bool {
+///         *self == other.format
 ///     }
 /// }
 ///
 /// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
 ///
 /// assert!(b1 == BookFormat::Paperback);
-/// assert!(b1 != BookFormat::Ebook);
+/// assert!(BookFormat::Ebook != b1);
 /// ```
 ///
 /// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
-/// we've changed what type we can use on the right side of the `==` operator.
-/// This lets us use it in the `assert!` statements at the bottom.
+/// we allow `BookFormat`s to be compared with `Book`s.
 ///
 /// You can also combine these implementations to let the `==` operator work with
 /// two different types:
 ///
 /// ```
+/// #[derive(PartialEq)]
 /// enum BookFormat {
 ///     Paperback,
 ///     Hardback,
@@ -140,12 +145,13 @@
 ///
 /// impl PartialEq<BookFormat> for Book {
 ///     fn eq(&self, other: &BookFormat) -> bool {
-///         match (&self.format, other) {
-///            (&BookFormat::Paperback, &BookFormat::Paperback) => true,
-///            (&BookFormat::Hardback,  &BookFormat::Hardback)  => true,
-///            (&BookFormat::Ebook,     &BookFormat::Ebook)     => true,
-///            (_, _) => false,
-///         }
+///         self.format == *other
+///     }
+/// }
+///
+/// impl PartialEq<Book> for BookFormat {
+///     fn eq(&self, other: &Book) -> bool {
+///         *self == other.format
 ///     }
 /// }
 ///
@@ -159,7 +165,7 @@
 /// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
 ///
 /// assert!(b1 == BookFormat::Paperback);
-/// assert!(b1 != BookFormat::Ebook);
+/// assert!(BookFormat::Ebook != b1);
 /// assert!(b1 == b2);
 /// ```
 ///
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs
index 0717a88..644380c 100644
--- a/src/libcore/ffi.rs
+++ b/src/libcore/ffi.rs
@@ -12,24 +12,27 @@
 /// and `*mut c_void` is equivalent to C's `void*`. That said, this is
 /// *not* the same as C's `void` return type, which is Rust's `()` type.
 ///
-/// Ideally, this type would be equivalent to [`!`], but currently it may
-/// be more ideal to use `c_void` for FFI purposes.
+/// To model pointers to opaque types in FFI, until `extern type` is
+/// stabilized, it is recommended to use a newtype wrapper around an empty
+/// byte array. See the [Nomicon] for details.
 ///
-/// [`!`]: ../../std/primitive.never.html
 /// [pointer]: ../../std/primitive.pointer.html
+/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
 // N.B., for LLVM to recognize the void pointer type and by extension
 //     functions like malloc(), we need to have it represented as i8* in
 //     LLVM bitcode. The enum used here ensures this and prevents misuse
-//     of the "raw" type by only having private variants.. We need two
+//     of the "raw" type by only having private variants. We need two
 //     variants, because the compiler complains about the repr attribute
-//     otherwise.
+//     otherwise and we need at least one variant as otherwise the enum
+//     would be uninhabited and at least dereferencing such pointers would
+//     be UB.
 #[repr(u8)]
 #[stable(feature = "raw_os", since = "1.1.0")]
 pub enum c_void {
-    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
+    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
                issue = "0")]
     #[doc(hidden)] __variant1,
-    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
+    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
                issue = "0")]
     #[doc(hidden)] __variant2,
 }
@@ -49,7 +52,7 @@
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 extern {
     type VaListImpl;
 }
@@ -74,7 +77,7 @@
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 struct VaListImpl {
     stack: *mut (),
     gr_top: *mut (),
@@ -90,7 +93,7 @@
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 struct VaListImpl {
     gpr: u8,
     fpr: u8,
@@ -106,7 +109,7 @@
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 struct VaListImpl {
     gp_offset: i32,
     fp_offset: i32,
@@ -120,7 +123,7 @@
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 #[repr(transparent)]
 pub struct VaList<'a>(&'a mut VaListImpl);
 
@@ -140,7 +143,7 @@
     #[unstable(feature = "c_variadic",
                reason = "the `c_variadic` feature has not been properly tested on \
                          all supported platforms",
-               issue = "27745")]
+               issue = "44930")]
     pub trait VaArgSafe {}
 }
 
@@ -150,7 +153,7 @@
             #[unstable(feature = "c_variadic",
                        reason = "the `c_variadic` feature has not been properly tested on \
                                  all supported platforms",
-                       issue = "27745")]
+                       issue = "44930")]
             impl sealed_trait::VaArgSafe for $t {}
         )+
     }
@@ -163,12 +166,12 @@
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 impl<T> sealed_trait::VaArgSafe for *mut T {}
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 impl<T> sealed_trait::VaArgSafe for *const T {}
 
 impl<'a> VaList<'a> {
@@ -176,7 +179,7 @@
     #[unstable(feature = "c_variadic",
                reason = "the `c_variadic` feature has not been properly tested on \
                          all supported platforms",
-               issue = "27745")]
+               issue = "44930")]
     pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
         va_arg(self)
     }
@@ -185,7 +188,7 @@
     #[unstable(feature = "c_variadic",
                reason = "the `c_variadic` feature has not been properly tested on \
                          all supported platforms",
-               issue = "27745")]
+               issue = "44930")]
     pub unsafe fn copy<F, R>(&self, f: F) -> R
             where F: for<'copy> FnOnce(VaList<'copy>) -> R {
         #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 214b5d3..5221d6f 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -211,9 +211,18 @@
     }
 }
 
-/// A struct to represent both where to emit formatting strings to and how they
-/// should be formatted. A mutable version of this is passed to all formatting
-/// traits.
+/// Configuration for formatting.
+///
+/// A `Formatter` represents various options related to formatting. Users do not
+/// construct `Formatter`s directly; a mutable reference to one is passed to
+/// the `fmt` method of all formatting traits, like [`Debug`] and [`Display`].
+///
+/// To interact with a `Formatter`, you'll call various methods to change the
+/// various options related to formatting. For examples, please see the
+/// documentation of the methods defined on `Formatter` below.
+///
+/// [`Debug`]: trait.Debug.html
+/// [`Display`]: trait.Display.html
 #[allow(missing_debug_implementations)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Formatter<'a> {
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 9e57a4e..ad5a207 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -49,3 +49,26 @@
 pub unsafe fn unreachable_unchecked() -> ! {
     intrinsics::unreachable()
 }
+
+/// Save power or switch hyperthreads in a busy-wait spin-loop.
+///
+/// This function is deliberately more primitive than
+/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
+/// does not directly yield to the system's scheduler.
+/// In some cases it might be useful to use a combination of both functions.
+/// Careful benchmarking is advised.
+///
+/// On some platforms this function may not do anything at all.
+#[inline]
+#[unstable(feature = "renamed_spin_loop", issue = "55002")]
+pub fn spin_loop() {
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    unsafe {
+        asm!("pause" ::: "memory" : "volatile");
+    }
+
+    #[cfg(target_arch = "aarch64")]
+    unsafe {
+        asm!("yield" ::: "memory" : "volatile");
+    }
+}
diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs
index 4f55c68..6cfa367 100644
--- a/src/libcore/ops/index.rs
+++ b/src/libcore/ops/index.rs
@@ -51,6 +51,21 @@
 /// ```
 #[lang = "index"]
 #[rustc_on_unimplemented(
+    on(
+        _Self="&str",
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
+    on(
+        _Self="str",
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
+    on(
+        _Self="std::string::String",
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
     message="the type `{Self}` cannot be indexed by `{Idx}`",
     label="`{Self}` cannot be indexed by `{Idx}`",
 )]
@@ -141,6 +156,21 @@
 /// ```
 #[lang = "index_mut"]
 #[rustc_on_unimplemented(
+    on(
+        _Self="&str",
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
+    on(
+        _Self="str",
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
+    on(
+        _Self="std::string::String",
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
     message="the type `{Self}` cannot be mutably indexed by `{Idx}`",
     label="`{Self}` cannot be mutably indexed by `{Idx}`",
 )]
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 762e075..7c09a36 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -99,6 +99,7 @@
 
 use fmt;
 use marker::{Sized, Unpin};
+use cmp::{self, PartialEq, PartialOrd};
 use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn};
 
 /// A pinned pointer.
@@ -112,16 +113,57 @@
 /// [`Unpin`]: ../../std/marker/trait.Unpin.html
 /// [`pin` module]: ../../std/pin/index.html
 //
-// Note: the derives below are allowed because they all only use `&P`, so they
-// cannot move the value behind `pointer`.
+// Note: the derives below, and the explicit `PartialEq` and `PartialOrd`
+// implementations, are allowed because they all only use `&P`, so they cannot move
+// the value behind `pointer`.
 #[stable(feature = "pin", since = "1.33.0")]
 #[fundamental]
 #[repr(transparent)]
-#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Hash, Eq, Ord)]
 pub struct Pin<P> {
     pointer: P,
 }
 
+#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
+impl<P, Q> PartialEq<Pin<Q>> for Pin<P>
+where
+    P: PartialEq<Q>,
+{
+    fn eq(&self, other: &Pin<Q>) -> bool {
+        self.pointer == other.pointer
+    }
+
+    fn ne(&self, other: &Pin<Q>) -> bool {
+        self.pointer != other.pointer
+    }
+}
+
+#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
+impl<P, Q> PartialOrd<Pin<Q>> for Pin<P>
+where
+    P: PartialOrd<Q>,
+{
+    fn partial_cmp(&self, other: &Pin<Q>) -> Option<cmp::Ordering> {
+        self.pointer.partial_cmp(&other.pointer)
+    }
+
+    fn lt(&self, other: &Pin<Q>) -> bool {
+        self.pointer < other.pointer
+    }
+
+    fn le(&self, other: &Pin<Q>) -> bool {
+        self.pointer <= other.pointer
+    }
+
+    fn gt(&self, other: &Pin<Q>) -> bool {
+        self.pointer > other.pointer
+    }
+
+    fn ge(&self, other: &Pin<Q>) -> bool {
+        self.pointer >= other.pointer
+    }
+}
+
 impl<P: Deref> Pin<P>
 where
     P::Target: Unpin,
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 99e6365..8992e51 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -84,6 +84,8 @@
 use cell::UnsafeCell;
 use fmt;
 
+use hint::spin_loop;
+
 /// Save power or switch hyperthreads in a busy-wait spin-loop.
 ///
 /// This function is deliberately more primitive than
@@ -96,15 +98,7 @@
 #[inline]
 #[stable(feature = "spin_loop_hint", since = "1.24.0")]
 pub fn spin_loop_hint() {
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    unsafe {
-        asm!("pause" ::: "memory" : "volatile");
-    }
-
-    #[cfg(target_arch = "aarch64")]
-    unsafe {
-        asm!("yield" ::: "memory" : "volatile");
-    }
+    spin_loop()
 }
 
 /// A boolean type which can be safely shared between threads.
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index 978d20e..6122fe6 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -99,30 +99,21 @@
     }
 
     fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex {
-        let hir_id = self.tcx.hir().node_to_hir_id(stmt.node.id());
-        match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                let exit = self.decl(&decl, pred);
-                self.add_ast_node(hir_id.local_id, &[exit])
-            }
-
-            hir::StmtKind::Expr(ref expr, _) |
-            hir::StmtKind::Semi(ref expr, _) => {
-                let exit = self.expr(&expr, pred);
-                self.add_ast_node(hir_id.local_id, &[exit])
-            }
-        }
-    }
-
-    fn decl(&mut self, decl: &hir::Decl, pred: CFGIndex) -> CFGIndex {
-        match decl.node {
-            hir::DeclKind::Local(ref local) => {
+        let hir_id = self.tcx.hir().node_to_hir_id(stmt.id);
+        let exit = match stmt.node {
+            hir::StmtKind::Local(ref local) => {
                 let init_exit = self.opt_expr(&local.init, pred);
                 self.pat(&local.pat, init_exit)
             }
-
-            hir::DeclKind::Item(_) => pred,
-        }
+            hir::StmtKind::Item(_) => {
+                pred
+            }
+            hir::StmtKind::Expr(ref expr) |
+            hir::StmtKind::Semi(ref expr) => {
+                self.expr(&expr, pred)
+            }
+        };
+        self.add_ast_node(hir_id.local_id, &[exit])
     }
 
     fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 427fe51..4cfebaa 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -476,6 +476,9 @@
     [] CheckModLoops(DefId),
     [] CheckModUnstableApiUsage(DefId),
     [] CheckModItemTypes(DefId),
+    [] CheckModPrivacy(DefId),
+    [] CheckModIntrinsics(DefId),
+    [] CheckModLiveness(DefId),
     [] CollectModItemTypes(DefId),
 
     [] Reachability,
@@ -583,6 +586,7 @@
     [] CheckImplItemWellFormed(DefId),
     [] ReachableNonGenerics(CrateNum),
     [] NativeLibraries(CrateNum),
+    [] EntryFn(CrateNum),
     [] PluginRegistrarFn(CrateNum),
     [] ProcMacroDeclsStatic(CrateNum),
     [input] CrateDisambiguator(CrateNum),
@@ -630,6 +634,7 @@
     [input] Freevars(DefId),
     [input] MaybeUnusedTraitImport(DefId),
     [input] MaybeUnusedExternCrates,
+    [input] NamesImportedByGlobUse(DefId),
     [eval_always] StabilityIndex,
     [eval_always] AllTraits,
     [input] AllCrateNums,
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 501ef01..a9e80dd 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -3,7 +3,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use smallvec::SmallVec;
-use rustc_data_structures::sync::{Lrc, Lock};
+use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, Ordering};
 use std::env;
 use std::hash::Hash;
 use std::collections::hash_map::Entry;
@@ -58,7 +58,7 @@
     /// nodes and edges as well as all fingerprints of nodes that have them.
     previous: PreviousDepGraph,
 
-    colors: Lock<DepNodeColorMap>,
+    colors: DepNodeColorMap,
 
     /// When we load, there may be `.o` files, cached mir, or other such
     /// things available to us. If we find that they are not dirty, we
@@ -84,7 +84,7 @@
                 dep_node_debug: Default::default(),
                 current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
                 previous: prev_graph,
-                colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)),
+                colors: DepNodeColorMap::new(prev_graph_node_count),
                 loaded_from_cache: Default::default(),
             })),
         }
@@ -282,12 +282,11 @@
                     DepNodeColor::Red
                 };
 
-                let mut colors = data.colors.borrow_mut();
-                debug_assert!(colors.get(prev_index).is_none(),
+                debug_assert!(data.colors.get(prev_index).is_none(),
                               "DepGraph::with_task() - Duplicate DepNodeColor \
                                insertion for {:?}", key);
 
-                colors.insert(prev_index, color);
+                data.colors.insert(prev_index, color);
             }
 
             (result, dep_node_index)
@@ -502,7 +501,7 @@
     pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
         if let Some(ref data) = self.data {
             if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) {
-                return data.colors.borrow().get(prev_index)
+                return data.colors.get(prev_index)
             } else {
                 // This is a node that did not exist in the previous compilation
                 // session, so we consider it to be red.
@@ -513,56 +512,89 @@
         None
     }
 
-    pub fn try_mark_green<'tcx>(&self,
-                                tcx: TyCtxt<'_, 'tcx, 'tcx>,
-                                dep_node: &DepNode)
-                                -> Option<DepNodeIndex> {
-        debug!("try_mark_green({:?}) - BEGIN", dep_node);
-        let data = self.data.as_ref().unwrap();
+    /// Try to read a node index for the node dep_node.
+    /// A node will have an index, when it's already been marked green, or when we can mark it
+    /// green. This function will mark the current task as a reader of the specified node, when
+    /// a node index can be found for that node.
+    pub fn try_mark_green_and_read(
+        &self,
+        tcx: TyCtxt<'_, '_, '_>,
+        dep_node: &DepNode
+    ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
+        self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| {
+            debug_assert!(self.is_green(&dep_node));
+            self.read_index(dep_node_index);
+            (prev_index, dep_node_index)
+        })
+    }
 
-        #[cfg(not(parallel_queries))]
-        debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
+    pub fn try_mark_green(
+        &self,
+        tcx: TyCtxt<'_, '_, '_>,
+        dep_node: &DepNode
+    ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
+        debug_assert!(!dep_node.kind.is_input());
 
-        if dep_node.kind.is_input() {
-            // We should only hit try_mark_green() for inputs that do not exist
-            // anymore in the current compilation session. Existing inputs are
-            // eagerly marked as either red/green before any queries are
-            // executed.
-            debug_assert!(dep_node.extract_def_id(tcx).is_none());
-            debug!("try_mark_green({:?}) - END - DepNode is deleted input", dep_node);
-            return None;
-        }
+        // Return None if the dep graph is disabled
+        let data = self.data.as_ref()?;
 
-        let (prev_deps, prev_dep_node_index) = match data.previous.edges_from(dep_node) {
-            Some(prev) => {
+        // Return None if the dep node didn't exist in the previous session
+        let prev_index = data.previous.node_to_index_opt(dep_node)?;
+
+        match data.colors.get(prev_index) {
+            Some(DepNodeColor::Green(dep_node_index)) => Some((prev_index, dep_node_index)),
+            Some(DepNodeColor::Red) => None,
+            None => {
                 // This DepNode and the corresponding query invocation existed
                 // in the previous compilation session too, so we can try to
                 // mark it as green by recursively marking all of its
                 // dependencies green.
-                prev
+                self.try_mark_previous_green(
+                    tcx.global_tcx(),
+                    data,
+                    prev_index,
+                    &dep_node
+                ).map(|dep_node_index| {
+                    (prev_index, dep_node_index)
+                })
             }
-            None => {
-                // This DepNode did not exist in the previous compilation session,
-                // so we cannot mark it as green.
-                debug!("try_mark_green({:?}) - END - DepNode does not exist in \
-                        current compilation session anymore", dep_node);
-                return None
-            }
-        };
+        }
+    }
 
-        debug_assert!(data.colors.borrow().get(prev_dep_node_index).is_none());
+    /// Try to mark a dep-node which existed in the previous compilation session as green
+    fn try_mark_previous_green<'tcx>(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, 'tcx>,
+        data: &DepGraphData,
+        prev_dep_node_index: SerializedDepNodeIndex,
+        dep_node: &DepNode
+    ) -> Option<DepNodeIndex> {
+        debug!("try_mark_previous_green({:?}) - BEGIN", dep_node);
+
+        #[cfg(not(parallel_queries))]
+        {
+            debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
+            debug_assert!(data.colors.get(prev_dep_node_index).is_none());
+        }
+
+        // We never try to mark inputs as green
+        debug_assert!(!dep_node.kind.is_input());
+
+        debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node);
+
+        let prev_deps = data.previous.edge_targets_from(prev_dep_node_index);
 
         let mut current_deps = SmallVec::new();
 
         for &dep_dep_node_index in prev_deps {
-            let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
+            let dep_dep_node_color = data.colors.get(dep_dep_node_index);
 
             match dep_dep_node_color {
                 Some(DepNodeColor::Green(node_index)) => {
                     // This dependency has been marked as green before, we are
                     // still fine and can continue with checking the other
                     // dependencies.
-                    debug!("try_mark_green({:?}) --- found dependency {:?} to \
+                    debug!("try_mark_previous_green({:?}) --- found dependency {:?} to \
                             be immediately green",
                             dep_node,
                             data.previous.index_to_node(dep_dep_node_index));
@@ -573,7 +605,7 @@
                     // compared to the previous compilation session. We cannot
                     // mark the DepNode as green and also don't need to bother
                     // with checking any of the other dependencies.
-                    debug!("try_mark_green({:?}) - END - dependency {:?} was \
+                    debug!("try_mark_previous_green({:?}) - END - dependency {:?} was \
                             immediately red",
                             dep_node,
                             data.previous.index_to_node(dep_dep_node_index));
@@ -585,12 +617,18 @@
                     // We don't know the state of this dependency. If it isn't
                     // an input node, let's try to mark it green recursively.
                     if !dep_dep_node.kind.is_input() {
-                         debug!("try_mark_green({:?}) --- state of dependency {:?} \
+                         debug!("try_mark_previous_green({:?}) --- state of dependency {:?} \
                                  is unknown, trying to mark it green", dep_node,
                                  dep_dep_node);
 
-                        if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
-                            debug!("try_mark_green({:?}) --- managed to MARK \
+                        let node_index = self.try_mark_previous_green(
+                            tcx,
+                            data,
+                            dep_dep_node_index,
+                            dep_dep_node
+                        );
+                        if let Some(node_index) = node_index {
+                            debug!("try_mark_previous_green({:?}) --- managed to MARK \
                                     dependency {:?} as green", dep_node, dep_dep_node);
                             current_deps.push(node_index);
                             continue;
@@ -600,7 +638,7 @@
                             DepKind::Hir |
                             DepKind::HirBody |
                             DepKind::CrateMetadata => {
-                                if dep_node.extract_def_id(tcx).is_none() {
+                                if dep_dep_node.extract_def_id(tcx).is_none() {
                                     // If the node does not exist anymore, we
                                     // just fail to mark green.
                                     return None
@@ -620,20 +658,20 @@
                     }
 
                     // We failed to mark it green, so we try to force the query.
-                    debug!("try_mark_green({:?}) --- trying to force \
+                    debug!("try_mark_previous_green({:?}) --- trying to force \
                             dependency {:?}", dep_node, dep_dep_node);
                     if ::ty::query::force_from_dep_node(tcx, dep_dep_node) {
-                        let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
+                        let dep_dep_node_color = data.colors.get(dep_dep_node_index);
 
                         match dep_dep_node_color {
                             Some(DepNodeColor::Green(node_index)) => {
-                                debug!("try_mark_green({:?}) --- managed to \
+                                debug!("try_mark_previous_green({:?}) --- managed to \
                                         FORCE dependency {:?} to green",
                                         dep_node, dep_dep_node);
                                 current_deps.push(node_index);
                             }
                             Some(DepNodeColor::Red) => {
-                                debug!("try_mark_green({:?}) - END - \
+                                debug!("try_mark_previous_green({:?}) - END - \
                                         dependency {:?} was red after forcing",
                                        dep_node,
                                        dep_dep_node);
@@ -641,7 +679,7 @@
                             }
                             None => {
                                 if !tcx.sess.has_errors() {
-                                    bug!("try_mark_green() - Forcing the DepNode \
+                                    bug!("try_mark_previous_green() - Forcing the DepNode \
                                           should have set its color")
                                 } else {
                                     // If the query we just forced has resulted
@@ -653,7 +691,7 @@
                         }
                     } else {
                         // The DepNode could not be forced.
-                        debug!("try_mark_green({:?}) - END - dependency {:?} \
+                        debug!("try_mark_previous_green({:?}) - END - dependency {:?} \
                                 could not be forced", dep_node, dep_dep_node);
                         return None
                     }
@@ -705,16 +743,15 @@
         }
 
         // ... and finally storing a "Green" entry in the color map.
-        let mut colors = data.colors.borrow_mut();
         // Multiple threads can all write the same color here
         #[cfg(not(parallel_queries))]
-        debug_assert!(colors.get(prev_dep_node_index).is_none(),
-                      "DepGraph::try_mark_green() - Duplicate DepNodeColor \
+        debug_assert!(data.colors.get(prev_dep_node_index).is_none(),
+                      "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
                       insertion for {:?}", dep_node);
 
-        colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
+        data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
 
-        debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node);
+        debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node);
         Some(dep_node_index)
     }
 
@@ -735,9 +772,8 @@
     pub fn exec_cache_promotions<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         let green_nodes: Vec<DepNode> = {
             let data = self.data.as_ref().unwrap();
-            let colors = data.colors.borrow();
-            colors.values.indices().filter_map(|prev_index| {
-                match colors.get(prev_index) {
+            data.colors.values.indices().filter_map(|prev_index| {
+                match data.colors.get(prev_index) {
                     Some(DepNodeColor::Green(_)) => {
                         let dep_node = data.previous.index_to_node(prev_index);
                         if dep_node.cache_on_disk(tcx) {
@@ -1035,7 +1071,7 @@
 // A data structure that stores Option<DepNodeColor> values as a contiguous
 // array, using one u32 per entry.
 struct DepNodeColorMap {
-    values: IndexVec<SerializedDepNodeIndex, u32>,
+    values: IndexVec<SerializedDepNodeIndex, AtomicU32>,
 }
 
 const COMPRESSED_NONE: u32 = 0;
@@ -1045,12 +1081,12 @@
 impl DepNodeColorMap {
     fn new(size: usize) -> DepNodeColorMap {
         DepNodeColorMap {
-            values: IndexVec::from_elem_n(COMPRESSED_NONE, size)
+            values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect(),
         }
     }
 
     fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
-        match self.values[index] {
+        match self.values[index].load(Ordering::Acquire) {
             COMPRESSED_NONE => None,
             COMPRESSED_RED => Some(DepNodeColor::Red),
             value => Some(DepNodeColor::Green(DepNodeIndex::from_u32(
@@ -1059,10 +1095,10 @@
         }
     }
 
-    fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) {
-        self.values[index] = match color {
+    fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
+        self.values[index].store(match color {
             DepNodeColor::Red => COMPRESSED_RED,
             DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN,
-        }
+        }, Ordering::Release)
     }
 }
diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs
index 76d2954..ea5350a 100644
--- a/src/librustc/dep_graph/prev.rs
+++ b/src/librustc/dep_graph/prev.rs
@@ -19,14 +19,11 @@
     }
 
     #[inline]
-    pub fn edges_from(&self,
-                      dep_node: &DepNode)
-                      -> Option<(&[SerializedDepNodeIndex], SerializedDepNodeIndex)> {
-        self.index
-            .get(dep_node)
-            .map(|&node_index| {
-                (self.data.edge_targets_from(node_index), node_index)
-            })
+    pub fn edge_targets_from(
+        &self,
+        dep_node_index: SerializedDepNodeIndex
+    ) -> &[SerializedDepNodeIndex] {
+        self.data.edge_targets_from(dep_node_index)
     }
 
     #[inline]
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index b4a0071..df111b2 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -283,8 +283,8 @@
 
     fn check_stmt_attributes(&self, stmt: &hir::Stmt) {
         // When checking statements ignore expressions, they will be checked later
-        if let hir::StmtKind::Decl(_, _) = stmt.node {
-            for attr in stmt.node.attrs() {
+        if let hir::StmtKind::Local(ref l) = stmt.node {
+            for attr in l.attrs.iter() {
                 if attr.check_name("inline") {
                     self.check_inline(attr, &stmt.span, Target::Statement);
                 }
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index f633703..592fb78 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -35,11 +35,9 @@
 use syntax_pos::Span;
 use hir::*;
 use hir::def::Def;
-use hir::map::{self, Map};
+use hir::map::Map;
 use super::itemlikevisit::DeepVisitor;
 
-use std::cmp;
-
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
     /// `#[xxx] pub async/const/extern "Abi" fn foo()`
@@ -260,9 +258,6 @@
     fn visit_pat(&mut self, p: &'v Pat) {
         walk_pat(self, p)
     }
-    fn visit_decl(&mut self, d: &'v Decl) {
-        walk_decl(self, d)
-    }
     fn visit_anon_const(&mut self, c: &'v AnonConst) {
         walk_anon_const(self, c)
     }
@@ -953,26 +948,17 @@
 }
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
+    visitor.visit_id(statement.id);
     match statement.node {
-        StmtKind::Decl(ref declaration, id) => {
-            visitor.visit_id(id);
-            visitor.visit_decl(declaration)
-        }
-        StmtKind::Expr(ref expression, id) |
-        StmtKind::Semi(ref expression, id) => {
-            visitor.visit_id(id);
+        StmtKind::Local(ref local) => visitor.visit_local(local),
+        StmtKind::Item(ref item) => visitor.visit_nested_item(**item),
+        StmtKind::Expr(ref expression) |
+        StmtKind::Semi(ref expression) => {
             visitor.visit_expr(expression)
         }
     }
 }
 
-pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
-    match declaration.node {
-        DeclKind::Local(ref local) => visitor.visit_local(local),
-        DeclKind::Item(item) => visitor.visit_nested_item(item),
-    }
-}
-
 pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
     visitor.visit_id(constant.id);
     visitor.visit_nested_body(constant.body);
@@ -1133,57 +1119,3 @@
     // the right thing to do, should content be added in the future,
     // would be to walk it.
 }
-
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct IdRange {
-    pub min: NodeId,
-    pub max: NodeId,
-}
-
-impl IdRange {
-    pub fn max() -> IdRange {
-        IdRange {
-            min: NodeId::MAX,
-            max: NodeId::from_u32(0),
-        }
-    }
-
-    pub fn empty(&self) -> bool {
-        self.min >= self.max
-    }
-
-    pub fn contains(&self, id: NodeId) -> bool {
-        id >= self.min && id < self.max
-    }
-
-    pub fn add(&mut self, id: NodeId) {
-        self.min = cmp::min(self.min, id);
-        self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1));
-    }
-}
-
-
-pub struct IdRangeComputingVisitor<'a, 'hir: 'a> {
-    result: IdRange,
-    map: &'a map::Map<'hir>,
-}
-
-impl<'a, 'hir> IdRangeComputingVisitor<'a, 'hir> {
-    pub fn new(map: &'a map::Map<'hir>) -> IdRangeComputingVisitor<'a, 'hir> {
-        IdRangeComputingVisitor { result: IdRange::max(), map: map }
-    }
-
-    pub fn result(&self) -> IdRange {
-        self.result
-    }
-}
-
-impl<'a, 'hir> Visitor<'hir> for IdRangeComputingVisitor<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
-        NestedVisitorMap::OnlyBodies(&self.map)
-    }
-
-    fn visit_id(&mut self, id: NodeId) {
-        self.result.add(id);
-    }
-}
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 8badcbf..2f7d8f0 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1957,7 +1957,7 @@
         )
     }
 
-    fn lower_local(&mut self, l: &Local) -> (P<hir::Local>, SmallVec<[hir::ItemId; 1]>) {
+    fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[hir::ItemId; 1]>) {
         let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
         let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
         if self.sess.features_untracked().impl_trait_in_bindings {
@@ -1967,7 +1967,7 @@
             }
         }
         let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
-        (P(hir::Local {
+        (hir::Local {
             id: node_id,
             hir_id,
             ty: l.ty
@@ -1984,7 +1984,7 @@
             span: l.span,
             attrs: l.attrs.clone(),
             source: hir::LocalSource::Normal,
-        }), ids)
+        }, ids)
     }
 
     fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
@@ -3775,7 +3775,7 @@
                 let ohs = P(self.lower_expr(ohs));
                 hir::ExprKind::Unary(op, ohs)
             }
-            ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((*l).clone())),
+            ExprKind::Lit(ref l) => hir::ExprKind::Lit((*l).clone()),
             ExprKind::Cast(ref expr, ref ty) => {
                 let expr = P(self.lower_expr(expr));
                 hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
@@ -4331,10 +4331,11 @@
                         ThinVec::new(),
                     ))
                 };
-                let match_stmt = respan(
-                    head_sp,
-                    hir::StmtKind::Expr(match_expr, self.next_id().node_id)
-                );
+                let match_stmt = hir::Stmt {
+                    id: self.next_id().node_id,
+                    node: hir::StmtKind::Expr(match_expr),
+                    span: head_sp,
+                };
 
                 let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id));
 
@@ -4357,10 +4358,11 @@
 
                 let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
                 let body_expr = P(self.expr_block(body_block, ThinVec::new()));
-                let body_stmt = respan(
-                    body.span,
-                    hir::StmtKind::Expr(body_expr, self.next_id().node_id)
-                );
+                let body_stmt = hir::Stmt {
+                    id: self.next_id().node_id,
+                    node: hir::StmtKind::Expr(body_expr),
+                    span: body.span,
+                };
 
                 let loop_block = P(self.block_all(
                     e.span,
@@ -4533,25 +4535,15 @@
                 let (l, item_ids) = self.lower_local(l);
                 let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
                     .into_iter()
-                    .map(|item_id| Spanned {
-                        node: hir::StmtKind::Decl(
-                            P(Spanned {
-                                node: hir::DeclKind::Item(item_id),
-                                span: s.span,
-                            }),
-                            self.next_id().node_id,
-                        ),
+                    .map(|item_id| hir::Stmt {
+                        id: self.next_id().node_id,
+                        node: hir::StmtKind::Item(P(item_id)),
                         span: s.span,
                     })
                     .collect();
-                ids.push(Spanned {
-                    node: hir::StmtKind::Decl(
-                        P(Spanned {
-                            node: hir::DeclKind::Local(l),
-                            span: s.span,
-                        }),
-                        self.lower_node_id(s.id).node_id,
-                    ),
+                ids.push(hir::Stmt {
+                    id: self.lower_node_id(s.id).node_id,
+                    node: hir::StmtKind::Local(P(l)),
                     span: s.span,
                 });
                 return ids;
@@ -4561,26 +4553,23 @@
                 let mut id = Some(s.id);
                 return self.lower_item_id(it)
                     .into_iter()
-                    .map(|item_id| Spanned {
-                        node: hir::StmtKind::Decl(
-                            P(Spanned {
-                                node: hir::DeclKind::Item(item_id),
-                                span: s.span,
-                            }),
-                            id.take()
+                    .map(|item_id| hir::Stmt {
+                        id: id.take()
                               .map(|id| self.lower_node_id(id).node_id)
                               .unwrap_or_else(|| self.next_id().node_id),
-                        ),
+                        node: hir::StmtKind::Item(P(item_id)),
                         span: s.span,
                     })
                     .collect();
             }
-            StmtKind::Expr(ref e) => Spanned {
-                node: hir::StmtKind::Expr(P(self.lower_expr(e)), self.lower_node_id(s.id).node_id),
+            StmtKind::Expr(ref e) => hir::Stmt {
+                id: self.lower_node_id(s.id).node_id,
+                node: hir::StmtKind::Expr(P(self.lower_expr(e))),
                 span: s.span,
             },
-            StmtKind::Semi(ref e) => Spanned {
-                node: hir::StmtKind::Semi(P(self.lower_expr(e)), self.lower_node_id(s.id).node_id),
+            StmtKind::Semi(ref e) => hir::Stmt {
+                id: self.lower_node_id(s.id).node_id,
+                node: hir::StmtKind::Semi(P(self.lower_expr(e))),
                 span: s.span,
             },
             StmtKind::Mac(..) => panic!("Shouldn't exist here"),
@@ -4795,7 +4784,7 @@
     ) -> hir::Stmt {
         let LoweredNodeId { node_id, hir_id } = self.next_id();
 
-        let local = P(hir::Local {
+        let local = hir::Local {
             pat,
             ty: None,
             init: ex,
@@ -4804,9 +4793,12 @@
             span: sp,
             attrs: ThinVec::new(),
             source,
-        });
-        let decl = respan(sp, hir::DeclKind::Local(local));
-        respan(sp, hir::StmtKind::Decl(P(decl), self.next_id().node_id))
+        };
+        hir::Stmt {
+            id: self.next_id().node_id,
+            node: hir::StmtKind::Local(P(local)),
+            span: sp
+        }
     }
 
     fn stmt_let(
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index ae9bb37..7cc5d75 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -426,7 +426,7 @@
     }
 
     fn visit_stmt(&mut self, stmt: &'hir Stmt) {
-        let id = stmt.node.id();
+        let id = stmt.id;
         self.insert(stmt.span, id, Node::Stmt(stmt));
 
         self.with_parent(id, |this| {
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bc0a64a..c9b4b2b 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -120,10 +120,10 @@
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
             ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
+            ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
-            ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
-            ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.as_interned_str()),
+            ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
+            ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 6b707dd..1b74451 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -373,7 +373,9 @@
     /// GlobalMetaData identifies a piece of crate metadata that is global to
     /// a whole crate (as opposed to just one item). GlobalMetaData components
     /// are only supposed to show up right below the crate root.
-    GlobalMetaData(InternedString)
+    GlobalMetaData(InternedString),
+    /// A trait alias.
+    TraitAlias(InternedString),
 }
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@@ -615,6 +617,7 @@
         match *self {
             TypeNs(name) |
             Trait(name) |
+            TraitAlias(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
             AssocExistentialInImpl(name) |
@@ -642,6 +645,7 @@
         let s = match *self {
             TypeNs(name) |
             Trait(name) |
+            TraitAlias(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
             AssocExistentialInImpl(name) |
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 869baef..d9ca37c 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -509,6 +509,21 @@
         &self.forest.krate.attrs
     }
 
+    pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, NodeId)
+    {
+        let node_id = self.as_local_node_id(module).unwrap();
+        self.read(node_id);
+        match self.find_entry(node_id).unwrap().node {
+            Node::Item(&Item {
+                span,
+                node: ItemKind::Mod(ref m),
+                ..
+            }) => (m, span, node_id),
+            Node::Crate => (&self.forest.krate.module, self.forest.krate.span, node_id),
+            _ => panic!("not a module")
+        }
+    }
+
     pub fn visit_item_likes_in_module<V>(&self, module: DefId, visitor: &mut V)
         where V: ItemLikeVisitor<'hir>
     {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index fc4bd05..65d9d5a 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -10,16 +10,17 @@
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
 
+use errors::FatalError;
 use hir::def::Def;
 use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
 use util::nodemap::{NodeMap, FxHashSet};
 use mir::mono::Linkage;
 
 use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
-use syntax::source_map::{self, Spanned};
+use syntax::source_map::Spanned;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
-use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy};
+use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy};
 use syntax::attr::InlineAttr;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
@@ -143,17 +144,6 @@
 pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
-pub struct Label {
-    pub ident: Ident,
-}
-
-impl fmt::Debug for Label {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "label({:?})", self.ident)
-    }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
 pub struct Lifetime {
     pub id: NodeId,
     pub span: Span,
@@ -1144,45 +1134,41 @@
 }
 
 /// A statement
-pub type Stmt = Spanned<StmtKind>;
+#[derive(Clone, RustcEncodable, RustcDecodable)]
+pub struct Stmt {
+    pub id: NodeId,
+    pub node: StmtKind,
+    pub span: Span,
+}
 
-impl fmt::Debug for StmtKind {
+impl fmt::Debug for Stmt {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Sadness.
-        let spanned = source_map::dummy_spanned(self.clone());
-        write!(f,
-               "stmt({}: {})",
-               spanned.node.id(),
-               print::to_string(print::NO_ANN, |s| s.print_stmt(&spanned)))
+        write!(f, "stmt({}: {})", self.id,
+               print::to_string(print::NO_ANN, |s| s.print_stmt(self)))
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub enum StmtKind {
-    /// Could be an item or a local (let) binding:
-    Decl(P<Decl>, NodeId),
+    /// A local (let) binding:
+    Local(P<Local>),
+    /// An item binding:
+    Item(P<ItemId>),
 
     /// Expr without trailing semi-colon (must have unit type):
-    Expr(P<Expr>, NodeId),
+    Expr(P<Expr>),
 
     /// Expr with trailing semi-colon (may have any type):
-    Semi(P<Expr>, NodeId),
+    Semi(P<Expr>),
 }
 
 impl StmtKind {
     pub fn attrs(&self) -> &[Attribute] {
         match *self {
-            StmtKind::Decl(ref d, _) => d.node.attrs(),
-            StmtKind::Expr(ref e, _) |
-            StmtKind::Semi(ref e, _) => &e.attrs,
-        }
-    }
-
-    pub fn id(&self) -> NodeId {
-        match *self {
-            StmtKind::Decl(_, id) |
-            StmtKind::Expr(_, id) |
-            StmtKind::Semi(_, id) => id,
+            StmtKind::Local(ref l) => &l.attrs,
+            StmtKind::Item(_) => &[],
+            StmtKind::Expr(ref e) |
+            StmtKind::Semi(ref e) => &e.attrs,
         }
     }
 }
@@ -1201,32 +1187,6 @@
     pub source: LocalSource,
 }
 
-pub type Decl = Spanned<DeclKind>;
-
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum DeclKind {
-    /// A local (let) binding:
-    Local(P<Local>),
-    /// An item binding:
-    Item(ItemId),
-}
-
-impl DeclKind {
-    pub fn attrs(&self) -> &[Attribute] {
-        match *self {
-            DeclKind::Local(ref l) => &l.attrs,
-            DeclKind::Item(_) => &[]
-        }
-    }
-
-    pub fn is_local(&self) -> bool {
-        match *self {
-            DeclKind::Local(_) => true,
-            _ => false,
-        }
-    }
-}
-
 /// represents one arm of a 'match'
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Arm {
@@ -1466,7 +1426,7 @@
     /// A unary operation (For example: `!x`, `*x`)
     Unary(UnOp, P<Expr>),
     /// A literal (For example: `1`, `"foo"`)
-    Lit(P<Lit>),
+    Lit(Lit),
     /// A cast (`foo as f64`)
     Cast(P<Expr>, P<Ty>),
     Type(P<Expr>, P<Ty>),
@@ -2066,6 +2026,20 @@
     pub hir_ref_id: HirId,
 }
 
+impl TraitRef {
+    /// Get the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
+    pub fn trait_def_id(&self) -> DefId {
+        match self.path.def {
+            Def::Trait(did) => did,
+            Def::TraitAlias(did) => did,
+            Def::Err => {
+                FatalError.raise();
+            }
+            _ => unreachable!(),
+        }
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct PolyTraitRef {
     /// The `'a` in `<'a> Foo<&'a T>`
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index d7acdef..e950f25 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -992,14 +992,29 @@
     pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
         self.maybe_print_comment(st.span.lo())?;
         match st.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                self.print_decl(&decl)?;
+            hir::StmtKind::Local(ref loc) => {
+                self.space_if_not_bol()?;
+                self.ibox(indent_unit)?;
+                self.word_nbsp("let")?;
+
+                self.ibox(indent_unit)?;
+                self.print_local_decl(&loc)?;
+                self.end()?;
+                if let Some(ref init) = loc.init {
+                    self.nbsp()?;
+                    self.word_space("=")?;
+                    self.print_expr(&init)?;
+                }
+                self.end()?
             }
-            hir::StmtKind::Expr(ref expr, _) => {
+            hir::StmtKind::Item(ref item) => {
+                self.ann.nested(self, Nested::Item(**item))?
+            }
+            hir::StmtKind::Expr(ref expr) => {
                 self.space_if_not_bol()?;
                 self.print_expr(&expr)?;
             }
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Semi(ref expr) => {
                 self.space_if_not_bol()?;
                 self.print_expr(&expr)?;
                 self.s.word(";")?;
@@ -1562,30 +1577,6 @@
         Ok(())
     }
 
-    pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
-        self.maybe_print_comment(decl.span.lo())?;
-        match decl.node {
-            hir::DeclKind::Local(ref loc) => {
-                self.space_if_not_bol()?;
-                self.ibox(indent_unit)?;
-                self.word_nbsp("let")?;
-
-                self.ibox(indent_unit)?;
-                self.print_local_decl(&loc)?;
-                self.end()?;
-                if let Some(ref init) = loc.init {
-                    self.nbsp()?;
-                    self.word_space("=")?;
-                    self.print_expr(&init)?;
-                }
-                self.end()
-            }
-            hir::DeclKind::Item(item) => {
-                self.ann.nested(self, Nested::Item(item))
-            }
-        }
-    }
-
     pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
         self.s.word(i.to_string())
     }
@@ -2401,18 +2392,10 @@
 /// seen the semicolon, and thus don't need another.
 fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool {
     match *stmt {
-        hir::StmtKind::Decl(ref d, _) => {
-            match d.node {
-                hir::DeclKind::Local(_) => true,
-                hir::DeclKind::Item(_) => false,
-            }
-        }
-        hir::StmtKind::Expr(ref e, _) => {
-            expr_requires_semi_to_be_stmt(&e)
-        }
-        hir::StmtKind::Semi(..) => {
-            false
-        }
+        hir::StmtKind::Local(_) => true,
+        hir::StmtKind::Item(_) => false,
+        hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e),
+        hir::StmtKind::Semi(..) => false,
     }
 }
 
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 8ff60e5..1590676 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -153,7 +153,7 @@
     Error,
 });
 
-impl_stable_hash_for!(struct hir::Label {
+impl_stable_hash_for!(struct ast::Label {
     ident
 });
 
@@ -483,7 +483,12 @@
     UnNeg
 });
 
-impl_stable_hash_for_spanned!(hir::StmtKind);
+impl_stable_hash_for!(struct hir::Stmt {
+    id,
+    node,
+    span,
+});
+
 
 impl_stable_hash_for!(struct hir::Local {
     pat,
@@ -496,12 +501,6 @@
     source
 });
 
-impl_stable_hash_for_spanned!(hir::DeclKind);
-impl_stable_hash_for!(enum hir::DeclKind {
-    Local(local),
-    Item(item_id)
-});
-
 impl_stable_hash_for!(struct hir::Arm {
     attrs,
     pats,
@@ -941,9 +940,10 @@
 });
 
 impl_stable_hash_for!(enum hir::StmtKind {
-    Decl(decl, id),
-    Expr(expr, id),
-    Semi(expr, id)
+    Local(local),
+    Item(item_id),
+    Expr(expr),
+    Semi(expr)
 });
 
 impl_stable_hash_for!(struct hir::Arg {
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 70ec72d..7e48554 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -164,6 +164,7 @@
 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
 impl_stable_hash_for!(enum ::syntax::ast::LitKind {
     Str(value, style),
+    Err(value),
     ByteStr(value),
     Byte(value),
     Char(value),
@@ -258,7 +259,7 @@
             tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
                 span.hash_stable(hcx, hasher);
                 std_hash::Hash::hash(&delim, hasher);
-                for sub_tt in tts.stream().trees() {
+                for sub_tt in tts.trees() {
                     sub_tt.hash_stable(hcx, hasher);
                 }
             }
@@ -329,6 +330,7 @@
             match *lit {
                 token::Lit::Byte(val) |
                 token::Lit::Char(val) |
+                token::Lit::Err(val) |
                 token::Lit::Integer(val) |
                 token::Lit::Float(val) |
                 token::Lit::Str_(val) |
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 39ce8cc..c0952fe 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -186,34 +186,39 @@
     }
 
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
-        self.iterate_until_fixed_point("Expansion", |constraint, origin| {
-            debug!("expansion: constraint={:?} origin={:?}", constraint, origin);
-            match *constraint {
+        self.iterate_until_fixed_point("Expansion", |constraint| {
+            debug!("expansion: constraint={:?}", constraint);
+            let (a_region, b_vid, b_data, retain) = match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
                     let b_data = var_values.value_mut(b_vid);
-                    (self.expand_node(a_region, b_vid, b_data), false)
+                    (a_region, b_vid, b_data, false)
                 }
                 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
-                    VarValue::ErrorValue => (false, false),
+                    VarValue::ErrorValue => return (false, false),
                     VarValue::Value(a_region) => {
-                        let b_node = var_values.value_mut(b_vid);
-                        let changed = self.expand_node(a_region, b_vid, b_node);
-                        let retain = match *b_node {
+                        let b_data = var_values.value_mut(b_vid);
+                        let retain = match *b_data {
                             VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
                             _ => true
                         };
-                        (changed, retain)
+                        (a_region, b_vid, b_data, retain)
                     }
                 },
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
                     // These constraints are checked after expansion
                     // is done, in `collect_errors`.
-                    (false, false)
+                    return (false, false)
                 }
-            }
+            };
+
+            let changed = self.expand_node(a_region, b_vid, b_data);
+            (changed, retain)
         })
     }
 
+    // This function is very hot in some workloads. There's a single callsite
+    // so always inlining is ok even though it's large.
+    #[inline(always)]
     fn expand_node(
         &self,
         a_region: Region<'tcx>,
@@ -236,6 +241,14 @@
 
         match *b_data {
             VarValue::Value(cur_region) => {
+                // Identical scopes can show up quite often, if the fixed point
+                // iteration converges slowly, skip them
+                if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) {
+                    if a_scope == cur_scope {
+                        return false;
+                    }
+                }
+
                 let mut lub = self.lub_concrete_regions(a_region, cur_region);
                 if lub == cur_region {
                     return false;
@@ -275,12 +288,6 @@
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
         let tcx = self.tcx();
 
-        // Equal scopes can show up quite often, if the fixed point
-        // iteration converges slowly, skip them
-        if a == b {
-            return a;
-        }
-
         match (a, b) {
             (&ty::ReClosureBound(..), _)
             | (_, &ty::ReClosureBound(..))
@@ -722,18 +729,17 @@
     }
 
     fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
-    where
-        F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> (bool, bool),
+        where F: FnMut(&Constraint<'tcx>) -> (bool, bool),
     {
-        let mut constraints: SmallVec<[_; 16]> = self.data.constraints.iter().collect();
+        let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
         let mut iteration = 0;
         let mut changed = true;
         while changed {
             changed = false;
             iteration += 1;
             debug!("---- {} Iteration {}{}", "#", tag, iteration);
-            constraints.retain(|(constraint, origin)| {
-                let (edge_changed, retain) = body(constraint, origin);
+            constraints.retain(|constraint| {
+                let (edge_changed, retain) = body(constraint);
                 if edge_changed {
                     debug!("Updated due to constraint {:?}", constraint);
                     changed = true;
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index c8d137a..a0bd4f0 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -368,6 +368,12 @@
     report_in_external_macro: true
 }
 
+declare_lint! {
+    pub AMBIGUOUS_ASSOCIATED_ITEMS,
+    Warn,
+    "ambiguous associated items"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// that are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -433,6 +439,7 @@
             parser::QUESTION_MARK_MACRO_SEP,
             parser::ILL_FORMED_ATTRIBUTE_INPUT,
             DEPRECATED_IN_FUTURE,
+            AMBIGUOUS_ASSOCIATED_ITEMS,
         )
     }
 }
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index f5a7919..837a364 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -941,11 +941,6 @@
         hir_visit::walk_arm(self, a);
     }
 
-    fn visit_decl(&mut self, d: &'tcx hir::Decl) {
-        run_lints!(self, check_decl, d);
-        hir_visit::walk_decl(self, d);
-    }
-
     fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) {
         run_lints!(self, check_generic_param, p);
         hir_visit::walk_generic_param(self, p);
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 730ce91..e83ba74 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -192,7 +192,6 @@
             fn check_stmt(a: &$hir hir::Stmt);
             fn check_arm(a: &$hir hir::Arm);
             fn check_pat(a: &$hir hir::Pat);
-            fn check_decl(a: &$hir hir::Decl);
             fn check_expr(a: &$hir hir::Expr);
             fn check_expr_post(a: &$hir hir::Expr);
             fn check_ty(a: &$hir hir::Ty);
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 0c769c9..abbf0ae 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -409,7 +409,7 @@
         }
     }).chain(
         // Seed entry point
-        tcx.sess.entry_fn.borrow().map(|(id, _, _)| id)
+        tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap())
     ).collect::<Vec<_>>();
 
     // Seed implemented trait items
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 6b593a1..218ca3b 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -1,5 +1,5 @@
 use hir::map as hir_map;
-use hir::def_id::{CRATE_DEF_INDEX};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
 use session::{config, Session};
 use session::config::EntryFnType;
 use syntax::ast::NodeId;
@@ -8,6 +8,8 @@
 use syntax_pos::Span;
 use hir::{Item, ItemKind, ImplItem, TraitItem};
 use hir::itemlikevisit::ItemLikeVisitor;
+use ty::TyCtxt;
+use ty::query::Providers;
 
 struct EntryContext<'a, 'tcx: 'a> {
     session: &'a Session,
@@ -45,36 +47,34 @@
     }
 }
 
-pub fn find_entry_point(session: &Session,
-                        hir_map: &hir_map::Map<'_>,
-                        crate_name: &str) {
-    let any_exe = session.crate_types.borrow().iter().any(|ty| {
+fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
+    assert_eq!(cnum, LOCAL_CRATE);
+
+    let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| {
         *ty == config::CrateType::Executable
     });
     if !any_exe {
         // No need to find a main function
-        session.entry_fn.set(None);
-        return
+        return None;
     }
 
     // If the user wants no main function at all, then stop here.
-    if attr::contains_name(&hir_map.krate().attrs, "no_main") {
-        session.entry_fn.set(None);
-        return
+    if attr::contains_name(&tcx.hir().krate().attrs, "no_main") {
+        return None;
     }
 
     let mut ctxt = EntryContext {
-        session,
-        map: hir_map,
+        session: tcx.sess,
+        map: tcx.hir(),
         main_fn: None,
         attr_main_fn: None,
         start_fn: None,
         non_main_fns: Vec::new(),
     };
 
-    hir_map.krate().visit_all_item_likes(&mut ctxt);
+    tcx.hir().krate().visit_all_item_likes(&mut ctxt);
 
-    configure_main(&mut ctxt, crate_name);
+    configure_main(tcx, &ctxt)
 }
 
 // Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep
@@ -135,43 +135,58 @@
                     .span_label(item.span, "multiple `start` functions")
                     .emit();
             }
-        },
-        EntryPointType::None => ()
+        }
+        EntryPointType::None => (),
     }
 }
 
-fn configure_main(this: &mut EntryContext<'_, '_>, crate_name: &str) {
-    if let Some((node_id, span)) = this.start_fn {
-        this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start)));
-    } else if let Some((node_id, span)) = this.attr_main_fn {
-        this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
-    } else if let Some((node_id, span)) = this.main_fn {
-        this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
+fn configure_main(
+    tcx: TyCtxt<'_, '_, '_>,
+    visitor: &EntryContext<'_, '_>,
+) -> Option<(DefId, EntryFnType)> {
+    if let Some((node_id, _)) = visitor.start_fn {
+        Some((tcx.hir().local_def_id(node_id), EntryFnType::Start))
+    } else if let Some((node_id, _)) = visitor.attr_main_fn {
+        Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
+    } else if let Some((node_id, _)) = visitor.main_fn {
+        Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
     } else {
         // No main function
-        this.session.entry_fn.set(None);
-        let mut err = struct_err!(this.session, E0601,
-            "`main` function not found in crate `{}`", crate_name);
-        if !this.non_main_fns.is_empty() {
+        let mut err = struct_err!(tcx.sess, E0601,
+            "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
+        if !visitor.non_main_fns.is_empty() {
             // There were some functions named 'main' though. Try to give the user a hint.
             err.note("the main function must be defined at the crate level \
                       but you have one or more functions named 'main' that are not \
                       defined at the crate level. Either move the definition or \
                       attach the `#[main]` attribute to override this behavior.");
-            for &(_, span) in &this.non_main_fns {
+            for &(_, span) in &visitor.non_main_fns {
                 err.span_note(span, "here is a function named 'main'");
             }
             err.emit();
-            this.session.abort_if_errors();
+            tcx.sess.abort_if_errors();
         } else {
-            if let Some(ref filename) = this.session.local_crate_source_file {
+            if let Some(ref filename) = tcx.sess.local_crate_source_file {
                 err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
             }
-            if this.session.teach(&err.get_code().unwrap()) {
+            if tcx.sess.teach(&err.get_code().unwrap()) {
                 err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
                           to get started: https://doc.rust-lang.org/book/");
             }
             err.emit();
         }
+
+        None
     }
 }
+
+pub fn find_entry_point(tcx: TyCtxt<'_, '_, '_>) -> Option<(DefId, EntryFnType)> {
+    tcx.entry_fn(LOCAL_CRATE)
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers {
+        entry_fn,
+        ..*providers
+    };
+}
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index c1aa25b..08210c3 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -589,21 +589,17 @@
 
     fn walk_stmt(&mut self, stmt: &hir::Stmt) {
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                match decl.node {
-                    hir::DeclKind::Local(ref local) => {
-                        self.walk_local(&local);
-                    }
-
-                    hir::DeclKind::Item(_) => {
-                        // we don't visit nested items in this visitor,
-                        // only the fn body we were given.
-                    }
-                }
+            hir::StmtKind::Local(ref local) => {
+                self.walk_local(&local);
             }
 
-            hir::StmtKind::Expr(ref expr, _) |
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Item(_) => {
+                // we don't visit nested items in this visitor,
+                // only the fn body we were given.
+            }
+
+            hir::StmtKind::Expr(ref expr) |
+            hir::StmtKind::Semi(ref expr) => {
                 self.consume_expr(&expr);
             }
         }
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 1716daa..a0f7954 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -2,6 +2,7 @@
 use hir::def_id::DefId;
 use ty::{self, Ty, TyCtxt};
 use ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
+use ty::query::{Providers, queries};
 
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 use rustc_data_structures::indexed_vec::Idx;
@@ -10,10 +11,23 @@
 use hir;
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut visitor = ItemVisitor {
-        tcx,
+    for &module in tcx.hir().krate().modules.keys() {
+        queries::check_mod_intrinsics::ensure(tcx, tcx.hir().local_def_id(module));
+    }
+}
+
+fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+    tcx.hir().visit_item_likes_in_module(
+        module_def_id,
+        &mut ItemVisitor { tcx }.as_deep_visitor()
+    );
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers {
+        check_mod_intrinsics,
+        ..*providers
     };
-    tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
 }
 
 struct ItemVisitor<'a, 'tcx: 'a> {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index a78cf1a..220bec7 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -100,6 +100,7 @@
 use hir::def::*;
 use hir::Node;
 use ty::{self, TyCtxt};
+use ty::query::{Providers, queries};
 use lint;
 use errors::Applicability;
 use util::nodemap::{NodeMap, HirIdMap, HirIdSet};
@@ -114,8 +115,9 @@
 use syntax::symbol::keywords;
 use syntax_pos::Span;
 
-use hir::{Expr, HirId};
 use hir;
+use hir::{Expr, HirId};
+use hir::def_id::DefId;
 use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 
 /// For use with `propagate_through_loop`.
@@ -179,11 +181,24 @@
     fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); }
 }
 
+fn check_mod_liveness<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+    tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx).as_deep_visitor());
+}
+
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.hir().krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor());
+    for &module in tcx.hir().krate().modules.keys() {
+        queries::check_mod_liveness::ensure(tcx, tcx.hir().local_def_id(module));
+    }
     tcx.sess.abort_if_errors();
 }
 
+pub fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers {
+        check_mod_liveness,
+        ..*providers
+    };
+}
+
 impl fmt::Debug for LiveNode {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "ln({})", self.get())
@@ -911,17 +926,8 @@
     }
 
     fn compute(&mut self, body: &hir::Expr) -> LiveNode {
-        // if there is a `break` or `again` at the top level, then it's
-        // effectively a return---this only occurs in `for` loops,
-        // where the body is really a closure.
-
         debug!("compute: using id for body, {}", self.ir.tcx.hir().node_to_pretty_string(body.id));
 
-        let exit_ln = self.s.exit_ln;
-
-        self.break_ln.insert(body.id, exit_ln);
-        self.cont_ln.insert(body.id, exit_ln);
-
         // the fallthrough exit is only for those cases where we do not
         // explicitly return:
         let s = self.s;
@@ -956,46 +962,31 @@
     fn propagate_through_stmt(&mut self, stmt: &hir::Stmt, succ: LiveNode)
                               -> LiveNode {
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                self.propagate_through_decl(&decl, succ)
-            }
+            hir::StmtKind::Local(ref local) => {
+                // Note: we mark the variable as defined regardless of whether
+                // there is an initializer.  Initially I had thought to only mark
+                // the live variable as defined if it was initialized, and then we
+                // could check for uninit variables just by scanning what is live
+                // at the start of the function. But that doesn't work so well for
+                // immutable variables defined in a loop:
+                //     loop { let x; x = 5; }
+                // because the "assignment" loops back around and generates an error.
+                //
+                // So now we just check that variables defined w/o an
+                // initializer are not live at the point of their
+                // initialization, which is mildly more complex than checking
+                // once at the func header but otherwise equivalent.
 
-            hir::StmtKind::Expr(ref expr, _) | hir::StmtKind::Semi(ref expr, _) => {
+                let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
+                self.define_bindings_in_pat(&local.pat, succ)
+            }
+            hir::StmtKind::Item(..) => succ,
+            hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
                 self.propagate_through_expr(&expr, succ)
             }
         }
     }
 
-    fn propagate_through_decl(&mut self, decl: &hir::Decl, succ: LiveNode)
-                              -> LiveNode {
-        match decl.node {
-            hir::DeclKind::Local(ref local) => {
-                self.propagate_through_local(&local, succ)
-            }
-            hir::DeclKind::Item(_) => succ,
-        }
-    }
-
-    fn propagate_through_local(&mut self, local: &hir::Local, succ: LiveNode)
-                               -> LiveNode {
-        // Note: we mark the variable as defined regardless of whether
-        // there is an initializer.  Initially I had thought to only mark
-        // the live variable as defined if it was initialized, and then we
-        // could check for uninit variables just by scanning what is live
-        // at the start of the function. But that doesn't work so well for
-        // immutable variables defined in a loop:
-        //     loop { let x; x = 5; }
-        // because the "assignment" loops back around and generates an error.
-        //
-        // So now we just check that variables defined w/o an
-        // initializer are not live at the point of their
-        // initialization, which is mildly more complex than checking
-        // once at the func header but otherwise equivalent.
-
-        let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
-        self.define_bindings_in_pat(&local.pat, succ)
-    }
-
     fn propagate_through_exprs(&mut self, exprs: &[Expr], succ: LiveNode)
                                -> LiveNode {
         exprs.iter().rev().fold(succ, |succ, expr| {
@@ -1024,19 +1015,10 @@
                 self.propagate_through_expr(&e, succ)
             }
 
-            hir::ExprKind::Closure(.., blk_id, _, _) => {
+            hir::ExprKind::Closure(..) => {
                 debug!("{} is an ExprKind::Closure",
                        self.ir.tcx.hir().node_to_pretty_string(expr.id));
 
-                // The next-node for a break is the successor of the entire
-                // loop. The next-node for a continue is the top of this loop.
-                let node = self.live_node(expr.hir_id, expr.span);
-
-                let break_ln = succ;
-                let cont_ln = node;
-                self.break_ln.insert(blk_id.node_id, break_ln);
-                self.cont_ln.insert(blk_id.node_id, cont_ln);
-
                 // the construction of a closure itself is not important,
                 // but we have to consider the closed over variables.
                 let caps = self.ir.capture_info_map.get(&expr.id).cloned().unwrap_or_else(||
@@ -1407,15 +1389,16 @@
         debug!("propagate_through_loop: using id for loop body {} {}",
                expr.id, self.ir.tcx.hir().node_to_pretty_string(body.id));
 
-        let break_ln = succ;
-        let cont_ln = ln;
-        self.break_ln.insert(expr.id, break_ln);
-        self.cont_ln.insert(expr.id, cont_ln);
+
+        self.break_ln.insert(expr.id, succ);
 
         let cond_ln = match kind {
             LoopLoop => ln,
             WhileLoop(ref cond) => self.propagate_through_expr(&cond, ln),
         };
+
+        self.cont_ln.insert(expr.id, cond_ln);
+
         let body_ln = self.propagate_through_block(body, cond_ln);
 
         // repeat until fixed point is reached:
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index ce2a348..819dd8a 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -784,20 +784,25 @@
         // index information.)
 
         for (i, statement) in blk.stmts.iter().enumerate() {
-            if let hir::StmtKind::Decl(..) = statement.node {
-                // Each StmtKind::Decl introduces a subscope for bindings
-                // introduced by the declaration; this subscope covers
-                // a suffix of the block . Each subscope in a block
-                // has the previous subscope in the block as a parent,
-                // except for the first such subscope, which has the
-                // block itself as a parent.
-                visitor.enter_scope(
-                    Scope {
-                        id: blk.hir_id.local_id,
-                        data: ScopeData::Remainder(FirstStatementIndex::new(i))
-                    }
-                );
-                visitor.cx.var_parent = visitor.cx.parent;
+            match statement.node {
+                hir::StmtKind::Local(..) |
+                hir::StmtKind::Item(..) => {
+                    // Each declaration introduces a subscope for bindings
+                    // introduced by the declaration; this subscope covers a
+                    // suffix of the block. Each subscope in a block has the
+                    // previous subscope in the block as a parent, except for
+                    // the first such subscope, which has the block itself as a
+                    // parent.
+                    visitor.enter_scope(
+                        Scope {
+                            id: blk.hir_id.local_id,
+                            data: ScopeData::Remainder(FirstStatementIndex::new(i))
+                        }
+                    );
+                    visitor.cx.var_parent = visitor.cx.parent;
+                }
+                hir::StmtKind::Expr(..) |
+                hir::StmtKind::Semi(..) => {}
             }
             visitor.visit_stmt(statement)
         }
@@ -835,7 +840,7 @@
 }
 
 fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt: &'tcx hir::Stmt) {
-    let stmt_id = visitor.tcx.hir().node_to_hir_id(stmt.node.id()).local_id;
+    let stmt_id = visitor.tcx.hir().node_to_hir_id(stmt.id).local_id;
     debug!("resolve_stmt(stmt.id={:?})", stmt_id);
 
     // Every statement will clean up the temporaries created during
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 42adc6a..cdbef56 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -6,7 +6,7 @@
 use session::{early_error, early_warn, Session};
 use session::search_paths::SearchPath;
 
-use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
+use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
 use rustc_target::spec::{Target, TargetTriple};
 use lint;
 use middle::cstore;
@@ -649,15 +649,15 @@
     }
 }
 
-// The type of entry function, so
-// users can have their own entry
-// functions
-#[derive(Copy, Clone, PartialEq)]
+// The type of entry function, so users can have their own entry functions
+#[derive(Copy, Clone, PartialEq, Hash, Debug)]
 pub enum EntryFnType {
     Main,
     Start,
 }
 
+impl_stable_hash_via_hash!(EntryFnType);
+
 #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
 pub enum CrateType {
     Executable,
@@ -808,13 +808,16 @@
         pub const parse_cross_lang_lto: Option<&str> =
             Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
                   or the path to the linker plugin");
+        pub const parse_merge_functions: Option<&str> =
+            Some("one of: `disabled`, `trampolines`, or `aliases`");
     }
 
     #[allow(dead_code)]
     mod $mod_set {
         use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto};
-        use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
+        use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
+        use std::str::FromStr;
 
         $(
             pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -1046,6 +1049,14 @@
             };
             true
         }
+
+        fn parse_merge_functions(slot: &mut Option<MergeFunctions>, v: Option<&str>) -> bool {
+            match v.and_then(|s| MergeFunctions::from_str(s).ok()) {
+                Some(mergefunc) => *slot = Some(mergefunc),
+                _ => return false,
+            }
+            true
+        }
     }
 ) }
 
@@ -1342,10 +1353,15 @@
     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:
+        `expanded`, `expanded,identified`,
+        `expanded,hygiene` (with internal representations),
         `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+        `flowgraph,unlabelled=<nodeid>` (unlabelled 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)."),
+        `hir` (the HIR), `hir,identified`,
+        `hir,typed` (HIR with types for each node),
+        `hir-tree` (dump the raw HIR),
+        `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
     run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "run `dsymutil` and delete intermediate object files"),
     ui_testing: bool = (false, parse_bool, [UNTRACKED],
@@ -1376,6 +1392,9 @@
           "whether to use the PLT when calling into shared libraries;
           only has effect for PIC code on systems with ELF binaries
           (default: PLT is disabled if full relro is enabled)"),
+    merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
+        "control the operation of the MergeFunctions LLVM pass, taking
+         the same values as the target option of the same name"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -2394,7 +2413,7 @@
     use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
                 Passes, Sanitizer, LtoCli, CrossLangLto};
     use syntax::feature_gate::UnstableFeatures;
-    use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
+    use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
     use syntax::edition::Edition;
 
     pub trait DepTrackingHash {
@@ -2437,12 +2456,14 @@
     impl_dep_tracking_hash_via_hash!(Option<usize>);
     impl_dep_tracking_hash_via_hash!(Option<String>);
     impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
+    impl_dep_tracking_hash_via_hash!(Option<MergeFunctions>);
     impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
     impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
     impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
     impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
     impl_dep_tracking_hash_via_hash!(Option<cstore::NativeLibraryKind>);
     impl_dep_tracking_hash_via_hash!(CrateType);
+    impl_dep_tracking_hash_via_hash!(MergeFunctions);
     impl_dep_tracking_hash_via_hash!(PanicStrategy);
     impl_dep_tracking_hash_via_hash!(RelroLevel);
     impl_dep_tracking_hash_via_hash!(Passes);
@@ -2528,7 +2549,7 @@
     use std::iter::FromIterator;
     use std::path::PathBuf;
     use super::{Externs, OutputType, OutputTypes};
-    use rustc_target::spec::{PanicStrategy, RelroLevel};
+    use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel};
     use syntax::symbol::Symbol;
     use syntax::edition::{Edition, DEFAULT_EDITION};
     use syntax;
@@ -3183,6 +3204,10 @@
         opts = reference.clone();
         opts.debugging_opts.cross_lang_lto = CrossLangLto::LinkerPluginAuto;
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
+        opts = reference.clone();
+        opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled);
+        assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
     }
 
     #[test]
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 7363b8b..cf00bf3 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -67,8 +67,6 @@
     /// This is `None` if the host and target are the same.
     pub target_tlib_path: Option<SearchPath>,
     pub parse_sess: ParseSess,
-    /// For a library crate, this is always none
-    pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
     pub sysroot: PathBuf,
     /// The name of the root source file of the crate, in the local file system.
     /// `None` means that there is no source file.
@@ -1173,8 +1171,6 @@
         host_tlib_path,
         target_tlib_path,
         parse_sess: p_s,
-        // For a library crate, this is always none
-        entry_fn: Once::new(),
         sysroot,
         local_crate_source_file,
         working_dir,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 6db6fe3..9a0610f 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -42,7 +42,7 @@
 use rustc_data_structures::sync::Lock;
 use rustc_target::spec::abi::Abi;
 use std::cmp;
-use std::fmt;
+use std::fmt::{self, Display};
 use std::iter;
 use std::rc::Rc;
 use util::nodemap::{FxHashMap, FxHashSet};
@@ -629,7 +629,8 @@
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         self.evaluation_probe(|this| {
-            this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
+            this.evaluate_predicate_recursively(TraitObligationStackList::empty(),
+                obligation.clone())
         })
     }
 
@@ -655,12 +656,12 @@
         predicates: I,
     ) -> Result<EvaluationResult, OverflowError>
     where
-        I: IntoIterator<Item = &'a PredicateObligation<'tcx>>,
+        I: IntoIterator<Item = PredicateObligation<'tcx>>,
         'tcx: 'a,
     {
         let mut result = EvaluatedToOk;
         for obligation in predicates {
-            let eval = self.evaluate_predicate_recursively(stack, obligation)?;
+            let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
             debug!(
                 "evaluate_predicate_recursively({:?}) = {:?}",
                 obligation, eval
@@ -679,9 +680,19 @@
     fn evaluate_predicate_recursively<'o>(
         &mut self,
         previous_stack: TraitObligationStackList<'o, 'tcx>,
-        obligation: &PredicateObligation<'tcx>,
+        obligation: PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
-        debug!("evaluate_predicate_recursively({:?})", obligation);
+        debug!("evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
+            previous_stack.head(), obligation);
+
+        // Previous_stack stores a TraitObligatiom, while 'obligation' is
+        // a PredicateObligation. These are distinct types, so we can't
+        // use any Option combinator method that would force them to be
+        // the same
+        match previous_stack.head() {
+            Some(h) => self.check_recursion_limit(&obligation, h.obligation)?,
+            None => self.check_recursion_limit(&obligation, &obligation)?
+        }
 
         match obligation.predicate {
             ty::Predicate::Trait(ref t) => {
@@ -695,8 +706,9 @@
                 match self.infcx
                     .subtype_predicate(&obligation.cause, obligation.param_env, p)
                 {
-                    Some(Ok(InferOk { obligations, .. })) => {
-                        self.evaluate_predicates_recursively(previous_stack, &obligations)
+                    Some(Ok(InferOk { mut obligations, .. })) => {
+                        self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
+                        self.evaluate_predicates_recursively(previous_stack,obligations.into_iter())
                     }
                     Some(Err(_)) => Ok(EvaluatedToErr),
                     None => Ok(EvaluatedToAmbig),
@@ -710,8 +722,9 @@
                 ty,
                 obligation.cause.span,
             ) {
-                Some(obligations) => {
-                    self.evaluate_predicates_recursively(previous_stack, obligations.iter())
+                Some(mut obligations) => {
+                    self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
+                    self.evaluate_predicates_recursively(previous_stack, obligations.into_iter())
                 }
                 None => Ok(EvaluatedToAmbig),
             },
@@ -733,10 +746,11 @@
             ty::Predicate::Projection(ref data) => {
                 let project_obligation = obligation.with(data.clone());
                 match project::poly_project_and_unify_type(self, &project_obligation) {
-                    Ok(Some(subobligations)) => {
+                    Ok(Some(mut subobligations)) => {
+                        self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
                         let result = self.evaluate_predicates_recursively(
                             previous_stack,
-                            subobligations.iter(),
+                            subobligations.into_iter(),
                         );
                         if let Some(key) =
                             ProjectionCacheKey::from_poly_projection_predicate(self, data)
@@ -1005,7 +1019,7 @@
             match this.confirm_candidate(stack.obligation, candidate) {
                 Ok(selection) => this.evaluate_predicates_recursively(
                     stack.list(),
-                    selection.nested_obligations().iter(),
+                    selection.nested_obligations().into_iter()
                 ),
                 Err(..) => Ok(EvaluatedToErr),
             }
@@ -1080,6 +1094,45 @@
             .insert(trait_ref, WithDepNode::new(dep_node, result));
     }
 
+    // For various reasons, it's possible for a subobligation
+    // to have a *lower* recursion_depth than the obligation used to create it.
+    // Projection sub-obligations may be returned from the projection cache,
+    // which results in obligations with an 'old' recursion_depth.
+    // Additionally, methods like ty::wf::obligations and
+    // InferCtxt.subtype_predicate produce subobligations without
+    // taking in a 'parent' depth, causing the generated subobligations
+    // to have a recursion_depth of 0
+    //
+    // To ensure that obligation_depth never decreasees, we force all subobligations
+    // to have at least the depth of the original obligation.
+    fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(&self, it: I,
+                                                                           min_depth: usize) {
+        it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
+    }
+
+    // Check that the recursion limit has not been exceeded.
+    //
+    // The weird return type of this function allows it to be used with the 'try' (?)
+    // operator within certain functions
+    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        error_obligation: &Obligation<'tcx, V>
+    ) -> Result<(), OverflowError>  {
+        let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
+        if obligation.recursion_depth >= recursion_limit {
+            match self.query_mode {
+                TraitQueryMode::Standard => {
+                    self.infcx().report_overflow_error(error_obligation, true);
+                }
+                TraitQueryMode::Canonical => {
+                    return Err(OverflowError);
+                }
+            }
+        }
+        Ok(())
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // CANDIDATE ASSEMBLY
     //
@@ -1096,17 +1149,8 @@
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         // Watch out for overflow. This intentionally bypasses (and does
         // not update) the cache.
-        let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
-        if stack.obligation.recursion_depth >= recursion_limit {
-            match self.query_mode {
-                TraitQueryMode::Standard => {
-                    self.infcx().report_overflow_error(&stack.obligation, true);
-                }
-                TraitQueryMode::Canonical => {
-                    return Err(Overflow);
-                }
-            }
-        }
+        self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
+
 
         // Check the cache. Note that we freshen the trait-ref
         // separately rather than using `stack.fresh_trait_ref` --
@@ -1767,7 +1811,7 @@
         self.evaluation_probe(|this| {
             match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
                 Ok(obligations) => {
-                    this.evaluate_predicates_recursively(stack.list(), obligations.iter())
+                    this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
                 }
                 Err(()) => Ok(EvaluatedToErr),
             }
@@ -2154,7 +2198,7 @@
 
         let def_id = obligation.predicate.def_id();
 
-        if ty::is_trait_alias(self.tcx(), def_id) {
+        if self.tcx().is_trait_alias(def_id) {
             candidates.vec.push(TraitAliasCandidate(def_id.clone()));
         }
 
@@ -3802,6 +3846,10 @@
     fn with(r: &'o TraitObligationStack<'o, 'tcx>) -> TraitObligationStackList<'o, 'tcx> {
         TraitObligationStackList { head: Some(r) }
     }
+
+    fn head(&self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
+        self.head
+    }
 }
 
 impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index d69219e..e37eab6 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -983,6 +983,9 @@
 
     maybe_unused_trait_imports: FxHashSet<DefId>,
     maybe_unused_extern_crates: Vec<(DefId, Span)>,
+    /// A map of glob use to a set of names it actually imports. Currently only
+    /// used in save-analysis.
+    glob_map: FxHashMap<DefId, FxHashSet<ast::Name>>,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
     pub extern_prelude: FxHashMap<ast::Name, bool>,
@@ -1232,6 +1235,9 @@
                     .into_iter()
                     .map(|(id, sp)| (hir.local_def_id(id), sp))
                     .collect(),
+            glob_map: resolutions.glob_map.into_iter().map(|(id, names)| {
+                (hir.local_def_id(id), names)
+            }).collect(),
             extern_prelude: resolutions.extern_prelude,
             hir_map: hir,
             def_path_hash_to_def_id,
@@ -2972,6 +2978,10 @@
         assert_eq!(cnum, LOCAL_CRATE);
         Lrc::new(tcx.maybe_unused_extern_crates.clone())
     };
+    providers.names_imported_by_glob_use = |tcx, id| {
+        assert_eq!(id.krate, LOCAL_CRATE);
+        Lrc::new(tcx.glob_map.get(&id).cloned().unwrap_or_default())
+    };
 
     providers.stability_index = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 417e140..9328de4 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -311,6 +311,7 @@
             data @ DefPathData::Misc |
             data @ DefPathData::TypeNs(..) |
             data @ DefPathData::Trait(..) |
+            data @ DefPathData::TraitAlias(..) |
             data @ DefPathData::AssocTypeInTrait(..) |
             data @ DefPathData::AssocTypeInImpl(..) |
             data @ DefPathData::AssocExistentialInImpl(..) |
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 26b4735..dd315cf 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -4,7 +4,7 @@
 pub use self::IntVarValue::*;
 pub use self::fold::TypeFoldable;
 
-use hir::{map as hir_map, FreevarMap, TraitMap};
+use hir::{map as hir_map, FreevarMap, GlobMap, TraitMap};
 use hir::Node;
 use hir::def::{Def, CtorKind, ExportMap};
 use hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -115,16 +115,6 @@
 
 // Data types
 
-/// The complete set of all analyses described in this module. This is
-/// produced by the driver and fed to codegen and later passes.
-///
-/// N.B., these contents are being migrated into queries using the
-/// *on-demand* infrastructure.
-#[derive(Clone)]
-pub struct CrateAnalysis {
-    pub glob_map: hir::GlobMap,
-}
-
 #[derive(Clone)]
 pub struct Resolutions {
     pub freevars: FreevarMap,
@@ -132,6 +122,7 @@
     pub maybe_unused_trait_imports: NodeSet,
     pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
     pub export_map: ExportMap,
+    pub glob_map: GlobMap,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
     pub extern_prelude: FxHashMap<Name, bool>,
@@ -3179,18 +3170,6 @@
     None
 }
 
-/// Returns `true` if `def_id` is a trait alias.
-pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
-    if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
-        if let Node::Item(item) = tcx.hir().get(node_id) {
-            if let hir::ItemKind::TraitAlias(..) = item.node {
-                return true;
-            }
-        }
-    }
-    false
-}
-
 /// See `ParamEnv` struct definition for details.
 fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        def_id: DefId)
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index ca5d1f6..ae41ca0 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -109,6 +109,33 @@
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_privacy<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("checking privacy in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_intrinsics<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("checking intrinsics in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_liveness<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("checking liveness of variables in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> {
     fn describe(
         tcx: TyCtxt<'_, '_, '_>,
@@ -629,6 +656,12 @@
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::entry_fn<'tcx> {
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the entry function of a crate".into()
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
         "looking up the plugin registrar for a crate".into()
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 39d76ce..10f3571 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -22,7 +22,7 @@
 use mir;
 use mir::interpret::GlobalId;
 use session::{CompileResult, CrateDisambiguator};
-use session::config::OutputFilenames;
+use session::config::{EntryFnType, OutputFilenames};
 use traits::{self, Vtable};
 use traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal,
@@ -264,6 +264,12 @@
 
         [] fn check_mod_item_types: CheckModItemTypes(DefId) -> (),
 
+        [] fn check_mod_privacy: CheckModPrivacy(DefId) -> (),
+
+        [] fn check_mod_intrinsics: CheckModIntrinsics(DefId) -> (),
+
+        [] fn check_mod_liveness: CheckModLiveness(DefId) -> (),
+
         [] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (),
 
         /// Caches CoerceUnsized kinds for impls on custom types.
@@ -476,6 +482,9 @@
 
         [] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,
 
+        /// Identifies the entry-point (e.g. the `main` function) for a given
+        /// crate, returning `None` if there is no entry point (such as for library crates).
+        [] fn entry_fn: EntryFn(CrateNum) -> Option<(DefId, EntryFnType)>,
         [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
         [] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option<DefId>,
         [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
@@ -541,6 +550,8 @@
         [] fn maybe_unused_trait_import: MaybeUnusedTraitImport(DefId) -> bool,
         [] fn maybe_unused_extern_crates: maybe_unused_extern_crates_node(CrateNum)
             -> Lrc<Vec<(DefId, Span)>>,
+        [] fn names_imported_by_glob_use: NamesImportedByGlobUse(DefId)
+            -> Lrc<FxHashSet<ast::Name>>,
 
         [] fn stability_index: stability_index_node(CrateNum) -> Lrc<stability::Index<'tcx>>,
         [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 562cd75..1cc9bbd 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -2,7 +2,7 @@
 //! that generate the actual methods on tcx which find and execute the
 //! provider, manage the caches, and so forth.
 
-use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
+use dep_graph::{DepNodeIndex, DepNode, DepKind, SerializedDepNodeIndex};
 use errors::DiagnosticBuilder;
 use errors::Level;
 use errors::Diagnostic;
@@ -335,40 +335,6 @@
         eprintln!("end of query stack");
     }
 
-    /// Try to read a node index for the node dep_node.
-    /// A node will have an index, when it's already been marked green, or when we can mark it
-    /// green. This function will mark the current task as a reader of the specified node, when
-    /// a node index can be found for that node.
-    pub(super) fn try_mark_green_and_read(self, dep_node: &DepNode) -> Option<DepNodeIndex> {
-        match self.dep_graph.node_color(dep_node) {
-            Some(DepNodeColor::Green(dep_node_index)) => {
-                self.dep_graph.read_index(dep_node_index);
-                Some(dep_node_index)
-            }
-            Some(DepNodeColor::Red) => {
-                None
-            }
-            None => {
-                // try_mark_green (called below) will panic when full incremental
-                // compilation is disabled. If that's the case, we can't try to mark nodes
-                // as green anyway, so we can safely return None here.
-                if !self.dep_graph.is_fully_enabled() {
-                    return None;
-                }
-                match self.dep_graph.try_mark_green(self.global_tcx(), &dep_node) {
-                    Some(dep_node_index) => {
-                        debug_assert!(self.dep_graph.is_green(&dep_node));
-                        self.dep_graph.read_index(dep_node_index);
-                        Some(dep_node_index)
-                    }
-                    None => {
-                        None
-                    }
-                }
-            }
-        }
-    }
-
     #[inline(never)]
     fn try_get_with<Q: QueryDescription<'gcx>>(
         self,
@@ -435,10 +401,13 @@
         }
 
         if !dep_node.kind.is_input() {
-            if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
+            if let Some((prev_dep_node_index,
+                         dep_node_index)) = self.dep_graph.try_mark_green_and_read(self,
+                                                                                   &dep_node) {
                 return Ok(self.load_from_disk_and_cache_in_memory::<Q>(
                     key,
                     job,
+                    prev_dep_node_index,
                     dep_node_index,
                     &dep_node
                 ))
@@ -454,6 +423,7 @@
         self,
         key: Q::Key,
         job: JobOwner<'a, 'gcx, Q>,
+        prev_dep_node_index: SerializedDepNodeIndex,
         dep_node_index: DepNodeIndex,
         dep_node: &DepNode
     ) -> Q::Value
@@ -466,10 +436,7 @@
         // First we try to load the result from the on-disk cache
         let result = if Q::cache_on_disk(key.clone()) &&
                         self.sess.opts.debugging_opts.incremental_queries {
-            let prev_dep_node_index =
-                self.dep_graph.prev_dep_node_index_of(dep_node);
-            let result = Q::try_load_from_disk(self.global_tcx(),
-                                               prev_dep_node_index);
+            let result = Q::try_load_from_disk(self.global_tcx(), prev_dep_node_index);
 
             // We always expect to find a cached result for things that
             // can be forced from DepNode.
@@ -624,7 +591,7 @@
         // Ensuring an "input" or anonymous query makes no sense
         assert!(!dep_node.kind.is_anon());
         assert!(!dep_node.kind.is_input());
-        if self.try_mark_green_and_read(&dep_node).is_none() {
+        if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
             // A None return from `try_mark_green_and_read` means that this is either
             // a new dep node or that the dep node has already been marked red.
             // Either way, we can't call `dep_graph.read()` as we don't have the
@@ -1281,6 +1248,9 @@
         DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
         DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
         DepKind::CheckModItemTypes => { force!(check_mod_item_types, def_id!()); }
+        DepKind::CheckModPrivacy => { force!(check_mod_privacy, def_id!()); }
+        DepKind::CheckModIntrinsics => { force!(check_mod_intrinsics, def_id!()); }
+        DepKind::CheckModLiveness => { force!(check_mod_liveness, def_id!()); }
         DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
         DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
         DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
@@ -1362,6 +1332,7 @@
         DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
         DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
         DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
+        DepKind::EntryFn => { force!(entry_fn, krate!()); }
         DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
         DepKind::ProcMacroDeclsStatic => { force!(proc_macro_decls_static, krate!()); }
         DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
@@ -1413,6 +1384,7 @@
         DepKind::MaybeUnusedTraitImport => {
             force!(maybe_unused_trait_import, def_id!());
         }
+        DepKind::NamesImportedByGlobUse => { force!(names_imported_by_glob_use, def_id!()); }
         DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
         DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); }
         DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index e989ef8..75fc0f7 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -526,6 +526,15 @@
         }
     }
 
+    /// True if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`).
+    pub fn is_trait_alias(self, def_id: DefId) -> bool {
+        if let DefPathData::TraitAlias(_) = self.def_key(def_id).disambiguated_data.data {
+            true
+        } else {
+            false
+        }
+    }
+
     /// True if this def-id refers to the implicit constructor for
     /// a tuple struct like `struct Foo(u32)`.
     pub fn is_struct_constructor(self, def_id: DefId) -> bool {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 04e5718..51e9192 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -409,6 +409,7 @@
                     DefPathData::AssocTypeInImpl(_) |
                     DefPathData::AssocExistentialInImpl(_) |
                     DefPathData::Trait(_) |
+                    DefPathData::TraitAlias(_) |
                     DefPathData::Impl |
                     DefPathData::TypeNs(_) => {
                         break;
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 66303ab..72963cb 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -39,7 +39,6 @@
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use rustc::hir;
-use rustc::hir::intravisit::{self, Visitor};
 
 use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom};
 
@@ -157,12 +156,6 @@
     where F: FnOnce(&mut BorrowckCtxt<'a, 'tcx>) -> &'c cfg::CFG
 {
     // Check the body of fn items.
-    let tcx = this.tcx;
-    let id_range = {
-        let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir());
-        visitor.visit_body(this.body);
-        visitor.result()
-    };
     let (all_loans, move_data) =
         gather_loans::gather_loans_in_fn(this, body_id);
 
@@ -184,7 +177,6 @@
                              Some(this.body),
                              cfg,
                              LoanDataFlowOperator,
-                             id_range,
                              all_loans.len());
     for (loan_idx, loan) in all_loans.iter().enumerate() {
         loan_dfcx.add_gen(loan.gen_scope.item_local_id(), loan_idx);
@@ -198,7 +190,6 @@
     let flowed_moves = move_data::FlowedMoveData::new(move_data,
                                                       this,
                                                       cfg,
-                                                      id_range,
                                                       this.body);
 
     Some(AnalysisData { all_loans,
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index c5bee87..56c9f92 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -15,7 +15,6 @@
 use std::usize;
 use syntax_pos::Span;
 use rustc::hir;
-use rustc::hir::intravisit::IdRange;
 
 #[derive(Default)]
 pub struct MoveData<'tcx> {
@@ -559,7 +558,6 @@
     pub fn new(move_data: MoveData<'tcx>,
                bccx: &BorrowckCtxt<'a, 'tcx>,
                cfg: &cfg::CFG,
-               id_range: IdRange,
                body: &hir::Body)
                -> FlowedMoveData<'a, 'tcx> {
         let tcx = bccx.tcx;
@@ -570,7 +568,6 @@
                                  Some(body),
                                  cfg,
                                  MoveDataFlowOperator,
-                                 id_range,
                                  move_data.moves.borrow().len());
         let mut dfcx_assign =
             DataFlowContext::new(tcx,
@@ -578,7 +575,6 @@
                                  Some(body),
                                  cfg,
                                  AssignDataFlowOperator,
-                                 id_range,
                                  move_data.var_assignments.borrow().len());
 
         move_data.add_gen_kills(bccx,
diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs
index 56e25bd..8cf6205 100644
--- a/src/librustc_borrowck/dataflow.rs
+++ b/src/librustc_borrowck/dataflow.rs
@@ -15,7 +15,7 @@
 
 use rustc::util::nodemap::FxHashMap;
 use rustc::hir;
-use rustc::hir::intravisit::{self, IdRange};
+use rustc::hir::intravisit;
 use rustc::hir::print as pprust;
 
 
@@ -230,16 +230,15 @@
                body: Option<&hir::Body>,
                cfg: &cfg::CFG,
                oper: O,
-               id_range: IdRange,
                bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> {
         let usize_bits = mem::size_of::<usize>() * 8;
         let words_per_id = (bits_per_id + usize_bits - 1) / usize_bits;
         let num_nodes = cfg.graph.all_nodes().len();
 
-        debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \
+        debug!("DataFlowContext::new(analysis_name: {}, \
                                      bits_per_id={}, words_per_id={}) \
                                      num_nodes: {}",
-               analysis_name, id_range, bits_per_id, words_per_id,
+               analysis_name, bits_per_id, words_per_id,
                num_nodes);
 
         let entry = if oper.initial_value() { usize::MAX } else {0};
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 2eab626..b504aa5 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -14,7 +14,7 @@
 use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
     DILexicalBlock};
 use rustc::hir::CodegenFnAttrFlags;
-use rustc::hir::def_id::{DefId, CrateNum};
+use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use rustc::ty::subst::{Substs, UnpackedKind};
 
 use abi::Abi;
@@ -290,9 +290,8 @@
 
         let mut flags = DIFlags::FlagPrototyped;
 
-        let local_id = self.tcx().hir().as_local_node_id(def_id);
-        if let Some((id, _, _)) = *self.sess().entry_fn.borrow() {
-            if local_id == Some(id) {
+        if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
+            if id == def_id {
                 flags |= DIFlags::FlagMainSubprogram;
             }
         }
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index ad9ebbc..dc70ebc 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -3,6 +3,7 @@
 use llvm;
 use rustc::session::Session;
 use rustc::session::config::PrintRequest;
+use rustc_target::spec::MergeFunctions;
 use libc::c_int;
 use std::ffi::CString;
 use syntax::feature_gate::UnstableFeatures;
@@ -61,7 +62,14 @@
             add("-disable-preinline");
         }
         if llvm::LLVMRustIsRustLLVM() {
-            add("-mergefunc-use-aliases");
+            match sess.opts.debugging_opts.merge_functions
+                  .unwrap_or(sess.target.target.options.merge_functions) {
+                MergeFunctions::Disabled |
+                MergeFunctions::Trampolines => {}
+                MergeFunctions::Aliases => {
+                    add("-mergefunc-use-aliases");
+                }
+            }
         }
 
         // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index bf69089..c372892 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -194,7 +194,7 @@
                                  })
                                  .collect();
 
-    if tcx.sess.entry_fn.borrow().is_some() {
+    if tcx.entry_fn(LOCAL_CRATE).is_some() {
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new("main"));
 
         symbols.push((exported_symbol, SymbolExportLevel::C));
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index fb3e7ea..39bdc70 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -24,6 +24,7 @@
 use rustc_data_structures::svh::Svh;
 use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
 use rustc_errors::emitter::{Emitter};
+use rustc_target::spec::MergeFunctions;
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
 use syntax_pos::MultiSpan;
@@ -152,8 +153,24 @@
                             sess.opts.optimize == config::OptLevel::Aggressive &&
                             !sess.target.target.options.is_like_emscripten;
 
-        self.merge_functions = sess.opts.optimize == config::OptLevel::Default ||
-                               sess.opts.optimize == config::OptLevel::Aggressive;
+        // Some targets (namely, NVPTX) interact badly with the MergeFunctions
+        // pass. This is because MergeFunctions can generate new function calls
+        // which may interfere with the target calling convention; e.g. for the
+        // NVPTX target, PTX kernels should not call other PTX kernels.
+        // MergeFunctions can also be configured to generate aliases instead,
+        // but aliases are not supported by some backends (again, NVPTX).
+        // Therefore, allow targets to opt out of the MergeFunctions pass,
+        // but otherwise keep the pass enabled (at O2 and O3) since it can be
+        // useful for reducing code size.
+        self.merge_functions = match sess.opts.debugging_opts.merge_functions
+                                     .unwrap_or(sess.target.target.options.merge_functions) {
+            MergeFunctions::Disabled => false,
+            MergeFunctions::Trampolines |
+            MergeFunctions::Aliases => {
+                sess.opts.optimize == config::OptLevel::Default ||
+                sess.opts.optimize == config::OptLevel::Aggressive
+            }
+        };
     }
 
     pub fn bitcode_needed(&self) -> bool {
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index b88ec07..38caacb 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -441,10 +441,8 @@
 pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx
 ) {
-    let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
-        Some((id, span, _)) => {
-            (cx.tcx().hir().local_def_id(id), span)
-        }
+    let (main_def_id, span) = match cx.tcx().entry_fn(LOCAL_CRATE) {
+        Some((def_id, _)) => { (def_id, cx.tcx().def_span(def_id)) },
         None => return,
     };
 
@@ -458,7 +456,7 @@
 
     let main_llfn = cx.get_fn(instance);
 
-    let et = cx.sess().entry_fn.get().map(|e| e.2);
+    let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1);
     match et {
         Some(EntryFnType::Main) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, true),
         Some(EntryFnType::Start) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, false),
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index b59bca0..5f61852 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -31,6 +31,7 @@
 #[macro_use] extern crate rustc_data_structures;
 
 use rustc::ty::TyCtxt;
+use rustc::hir::def_id::LOCAL_CRATE;
 
 pub mod link;
 pub mod codegen_backend;
@@ -42,11 +43,9 @@
 /// that actually test that compilation succeeds without
 /// reporting an error.
 pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
-    if let Some((id, span, _)) = *tcx.sess.entry_fn.borrow() {
-        let main_def_id = tcx.hir().local_def_id(id);
-
-        if tcx.has_attr(main_def_id, "rustc_error") {
-            tcx.sess.span_fatal(span, "compilation successful");
+    if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
+        if tcx.has_attr(def_id, "rustc_error") {
+            tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful");
         }
     }
 }
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index f9f94f0..0253eef 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -70,6 +70,7 @@
         pub struct Atomic<T: Copy>(Cell<T>);
 
         impl<T: Copy> Atomic<T> {
+            #[inline]
             pub fn new(v: T) -> Self {
                 Atomic(Cell::new(v))
             }
@@ -80,10 +81,12 @@
                 self.0.into_inner()
             }
 
+            #[inline]
             pub fn load(&self, _: Ordering) -> T {
                 self.0.get()
             }
 
+            #[inline]
             pub fn store(&self, val: T, _: Ordering) {
                 self.0.set(val)
             }
@@ -118,6 +121,7 @@
 
         pub type AtomicUsize = Atomic<usize>;
         pub type AtomicBool = Atomic<bool>;
+        pub type AtomicU32 = Atomic<u32>;
         pub type AtomicU64 = Atomic<u64>;
 
         pub use self::serial_join as join;
@@ -223,7 +227,7 @@
         pub use parking_lot::MutexGuard as LockGuard;
         pub use parking_lot::MappedMutexGuard as MappedLockGuard;
 
-        pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU64};
+        pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
 
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 1ecb8ef..d23d8b8 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -168,7 +168,6 @@
         let ExpansionResult {
             expanded_crate,
             defs,
-            analysis,
             resolutions,
             mut hir_forest,
         } = {
@@ -251,7 +250,6 @@
                     output,
                     &cstore,
                     &hir_map,
-                    &analysis,
                     &resolutions,
                     &expanded_crate,
                     &hir_map.krate(),
@@ -277,12 +275,11 @@
             sess,
             cstore,
             hir_map,
-            analysis,
             resolutions,
             &mut arenas,
             &crate_name,
             &outputs,
-            |tcx, analysis, rx, result| {
+            |tcx, rx, result| {
                 {
                     // Eventually, we will want to track plugins.
                     tcx.dep_graph.with_ignore(|| {
@@ -293,7 +290,6 @@
                             output,
                             opt_crate,
                             tcx.hir().krate(),
-                            &analysis,
                             tcx,
                             &crate_name,
                         );
@@ -527,7 +523,6 @@
     pub hir_crate: Option<&'a hir::Crate>,
     pub hir_map: Option<&'a hir_map::Map<'tcx>>,
     pub resolutions: Option<&'a Resolutions>,
-    pub analysis: Option<&'a ty::CrateAnalysis>,
     pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
 }
 
@@ -547,7 +542,6 @@
             hir_crate: None,
             hir_map: None,
             resolutions: None,
-            analysis: None,
             tcx: None,
         }
     }
@@ -595,7 +589,6 @@
         out_file: &'a Option<PathBuf>,
         cstore: &'tcx CStore,
         hir_map: &'a hir_map::Map<'tcx>,
-        analysis: &'a ty::CrateAnalysis,
         resolutions: &'a Resolutions,
         krate: &'a ast::Crate,
         hir_crate: &'a hir::Crate,
@@ -606,7 +599,6 @@
             crate_name: Some(crate_name),
             cstore: Some(cstore),
             hir_map: Some(hir_map),
-            analysis: Some(analysis),
             resolutions: Some(resolutions),
             expanded_crate: Some(krate),
             hir_crate: Some(hir_crate),
@@ -623,12 +615,10 @@
         out_file: &'a Option<PathBuf>,
         krate: Option<&'a ast::Crate>,
         hir_crate: &'a hir::Crate,
-        analysis: &'a ty::CrateAnalysis,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         crate_name: &'a str,
     ) -> Self {
         CompileState {
-            analysis: Some(analysis),
             tcx: Some(tcx),
             expanded_crate: krate,
             hir_crate: Some(hir_crate),
@@ -711,7 +701,6 @@
 pub struct ExpansionResult {
     pub expanded_crate: ast::Crate,
     pub defs: hir_map::Definitions,
-    pub analysis: ty::CrateAnalysis,
     pub resolutions: Resolutions,
     pub hir_forest: hir_map::Forest,
 }
@@ -772,16 +761,13 @@
                 freevars: resolver.freevars,
                 export_map: resolver.export_map,
                 trait_map: resolver.trait_map,
+                glob_map: resolver.glob_map,
                 maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
                 maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
                 extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
                     (ident.name, entry.introduced_by_item)
                 }).collect(),
             },
-
-            analysis: ty::CrateAnalysis {
-                glob_map: resolver.glob_map
-            },
         }),
         Err(x) => Err(x),
     }
@@ -1159,10 +1145,13 @@
     ty::provide(providers);
     traits::provide(providers);
     stability::provide(providers);
+    middle::intrinsicck::provide(providers);
+    middle::liveness::provide(providers);
     reachable::provide(providers);
     rustc_passes::provide(providers);
     rustc_traits::provide(providers);
     middle::region::provide(providers);
+    middle::entry::provide(providers);
     cstore::provide(providers);
     lint::provide(providers);
 }
@@ -1180,7 +1169,6 @@
     sess: &'tcx Session,
     cstore: &'tcx CStore,
     hir_map: hir_map::Map<'tcx>,
-    analysis: ty::CrateAnalysis,
     resolutions: Resolutions,
     arenas: &'tcx mut AllArenas<'tcx>,
     name: &str,
@@ -1190,7 +1178,6 @@
 where
     F: for<'a> FnOnce(
         TyCtxt<'a, 'tcx, 'tcx>,
-        ty::CrateAnalysis,
         mpsc::Receiver<Box<dyn Any + Send>>,
         CompileResult,
     ) -> R,
@@ -1199,10 +1186,6 @@
         rustc_incremental::load_query_result_cache(sess)
     });
 
-    time(sess, "looking for entry point", || {
-        middle::entry::find_entry_point(sess, &hir_map, name)
-    });
-
     let mut local_providers = ty::query::Providers::default();
     default_provide(&mut local_providers);
     codegen_backend.provide(&mut local_providers);
@@ -1232,6 +1215,10 @@
             // tcx available.
             time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
 
+            time(sess, "looking for entry point", || {
+                middle::entry::find_entry_point(tcx)
+            });
+
             time(sess, "looking for plugin registrar", || {
                 plugin::build::find_plugin_registrar(tcx)
             });
@@ -1254,7 +1241,7 @@
             match typeck::check_crate(tcx) {
                 Ok(x) => x,
                 Err(x) => {
-                    f(tcx, analysis, rx, Err(x));
+                    f(tcx, rx, Err(x));
                     return Err(x);
                 }
             }
@@ -1307,7 +1294,7 @@
             // lint warnings and so on -- kindck used to do this abort, but
             // kindck is gone now). -nmatsakis
             if sess.err_count() > 0 {
-                return Ok(f(tcx, analysis, rx, sess.compile_status()));
+                return Ok(f(tcx, rx, sess.compile_status()));
             }
 
             time(sess, "death checking", || middle::dead::check_crate(tcx));
@@ -1318,7 +1305,7 @@
 
             time(sess, "lint checking", || lint::check_crate(tcx));
 
-            return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
+            return Ok(f(tcx, rx, tcx.sess.compile_status()));
         },
     )
 }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 010ac28..c8a5bbe 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -879,7 +879,6 @@
                     pretty::print_after_hir_lowering(state.session,
                                                      state.cstore.unwrap(),
                                                      state.hir_map.unwrap(),
-                                                     state.analysis.unwrap(),
                                                      state.resolutions.unwrap(),
                                                      state.input,
                                                      &state.expanded_crate.take().unwrap(),
@@ -940,7 +939,6 @@
         time(state.session, "save analysis", || {
             save::process_crate(state.tcx.unwrap(),
                                 state.expanded_crate.unwrap(),
-                                state.analysis.unwrap(),
                                 state.crate_name.unwrap(),
                                 state.input,
                                 None,
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index a9ec993..d980c5a 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -123,7 +123,8 @@
                 sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \
                                      `expanded`, `flowgraph[,unlabelled]=<nodeid>`, \
                                      `identified`, `expanded,identified`, `everybody_loops`, \
-                                     `hir`, `hir,identified`, `hir,typed`, or `mir`; got {}",
+                                     `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \
+                                     `mir` or `mir-cfg`; got {}",
                                     name));
             } else {
                 sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \
@@ -190,7 +191,6 @@
         sess: &'tcx Session,
         cstore: &'tcx CStore,
         hir_map: &hir_map::Map<'tcx>,
-        analysis: &ty::CrateAnalysis,
         resolutions: &Resolutions,
         output_filenames: &OutputFilenames,
         id: &str,
@@ -223,12 +223,11 @@
                                                                  sess,
                                                                  cstore,
                                                                  hir_map.clone(),
-                                                                 analysis.clone(),
                                                                  resolutions.clone(),
                                                                  &mut arenas,
                                                                  id,
                                                                  output_filenames,
-                                                                 |tcx, _, _, _| {
+                                                                 |tcx, _, _| {
                     let empty_tables = ty::TypeckTables::empty(None);
                     let annotation = TypedAnnotation {
                         tcx,
@@ -959,7 +958,6 @@
 pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                 cstore: &'tcx CStore,
                                                 hir_map: &hir_map::Map<'tcx>,
-                                                analysis: &ty::CrateAnalysis,
                                                 resolutions: &Resolutions,
                                                 input: &Input,
                                                 krate: &ast::Crate,
@@ -972,7 +970,6 @@
         print_with_analysis(sess,
                             cstore,
                             hir_map,
-                            analysis,
                             resolutions,
                             crate_name,
                             output_filenames,
@@ -1010,7 +1007,6 @@
                 s.call_with_pp_support_hir(sess,
                                            cstore,
                                            hir_map,
-                                           analysis,
                                            resolutions,
                                            output_filenames,
                                            crate_name,
@@ -1033,7 +1029,6 @@
                 s.call_with_pp_support_hir(sess,
                                            cstore,
                                            hir_map,
-                                           analysis,
                                            resolutions,
                                            output_filenames,
                                            crate_name,
@@ -1048,7 +1043,6 @@
                 s.call_with_pp_support_hir(sess,
                                            cstore,
                                            hir_map,
-                                           analysis,
                                            resolutions,
                                            output_filenames,
                                            crate_name,
@@ -1081,7 +1075,6 @@
                 s.call_with_pp_support_hir(sess,
                                            cstore,
                                            hir_map,
-                                           analysis,
                                            resolutions,
                                            output_filenames,
                                            crate_name,
@@ -1103,13 +1096,12 @@
 }
 
 // In an ideal world, this would be a public function called by the driver after
-// analsysis is performed. However, we want to call `phase_3_run_analysis_passes`
+// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
 // with a different callback than the standard driver, so that isn't easy.
 // Instead, we call that function ourselves.
 fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                        cstore: &'a CStore,
                                        hir_map: &hir_map::Map<'tcx>,
-                                       analysis: &ty::CrateAnalysis,
                                        resolutions: &Resolutions,
                                        crate_name: &str,
                                        output_filenames: &OutputFilenames,
@@ -1134,12 +1126,11 @@
                                                      sess,
                                                      cstore,
                                                      hir_map.clone(),
-                                                     analysis.clone(),
                                                      resolutions.clone(),
                                                      &mut arenas,
                                                      crate_name,
                                                      output_filenames,
-                                                     |tcx, _, _, _| {
+                                                     |tcx, _, _| {
         match ppm {
             PpmMir | PpmMirCFG => {
                 if let Some(nodeid) = nodeid {
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 7449b2b..736cca6 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -33,7 +33,11 @@
 /// it easy to declare such methods on the builder.
 macro_rules! forward {
     // Forward pattern for &self -> &Self
-    (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n(&self, $($name: $ty),*) -> &Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -42,7 +46,11 @@
     };
 
     // Forward pattern for &mut self -> &mut Self
-    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -52,10 +60,15 @@
 
     // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
     // type parameter. No obvious way to make this more generic.
-    (pub fn $n:ident<S: Into<MultiSpan>>(
-                    &mut self,
-                    $($name:ident: $ty:ty),*
-                    $(,)*) -> &mut Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident<S: Into<MultiSpan>>(
+            &mut self,
+            $($name:ident: $ty:ty),*
+            $(,)*
+        ) -> &mut Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -177,34 +190,43 @@
                                                   msg: &str,
                                                   ) -> &mut Self);
 
-    #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
-    forward!(pub fn span_suggestion_short(
-                                      &mut self,
-                                      sp: Span,
-                                      msg: &str,
-                                      suggestion: String,
-                                      ) -> &mut Self);
+    forward!(
+        #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
+        pub fn span_suggestion_short(
+            &mut self,
+            sp: Span,
+            msg: &str,
+            suggestion: String,
+        ) -> &mut Self
+    );
 
-    #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
-    forward!(pub fn multipart_suggestion(
-        &mut self,
-        msg: &str,
-        suggestion: Vec<(Span, String)>,
-    ) -> &mut Self);
+    forward!(
+        #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
+        pub fn multipart_suggestion(
+            &mut self,
+            msg: &str,
+            suggestion: Vec<(Span, String)>,
+        ) -> &mut Self
+    );
 
-    #[deprecated(note = "Use `span_suggestion_with_applicability`")]
-    forward!(pub fn span_suggestion(&mut self,
-                                    sp: Span,
-                                    msg: &str,
-                                    suggestion: String,
-                                    ) -> &mut Self);
+    forward!(
+        #[deprecated(note = "Use `span_suggestion_with_applicability`")]
+        pub fn span_suggestion(
+            &mut self,
+            sp: Span,
+            msg: &str,
+            suggestion: String,
+        ) -> &mut Self
+    );
 
-    #[deprecated(note = "Use `span_suggestions_with_applicability`")]
-    forward!(pub fn span_suggestions(&mut self,
-                                     sp: Span,
-                                     msg: &str,
-                                     suggestions: Vec<String>,
-                                     ) -> &mut Self);
+    forward!(
+        #[deprecated(note = "Use `span_suggestions_with_applicability`")]
+        pub fn span_suggestions(&mut self,
+            sp: Span,
+            msg: &str,
+            suggestions: Vec<String>,
+        ) -> &mut Self
+    );
 
     pub fn multipart_suggestion_with_applicability(&mut self,
                                               msg: &str,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index a074441..3e25f98 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -135,10 +135,11 @@
             if let Some(line) = line_opt {
                 if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) {
                     let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi));
-                    buf.push_str(match hi_opt {
-                        Some(hi) => &line[lo..hi],
-                        None => &line[lo..],
-                    });
+                    match hi_opt {
+                        Some(hi) if hi > lo => buf.push_str(&line[lo..hi]),
+                        Some(_) => (),
+                        None => buf.push_str(&line[lo..]),
+                    }
                 }
                 if let None = hi_opt {
                     buf.push('\n');
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index f895542..f6c381f 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1474,7 +1474,7 @@
                     _ => {},
                 }
                 TokenTree::Delimited(_, _, tts) => {
-                    self.check_tokens(cx, tts.stream())
+                    self.check_tokens(cx, tts)
                 },
             }
         }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 2d764d1..71c859d 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -341,6 +341,11 @@
             reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
             edition: None,
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS),
+            reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
+            edition: None,
+        },
         ]);
 
     // Register renamed and removed lints.
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index bc29020..8a68f1b 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -41,7 +41,7 @@
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
         let expr = match s.node {
-            hir::StmtKind::Semi(ref expr, _) => &**expr,
+            hir::StmtKind::Semi(ref expr) => &**expr,
             _ => return,
         };
 
@@ -205,7 +205,7 @@
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements {
     fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
-        if let hir::StmtKind::Semi(ref expr, _) = s.node {
+        if let hir::StmtKind::Semi(ref expr) = s.node {
             if let hir::ExprKind::Path(_) = expr.node {
                 cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect");
             }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index dc8db5b..1f07e8f 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -418,6 +418,7 @@
             EntryKind::Mod(_) => Def::Mod(did),
             EntryKind::Variant(_) => Def::Variant(did),
             EntryKind::Trait(_) => Def::Trait(did),
+            EntryKind::TraitAlias(_) => Def::TraitAlias(did),
             EntryKind::Enum(..) => Def::Enum(did),
             EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
             EntryKind::ForeignType => Def::ForeignTy(did),
@@ -520,17 +521,26 @@
     }
 
     pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
-        let data = match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode((self, sess)),
-            _ => bug!(),
-        };
-
-        ty::TraitDef::new(self.local_def_id(item_id),
-                          data.unsafety,
-                          data.paren_sugar,
-                          data.has_auto_impl,
-                          data.is_marker,
-                          self.def_path_table.def_path_hash(item_id))
+        match self.entry(item_id).kind {
+            EntryKind::Trait(data) => {
+                let data = data.decode((self, sess));
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  data.unsafety,
+                                  data.paren_sugar,
+                                  data.has_auto_impl,
+                                  data.is_marker,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            EntryKind::TraitAlias(_) => {
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  hir::Unsafety::Normal,
+                                  false,
+                                  false,
+                                  false,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            _ => bug!("def-index does not refer to trait or trait alias"),
+        }
     }
 
     fn get_variant(&self,
@@ -615,10 +625,13 @@
                                 item_id: DefIndex,
                                 tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                 -> ty::GenericPredicates<'tcx> {
-        match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)),
-            _ => bug!(),
-        }
+        let super_predicates = match self.entry(item_id).kind {
+            EntryKind::Trait(data) => data.decode(self).super_predicates,
+            EntryKind::TraitAlias(data) => data.decode(self).super_predicates,
+            _ => bug!("def-index does not refer to trait or trait alias"),
+        };
+
+        super_predicates.decode((self, tcx))
     }
 
     pub fn get_generics(&self,
@@ -1014,7 +1027,8 @@
         }
         def_key.parent.and_then(|parent_index| {
             match self.entry(parent_index).kind {
-                EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
+                EntryKind::Trait(_) |
+                EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)),
                 _ => None,
             }
         })
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 2de1637..afb0218 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1128,8 +1128,7 @@
 
                 EntryKind::Impl(self.lazy(&data))
             }
-            hir::ItemKind::Trait(..) |
-            hir::ItemKind::TraitAlias(..) => {
+            hir::ItemKind::Trait(..) => {
                 let trait_def = tcx.trait_def(def_id);
                 let data = TraitData {
                     unsafety: trait_def.unsafety,
@@ -1141,6 +1140,13 @@
 
                 EntryKind::Trait(self.lazy(&data))
             }
+            hir::ItemKind::TraitAlias(..) => {
+                let data = TraitAliasData {
+                    super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
+                };
+
+                EntryKind::TraitAlias(self.lazy(&data))
+            }
             hir::ItemKind::ExternCrate(_) |
             hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
         };
@@ -1214,6 +1220,7 @@
                 hir::ItemKind::Impl(..) |
                 hir::ItemKind::Existential(..) |
                 hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)),
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)),
                 _ => None,
             },
             predicates: match item.node {
@@ -1226,7 +1233,8 @@
                 hir::ItemKind::Union(..) |
                 hir::ItemKind::Impl(..) |
                 hir::ItemKind::Existential(..) |
-                hir::ItemKind::Trait(..) => Some(self.encode_predicates(def_id)),
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)),
                 _ => None,
             },
 
@@ -1236,7 +1244,8 @@
             // hack. (No reason not to expand it in the future if
             // necessary.)
             predicates_defined_on: match item.node {
-                hir::ItemKind::Trait(..) => Some(self.encode_predicates_defined_on(def_id)),
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)),
                 _ => None, // not *wrong* for other kinds of items, but not needed
             },
 
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index d35d649..1f00086 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -163,7 +163,7 @@
            !self.tcx.features().static_nobundle {
             feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
                                            "static_nobundle",
-                                           span.unwrap(),
+                                           span.unwrap_or_else(|| syntax_pos::DUMMY_SP),
                                            GateIssue::Language,
                                            "kind=\"static-nobundle\" is feature gated");
         }
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 25f499b..f3ff974 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -316,6 +316,7 @@
     AssociatedType(AssociatedContainer),
     AssociatedExistential(AssociatedContainer),
     AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
+    TraitAlias(Lazy<TraitAliasData<'tcx>>),
 }
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
@@ -370,6 +371,9 @@
             EntryKind::Trait(ref trait_data) => {
                 trait_data.hash_stable(hcx, hasher);
             }
+            EntryKind::TraitAlias(ref trait_alias_data) => {
+                trait_alias_data.hash_stable(hcx, hasher);
+            }
             EntryKind::Impl(ref impl_data) => {
                 impl_data.hash_stable(hcx, hasher);
             }
@@ -475,6 +479,15 @@
 });
 
 #[derive(RustcEncodable, RustcDecodable)]
+pub struct TraitAliasData<'tcx> {
+    pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
+}
+
+impl_stable_hash_for!(struct TraitAliasData<'tcx> {
+    super_predicates
+});
+
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
     pub defaultness: hir::Defaultness,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 77c8a89..2a858bd 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -505,7 +505,7 @@
     ) {
         let mut diag = infcx.tcx.sess.struct_span_err(
             span,
-            "unsatisfied lifetime constraints", // FIXME
+            "lifetime may not live long enough"
         );
 
         let counter = &mut 1;
diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs
index 37d741d..f63c3e2 100644
--- a/src/librustc_mir/hair/constant.rs
+++ b/src/librustc_mir/hair/constant.rs
@@ -37,6 +37,14 @@
             let id = tcx.allocate_bytes(s.as_bytes());
             ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx)
         },
+        LitKind::Err(ref s) => {
+            let s = s.as_str();
+            let id = tcx.allocate_bytes(s.as_bytes());
+            return Ok(ty::Const {
+                val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx),
+                ty: tcx.types.err,
+            });
+        },
         LitKind::ByteStr(ref data) => {
             let id = tcx.allocate_bytes(data);
             ConstValue::Scalar(Scalar::Ptr(id.into()))
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index ea8b282..c50d9dd 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -46,12 +46,12 @@
                                 -> Vec<StmtRef<'tcx>> {
     let mut result = vec![];
     for (index, stmt) in stmts.iter().enumerate() {
-        let hir_id = cx.tcx.hir().node_to_hir_id(stmt.node.id());
+        let hir_id = cx.tcx.hir().node_to_hir_id(stmt.id);
         let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
-        let stmt_span = StatementSpan(cx.tcx.hir().span(stmt.node.id()));
+        let stmt_span = StatementSpan(cx.tcx.hir().span(stmt.id));
         match stmt.node {
-            hir::StmtKind::Expr(ref expr, _) |
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Expr(ref expr) |
+            hir::StmtKind::Semi(ref expr) => {
                 result.push(StmtRef::Mirror(Box::new(Stmt {
                     kind: StmtKind::Expr {
                         scope: region::Scope {
@@ -64,52 +64,48 @@
                     span: stmt_span,
                 })))
             }
-            hir::StmtKind::Decl(ref decl, _) => {
-                match decl.node {
-                    hir::DeclKind::Item(..) => {
-                        // ignore for purposes of the MIR
-                    }
-                    hir::DeclKind::Local(ref local) => {
-                        let remainder_scope = region::Scope {
-                            id: block_id,
-                            data: region::ScopeData::Remainder(
-                                region::FirstStatementIndex::new(index)),
+            hir::StmtKind::Item(..) => {
+                // ignore for purposes of the MIR
+            }
+            hir::StmtKind::Local(ref local) => {
+                let remainder_scope = region::Scope {
+                    id: block_id,
+                    data: region::ScopeData::Remainder(
+                        region::FirstStatementIndex::new(index)),
+                };
+
+                let mut pattern = cx.pattern_from_hir(&local.pat);
+
+                if let Some(ty) = &local.ty {
+                    if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
+                        debug!("mirror_stmts: user_ty={:?}", user_ty);
+                        pattern = Pattern {
+                            ty: pattern.ty,
+                            span: pattern.span,
+                            kind: Box::new(PatternKind::AscribeUserType {
+                                user_ty: PatternTypeProjection::from_user_type(user_ty),
+                                user_ty_span: ty.span,
+                                subpattern: pattern,
+                                variance: ty::Variance::Covariant,
+                            })
                         };
-
-                        let mut pattern = cx.pattern_from_hir(&local.pat);
-
-                        if let Some(ty) = &local.ty {
-                            if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
-                                debug!("mirror_stmts: user_ty={:?}", user_ty);
-                                pattern = Pattern {
-                                    ty: pattern.ty,
-                                    span: pattern.span,
-                                    kind: Box::new(PatternKind::AscribeUserType {
-                                        user_ty: PatternTypeProjection::from_user_type(user_ty),
-                                        user_ty_span: ty.span,
-                                        subpattern: pattern,
-                                        variance: ty::Variance::Covariant,
-                                    })
-                                };
-                            }
-                        }
-
-                        result.push(StmtRef::Mirror(Box::new(Stmt {
-                            kind: StmtKind::Let {
-                                remainder_scope: remainder_scope,
-                                init_scope: region::Scope {
-                                    id: hir_id.local_id,
-                                    data: region::ScopeData::Node
-                                },
-                                pattern,
-                                initializer: local.init.to_ref(),
-                                lint_level: cx.lint_level_of(local.id),
-                            },
-                            opt_destruction_scope: opt_dxn_ext,
-                            span: stmt_span,
-                        })));
                     }
                 }
+
+                result.push(StmtRef::Mirror(Box::new(Stmt {
+                    kind: StmtKind::Let {
+                        remainder_scope: remainder_scope,
+                        init_scope: region::Scope {
+                            id: hir_id.local_id,
+                            data: region::ScopeData::Node
+                        },
+                        pattern,
+                        initializer: local.init.to_ref(),
+                        lint_level: cx.lint_level_of(local.id),
+                    },
+                    opt_destruction_scope: opt_dxn_ext,
+                    span: stmt_span,
+                })));
             }
         }
     }
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index a6a8fe5..eb49547 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -177,13 +177,13 @@
 use rustc::hir::{self, CodegenFnAttrFlags};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::interpret::{AllocId, ConstValue};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
 use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::session::config;
+use rustc::session::config::EntryFnType;
 use rustc::mir::{self, Location, Promoted};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::MonoItem;
@@ -321,9 +321,7 @@
     let mut roots = Vec::new();
 
     {
-        let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _, _)| {
-            tcx.hir().local_def_id(node_id)
-        });
+        let entry_fn = tcx.entry_fn(LOCAL_CRATE);
 
         debug!("collect_roots: entry_fn = {:?}", entry_fn);
 
@@ -924,7 +922,7 @@
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mode: MonoItemCollectionMode,
     output: &'b mut Vec<MonoItem<'tcx>>,
-    entry_fn: Option<DefId>,
+    entry_fn: Option<(DefId, EntryFnType)>,
 }
 
 impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
@@ -1023,7 +1021,7 @@
                 true
             }
             MonoItemCollectionMode::Lazy => {
-                self.entry_fn == Some(def_id) ||
+                self.entry_fn.map(|(id, _)| id) == Some(def_id) ||
                 self.tcx.is_reachable_non_generic(def_id) ||
                 self.tcx.codegen_fn_attrs(def_id).flags.contains(
                     CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
@@ -1048,14 +1046,9 @@
     /// the return type of `main`. This is not needed when
     /// the user writes their own `start` manually.
     fn push_extra_entry_roots(&mut self) {
-        if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryFnType::Main) {
-            return
-        }
-
-        let main_def_id = if let Some(def_id) = self.entry_fn {
-            def_id
-        } else {
-            return
+        let main_def_id = match self.entry_fn {
+            Some((def_id, EntryFnType::Main)) => def_id,
+            _ => return,
         };
 
         let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) {
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 7014f53..c831cbd 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -1,6 +1,6 @@
 use monomorphize::Instance;
 use rustc::hir;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::session::config::OptLevel;
 use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
 use rustc::ty::subst::Substs;
@@ -75,8 +75,7 @@
 
         match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => {
-                let entry_def_id =
-                    tcx.sess.entry_fn.borrow().map(|(id, _, _)| tcx.hir().local_def_id(id));
+                let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
                 // If this function isn't inlined or otherwise has explicit
                 // linkage, then we'll be creating a globally shared version.
                 if self.explicit_linkage(tcx).is_some() ||
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 059b88a..85bf1e7 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -21,6 +21,7 @@
                 | Predicate::RegionOutlives(_)
                 | Predicate::TypeOutlives(_)
                 | Predicate::WellFormed(_)
+                | Predicate::Projection(_)
                 | Predicate::ConstEvaluatable(..) => continue,
                 | Predicate::ObjectSafe(_) => {
                     bug!("object safe predicate on function: {:#?}", predicate)
@@ -29,13 +30,6 @@
                     bug!("closure kind predicate on function: {:#?}", predicate)
                 }
                 Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
-                Predicate::Projection(_) => {
-                    let span = tcx.def_span(current);
-                    // we'll hit a `Predicate::Trait` later which will report an error
-                    tcx.sess
-                        .delay_span_bug(span, "projection without trait bound");
-                    continue;
-                }
                 Predicate::Trait(pred) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index 604b31e..74d6d75 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -144,7 +144,7 @@
     }
 
     fn visit_stmt(&mut self, s: &'v hir::Stmt) {
-        self.record("Stmt", Id::Node(s.node.id()), s);
+        self.record("Stmt", Id::Node(s.id), s);
         hir_visit::walk_stmt(self, s)
     }
 
@@ -158,11 +158,6 @@
         hir_visit::walk_pat(self, p)
     }
 
-    fn visit_decl(&mut self, d: &'v hir::Decl) {
-        self.record("Decl", Id::None, d);
-        hir_visit::walk_decl(self, d)
-    }
-
     fn visit_expr(&mut self, ex: &'v hir::Expr) {
         self.record("Expr", Id::Node(ex.id), ex);
         hir_visit::walk_expr(self, ex)
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index f0b559f..49914dc 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -220,26 +220,22 @@
 
     fn check_stmt(&mut self, stmt: &'tcx hir::Stmt) -> Promotability {
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _node_id) => {
-                match &decl.node {
-                    hir::DeclKind::Local(local) => {
-                        if self.remove_mut_rvalue_borrow(&local.pat) {
-                            if let Some(init) = &local.init {
-                                self.mut_rvalue_borrows.insert(init.id);
-                            }
-                        }
-
-                        if let Some(ref expr) = local.init {
-                            let _ = self.check_expr(&expr);
-                        }
-                        NotPromotable
+            hir::StmtKind::Local(ref local) => {
+                if self.remove_mut_rvalue_borrow(&local.pat) {
+                    if let Some(init) = &local.init {
+                        self.mut_rvalue_borrows.insert(init.id);
                     }
-                    // Item statements are allowed
-                    hir::DeclKind::Item(_) => Promotable
                 }
+
+                if let Some(ref expr) = local.init {
+                    let _ = self.check_expr(&expr);
+                }
+                NotPromotable
             }
-            hir::StmtKind::Expr(ref box_expr, _node_id) |
-            hir::StmtKind::Semi(ref box_expr, _node_id) => {
+            // Item statements are allowed
+            hir::StmtKind::Item(..) => Promotable,
+            hir::StmtKind::Expr(ref box_expr) |
+            hir::StmtKind::Semi(ref box_expr) => {
                 let _ = self.check_expr(box_expr);
                 NotPromotable
             }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 4890369..dcbb9ff 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -13,7 +13,7 @@
 extern crate syntax_pos;
 extern crate rustc_data_structures;
 
-use rustc::hir::{self, Node, PatKind};
+use rustc::hir::{self, Node, PatKind, AssociatedItemKind};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -22,12 +22,12 @@
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind};
 use rustc::ty::fold::TypeVisitor;
-use rustc::ty::query::Providers;
+use rustc::ty::query::{Providers, queries};
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::NodeSet;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
-use syntax::ast::{self, CRATE_NODE_ID, Ident};
+use syntax::ast::{self, DUMMY_NODE_ID, Ident};
 use syntax::attr;
 use syntax::symbol::keywords;
 use syntax_pos::Span;
@@ -548,7 +548,7 @@
                         let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
                         reach.generics().predicates();
 
-                        if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+                        if trait_item_ref.kind == AssociatedItemKind::Type &&
                            !trait_item_ref.defaultness.has_value() {
                             // No type to visit.
                         } else {
@@ -782,6 +782,11 @@
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
+    fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) {
+        // Don't visit nested modules, since we run a separate visitor walk
+        // for each module in `privacy_access_levels`
+    }
+
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
         let body = self.tcx.hir().body(body);
@@ -917,6 +922,11 @@
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
+    fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) {
+        // Don't visit nested modules, since we run a separate visitor walk
+        // for each module in `privacy_access_levels`
+    }
+
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
         let orig_in_body = mem::replace(&mut self.in_body, true);
@@ -1333,11 +1343,11 @@
                         if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                             match impl_item_ref.kind {
-                                hir::AssociatedItemKind::Const => {
+                                AssociatedItemKind::Const => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
-                                hir::AssociatedItemKind::Method { has_self: false } => {
+                                AssociatedItemKind::Method { has_self: false } => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
@@ -1558,6 +1568,24 @@
             in_assoc_ty: false,
         }
     }
+
+    fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
+                                defaultness: hir::Defaultness, vis: ty::Visibility) {
+        let mut check = self.check(node_id, vis);
+
+        let (check_ty, is_assoc_ty) = match assoc_item_kind {
+            AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
+            AssociatedItemKind::Type => (defaultness.has_value(), true),
+            // `ty()` for existential types is the underlying type,
+            // it's not a part of interface, so we skip it.
+            AssociatedItemKind::Existential => (false, true),
+        };
+        check.in_assoc_ty = is_assoc_ty;
+        check.generics().predicates();
+        if check_ty {
+            check.ty();
+        }
+    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
@@ -1592,16 +1620,8 @@
                 self.check(item.id, item_visibility).generics().predicates();
 
                 for trait_item_ref in trait_item_refs {
-                    let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
-                    check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
-                    check.generics().predicates();
-
-                    if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
-                       !trait_item_ref.defaultness.has_value() {
-                        // No type to visit.
-                    } else {
-                        check.ty();
-                    }
+                    self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
+                                                  trait_item_ref.defaultness, item_visibility);
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
@@ -1647,9 +1667,8 @@
                     } else {
                         impl_vis
                     };
-                    let mut check = self.check(impl_item.id, impl_item_vis);
-                    check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
-                    check.generics().predicates().ty();
+                    self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
+                                                  impl_item_ref.defaultness, impl_item_vis);
                 }
             }
         }
@@ -1659,6 +1678,7 @@
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         privacy_access_levels,
+        check_mod_privacy,
         ..*providers
     };
 }
@@ -1667,34 +1687,43 @@
     tcx.privacy_access_levels(LOCAL_CRATE)
 }
 
-fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   krate: CrateNum)
-                                   -> Lrc<AccessLevels> {
-    assert_eq!(krate, LOCAL_CRATE);
-
-    let krate = tcx.hir().krate();
+fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
     let empty_tables = ty::TypeckTables::empty(None);
 
     // Check privacy of names not checked in previous compilation stages.
     let mut visitor = NamePrivacyVisitor {
         tcx,
         tables: &empty_tables,
-        current_item: CRATE_NODE_ID,
+        current_item: DUMMY_NODE_ID,
         empty_tables: &empty_tables,
     };
-    intravisit::walk_crate(&mut visitor, krate);
+    let (module, span, node_id) = tcx.hir().get_module(module_def_id);
+    intravisit::walk_mod(&mut visitor, module, node_id);
 
     // Check privacy of explicitly written types and traits as well as
     // inferred types of expressions and patterns.
     let mut visitor = TypePrivacyVisitor {
         tcx,
         tables: &empty_tables,
-        current_item: DefId::local(CRATE_DEF_INDEX),
+        current_item: module_def_id,
         in_body: false,
-        span: krate.span,
+        span,
         empty_tables: &empty_tables,
     };
-    intravisit::walk_crate(&mut visitor, krate);
+    intravisit::walk_mod(&mut visitor, module, node_id);
+}
+
+fn privacy_access_levels<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    krate: CrateNum,
+) -> Lrc<AccessLevels> {
+    assert_eq!(krate, LOCAL_CRATE);
+
+    let krate = tcx.hir().krate();
+
+    for &module in krate.modules.keys() {
+        queries::check_mod_privacy::ensure(tcx, tcx.hir().local_def_id(module));
+    }
 
     // Build up a set of all exported items in the AST. This is a set of all
     // items which are reachable from external crates based on visibility.
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index a452bbf..35616cc 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -21,6 +21,8 @@
 use std::ptr;
 use rustc_data_structures::sync::Lrc;
 
+use errors::Applicability;
+
 use syntax::ast::{Name, Ident};
 use syntax::attr;
 
@@ -345,7 +347,12 @@
                 let module = if orig_name.is_none() && ident.name == keywords::SelfLower.name() {
                     self.session
                         .struct_span_err(item.span, "`extern crate self;` requires renaming")
-                        .span_suggestion(item.span, "try", "extern crate self as name;".into())
+                        .span_suggestion_with_applicability(
+                            item.span,
+                            "try",
+                            "extern crate self as name;".into(),
+                            Applicability::HasPlaceholders,
+                        )
                         .emit();
                     return;
                 } else if orig_name == Some(keywords::SelfLower.name()) {
@@ -673,6 +680,9 @@
                 }
                 module.populated.set(true);
             }
+            Def::TraitAlias(..) => {
+                self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
+            }
             Def::Struct(..) | Def::Union(..) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b411937..1cd4404 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3318,7 +3318,12 @@
             if let Some(def) = def {
                 match (def, source) {
                     (Def::Macro(..), _) => {
-                        err.span_label(span, format!("did you mean `{}!(...)`?", path_str));
+                        err.span_suggestion_with_applicability(
+                            span,
+                            "use `!` to invoke the macro",
+                            format!("{}!", path_str),
+                            Applicability::MaybeIncorrect,
+                        );
                         return (err, candidates);
                     }
                     (Def::TyAlias(..), PathSource::Trait(_)) => {
@@ -3330,13 +3335,22 @@
                     }
                     (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
                         ExprKind::Field(_, ident) => {
-                            err.span_label(parent.span, format!("did you mean `{}::{}`?",
-                                                                 path_str, ident));
+                            err.span_suggestion_with_applicability(
+                                parent.span,
+                                "use the path separator to refer to an item",
+                                format!("{}::{}", path_str, ident),
+                                Applicability::MaybeIncorrect,
+                            );
                             return (err, candidates);
                         }
                         ExprKind::MethodCall(ref segment, ..) => {
-                            err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
-                                                                 path_str, segment.ident));
+                            let span = parent.span.with_hi(segment.ident.span.hi());
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "use the path separator to refer to an item",
+                                format!("{}::{}", path_str, segment.ident),
+                                Applicability::MaybeIncorrect,
+                            );
                             return (err, candidates);
                         }
                         _ => {}
@@ -3387,6 +3401,29 @@
                                 Ok(ref snippet) if snippet == "{" => true,
                                 _ => false,
                             };
+                            // In case this could be a struct literal that needs to be surrounded
+                            // by parenthesis, find the appropriate span.
+                            let mut i = 0;
+                            let mut closing_brace = None;
+                            loop {
+                                sp = sm.next_point(sp);
+                                match sm.span_to_snippet(sp) {
+                                    Ok(ref snippet) => {
+                                        if snippet == "}" {
+                                            let sp = span.to(sp);
+                                            if let Ok(snippet) = sm.span_to_snippet(sp) {
+                                                closing_brace = Some((sp, snippet));
+                                            }
+                                            break;
+                                        }
+                                    }
+                                    _ => break,
+                                }
+                                i += 1;
+                                if i > 100 { // The bigger the span the more likely we're
+                                    break;   // incorrect. Bound it to 100 chars long.
+                                }
+                            }
                             match source {
                                 PathSource::Expr(Some(parent)) => {
                                     match parent.node {
@@ -3413,11 +3450,20 @@
                                     }
                                 },
                                 PathSource::Expr(None) if followed_by_brace == true => {
-                                    err.span_label(
-                                        span,
-                                        format!("did you mean `({} {{ /* fields */ }})`?",
-                                                path_str),
-                                    );
+                                    if let Some((sp, snippet)) = closing_brace {
+                                        err.span_suggestion_with_applicability(
+                                            sp,
+                                            "surround the struct literal with parenthesis",
+                                            format!("({})", snippet),
+                                            Applicability::MaybeIncorrect,
+                                        );
+                                    } else {
+                                        err.span_label(
+                                            span,
+                                            format!("did you mean `({} {{ /* fields */ }})`?",
+                                                    path_str),
+                                        );
+                                    }
                                     return (err, candidates);
                                 },
                                 _ => {
@@ -4820,8 +4866,13 @@
                 } else if ident.span.rust_2018() {
                     let msg = "relative paths are not supported in visibilities on 2018 edition";
                     self.session.struct_span_err(ident.span, msg)
-                                .span_suggestion(path.span, "try", format!("crate::{}", path))
-                                .emit();
+                        .span_suggestion_with_applicability(
+                            path.span,
+                            "try",
+                            format!("crate::{}", path),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
                     return ty::Visibility::Public;
                 } else {
                     let ctxt = ident.span.ctxt();
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 05156fb..995df38 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1238,12 +1238,9 @@
                 };
 
                 // Make a comma-separated list of names of imported modules.
-                let glob_map = &self.save_ctxt.analysis.glob_map;
-                let names = if glob_map.contains_key(&id) {
-                    glob_map.get(&id).unwrap().iter().map(|n| n.to_string()).collect()
-                } else {
-                    Vec::new()
-                };
+                let def_id = self.tcx.hir().local_def_id(id);
+                let names = self.tcx.names_imported_by_glob_use(def_id);
+                let names: Vec<_> = names.iter().map(|n| n.to_string()).collect();
 
                 // Otherwise it's a span with wrong macro expansion info, which
                 // we don't want to track anyway, since it's probably macro-internal `use`
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 4d55004..73eb5de 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -71,7 +71,6 @@
     tcx: TyCtxt<'l, 'tcx, 'tcx>,
     tables: &'l ty::TypeckTables<'tcx>,
     access_levels: &'l AccessLevels,
-    analysis: &'l ty::CrateAnalysis,
     span_utils: SpanUtils<'tcx>,
     config: Config,
     impl_counter: Cell<u32>,
@@ -1120,7 +1119,6 @@
 pub fn process_crate<'l, 'tcx, H: SaveHandler>(
     tcx: TyCtxt<'l, 'tcx, 'tcx>,
     krate: &ast::Crate,
-    analysis: &'l ty::CrateAnalysis,
     cratename: &str,
     input: &'l Input,
     config: Option<Config>,
@@ -1139,7 +1137,6 @@
         let save_ctxt = SaveContext {
             tcx,
             tables: &ty::TypeckTables::empty(None),
-            analysis,
             access_levels: &access_levels,
             span_utils: SpanUtils::new(&tcx.sess),
             config: find_config(config),
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index f42b0a1..3a21ca1 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -217,6 +217,46 @@
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub enum MergeFunctions {
+    Disabled,
+    Trampolines,
+    Aliases
+}
+
+impl MergeFunctions {
+    pub fn desc(&self) -> &str {
+        match *self {
+            MergeFunctions::Disabled => "disabled",
+            MergeFunctions::Trampolines => "trampolines",
+            MergeFunctions::Aliases => "aliases",
+        }
+    }
+}
+
+impl FromStr for MergeFunctions {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<MergeFunctions, ()> {
+        match s {
+            "disabled" => Ok(MergeFunctions::Disabled),
+            "trampolines" => Ok(MergeFunctions::Trampolines),
+            "aliases" => Ok(MergeFunctions::Aliases),
+            _ => Err(()),
+        }
+    }
+}
+
+impl ToJson for MergeFunctions {
+    fn to_json(&self) -> Json {
+        match *self {
+            MergeFunctions::Disabled => "disabled".to_json(),
+            MergeFunctions::Trampolines => "trampolines".to_json(),
+            MergeFunctions::Aliases => "aliases".to_json(),
+        }
+    }
+}
+
 pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
 pub type TargetResult = Result<Target, String>;
 
@@ -690,7 +730,15 @@
 
     /// If set, have the linker export exactly these symbols, instead of using
     /// the usual logic to figure this out from the crate itself.
-    pub override_export_symbols: Option<Vec<String>>
+    pub override_export_symbols: Option<Vec<String>>,
+
+    /// Determines how or whether the MergeFunctions LLVM pass should run for
+    /// this target. Either "disabled", "trampolines", or "aliases".
+    /// The MergeFunctions pass is generally useful, but some targets may need
+    /// to opt out. The default is "aliases".
+    ///
+    /// Workaround for: https://github.com/rust-lang/rust/issues/57356
+    pub merge_functions: MergeFunctions
 }
 
 impl Default for TargetOptions {
@@ -773,6 +821,7 @@
             requires_uwtable: false,
             simd_types_indirect: true,
             override_export_symbols: None,
+            merge_functions: MergeFunctions::Aliases,
         }
     }
 }
@@ -875,6 +924,19 @@
                     .map(|o| o.as_u64()
                          .map(|s| base.options.$key_name = Some(s)));
             } );
+            ($key_name:ident, MergeFunctions) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                    match s.parse::<MergeFunctions>() {
+                        Ok(mergefunc) => base.options.$key_name = mergefunc,
+                        _ => return Some(Err(format!("'{}' is not a valid value for \
+                                                      merge-functions. Use 'disabled', \
+                                                      'trampolines', or 'aliases'.",
+                                                      s))),
+                    }
+                    Some(Ok(()))
+                })).unwrap_or(Ok(()))
+            } );
             ($key_name:ident, PanicStrategy) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
@@ -1064,6 +1126,7 @@
         key!(requires_uwtable, bool);
         key!(simd_types_indirect, bool);
         key!(override_export_symbols, opt_list);
+        key!(merge_functions, MergeFunctions)?;
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1275,6 +1338,7 @@
         target_option_val!(requires_uwtable);
         target_option_val!(simd_types_indirect);
         target_option_val!(override_export_symbols);
+        target_option_val!(merge_functions);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 5502a1d..9bdef30 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -158,7 +158,8 @@
     def_id: DefId,
 ) -> Clauses<'tcx> {
     match tcx.def_key(def_id).disambiguated_data.data {
-        DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
+        DefPathData::Trait(_) |
+        DefPathData::TraitAlias(_) => program_clauses_for_trait(tcx, def_id),
         DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
         DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
         DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 8e5eaa1..e89506a 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -2,7 +2,7 @@
 //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
 //! instance of `AstConv`.
 
-use errors::{Applicability, FatalError, DiagnosticId};
+use errors::{Applicability, DiagnosticId};
 use hir::{self, GenericArg, GenericArgs};
 use hir::def::Def;
 use hir::def_id::DefId;
@@ -10,6 +10,7 @@
 use lint;
 use middle::resolve_lifetime as rl;
 use namespace::Namespace;
+use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
@@ -689,27 +690,13 @@
     {
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
 
-        let trait_def_id = self.trait_def_id(trait_ref);
         self.ast_path_to_mono_trait_ref(trait_ref.path.span,
-                                        trait_def_id,
+                                        trait_ref.trait_def_id(),
                                         self_ty,
                                         trait_ref.path.segments.last().unwrap())
     }
 
-    /// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
-    fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
-        let path = &trait_ref.path;
-        match path.def {
-            Def::Trait(trait_def_id) => trait_def_id,
-            Def::TraitAlias(alias_def_id) => alias_def_id,
-            Def::Err => {
-                FatalError.raise();
-            }
-            _ => unreachable!(),
-        }
-    }
-
-    /// The given trait ref must actually be a trait.
+    /// The given trait-ref must actually be a trait.
     pub(super) fn instantiate_poly_trait_ref_inner(&self,
         trait_ref: &hir::TraitRef,
         self_ty: Ty<'tcx>,
@@ -717,7 +704,7 @@
         speculative: bool)
         -> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
     {
-        let trait_def_id = self.trait_def_id(trait_ref);
+        let trait_def_id = trait_ref.trait_def_id();
 
         debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
 
@@ -1278,29 +1265,50 @@
     }
 
     // Create a type from a path to an associated type.
-    // For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C`
+    // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
     // and item_segment is the path segment for `D`. We return a type and a def for
     // the whole path.
-    // Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type
+    // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
     // parameter or `Self`.
-    pub fn associated_path_def_to_ty(&self,
-                                     ref_id: ast::NodeId,
-                                     span: Span,
-                                     ty: Ty<'tcx>,
-                                     ty_path_def: Def,
-                                     item_segment: &hir::PathSegment)
-                                     -> (Ty<'tcx>, Def)
-    {
+    pub fn associated_path_to_ty(
+        &self,
+        ref_id: ast::NodeId,
+        span: Span,
+        qself_ty: Ty<'tcx>,
+        qself_def: Def,
+        assoc_segment: &hir::PathSegment,
+        permit_variants: bool,
+    ) -> (Ty<'tcx>, Def) {
         let tcx = self.tcx();
-        let assoc_name = item_segment.ident;
+        let assoc_ident = assoc_segment.ident;
 
-        debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
+        debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
 
-        self.prohibit_generics(slice::from_ref(item_segment));
+        self.prohibit_generics(slice::from_ref(assoc_segment));
+
+        // Check if we have an enum variant.
+        let mut variant_resolution = None;
+        if let ty::Adt(adt_def, _) = qself_ty.sty {
+            if adt_def.is_enum() {
+                let variant_def = adt_def.variants.iter().find(|vd| {
+                    tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did)
+                });
+                if let Some(variant_def) = variant_def {
+                    let def = Def::Variant(variant_def.did);
+                    if permit_variants {
+                        check_type_alias_enum_variants_enabled(tcx, span);
+                        tcx.check_stability(variant_def.did, Some(ref_id), span);
+                        return (qself_ty, def);
+                    } else {
+                        variant_resolution = Some(def);
+                    }
+                }
+            }
+        }
 
         // Find the type of the associated item, and the trait where the associated
         // item is declared.
-        let bound = match (&ty.sty, ty_path_def) {
+        let bound = match (&qself_ty.sty, qself_def) {
             (_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
                 // `Self` in an impl of a trait -- we have a concrete self type and a
                 // trait reference.
@@ -1313,77 +1321,61 @@
                 };
 
                 let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref))
-                    .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
+                    .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_ident));
 
-                match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) {
+                match self.one_bound_for_assoc_type(candidates, "Self", assoc_ident, span) {
                     Ok(bound) => bound,
                     Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
             (&ty::Param(_), Def::SelfTy(Some(param_did), None)) |
             (&ty::Param(_), Def::TyParam(param_did)) => {
-                match self.find_bound_for_assoc_item(param_did, assoc_name, span) {
+                match self.find_bound_for_assoc_item(param_did, assoc_ident, span) {
                     Ok(bound) => bound,
                     Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
-            (&ty::Adt(adt_def, _substs), Def::Enum(_did)) => {
-                let ty_str = ty.to_string();
-                // Incorrect enum variant.
-                let mut err = tcx.sess.struct_span_err(
-                    span,
-                    &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str),
-                );
-                // Check if it was a typo.
-                let input = adt_def.variants.iter().map(|variant| &variant.ident.name);
-                if let Some(suggested_name) = find_best_match_for_name(
-                    input,
-                    &assoc_name.as_str(),
-                    None,
-                ) {
-                    err.span_suggestion_with_applicability(
-                        span,
-                        "did you mean",
-                        format!("{}::{}", ty_str, suggested_name.to_string()),
-                        Applicability::MaybeIncorrect,
-                    );
-                } else {
-                    err.span_label(span, "unknown variant");
-                }
-                err.emit();
-                return (tcx.types.err, Def::Err);
-            }
             _ => {
-                // Check if we have an enum variant.
-                match ty.sty {
-                    ty::Adt(adt_def, _) if adt_def.is_enum() => {
-                        let variant_def = adt_def.variants.iter().find(|vd| {
-                            tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
-                        });
-                        if let Some(variant_def) = variant_def {
-                            check_type_alias_enum_variants_enabled(tcx, span);
-
-                            let def = Def::Variant(variant_def.did);
-                            tcx.check_stability(def.def_id(), Some(ref_id), span);
-                            return (ty, def);
-                        }
-                    },
-                    _ => (),
-                }
-
-                // Don't print `TyErr` to the user.
-                if !ty.references_error() {
+                if variant_resolution.is_some() {
+                    // Variant in type position
+                    let msg = format!("expected type, found variant `{}`", assoc_ident);
+                    tcx.sess.span_err(span, &msg);
+                } else if qself_ty.is_enum() {
+                    // Report as incorrect enum variant rather than ambiguous type.
+                    let mut err = tcx.sess.struct_span_err(
+                        span,
+                        &format!("no variant `{}` on enum `{}`", &assoc_ident.as_str(), qself_ty),
+                    );
+                    // Check if it was a typo.
+                    let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
+                    if let Some(suggested_name) = find_best_match_for_name(
+                        adt_def.variants.iter().map(|variant| &variant.ident.name),
+                        &assoc_ident.as_str(),
+                        None,
+                    ) {
+                        err.span_suggestion_with_applicability(
+                            span,
+                            "did you mean",
+                            format!("{}::{}", qself_ty, suggested_name),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        err.span_label(span, "unknown variant");
+                    }
+                    err.emit();
+                } else if !qself_ty.references_error() {
+                    // Don't print `TyErr` to the user.
                     self.report_ambiguous_associated_type(span,
-                                                          &ty.to_string(),
+                                                          &qself_ty.to_string(),
                                                           "Trait",
-                                                          &assoc_name.as_str());
+                                                          &assoc_ident.as_str());
                 }
                 return (tcx.types.err, Def::Err);
             }
         };
 
         let trait_did = bound.def_id();
-        let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_name, trait_did, ref_id);
+        let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, ref_id);
         let item = tcx.associated_items(trait_did).find(|i| {
             Namespace::from(i.kind) == Namespace::Type &&
                 i.ident.modern() == assoc_ident
@@ -1394,11 +1386,35 @@
 
         let def = Def::AssociatedTy(item.def_id);
         if !item.vis.is_accessible_from(def_scope, tcx) {
-            let msg = format!("{} `{}` is private", def.kind_name(), assoc_name);
+            let msg = format!("{} `{}` is private", def.kind_name(), assoc_ident);
             tcx.sess.span_err(span, &msg);
         }
         tcx.check_stability(item.def_id, Some(ref_id), span);
 
+        if let Some(variant_def) = variant_resolution {
+            let mut err = tcx.struct_span_lint_node(
+                AMBIGUOUS_ASSOCIATED_ITEMS,
+                ref_id,
+                span,
+                "ambiguous associated item",
+            );
+
+            let mut could_refer_to = |def: Def, also| {
+                let note_msg = format!("`{}` could{} refer to {} defined here",
+                                       assoc_ident, also, def.kind_name());
+                err.span_note(tcx.def_span(def.def_id()), &note_msg);
+            };
+            could_refer_to(variant_def, "");
+            could_refer_to(def, " also");
+
+            err.span_suggestion_with_applicability(
+                span,
+                "use fully-qualified syntax",
+                format!("<{} as {}>::{}", qself_ty, "Trait", assoc_ident),
+                Applicability::HasPlaceholders,
+            ).emit();
+        }
+
         (ty, def)
     }
 
@@ -1773,7 +1789,7 @@
                 } else {
                     Def::Err
                 };
-                self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
+                self.associated_path_to_ty(ast_ty.id, ast_ty.span, ty, def, segment, false).0
             }
             hir::TyKind::Array(ref ty, ref length) => {
                 let length_def_id = tcx.hir().local_def_id(length.id);
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 1767af4..47f258e 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -1,5 +1,6 @@
 use check::{FnCtxt, Expectation, Diverges, Needs};
 use check::coercion::CoerceMany;
+use errors::Applicability;
 use rustc::hir::{self, PatKind};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -989,7 +990,13 @@
                     let suggested_name =
                         find_best_match_for_name(input, &ident.as_str(), None);
                     if let Some(suggested_name) = suggested_name {
-                        err.span_suggestion(*span, "did you mean", suggested_name.to_string());
+                        err.span_suggestion_with_applicability(
+                            *span,
+                            "did you mean",
+                            suggested_name.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+
                         // we don't want to throw `E0027` in case we have thrown `E0026` for them
                         unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
                     }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index a82a0d3..dd63b4f 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1216,7 +1216,7 @@
                                       "supposed to be part of a block tail expression, but the \
                                        expression is empty");
                         });
-                        fcx.suggest_mismatched_types_on_tail(
+                        let pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
                             &mut db,
                             expr,
                             expected,
@@ -1224,7 +1224,44 @@
                             cause.span,
                             blk_id,
                         );
-                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+                        // FIXME: replace with navigating up the chain until hitting an fn or
+                        // bailing if no "pass-through" Node is found, in order to provide a
+                        // suggestion when encountering something like:
+                        // ```
+                        // fn foo(a: bool) -> impl Debug {
+                        //     if a {
+                        //         bar()?;
+                        //     }
+                        //     {
+                        //         let x = unsafe { bar() };
+                        //         x
+                        //     }
+                        // }
+                        // ```
+                        //
+                        // Verify that this is a tail expression of a function, otherwise the
+                        // label pointing out the cause for the type coercion will be wrong
+                        // as prior return coercions would not be relevant (#57664).
+                        let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
+                        let parent = fcx.tcx.hir().get(fcx.tcx.hir().get_parent_node(parent_id));
+                        if fcx.get_node_fn_decl(parent).is_some() && !pointing_at_return_type {
+                            if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+                                db.span_label(*sp, reason_label);
+                            }
+                        }
+                    }
+                    ObligationCauseCode::ReturnType(_id) => {
+                        db = fcx.report_mismatched_types(cause, expected, found, err);
+                        let _id = fcx.tcx.hir().get_parent_node(_id);
+                        let mut pointing_at_return_type = false;
+                        if let Some((fn_decl, can_suggest)) = fcx.get_fn_decl(_id) {
+                            pointing_at_return_type = fcx.suggest_missing_return_type(
+                                &mut db, &fn_decl, expected, found, can_suggest);
+                        }
+                        if let (Some(sp), false) = (
+                            fcx.ret_coercion_span.borrow().as_ref(),
+                            pointing_at_return_type,
+                        ) {
                             if !sp.overlaps(cause.span) {
                                 db.span_label(*sp, reason_label);
                             }
@@ -1232,11 +1269,6 @@
                     }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
-                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
-                            if !sp.overlaps(cause.span) {
-                                db.span_label(*sp, reason_label);
-                            }
-                        }
                     }
                 }
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 02687df..e71dc01 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -408,45 +408,36 @@
 
         let tcx = self.tcx;
 
-        let mode = probe::Mode::Path;
-        match self.probe_for_name(span, mode, method_name, IsSuggestion(false),
-                                  self_ty, expr_id, ProbeScope::TraitsInScope) {
-            Ok(pick) => {
-                debug!("resolve_ufcs: pick={:?}", pick);
-                if let Some(import_id) = pick.import_id {
-                    let import_def_id = tcx.hir().local_def_id(import_id);
-                    debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
-                    Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
-                                                .unwrap().insert(import_def_id);
+        // Check if we have an enum variant.
+        if let ty::Adt(adt_def, _) = self_ty.sty {
+            if adt_def.is_enum() {
+                let variant_def = adt_def.variants.iter().find(|vd| {
+                    tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
+                });
+                if let Some(variant_def) = variant_def {
+                    check_type_alias_enum_variants_enabled(tcx, span);
+
+                    let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
+                    tcx.check_stability(def.def_id(), Some(expr_id), span);
+                    return Ok(def);
                 }
-
-                let def = pick.item.def();
-                debug!("resolve_ufcs: def={:?}", def);
-                tcx.check_stability(def.def_id(), Some(expr_id), span);
-
-                Ok(def)
-            }
-            Err(err) => {
-                // Check if we have an enum variant.
-                match self_ty.sty {
-                    ty::Adt(adt_def, _) if adt_def.is_enum() => {
-                        let variant_def = adt_def.variants.iter().find(|vd| {
-                            tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
-                        });
-                        if let Some(variant_def) = variant_def {
-                            check_type_alias_enum_variants_enabled(tcx, span);
-
-                            let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
-                            tcx.check_stability(def.def_id(), Some(expr_id), span);
-                            return Ok(def);
-                        }
-                    },
-                    _ => (),
-                }
-
-                Err(err)
             }
         }
+
+        let pick = self.probe_for_name(span, probe::Mode::Path, method_name, IsSuggestion(false),
+                                       self_ty, expr_id, ProbeScope::TraitsInScope)?;
+        debug!("resolve_ufcs: pick={:?}", pick);
+        if let Some(import_id) = pick.import_id {
+            let import_def_id = tcx.hir().local_def_id(import_id);
+            debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
+            Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
+                .unwrap().insert(import_def_id);
+        }
+
+        let def = pick.item.def();
+        debug!("resolve_ufcs: def={:?}", def);
+        tcx.check_stability(def.def_id(), Some(expr_id), span);
+        Ok(def)
     }
 
     /// Find item with name `item_name` defined in impl/trait `def_id`
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 1b07385..ad4bc3c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -132,7 +132,8 @@
 use std::slice;
 
 use require_c_abi_if_variadic;
-use session::{CompileIncomplete, config, Session};
+use session::{CompileIncomplete, Session};
+use session::config::EntryFnType;
 use TypeAndSubsts;
 use lint;
 use util::captures::Captures;
@@ -1163,19 +1164,18 @@
 
     // Check that the main return type implements the termination trait.
     if let Some(term_id) = fcx.tcx.lang_items().termination() {
-        if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() {
-            if id == fn_id {
-                if let config::EntryFnType::Main = entry_type {
-                    let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
-                    let trait_ref = ty::TraitRef::new(term_id, substs);
-                    let return_ty_span = decl.output.span();
-                    let cause = traits::ObligationCause::new(
-                        return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
+        if let Some((def_id, EntryFnType::Main)) = fcx.tcx.entry_fn(LOCAL_CRATE) {
+            let main_id = fcx.tcx.hir().as_local_node_id(def_id).unwrap();
+            if main_id == fn_id {
+                let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
+                let trait_ref = ty::TraitRef::new(term_id, substs);
+                let return_ty_span = decl.output.span();
+                let cause = traits::ObligationCause::new(
+                    return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
 
-                    inherited.register_predicate(
-                        traits::Obligation::new(
-                            cause, param_env, trait_ref.to_predicate()));
-                }
+                inherited.register_predicate(
+                    traits::Obligation::new(
+                        cause, param_env, trait_ref.to_predicate()));
             }
         }
     }
@@ -3121,7 +3121,8 @@
                 opt_ty.unwrap_or_else(
                     || tcx.mk_float_var(self.next_float_var_id()))
             }
-            ast::LitKind::Bool(_) => tcx.types.bool
+            ast::LitKind::Bool(_) => tcx.types.bool,
+            ast::LitKind::Err(_) => tcx.types.err,
         }
     }
 
@@ -4347,11 +4348,15 @@
                     struct_span_err!(self.tcx.sess, expr.span, E0572,
                                      "return statement outside of function body").emit();
                 } else if let Some(ref e) = *expr_opt {
-                    *self.ret_coercion_span.borrow_mut() = Some(e.span);
+                    if self.ret_coercion_span.borrow().is_none() {
+                        *self.ret_coercion_span.borrow_mut() = Some(e.span);
+                    }
                     self.check_return_expr(e);
                 } else {
                     let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
-                    *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+                    if self.ret_coercion_span.borrow().is_none() {
+                        *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+                    }
                     let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
                     if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
                         coercion.coerce_forced_unit(
@@ -4724,8 +4729,8 @@
                 } else {
                     Def::Err
                 };
-                let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span,
-                                                                   ty, def, segment);
+                let (ty, def) = AstConv::associated_path_to_ty(self, node_id, path_span,
+                                                               ty, def, segment, true);
 
                 // Write back the new resolution.
                 let hir_id = self.tcx.hir().node_to_hir_id(node_id);
@@ -4840,15 +4845,11 @@
     pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
         // Don't do all the complex logic below for `DeclItem`.
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                if let hir::DeclKind::Item(_) = decl.node {
-                    return
-                }
-            }
-            hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
+            hir::StmtKind::Item(..) => return,
+            hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
         }
 
-        self.warn_if_unreachable(stmt.node.id(), stmt.span, "statement");
+        self.warn_if_unreachable(stmt.id, stmt.span, "statement");
 
         // Hide the outer diverging and `has_errors` flags.
         let old_diverges = self.diverges.get();
@@ -4857,20 +4858,16 @@
         self.has_errors.set(false);
 
         match stmt.node {
-            hir::StmtKind::Decl(ref decl, _) => {
-                match decl.node {
-                    hir::DeclKind::Local(ref l) => {
-                        self.check_decl_local(&l);
-                    }
-                    // Ignore for now.
-                    hir::DeclKind::Item(_) => ()
-                }
+            hir::StmtKind::Local(ref l) => {
+                self.check_decl_local(&l);
             }
-            hir::StmtKind::Expr(ref expr, _) => {
+            // Ignore for now.
+            hir::StmtKind::Item(_) => {}
+            hir::StmtKind::Expr(ref expr) => {
                 // Check with expected type of `()`.
                 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit());
             }
-            hir::StmtKind::Semi(ref expr, _) => {
+            hir::StmtKind::Semi(ref expr) => {
                 self.check_expr(&expr);
             }
         }
@@ -5089,12 +5086,15 @@
         found: Ty<'tcx>,
         cause_span: Span,
         blk_id: ast::NodeId,
-    ) {
+    ) -> bool {
         self.suggest_missing_semicolon(err, expression, expected, cause_span);
+        let mut pointing_at_return_type = false;
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
-            self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
+            pointing_at_return_type = self.suggest_missing_return_type(
+                err, &fn_decl, expected, found, can_suggest);
         }
         self.suggest_ref_or_into(err, expression, expected, found);
+        pointing_at_return_type
     }
 
     pub fn suggest_ref_or_into(
@@ -5193,12 +5193,14 @@
     /// This routine checks if the return type is left as default, the method is not part of an
     /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
     /// type.
-    fn suggest_missing_return_type(&self,
-                                   err: &mut DiagnosticBuilder<'tcx>,
-                                   fn_decl: &hir::FnDecl,
-                                   expected: Ty<'tcx>,
-                                   found: Ty<'tcx>,
-                                   can_suggest: bool) {
+    fn suggest_missing_return_type(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        fn_decl: &hir::FnDecl,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+        can_suggest: bool,
+    ) -> bool {
         // Only suggest changing the return type for methods that
         // haven't set a return type at all (and aren't `fn main()` or an impl).
         match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) {
@@ -5208,16 +5210,19 @@
                     "try adding a return type",
                     format!("-> {} ", self.resolve_type_vars_with_obligations(found)),
                     Applicability::MachineApplicable);
+                true
             }
             (&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => {
                 err.span_label(span, "possibly return type missing here?");
+                true
             }
             (&hir::FunctionRetTy::DefaultReturn(span), _, false, true) => {
                 // `fn main()` must return `()`, do not suggest changing return type
                 err.span_label(span, "expected `()` because of default return type");
+                true
             }
             // expectation was caused by something else, not the default return
-            (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => {}
+            (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => false,
             (&hir::FunctionRetTy::Return(ref ty), _, _, _) => {
                 // Only point to return type if the expected type is the return type, as if they
                 // are not, the expectation must have been caused by something else.
@@ -5229,7 +5234,9 @@
                 if ty.sty == expected.sty {
                     err.span_label(sp, format!("expected `{}` because of return type",
                                                expected));
+                    return true;
                 }
+                false
             }
         }
     }
@@ -5273,7 +5280,7 @@
             None => return None,
         };
         let last_expr = match last_stmt.node {
-            hir::StmtKind::Semi(ref e, _) => e,
+            hir::StmtKind::Semi(ref e) => e,
             _ => return None,
         };
         let last_expr_ty = self.node_ty(last_expr.hir_id);
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 3a546f8..93f14a2 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -715,7 +715,7 @@
     // In the case of trait aliases, however, we include all bounds in the where clause,
     // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
     // as one of its "superpredicates".
-    let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
+    let is_trait_alias = tcx.is_trait_alias(trait_def_id);
     let superbounds2 = icx.type_parameter_bounds_in_generics(
         generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
 
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 4e3ea5c..c0a8dd8 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -516,7 +516,7 @@
 For a somewhat artificial example:
 
 ```compile_fail,E0055
-#![recursion_limit="2"]
+#![recursion_limit="5"]
 
 struct Foo;
 
@@ -526,9 +526,9 @@
 
 fn main() {
     let foo = Foo;
-    let ref_foo = &&Foo;
+    let ref_foo = &&&&&Foo;
 
-    // error, reached the recursion limit while auto-dereferencing `&&Foo`
+    // error, reached the recursion limit while auto-dereferencing `&&&&&Foo`
     ref_foo.foo();
 }
 ```
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8bd484a..6c1c49b 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -103,23 +103,22 @@
 mod outlives;
 mod variance;
 
-use hir::Node;
 use rustc_target::spec::abi::Abi;
-use rustc::hir;
+use rustc::hir::{self, Node};
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::infer::InferOk;
 use rustc::lint;
 use rustc::middle;
 use rustc::session;
-use rustc::session::config::nightly_options;
+use rustc::session::CompileIncomplete;
+use rustc::session::config::{EntryFnType, nightly_options};
 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::query::Providers;
 use rustc::util;
 use rustc::util::profiling::ProfileCategory;
-use session::{CompileIncomplete, config};
 use syntax_pos::Span;
-use syntax::ast;
 use util::common::time;
 
 use std::iter;
@@ -184,10 +183,9 @@
     })
 }
 
-fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              main_id: ast::NodeId,
-                              main_span: Span) {
-    let main_def_id = tcx.hir().local_def_id(main_id);
+fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) {
+    let main_id = tcx.hir().as_local_node_id(main_def_id).unwrap();
+    let main_span = tcx.def_span(main_def_id);
     let main_t = tcx.type_of(main_def_id);
     match main_t.sty {
         ty::FnDef(..) => {
@@ -250,10 +248,9 @@
     }
 }
 
-fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                               start_id: ast::NodeId,
-                               start_span: Span) {
-    let start_def_id = tcx.hir().local_def_id(start_id);
+fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_def_id: DefId) {
+    let start_id = tcx.hir().as_local_node_id(start_def_id).unwrap();
+    let start_span = tcx.def_span(start_def_id);
     let start_t = tcx.type_of(start_def_id);
     match start_t.sty {
         ty::FnDef(..) => {
@@ -309,11 +306,10 @@
 }
 
 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
-        match entry_type {
-            config::EntryFnType::Main => check_main_fn_ty(tcx, id, sp),
-            config::EntryFnType::Start => check_start_fn_ty(tcx, id, sp),
-        }
+    match tcx.entry_fn(LOCAL_CRATE) {
+        Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
+        Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
+        _ => {}
     }
 }
 
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index d991368..635d071 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -68,6 +68,9 @@
     pub should_test: bool,
     /// List of arguments to pass to the test harness, if running tests.
     pub test_args: Vec<String>,
+    /// Optional path to persist the doctest executables to, defaults to a
+    /// temporary directory if not set.
+    pub persist_doctests: Option<PathBuf>,
 
     // Options that affect the documentation process
 
@@ -121,6 +124,7 @@
             .field("lint_cap", &self.lint_cap)
             .field("should_test", &self.should_test)
             .field("test_args", &self.test_args)
+            .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
             .field("manual_passes", &self.manual_passes)
             .field("display_warnings", &self.display_warnings)
@@ -431,6 +435,7 @@
         let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
         let static_root_path = matches.opt_str("static-root-path");
         let generate_search_filter = !matches.opt_present("disable-per-crate-search");
+        let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
 
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -456,6 +461,7 @@
             manual_passes,
             display_warnings,
             crate_version,
+            persist_doctests,
             render_options: RenderOptions {
                 output,
                 external_html,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 78dbf41..7069f04 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -51,9 +51,6 @@
     /// The stack of module NodeIds up till this point
     pub crate_name: Option<String>,
     pub cstore: Rc<CStore>,
-    // 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
-    // the access levels from crateanalysis.
     /// Later on moved into `html::render::CACHE_KEY`
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
@@ -468,15 +465,13 @@
             freevars: resolver.freevars.clone(),
             export_map: resolver.export_map.clone(),
             trait_map: resolver.trait_map.clone(),
+            glob_map: resolver.glob_map.clone(),
             maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
             maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
             extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
                 (ident.name, entry.introduced_by_item)
             }).collect(),
         };
-        let analysis = ty::CrateAnalysis {
-            glob_map: resolver.glob_map.clone(),
-        };
 
         let mut arenas = AllArenas::new();
         let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
@@ -492,12 +487,11 @@
                                                         &sess,
                                                         &*cstore,
                                                         hir_map,
-                                                        analysis,
                                                         resolutions,
                                                         &mut arenas,
                                                         &name,
                                                         &output_filenames,
-                                                        |tcx, _, _, result| {
+                                                        |tcx, _, result| {
             if result.is_err() {
                 sess.fatal("Compilation failed, aborting rustdoc");
             }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 87e979b..e43251b 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -25,40 +25,51 @@
     tooltip: Option<(&str, &str)>,
 ) -> String {
     debug!("highlighting: ================\n{}\n==============", src);
-    let sess = parse::ParseSess::new(FilePathMapping::empty());
-    let fm = sess.source_map().new_source_file(FileName::Custom("stdin".to_string()),
-                                               src.to_string());
-
     let mut out = Vec::new();
     if let Some((tooltip, class)) = tooltip {
         write!(out, "<div class='information'><div class='tooltip {}'>ⓘ<span \
                      class='tooltiptext'>{}</span></div></div>",
                class, tooltip).unwrap();
     }
-    write_header(class, &mut out).unwrap();
 
-    let lexer = match lexer::StringReader::new_without_err(&sess, fm, None, "Output from rustc:") {
-        Ok(l) => l,
-        Err(_) => {
-            let first_line = src.lines().next().unwrap_or_else(|| "");
-            let mut err = sess.span_diagnostic
-                              .struct_warn(&format!("Invalid doc comment starting with: `{}`\n\
-                                                     (Ignoring this codeblock)",
-                                                    first_line));
-            err.emit();
-            return String::new();
+    let sess = parse::ParseSess::new(FilePathMapping::empty());
+    let fm = sess.source_map().new_source_file(
+        FileName::Custom(String::from("rustdoc-highlighting")),
+        src.to_owned(),
+    );
+    let highlight_result =
+        lexer::StringReader::new_or_buffered_errs(&sess, fm, None).and_then(|lexer| {
+            let mut classifier = Classifier::new(lexer, sess.source_map());
+
+            let mut highlighted_source = vec![];
+            if classifier.write_source(&mut highlighted_source).is_err() {
+                Err(classifier.lexer.buffer_fatal_errors())
+            } else {
+                Ok(String::from_utf8_lossy(&highlighted_source).into_owned())
+            }
+        });
+
+    match highlight_result {
+        Ok(highlighted_source) => {
+            write_header(class, &mut out).unwrap();
+            write!(out, "{}", highlighted_source).unwrap();
+            if let Some(extension) = extension {
+                write!(out, "{}", extension).unwrap();
+            }
+            write_footer(&mut out).unwrap();
         }
-    };
-    let mut classifier = Classifier::new(lexer, sess.source_map());
-    if classifier.write_source(&mut out).is_err() {
-        classifier.lexer.emit_fatal_errors();
-        return format!("<pre>{}</pre>", src);
+        Err(errors) => {
+            // If errors are encountered while trying to highlight, cancel the errors and just emit
+            // the unhighlighted source. The errors will have already been reported in the
+            // `check-code-block-syntax` pass.
+            for mut error in errors {
+                error.cancel();
+            }
+
+            write!(out, "<pre><code>{}</code></pre>", src).unwrap();
+        }
     }
 
-    if let Some(extension) = extension {
-        write!(out, "{}", extension).unwrap();
-    }
-    write_footer(&mut out).unwrap();
     String::from_utf8_lossy(&out[..]).into_owned()
 }
 
@@ -151,6 +162,17 @@
     }
 }
 
+enum HighlightError {
+    LexError,
+    IoError(io::Error),
+}
+
+impl From<io::Error> for HighlightError {
+    fn from(err: io::Error) -> Self {
+        HighlightError::IoError(err)
+    }
+}
+
 impl<'a> Classifier<'a> {
     fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<'a> {
         Classifier {
@@ -162,17 +184,11 @@
         }
     }
 
-    /// Gets the next token out of the lexer, emitting fatal errors if lexing fails.
-    fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
+    /// Gets the next token out of the lexer.
+    fn try_next_token(&mut self) -> Result<TokenAndSpan, HighlightError> {
         match self.lexer.try_next_token() {
             Ok(tas) => Ok(tas),
-            Err(_) => {
-                let mut err = self.lexer.sess.span_diagnostic
-                                  .struct_warn("Backing out of syntax highlighting");
-                err.note("You probably did not intend to render this as a rust code-block");
-                err.emit();
-                Err(io::Error::new(io::ErrorKind::Other, ""))
-            }
+            Err(_) => Err(HighlightError::LexError),
         }
     }
 
@@ -185,7 +201,7 @@
     /// source.
     fn write_source<W: Writer>(&mut self,
                                    out: &mut W)
-                                   -> io::Result<()> {
+                                   -> Result<(), HighlightError> {
         loop {
             let next = self.try_next_token()?;
             if next.tok == token::Eof {
@@ -202,7 +218,7 @@
     fn write_token<W: Writer>(&mut self,
                               out: &mut W,
                               tas: TokenAndSpan)
-                              -> io::Result<()> {
+                              -> Result<(), HighlightError> {
         let klass = match tas.tok {
             token::Shebang(s) => {
                 out.string(Escape(&s.as_str()), Class::None)?;
@@ -296,7 +312,7 @@
             token::Literal(lit, _suf) => {
                 match lit {
                     // Text literals.
-                    token::Byte(..) | token::Char(..) |
+                    token::Byte(..) | token::Char(..) | token::Err(..) |
                         token::ByteStr(..) | token::ByteStrRaw(..) |
                         token::Str_(..) | token::StrRaw(..) => Class::String,
 
@@ -341,7 +357,9 @@
 
         // Anything that didn't return above is the simple case where we the
         // class just spans a single token, so we can use the `string` method.
-        out.string(Escape(&self.snip(tas.sp)), klass)
+        out.string(Escape(&self.snip(tas.sp)), klass)?;
+
+        Ok(())
     }
 
     // Helper function to get a snippet from the source_map.
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 05a9a2d..6b7f540 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -919,6 +919,115 @@
     links
 }
 
+#[derive(Debug)]
+crate struct RustCodeBlock {
+    /// The range in the markdown that the code block occupies. Note that this includes the fences
+    /// for fenced code blocks.
+    pub range: Range<usize>,
+    /// The range in the markdown that the code within the code block occupies.
+    pub code: Range<usize>,
+    pub is_fenced: bool,
+    pub syntax: Option<String>,
+}
+
+/// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
+/// untagged (and assumed to be rust).
+crate fn rust_code_blocks(md: &str) -> Vec<RustCodeBlock> {
+    let mut code_blocks = vec![];
+
+    if md.is_empty() {
+        return code_blocks;
+    }
+
+    let mut opts = Options::empty();
+    opts.insert(OPTION_ENABLE_TABLES);
+    opts.insert(OPTION_ENABLE_FOOTNOTES);
+    let mut p = Parser::new_ext(md, opts);
+
+    let mut code_block_start = 0;
+    let mut code_start = 0;
+    let mut is_fenced = false;
+    let mut previous_offset = 0;
+    let mut in_rust_code_block = false;
+    while let Some(event) = p.next() {
+        let offset = p.get_offset();
+
+        match event {
+            Event::Start(Tag::CodeBlock(syntax)) => {
+                let lang_string = if syntax.is_empty() {
+                    LangString::all_false()
+                } else {
+                    LangString::parse(&*syntax, ErrorCodes::Yes)
+                };
+
+                if lang_string.rust {
+                    in_rust_code_block = true;
+
+                    code_start = offset;
+                    code_block_start = match md[previous_offset..offset].find("```") {
+                        Some(fence_idx) => {
+                            is_fenced = true;
+                            previous_offset + fence_idx
+                        }
+                        None => offset,
+                    };
+                }
+            }
+            Event::End(Tag::CodeBlock(syntax)) if in_rust_code_block => {
+                in_rust_code_block = false;
+
+                let code_block_end = if is_fenced {
+                    let fence_str = &md[previous_offset..offset]
+                        .chars()
+                        .rev()
+                        .collect::<String>();
+                    fence_str
+                        .find("```")
+                        .map(|fence_idx| offset - fence_idx)
+                        .unwrap_or_else(|| offset)
+                } else if md
+                    .as_bytes()
+                    .get(offset)
+                    .map(|b| *b == b'\n')
+                    .unwrap_or_default()
+                {
+                    offset - 1
+                } else {
+                    offset
+                };
+
+                let code_end = if is_fenced {
+                    previous_offset
+                } else {
+                    code_block_end
+                };
+
+                code_blocks.push(RustCodeBlock {
+                    is_fenced,
+                    range: Range {
+                        start: code_block_start,
+                        end: code_block_end,
+                    },
+                    code: Range {
+                        start: code_start,
+                        end: code_end,
+                    },
+                    syntax: if !syntax.is_empty() {
+                        Some(syntax.into_owned())
+                    } else {
+                        None
+                    },
+                });
+            }
+            _ => (),
+        }
+
+        previous_offset = offset;
+    }
+
+    code_blocks
+}
+
 #[derive(Clone, Default, Debug)]
 pub struct IdMap {
     map: FxHashMap<String, usize>,
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 3a64c56..ad1659b 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -309,7 +309,7 @@
 
     // 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
-    // the access levels from crateanalysis.
+    // the access levels from the privacy check pass.
     pub access_levels: AccessLevels<DefId>,
 
     /// The version of the crate being documented, if given from the `--crate-version` flag.
@@ -1076,7 +1076,7 @@
         all_sources.sort();
         let mut w = try_err!(File::create(&dst), &dst);
         try_err!(writeln!(&mut w,
-                          "var N = null;var sourcesIndex = {{}};\n{}",
+                          "var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();",
                           all_sources.join("\n")),
                  &dst);
     }
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 8a8b7ad..3676549 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -391,10 +391,6 @@
 	display: block;
 }
 
-.in-band, code {
-	z-index: -5;
-}
-
 .invisible {
 	width: 100%;
 	display: inline-block;
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
index 0affe1c..c5d6fa1 100644
--- a/src/librustdoc/html/static/source-script.js
+++ b/src/librustdoc/html/static/source-script.js
@@ -137,5 +137,3 @@
 
     main.insertBefore(sidebar, main.firstChild);
 }
-
-createSourceSidebar();
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 1390be7..52a3096 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -82,12 +82,6 @@
 	border-bottom-color: #ddd;
 }
 
-:target { background: #494a3d; }
-
-:target > .in-band {
-	background: #494a3d;
-}
-
 .content .method .where,
 .content .fn .where,
 .content .where.fmt-newline {
@@ -252,7 +246,7 @@
 	color: #999;
 }
 
-:target > code {
+:target > code, :target > .in-band {
 	background-color: #494a3d;
 }
 
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 2b04dd2..d20fea6 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -84,12 +84,6 @@
 	border-bottom-color: #ddd;
 }
 
-:target { background: #FDFFD3; }
-
-:target > .in-band {
-	background: #FDFFD3;
-}
-
 .content .method .where,
 .content .fn .where,
 .content .where.fmt-newline {
@@ -247,7 +241,7 @@
 	color: #999;
 }
 
-:target > code {
+:target > code, :target > .in-band {
 	background: #FDFFD3;
 }
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 1b6d7e8..f4149b5 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -3,6 +3,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
 
+#![feature(bind_by_move_pattern_guards)]
 #![feature(rustc_private)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -341,6 +342,12 @@
                       "disable-per-crate-search",
                       "disables generating the crate selector on the search box")
         }),
+        unstable("persist-doctests", |o| {
+             o.optopt("",
+                       "persist-doctests",
+                       "Directory to persist doctest executables into",
+                       "PATH")
+        }),
     ]
 }
 
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index da56194..65a96e9 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -142,7 +142,7 @@
                                        options.libs, options.codegen_options, options.externs,
                                        true, opts, options.maybe_sysroot, None,
                                        Some(options.input),
-                                       options.linker, options.edition);
+                                       options.linker, options.edition, options.persist_doctests);
     collector.set_position(DUMMY_SP);
     let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
     let res = find_testable_code(&input_str, &mut collector, codes);
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
new file mode 100644
index 0000000..a013cc3
--- /dev/null
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -0,0 +1,109 @@
+use errors::Applicability;
+use syntax::parse::lexer::{TokenAndSpan, StringReader as Lexer};
+use syntax::parse::{ParseSess, token};
+use syntax::source_map::FilePathMapping;
+use syntax_pos::FileName;
+
+use clean;
+use core::DocContext;
+use fold::DocFolder;
+use html::markdown::{self, RustCodeBlock};
+use passes::Pass;
+
+pub const CHECK_CODE_BLOCK_SYNTAX: Pass =
+    Pass::early("check-code-block-syntax", check_code_block_syntax,
+                "validates syntax inside Rust code blocks");
+
+pub fn check_code_block_syntax(krate: clean::Crate, cx: &DocContext) -> clean::Crate {
+    SyntaxChecker { cx }.fold_crate(krate)
+}
+
+struct SyntaxChecker<'a, 'tcx: 'a, 'rcx: 'a> {
+    cx: &'a DocContext<'a, 'tcx, 'rcx>,
+}
+
+impl<'a, 'tcx, 'rcx> SyntaxChecker<'a, 'tcx, 'rcx> {
+    fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) {
+        let sess = ParseSess::new(FilePathMapping::empty());
+        let source_file = sess.source_map().new_source_file(
+            FileName::Custom(String::from("doctest")),
+            dox[code_block.code].to_owned(),
+        );
+
+        let errors = Lexer::new_or_buffered_errs(&sess, source_file, None).and_then(|mut lexer| {
+            while let Ok(TokenAndSpan { tok, .. }) = lexer.try_next_token() {
+                if tok == token::Eof {
+                    break;
+                }
+            }
+
+            let errors = lexer.buffer_fatal_errors();
+
+            if !errors.is_empty() {
+                Err(errors)
+            } else {
+                Ok(())
+            }
+        });
+
+        if let Err(errors) = errors {
+            let mut diag = if let Some(sp) =
+                super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
+            {
+                let mut diag = self
+                    .cx
+                    .sess()
+                    .struct_span_warn(sp, "could not parse code block as Rust code");
+
+                for mut err in errors {
+                    diag.note(&format!("error from rustc: {}", err.message()));
+                    err.cancel();
+                }
+
+                if code_block.syntax.is_none() && code_block.is_fenced {
+                    let sp = sp.from_inner_byte_pos(0, 3);
+                    diag.span_suggestion_with_applicability(
+                        sp,
+                        "mark blocks that do not contain Rust code as text",
+                        String::from("```text"),
+                        Applicability::MachineApplicable,
+                    );
+                }
+
+                diag
+            } else {
+                // We couldn't calculate the span of the markdown block that had the error, so our
+                // diagnostics are going to be a bit lacking.
+                let mut diag = self.cx.sess().struct_span_warn(
+                    super::span_of_attrs(&item.attrs),
+                    "doc comment contains an invalid Rust code block",
+                );
+
+                for mut err in errors {
+                    // Don't bother reporting the error, because we can't show where it happened.
+                    err.cancel();
+                }
+
+                if code_block.syntax.is_none() && code_block.is_fenced {
+                    diag.help("mark blocks that do not contain Rust code as text: ```text");
+                }
+
+                diag
+            };
+
+            diag.emit();
+        }
+    }
+}
+
+impl<'a, 'tcx, 'rcx> DocFolder for SyntaxChecker<'a, 'tcx, 'rcx> {
+    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+        if let Some(dox) = &item.attrs.collapsed_doc_value() {
+            for code_block in markdown::rust_code_blocks(&dox) {
+                self.check_rust_syntax(&item, &dox, code_block);
+            }
+        }
+
+        self.fold_item_recur(item)
+    }
+}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index fdc1c06..3d6096b 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -6,7 +6,7 @@
 use syntax::ast::{self, Ident, NodeId};
 use syntax::feature_gate::UnstableFeatures;
 use syntax::symbol::Symbol;
-use syntax_pos::{self, DUMMY_SP};
+use syntax_pos::DUMMY_SP;
 
 use std::ops::Range;
 
@@ -16,6 +16,7 @@
 
 use clean::*;
 use passes::{look_for_tests, Pass};
+use super::span_of_attrs;
 
 pub const COLLECT_INTRA_DOC_LINKS: Pass =
     Pass::early("collect-intra-doc-links", collect_intra_doc_links,
@@ -440,28 +441,11 @@
     None
 }
 
-pub fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
-    if attrs.doc_strings.is_empty() {
-        return DUMMY_SP;
-    }
-    let start = attrs.doc_strings[0].span();
-    let end = attrs.doc_strings.last().expect("No doc strings provided").span();
-    start.to(end)
-}
-
 /// Reports a resolution failure diagnostic.
 ///
-/// Ideally we can report the diagnostic with the actual span in the source where the link failure
-/// occurred. However, there's a mismatch between the span in the source code and the span in the
-/// markdown, so we have to do a bit of work to figure out the correspondence.
-///
-/// It's not too hard to find the span for sugared doc comments (`///` and `/**`), because the
-/// source will match the markdown exactly, excluding the comment markers. However, it's much more
-/// difficult to calculate the spans for unsugared docs, because we have to deal with escaping and
-/// other source features. So, we attempt to find the exact source span of the resolution failure
-/// in sugared docs, but use the span of the documentation attributes themselves for unsugared
-/// docs. Because this span might be overly large, we display the markdown line containing the
-/// failure as a note.
+/// If we cannot find the exact source span of the resolution failure, we use the span of the
+/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
+/// line containing the failure as a note as well.
 fn resolution_failure(
     cx: &DocContext,
     attrs: &Attributes,
@@ -473,54 +457,7 @@
     let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
 
     let mut diag = if let Some(link_range) = link_range {
-        let src = cx.sess().source_map().span_to_snippet(sp);
-        let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
-            DocFragment::SugaredDoc(..) => true,
-            _ => false,
-        });
-
-        if let (Ok(src), true) = (src, is_all_sugared_doc) {
-            // The number of markdown lines up to and including the resolution failure.
-            let num_lines = dox[..link_range.start].lines().count();
-
-            // We use `split_terminator('\n')` instead of `lines()` when counting bytes to ensure
-            // that DOS-style line endings do not cause the spans to be calculated incorrectly.
-            let mut src_lines = src.split_terminator('\n');
-            let mut md_lines = dox.split_terminator('\n').take(num_lines).peekable();
-
-            // The number of bytes from the start of the source span to the resolution failure that
-            // are *not* part of the markdown, like comment markers.
-            let mut extra_src_bytes = 0;
-
-            while let Some(md_line) = md_lines.next() {
-                loop {
-                    let source_line = src_lines
-                        .next()
-                        .expect("could not find markdown line in source");
-
-                    match source_line.find(md_line) {
-                        Some(offset) => {
-                            extra_src_bytes += if md_lines.peek().is_some() {
-                                source_line.len() - md_line.len()
-                            } else {
-                                offset
-                            };
-                            break;
-                        }
-                        None => {
-                            // Since this is a source line that doesn't include a markdown line,
-                            // we have to count the newline that we split from earlier.
-                            extra_src_bytes += source_line.len() + 1;
-                        }
-                    }
-                }
-            }
-
-            let sp = sp.from_inner_byte_pos(
-                link_range.start + extra_src_bytes,
-                link_range.end + extra_src_bytes,
-            );
-
+        if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) {
             let mut diag = cx.tcx.struct_span_lint_node(
                 lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
                 NodeId::from_u32(0),
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index e897b9a..c9a3a2c 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -8,6 +8,8 @@
 use std::mem;
 use std::fmt;
 use syntax::ast::NodeId;
+use syntax_pos::{DUMMY_SP, Span};
+use std::ops::Range;
 
 use clean::{self, GetDefId, Item};
 use core::{DocContext, DocAccessLevels};
@@ -16,8 +18,6 @@
 
 use html::markdown::{find_testable_code, ErrorCodes, LangString};
 
-use self::collect_intra_doc_links::span_of_attrs;
-
 mod collapse_docs;
 pub use self::collapse_docs::COLLAPSE_DOCS;
 
@@ -45,6 +45,9 @@
 mod collect_trait_impls;
 pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
 
+mod check_code_block_syntax;
+pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;
+
 /// Represents a single pass.
 #[derive(Copy, Clone)]
 pub enum Pass {
@@ -135,6 +138,7 @@
     STRIP_PRIV_IMPORTS,
     PROPAGATE_DOC_CFG,
     COLLECT_INTRA_DOC_LINKS,
+    CHECK_CODE_BLOCK_SYNTAX,
     COLLECT_TRAIT_IMPLS,
 ];
 
@@ -145,6 +149,7 @@
     "strip-hidden",
     "strip-private",
     "collect-intra-doc-links",
+    "check-code-block-syntax",
     "collapse-docs",
     "unindent-comments",
     "propagate-doc-cfg",
@@ -156,6 +161,7 @@
     "check-private-items-doc-tests",
     "strip-priv-imports",
     "collect-intra-doc-links",
+    "check-code-block-syntax",
     "collapse-docs",
     "unindent-comments",
     "propagate-doc-cfg",
@@ -396,3 +402,94 @@
         }
     }
 }
+
+/// Return a span encompassing all the given attributes.
+crate fn span_of_attrs(attrs: &clean::Attributes) -> Span {
+    if attrs.doc_strings.is_empty() {
+        return DUMMY_SP;
+    }
+    let start = attrs.doc_strings[0].span();
+    let end = attrs.doc_strings.last().expect("No doc strings provided").span();
+    start.to(end)
+}
+
+/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
+///
+/// This method will return `None` if we cannot construct a span from the source map or if the
+/// attributes are not all sugared doc comments. It's difficult to calculate the correct span in
+/// that case due to escaping and other source features.
+crate fn source_span_for_markdown_range(
+    cx: &DocContext,
+    markdown: &str,
+    md_range: &Range<usize>,
+    attrs: &clean::Attributes,
+) -> Option<Span> {
+    let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
+        clean::DocFragment::SugaredDoc(..) => true,
+        _ => false,
+    });
+
+    if !is_all_sugared_doc {
+        return None;
+    }
+
+    let snippet = cx
+        .sess()
+        .source_map()
+        .span_to_snippet(span_of_attrs(attrs))
+        .ok()?;
+
+    let starting_line = markdown[..md_range.start].lines().count() - 1;
+    let ending_line = markdown[..md_range.end].lines().count() - 1;
+
+    // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we only
+    // we can treat CRLF and LF line endings the same way.
+    let mut src_lines = snippet.split_terminator('\n');
+    let md_lines = markdown.split_terminator('\n');
+
+    // The number of bytes from the source span to the markdown span that are not part
+    // of the markdown, like comment markers.
+    let mut start_bytes = 0;
+    let mut end_bytes = 0;
+
+    'outer: for (line_no, md_line) in md_lines.enumerate() {
+        loop {
+            let source_line = src_lines.next().expect("could not find markdown in source");
+            match source_line.find(md_line) {
+                Some(offset) => {
+                    if line_no == starting_line {
+                        start_bytes += offset;
+
+                        if starting_line == ending_line {
+                            break 'outer;
+                        }
+                    } else if line_no == ending_line {
+                        end_bytes += offset;
+                        break 'outer;
+                    } else if line_no < starting_line {
+                        start_bytes += source_line.len() - md_line.len();
+                    } else {
+                        end_bytes += source_line.len() - md_line.len();
+                    }
+                    break;
+                }
+                None => {
+                    // Since this is a source line that doesn't include a markdown line,
+                    // we have to count the newline that we split from earlier.
+                    if line_no <= starting_line {
+                        start_bytes += source_line.len() + 1;
+                    } else {
+                        end_bytes += source_line.len() + 1;
+                    }
+                }
+            }
+        }
+    }
+
+    let sp = span_of_attrs(attrs).from_inner_byte_pos(
+        md_range.start + start_bytes,
+        md_range.end + start_bytes + end_bytes,
+    );
+
+    Some(sp)
+}
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index af47c7d..0b9fbc8 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -120,7 +120,8 @@
             Some(source_map),
             None,
             options.linker,
-            options.edition
+            options.edition,
+            options.persist_doctests,
         );
 
         {
@@ -184,7 +185,8 @@
             cg: CodegenOptions, externs: Externs,
             should_panic: bool, no_run: bool, as_test_harness: bool,
             compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
-            maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition) {
+            maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
+            persist_doctests: Option<PathBuf>) {
     // The test harness wants its own `main` and top-level functions, so
     // never wrap the test in `fn main() { ... }`.
     let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts);
@@ -249,6 +251,20 @@
     let old = io::set_panic(Some(box Sink(data.clone())));
     let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
 
+    enum DirState {
+        Temp(tempfile::TempDir),
+        Perm(PathBuf),
+    }
+
+    impl DirState {
+        fn path(&self) -> &std::path::Path {
+            match self {
+                DirState::Temp(t) => t.path(),
+                DirState::Perm(p) => p.as_path(),
+            }
+        }
+    }
+
     let (libdir, outdir, compile_result) = driver::spawn_thread_pool(sessopts, |sessopts| {
         let source_map = Lrc::new(SourceMap::new(sessopts.file_path_mapping()));
         let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
@@ -267,7 +283,26 @@
         rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
         let outdir = Mutex::new(
-            TempFileBuilder::new().prefix("rustdoctest").tempdir().expect("rustdoc needs a tempdir")
+            if let Some(mut path) = persist_doctests {
+                path.push(format!("{}_{}",
+                    filename
+                        .to_string()
+                        .rsplit('/')
+                        .next()
+                        .unwrap()
+                        .replace(".", "_"),
+                        line)
+                );
+                std::fs::create_dir_all(&path)
+                    .expect("Couldn't create directory for doctest executables");
+
+                DirState::Perm(path)
+            } else {
+                DirState::Temp(TempFileBuilder::new()
+                                .prefix("rustdoctest")
+                                .tempdir()
+                                .expect("rustdoc needs a tempdir"))
+            }
         );
         let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
         let mut control = driver::CompileController::basic();
@@ -629,13 +664,15 @@
     filename: Option<PathBuf>,
     linker: Option<PathBuf>,
     edition: Edition,
+    persist_doctests: Option<PathBuf>,
 }
 
 impl Collector {
     pub fn new(cratename: String, cfgs: Vec<String>, libs: Vec<SearchPath>, cg: CodegenOptions,
                externs: Externs, use_headers: bool, opts: TestOptions,
                maybe_sysroot: Option<PathBuf>, source_map: Option<Lrc<SourceMap>>,
-               filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition) -> Collector {
+               filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
+               persist_doctests: Option<PathBuf>) -> Collector {
         Collector {
             tests: Vec::new(),
             names: Vec::new(),
@@ -652,6 +689,7 @@
             filename,
             linker,
             edition,
+            persist_doctests,
         }
     }
 
@@ -695,6 +733,8 @@
         let maybe_sysroot = self.maybe_sysroot.clone();
         let linker = self.linker.clone();
         let edition = config.edition.unwrap_or(self.edition);
+        let persist_doctests = self.persist_doctests.clone();
+
         debug!("Creating test {}: {}", name, test);
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
@@ -727,7 +767,8 @@
                                  &opts,
                                  maybe_sysroot,
                                  linker,
-                                 edition)
+                                 edition,
+                                 persist_doctests)
                     }))
                 } {
                     Ok(()) => (),
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index 62081e7..7a38f0e 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -169,7 +169,7 @@
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
-           issue = "27745")]
+           issue = "44930")]
 pub use core::ffi::VaList;
 
 mod c_str;
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 119b3f7..3538816 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1121,7 +1121,9 @@
     /// writing.
     ///
     /// This operation does **not** modify the filesystem. To modify the
-    /// filesystem use the `fs::set_permissions` function.
+    /// filesystem use the [`fs::set_permissions`] function.
+    ///
+    /// [`fs::set_permissions`]: fn.set_permissions.html
     ///
     /// # Examples
     ///
@@ -1639,10 +1641,15 @@
 ///
 /// The `dst` path will be a symbolic link pointing to the `src` path.
 /// On Windows, this will be a file symlink, not a directory symlink;
-/// for this reason, the platform-specific `std::os::unix::fs::symlink`
-/// and `std::os::windows::fs::{symlink_file, symlink_dir}` should be
+/// for this reason, the platform-specific [`std::os::unix::fs::symlink`]
+/// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be
 /// used instead to make the intent explicit.
 ///
+/// [`std::os::unix::fs::symlink`]: ../os/unix/fs/fn.symlink.html
+/// [`std::os::windows::fs::symlink_file`]: ../os/windows/fs/fn.symlink_file.html
+/// [`symlink_dir`]: ../os/windows/fs/fn.symlink_dir.html
+///
+///
 /// # Examples
 ///
 /// ```no_run
@@ -1795,7 +1802,7 @@
 /// * If any directory in the path specified by `path`
 /// does not already exist and it could not be created otherwise. The specific
 /// error conditions for when a directory is being created (after it is
-/// determined to not exist) are outlined by `fs::create_dir`.
+/// determined to not exist) are outlined by [`fs::create_dir`].
 ///
 /// Notable exception is made for situations where any of the directories
 /// specified in the `path` could not be created as it was being created concurrently.
@@ -1803,6 +1810,8 @@
 /// concurrently from multiple threads or processes is guaranteed not to fail
 /// due to a race condition with itself.
 ///
+/// [`fs::create_dir`]: fn.create_dir.html
+///
 /// # Examples
 ///
 /// ```no_run
@@ -1868,7 +1877,10 @@
 ///
 /// # Errors
 ///
-/// See `file::remove_file` and `fs::remove_dir`.
+/// See [`fs::remove_file`] and [`fs::remove_dir`].
+///
+/// [`fs::remove_file`]:  fn.remove_file.html
+/// [`fs::remove_dir`]: fn.remove_dir.html
 ///
 /// # Examples
 ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 41f1ac8..83db3f3 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -286,6 +286,7 @@
 #![feature(staged_api)]
 #![feature(stmt_expr_attributes)]
 #![feature(str_internals)]
+#![feature(renamed_spin_loop)]
 #![feature(rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs
index ec8318f..bf689ba 100644
--- a/src/libstd/prelude/mod.rs
+++ b/src/libstd/prelude/mod.rs
@@ -44,8 +44,8 @@
 //! The current version of the prelude (version 1) lives in
 //! [`std::prelude::v1`], and re-exports the following.
 //!
-//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
-//!   traits indicate fundamental properties of types.
+//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
+//!   marker traits indicate fundamental properties of types.
 //! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
 //!   operations for both destructors and overloading `()`.
 //! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
@@ -108,6 +108,7 @@
 //! [`Sync`]: ../marker/trait.Sync.html
 //! [`ToOwned`]: ../borrow/trait.ToOwned.html
 //! [`ToString`]: ../string/trait.ToString.html
+//! [`Unpin`]: ../marker/trait.Unpin.html
 //! [`Vec`]: ../vec/struct.Vec.html
 //! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
 //! [`mem::drop`]: ../mem/fn.drop.html
diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index d48d701d..742ffd1 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -33,30 +33,57 @@
     register_dtor_fallback(t, dtor);
 }
 
-// macOS's analog of the above linux function is this _tlv_atexit function.
-// The disassembly of thread_local globals in C++ (at least produced by
-// clang) will have this show up in the output.
+// This implementation is very similar to register_dtor_fallback in
+// sys_common/thread_local.rs. The main difference is that we want to hook into
+// macOS's analog of the above linux function, _tlv_atexit. OSX will run the
+// registered dtors before any TLS slots get freed, and when the main thread
+// exits.
+//
+// Unfortunately, calling _tlv_atexit while tls dtors are running is UB. The
+// workaround below is to register, via _tlv_atexit, a custom DTOR list once per
+// thread. thread_local dtors are pushed to the DTOR list without calling
+// _tlv_atexit.
 #[cfg(target_os = "macos")]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+    use cell::Cell;
+    use ptr;
+
+    #[thread_local]
+    static REGISTERED: Cell<bool> = Cell::new(false);
+    if !REGISTERED.get() {
+        _tlv_atexit(run_dtors, ptr::null_mut());
+        REGISTERED.set(true);
+    }
+
+    type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
+
+    #[thread_local]
+    static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
+    if DTORS.get().is_null() {
+        let v: Box<List> = box Vec::new();
+        DTORS.set(Box::into_raw(v));
+    }
+
     extern {
         fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
                        arg: *mut u8);
     }
-    _tlv_atexit(dtor, t);
+
+    let list: &mut List = &mut *DTORS.get();
+    list.push((t, dtor));
+
+    unsafe extern fn run_dtors(_: *mut u8) {
+        let mut ptr = DTORS.replace(ptr::null_mut());
+        while !ptr.is_null() {
+            let list = Box::from_raw(ptr);
+            for (ptr, dtor) in list.into_iter() {
+                dtor(ptr);
+            }
+            ptr = DTORS.replace(ptr::null_mut());
+        }
+    }
 }
 
 pub fn requires_move_before_drop() -> bool {
-    // The macOS implementation of TLS apparently had an odd aspect to it
-    // where the pointer we have may be overwritten while this destructor
-    // is running. Specifically if a TLS destructor re-accesses TLS it may
-    // trigger a re-initialization of all TLS variables, paving over at
-    // least some destroyed ones with initial values.
-    //
-    // This means that if we drop a TLS value in place on macOS that we could
-    // revert the value to its original state halfway through the
-    // destructor, which would be bad!
-    //
-    // Hence, we use `ptr::read` on macOS (to move to a "safe" location)
-    // instead of drop_in_place.
-    cfg!(target_os = "macos")
+    false
 }
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index efd231e..5d2eb5f 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -69,9 +69,6 @@
 ///    destroyed, but not all platforms have this guard. Those platforms that do
 ///    not guard typically have a synthetic limit after which point no more
 ///    destructors are run.
-/// 3. On macOS, initializing TLS during destruction of other TLS slots can
-///    sometimes cancel *all* destructors for the current thread, whether or not
-///    the slots have already had their destructors run or not.
 ///
 /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
 /// [`thread_local!`]: ../../std/macro.thread_local.html
@@ -604,11 +601,8 @@
     }
 
     // Note that this test will deadlock if TLS destructors aren't run (this
-    // requires the destructor to be run to pass the test). macOS has a known bug
-    // where dtors-in-dtors may cancel other destructors, so we just ignore this
-    // test on macOS.
+    // requires the destructor to be run to pass the test).
     #[test]
-    #[cfg_attr(target_os = "macos", ignore)]
     fn dtors_in_dtors_in_dtors() {
         struct S1(Sender<()>);
         thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 99ab9fb..f411e40 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -15,7 +15,7 @@
 use source_map::{dummy_spanned, respan, Spanned};
 use symbol::{keywords, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
-use tokenstream::{ThinTokenStream, TokenStream};
+use tokenstream::TokenStream;
 use ThinVec;
 
 use rustc_data_structures::fx::FxHashSet;
@@ -1216,7 +1216,7 @@
 pub struct Mac_ {
     pub path: Path,
     pub delim: MacDelimiter,
-    pub tts: ThinTokenStream,
+    pub tts: TokenStream,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
@@ -1228,13 +1228,13 @@
 
 impl Mac_ {
     pub fn stream(&self) -> TokenStream {
-        self.tts.stream()
+        self.tts.clone()
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct MacroDef {
-    pub tokens: ThinTokenStream,
+    pub tokens: TokenStream,
     pub legacy: bool,
 }
 
@@ -1285,6 +1285,8 @@
     FloatUnsuffixed(Symbol),
     /// A boolean literal.
     Bool(bool),
+    /// A recovered character literal that contains mutliple `char`s, most likely a typo.
+    Err(Symbol),
 }
 
 impl LitKind {
@@ -1321,6 +1323,7 @@
             | LitKind::ByteStr(..)
             | LitKind::Byte(..)
             | LitKind::Char(..)
+            | LitKind::Err(..)
             | LitKind::Int(_, LitIntType::Unsuffixed)
             | LitKind::FloatUnsuffixed(..)
             | LitKind::Bool(..) => true,
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index f83c1ec..e5ce6a3 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -570,7 +570,7 @@
             }
             Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => {
                 tokens.next();
-                tts.stream()
+                tts.clone()
             }
             _ => return Some(MetaItemKind::Word),
         };
@@ -666,6 +666,7 @@
             } else {
                 "false"
             })), false),
+            LitKind::Err(val) => Token::Literal(token::Lit::Err(val), None),
         }
     }
 
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index c312414..df3b49c 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -646,6 +646,7 @@
 
         token::Literal(token::Byte(i), suf) => return mk_lit!("Byte", suf, i),
         token::Literal(token::Char(i), suf) => return mk_lit!("Char", suf, i),
+        token::Literal(token::Err(_i), _suf) => return cx.expr(sp, ast::ExprKind::Err),
         token::Literal(token::Integer(i), suf) => return mk_lit!("Integer", suf, i),
         token::Literal(token::Float(i), suf) => return mk_lit!("Float", suf, i),
         token::Literal(token::Str_(i), suf) => return mk_lit!("Str_", suf, i),
@@ -748,7 +749,7 @@
         },
         TokenTree::Delimited(span, delim, ref tts) => {
             let mut stmts = statements_mk_tt(cx, &TokenTree::open_tt(span.open, delim), false);
-            stmts.extend(statements_mk_tts(cx, tts.stream()));
+            stmts.extend(statements_mk_tts(cx, tts.clone()));
             stmts.extend(statements_mk_tt(cx, &TokenTree::close_tt(span.close, delim), false));
             stmts
         }
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 24202ca..9a129e7 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -435,7 +435,8 @@
                     match *seq_tt {
                         TokenTree::MetaVarDecl(_, _, id) => id.name == "vis",
                         TokenTree::Sequence(_, ref sub_seq) =>
-                            sub_seq.op == quoted::KleeneOp::ZeroOrMore,
+                            sub_seq.op == quoted::KleeneOp::ZeroOrMore
+                            || sub_seq.op == quoted::KleeneOp::ZeroOrOne,
                         _ => false,
                     }
                 }) {
@@ -543,7 +544,10 @@
                         }
 
                         // Reverse scan: Sequence comes before `first`.
-                        if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore {
+                        if subfirst.maybe_empty
+                           || seq_rep.op == quoted::KleeneOp::ZeroOrMore
+                           || seq_rep.op == quoted::KleeneOp::ZeroOrOne
+                        {
                             // If sequence is potentially empty, then
                             // union them (preserving first emptiness).
                             first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
@@ -591,8 +595,10 @@
 
                             assert!(first.maybe_empty);
                             first.add_all(subfirst);
-                            if subfirst.maybe_empty ||
-                               seq_rep.op == quoted::KleeneOp::ZeroOrMore {
+                            if subfirst.maybe_empty
+                               || seq_rep.op == quoted::KleeneOp::ZeroOrMore
+                               || seq_rep.op == quoted::KleeneOp::ZeroOrOne
+                            {
                                 // continue scanning for more first
                                 // tokens, but also make sure we
                                 // restore empty-tracking state
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8ac1038..a4c3b38 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -598,7 +598,7 @@
         TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
             DelimSpan::from_pair(fld.new_span(span.open), fld.new_span(span.close)),
             delim,
-            fld.fold_tts(tts.stream()).into(),
+            fld.fold_tts(tts).into(),
         ),
     }
 }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 0e1c3b4..8827e04 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -238,19 +238,6 @@
         sr
     }
 
-    pub fn new_without_err(sess: &'a ParseSess,
-                           source_file: Lrc<syntax_pos::SourceFile>,
-                           override_span: Option<Span>,
-                           prepend_error_text: &str) -> Result<Self, ()> {
-        let mut sr = StringReader::new_raw(sess, source_file, override_span);
-        if sr.advance_token().is_err() {
-            eprintln!("{}", prepend_error_text);
-            sr.emit_fatal_errors();
-            return Err(());
-        }
-        Ok(sr)
-    }
-
     pub fn new_or_buffered_errs(sess: &'a ParseSess,
                                 source_file: Lrc<syntax_pos::SourceFile>,
                                 override_span: Option<Span>) -> Result<Self, Vec<Diagnostic>> {
@@ -1408,9 +1395,10 @@
                     // lifetimes shouldn't end with a single quote
                     // if we find one, then this is an invalid character literal
                     if self.ch_is('\'') {
-                        self.fatal_span_verbose(start_with_quote, self.next_pos,
-                                String::from("character literal may only contain one codepoint"))
-                            .raise();
+                        self.err_span_(start_with_quote, self.next_pos,
+                                "character literal may only contain one codepoint");
+                        self.bump();
+                        return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
 
                     }
 
@@ -1445,7 +1433,7 @@
                                     format!("\"{}\"", &self.src[start..end]),
                                     Applicability::MachineApplicable
                                 ).emit();
-                            return Ok(token::Literal(token::Str_(Symbol::intern("??")), None))
+                            return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
                         }
                         if self.ch_is('\n') || self.is_eof() || self.ch_is('/') {
                             // Only attempt to infer single line string literals. If we encounter
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index ea20553..8d03969 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -466,6 +466,7 @@
     match lit {
        token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))),
        token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))),
+       token::Err(i) => (true, Some(LitKind::Err(i))),
 
         // There are some valid suffixes for integer and float literals,
         // so all the handling is done internally.
@@ -817,7 +818,7 @@
                 )
                 if name_macro_rules.name == "macro_rules"
                 && name_zip.name == "zip" => {
-                    let tts = &macro_tts.stream().trees().collect::<Vec<_>>();
+                    let tts = &macro_tts.trees().collect::<Vec<_>>();
                     match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
                         (
                             3,
@@ -826,7 +827,7 @@
                             Some(&TokenTree::Delimited(_, second_delim, ref second_tts)),
                         )
                         if macro_delim == token::Paren => {
-                            let tts = &first_tts.stream().trees().collect::<Vec<_>>();
+                            let tts = &first_tts.trees().collect::<Vec<_>>();
                             match (tts.len(), tts.get(0), tts.get(1)) {
                                 (
                                     2,
@@ -836,7 +837,7 @@
                                 if first_delim == token::Paren && ident.name == "a" => {},
                                 _ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
                             }
-                            let tts = &second_tts.stream().trees().collect::<Vec<_>>();
+                            let tts = &second_tts.trees().collect::<Vec<_>>();
                             match (tts.len(), tts.get(0), tts.get(1)) {
                                 (
                                     2,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 823c786..7e15b231 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -46,7 +46,7 @@
 use ptr::P;
 use parse::PResult;
 use ThinVec;
-use tokenstream::{self, DelimSpan, ThinTokenStream, TokenTree, TokenStream};
+use tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
 use symbol::{Symbol, keywords};
 
 use std::borrow::Cow;
@@ -280,17 +280,17 @@
 /// on the parser.
 #[derive(Clone)]
 enum LastToken {
-    Collecting(Vec<TokenStream>),
-    Was(Option<TokenStream>),
+    Collecting(Vec<TreeAndJoint>),
+    Was(Option<TreeAndJoint>),
 }
 
 impl TokenCursorFrame {
-    fn new(sp: DelimSpan, delim: DelimToken, tts: &ThinTokenStream) -> Self {
+    fn new(sp: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self {
         TokenCursorFrame {
             delim: delim,
             span: sp,
             open_delim: delim == token::NoDelim,
-            tree_cursor: tts.stream().into_trees(),
+            tree_cursor: tts.clone().into_trees(),
             close_delim: delim == token::NoDelim,
             last_token: LastToken::Was(None),
         }
@@ -2330,7 +2330,7 @@
         })
     }
 
-    fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, ThinTokenStream)> {
+    fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
         let delim = match self.token {
             token::OpenDelim(delim) => delim,
             _ => {
@@ -2350,7 +2350,7 @@
             token::Brace => MacDelimiter::Brace,
             token::NoDelim => self.bug("unexpected no delimiter"),
         };
-        Ok((delim, tts.stream().into()))
+        Ok((delim, tts.into()))
     }
 
     /// At the bottom (top?) of the precedence hierarchy,
@@ -4063,12 +4063,13 @@
 
         if let Some(mut err) = delayed_err {
             if let Some(etc_span) = etc_span {
-                err.multipart_suggestion(
+                err.multipart_suggestion_with_applicability(
                     "move the `..` to the end of the field list",
                     vec![
                         (etc_span, String::new()),
                         (self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
                     ],
+                    Applicability::MachineApplicable,
                 );
             }
             err.emit();
@@ -4641,7 +4642,7 @@
                 let ident = self.parse_ident()?;
                 let tokens = if self.check(&token::OpenDelim(token::Brace)) {
                     match self.parse_token_tree() {
-                        TokenTree::Delimited(_, _, tts) => tts.stream(),
+                        TokenTree::Delimited(_, _, tts) => tts,
                         _ => unreachable!(),
                     }
                 } else if self.check(&token::OpenDelim(token::Paren)) {
@@ -5234,22 +5235,13 @@
                     kind: ast::GenericParamKind::Lifetime,
                 });
                 if let Some(sp) = seen_ty_param {
-                    let param_span = self.prev_span;
-                    let ate_comma = self.eat(&token::Comma);
-                    let remove_sp = if ate_comma {
-                        param_span.until(self.span)
-                    } else {
-                        last_comma_span.unwrap_or(param_span).to(param_span)
-                    };
-                    bad_lifetime_pos.push(param_span);
-
-                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) {
+                    let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span);
+                    bad_lifetime_pos.push(self.prev_span);
+                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) {
                         suggestions.push((remove_sp, String::new()));
-                        suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet)));
-                    }
-                    if ate_comma {
-                        last_comma_span = Some(self.prev_span);
-                        continue
+                        suggestions.push((
+                            sp.shrink_to_lo(),
+                            format!("{}, ", snippet)));
                     }
                 }
             } else if self.check_ident() {
@@ -6913,7 +6905,11 @@
 
             let mut err = self.struct_span_err(fixed_name_sp, error_msg);
             err.span_label(fixed_name_sp, "dash-separated idents are not valid");
-            err.multipart_suggestion(suggestion_msg, replacement);
+            err.multipart_suggestion_with_applicability(
+                suggestion_msg,
+                replacement,
+                Applicability::MachineApplicable,
+            );
             err.emit();
         }
         Ok(ident)
@@ -7766,7 +7762,7 @@
             &mut self.token_cursor.stack[prev].last_token
         };
 
-        // Pull our the toekns that we've collected from the call to `f` above
+        // Pull out the tokens that we've collected from the call to `f` above.
         let mut collected_tokens = match *last_token {
             LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()),
             LastToken::Was(_) => panic!("our vector went away?"),
@@ -7785,10 +7781,9 @@
         // call. In that case we need to record all the tokens we collected in
         // our parent list as well. To do that we push a clone of our stream
         // onto the previous list.
-        let stream = collected_tokens.into_iter().collect::<TokenStream>();
         match prev_collecting {
             Some(mut list) => {
-                list.push(stream.clone());
+                list.extend(collected_tokens.iter().cloned());
                 list.extend(extra_token);
                 *last_token = LastToken::Collecting(list);
             }
@@ -7797,7 +7792,7 @@
             }
         }
 
-        Ok((ret?, stream))
+        Ok((ret?, TokenStream::new(collected_tokens)))
     }
 
     pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 25a4da3..f06e975 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -60,6 +60,7 @@
 pub enum Lit {
     Byte(ast::Name),
     Char(ast::Name),
+    Err(ast::Name),
     Integer(ast::Name),
     Float(ast::Name),
     Str_(ast::Name),
@@ -73,6 +74,7 @@
         match *self {
             Byte(_) => "byte literal",
             Char(_) => "char literal",
+            Err(_) => "invalid literal",
             Integer(_) => "integer literal",
             Float(_) => "float literal",
             Str_(_) | StrRaw(..) => "string literal",
@@ -471,8 +473,7 @@
 
             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot |
             DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
-            Question | OpenDelim(..) | CloseDelim(..) => return None,
-
+            Question | OpenDelim(..) | CloseDelim(..) |
             Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
             Whitespace | Comment | Shebang(..) | Eof => return None,
         })
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 2ad3d3a..7cecf4b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -224,6 +224,7 @@
             let mut out = match lit {
                 token::Byte(b)           => format!("b'{}'", b),
                 token::Char(c)           => format!("'{}'", c),
+                token::Err(c)            => format!("'{}'", c),
                 token::Float(c)          |
                 token::Integer(c)        => c.to_string(),
                 token::Str_(s)           => format!("\"{}\"", s),
@@ -603,6 +604,14 @@
         }
         match lit.node {
             ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
+            ast::LitKind::Err(st) => {
+                let st = st.as_str().escape_debug();
+                let mut res = String::with_capacity(st.len() + 2);
+                res.push('\'');
+                res.push_str(&st);
+                res.push('\'');
+                self.writer().word(res)
+            }
             ast::LitKind::Byte(byte) => {
                 let mut res = String::from("b'");
                 res.extend(ascii::escape_default(byte).map(|c| c as char));
@@ -807,7 +816,7 @@
             TokenTree::Delimited(_, delim, tts) => {
                 self.writer().word(token_to_string(&token::OpenDelim(delim)))?;
                 self.writer().space()?;
-                self.print_tts(tts.stream())?;
+                self.print_tts(tts)?;
                 self.writer().space()?;
                 self.writer().word(token_to_string(&token::CloseDelim(delim)))
             },
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index fb72ef9..f5d2d6f 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -41,7 +41,7 @@
     /// A single token
     Token(Span, token::Token),
     /// A delimited sequence of token trees
-    Delimited(DelimSpan, DelimToken, ThinTokenStream),
+    Delimited(DelimSpan, DelimToken, TokenStream),
 }
 
 impl TokenTree {
@@ -62,8 +62,7 @@
             (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => tk == tk2,
             (&TokenTree::Delimited(_, delim, ref tts),
              &TokenTree::Delimited(_, delim2, ref tts2)) => {
-                delim == delim2 &&
-                tts.stream().eq_unspanned(&tts2.stream())
+                delim == delim2 && tts.eq_unspanned(&tts2)
             }
             (_, _) => false,
         }
@@ -81,8 +80,7 @@
             }
             (&TokenTree::Delimited(_, delim, ref tts),
              &TokenTree::Delimited(_, delim2, ref tts2)) => {
-                delim == delim2 &&
-                tts.stream().probably_equal_for_proc_macro(&tts2.stream())
+                delim == delim2 && tts.probably_equal_for_proc_macro(&tts2)
             }
             (_, _) => false,
         }
@@ -113,7 +111,7 @@
     }
 
     pub fn joint(self) -> TokenStream {
-        TokenStream::Tree(self, Joint)
+        TokenStream::new(vec![(self, Joint)])
     }
 
     /// Returns the opening delimiter as a token tree.
@@ -143,18 +141,19 @@
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat.
+///
+/// The use of `Option` is an optimization that avoids the need for an
+/// allocation when the stream is empty. However, it is not guaranteed that an
+/// empty stream is represented with `None`; it may be represented as a `Some`
+/// around an empty `Vec`.
 #[derive(Clone, Debug)]
-pub enum TokenStream {
-    Empty,
-    Tree(TokenTree, IsJoint),
-    Stream(Lrc<Vec<TreeAndJoint>>),
-}
+pub struct TokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
 
 pub type TreeAndJoint = (TokenTree, IsJoint);
 
 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
+static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 8);
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum IsJoint {
@@ -169,7 +168,7 @@
     /// separating the two arguments with a comma for diagnostic suggestions.
     pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
         // Used to suggest if a user writes `foo!(a b);`
-        if let TokenStream::Stream(ref stream) = self {
+        if let Some(ref stream) = self.0 {
             let mut suggestion = None;
             let mut iter = stream.iter().enumerate().peekable();
             while let Some((pos, ts)) = iter.next() {
@@ -201,7 +200,7 @@
 
 impl From<TokenTree> for TokenStream {
     fn from(tree: TokenTree) -> TokenStream {
-        TokenStream::Tree(tree, NonJoint)
+        TokenStream::new(vec![(tree, NonJoint)])
     }
 }
 
@@ -233,7 +232,7 @@
 
 impl TokenStream {
     pub fn len(&self) -> usize {
-        if let TokenStream::Stream(ref slice) = self {
+        if let Some(ref slice) = self.0 {
             slice.len()
         } else {
             0
@@ -241,13 +240,13 @@
     }
 
     pub fn empty() -> TokenStream {
-        TokenStream::Empty
+        TokenStream(None)
     }
 
     pub fn is_empty(&self) -> bool {
-        match self {
-            TokenStream::Empty => true,
-            _ => false,
+        match self.0 {
+            None => true,
+            Some(ref stream) => stream.is_empty(),
         }
     }
 
@@ -258,10 +257,9 @@
             _ => {
                 let mut vec = vec![];
                 for stream in streams {
-                    match stream {
-                        TokenStream::Empty => {},
-                        TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
-                        TokenStream::Stream(stream2) => vec.extend(stream2.iter().cloned()),
+                    match stream.0 {
+                        None => {},
+                        Some(stream2) => vec.extend(stream2.iter().cloned()),
                     }
                 }
                 TokenStream::new(vec)
@@ -269,22 +267,16 @@
         }
     }
 
-    pub fn new(mut streams: Vec<TreeAndJoint>) -> TokenStream {
+    pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
         match streams.len() {
-            0 => TokenStream::empty(),
-            1 => {
-                let (tree, is_joint) = streams.pop().unwrap();
-                TokenStream::Tree(tree, is_joint)
-            }
-            _ => TokenStream::Stream(Lrc::new(streams)),
+            0 => TokenStream(None),
+            _ => TokenStream(Some(Lrc::new(streams))),
         }
     }
 
     pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
-        match self {
-            TokenStream::Empty => {}
-            TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
-            TokenStream::Stream(stream) => vec.extend(stream.iter().cloned()),
+        if let Some(stream) = self.0 {
+            vec.extend(stream.iter().cloned());
         }
     }
 
@@ -349,51 +341,36 @@
     }
 
     pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        match self {
-            TokenStream::Empty => TokenStream::Empty,
-            TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(0, tree), is_joint),
-            TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+        TokenStream(self.0.map(|stream| {
+            Lrc::new(
                 stream
                     .iter()
                     .enumerate()
                     .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
-                    .collect()
-            )),
-        }
+                    .collect())
+        }))
     }
 
     pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        match self {
-            TokenStream::Empty => TokenStream::Empty,
-            TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint),
-            TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+        TokenStream(self.0.map(|stream| {
+            Lrc::new(
                 stream
                     .iter()
                     .map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
-                    .collect()
-            )),
-        }
+                    .collect())
+        }))
     }
 
-    fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> {
-        match self {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)),
-            TokenStream::Stream(ref stream) => Some(stream.first().unwrap().clone())
-        }
+    fn first_tree_and_joint(&self) -> Option<TreeAndJoint> {
+        self.0.as_ref().map(|stream| {
+            stream.first().unwrap().clone()
+        })
     }
 
     fn last_tree_if_joint(&self) -> Option<TokenTree> {
-        match self {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, is_joint) => {
-                if *is_joint == Joint {
-                    Some(tree.clone())
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) => {
+        match self.0 {
+            None => None,
+            Some(ref stream) => {
                 if let (tree, Joint) = stream.last().unwrap() {
                     Some(tree.clone())
                 } else {
@@ -422,7 +399,7 @@
                     self.push_all_but_last_tree(&last_stream);
                     let glued_span = last_span.to(span);
                     let glued_tt = TokenTree::Token(glued_span, glued_tok);
-                    let glued_tokenstream = TokenStream::Tree(glued_tt, is_joint);
+                    let glued_tokenstream = TokenStream::new(vec![(glued_tt, is_joint)]);
                     self.0.push(glued_tokenstream);
                     self.push_all_but_first_tree(&stream);
                     return
@@ -437,23 +414,21 @@
     }
 
     fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
-        if let TokenStream::Stream(ref streams) = stream {
+        if let Some(ref streams) = stream.0 {
             let len = streams.len();
             match len {
                 1 => {}
-                2 => self.0.push(TokenStream::Tree(streams[0].0.clone(), streams[0].1)),
-                _ => self.0.push(TokenStream::Stream(Lrc::new(streams[0 .. len - 1].to_vec()))),
+                _ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))),
             }
         }
     }
 
     fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
-        if let TokenStream::Stream(ref streams) = stream {
+        if let Some(ref streams) = stream.0 {
             let len = streams.len();
             match len {
                 1 => {}
-                2 => self.0.push(TokenStream::Tree(streams[1].0.clone(), streams[1].1)),
-                _ => self.0.push(TokenStream::Stream(Lrc::new(streams[1 .. len].to_vec()))),
+                _ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))),
             }
         }
     }
@@ -479,17 +454,9 @@
     }
 
     pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
-        match self.stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, ref is_joint) => {
-                if self.index == 0 {
-                    self.index = 1;
-                    Some((tree.clone(), *is_joint))
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) => {
+        match self.stream.0 {
+            None => None,
+            Some(ref stream) => {
                 if self.index < stream.len() {
                     self.index += 1;
                     Some(stream[self.index - 1].clone())
@@ -505,63 +472,19 @@
             return;
         }
         let index = self.index;
-        let stream = mem::replace(&mut self.stream, TokenStream::Empty);
+        let stream = mem::replace(&mut self.stream, TokenStream(None));
         *self = TokenStream::from_streams(vec![stream, new_stream]).into_trees();
         self.index = index;
     }
 
     pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
-        match self.stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, _) => {
-                if n == 0 && self.index == 0 {
-                    Some(tree.clone())
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) =>
-                stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
+        match self.stream.0 {
+            None => None,
+            Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
         }
     }
 }
 
-/// The `TokenStream` type is large enough to represent a single `TokenTree` without allocation.
-/// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
-/// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
-#[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
-
-impl ThinTokenStream {
-    pub fn stream(&self) -> TokenStream {
-        self.clone().into()
-    }
-}
-
-impl From<TokenStream> for ThinTokenStream {
-    fn from(stream: TokenStream) -> ThinTokenStream {
-        ThinTokenStream(match stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(tree, is_joint) => Some(Lrc::new(vec![(tree, is_joint)])),
-            TokenStream::Stream(stream) => Some(stream),
-        })
-    }
-}
-
-impl From<ThinTokenStream> for TokenStream {
-    fn from(stream: ThinTokenStream) -> TokenStream {
-        stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty)
-    }
-}
-
-impl Eq for ThinTokenStream {}
-
-impl PartialEq<ThinTokenStream> for ThinTokenStream {
-    fn eq(&self, other: &ThinTokenStream) -> bool {
-        TokenStream::from(self.clone()) == TokenStream::from(other.clone())
-    }
-}
-
 impl fmt::Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&pprust::tokens_to_string(self.clone()))
@@ -580,18 +503,6 @@
     }
 }
 
-impl Encodable for ThinTokenStream {
-    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
-        TokenStream::from(self.clone()).encode(encoder)
-    }
-}
-
-impl Decodable for ThinTokenStream {
-    fn decode<D: Decoder>(decoder: &mut D) -> Result<ThinTokenStream, D::Error> {
-        TokenStream::decode(decoder).map(Into::into)
-    }
-}
-
 #[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
 pub struct DelimSpan {
     pub open: Span,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 156546b..8cbd47c 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -832,7 +832,7 @@
 pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) {
     match tt {
         TokenTree::Token(_, tok) => visitor.visit_token(tok),
-        TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts.stream()),
+        TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts),
     }
 }
 
diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs
index 807f190..f148f8e 100644
--- a/src/libsyntax_ext/concat.rs
+++ b/src/libsyntax_ext/concat.rs
@@ -23,6 +23,7 @@
         match e.node {
             ast::ExprKind::Lit(ref lit) => match lit.node {
                 ast::LitKind::Str(ref s, _)
+                | ast::LitKind::Err(ref s)
                 | ast::LitKind::Float(ref s, _)
                 | ast::LitKind::FloatUnsuffixed(ref s) => {
                     accumulator.push_str(&s.as_str());
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
index 158cbc7..7de9b93 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax_ext/proc_macro_server.rs
@@ -269,7 +269,7 @@
         };
 
         let tree = tokenstream::TokenTree::Token(span, token);
-        TokenStream::Tree(tree, if joint { Joint } else { NonJoint })
+        TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
     }
 }
 
diff --git a/src/test/incremental/change_name_of_static_in_fn.rs b/src/test/incremental/change_name_of_static_in_fn.rs
new file mode 100644
index 0000000..5b27b68
--- /dev/null
+++ b/src/test/incremental/change_name_of_static_in_fn.rs
@@ -0,0 +1,17 @@
+
+// revisions:rpass1 rpass2 rpass3
+
+// See issue #57692.
+
+#![allow(warnings)]
+
+fn main() {
+    #[cfg(rpass1)]
+    {
+        static map: u64 = 0;
+    }
+    #[cfg(not(rpass1))]
+    {
+        static MAP: u64 = 0;
+    }
+}
diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs
index 6d0c5c1..7ce7e29 100644
--- a/src/test/run-pass/weird-exprs.rs
+++ b/src/test/run-pass/weird-exprs.rs
@@ -4,7 +4,7 @@
 #![allow(unused_parens)]
 // compile-flags: -Z borrowck=compare
 
-#![recursion_limit = "128"]
+#![recursion_limit = "256"]
 
 use std::cell::Cell;
 use std::mem::swap;
diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout
index d584845..8af05e9 100644
--- a/src/test/rustdoc-ui/failed-doctest-output.stdout
+++ b/src/test/rustdoc-ui/failed-doctest-output.stdout
@@ -12,7 +12,7 @@
 3 | no
   | ^^ not found in this scope
 
-thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:319:13
+thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:354:13
 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 ---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ----
@@ -21,7 +21,7 @@
 thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
-', src/librustdoc/test.rs:354:17
+', src/librustdoc/test.rs:389:17
 
 
 failures:
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
index 537816b..924e038 100644
--- a/src/test/rustdoc-ui/invalid-syntax.rs
+++ b/src/test/rustdoc-ui/invalid-syntax.rs
@@ -1,7 +1,66 @@
 // compile-pass
-// compile-flags: --error-format=human
 
 /// ```
 /// \__________pkt->size___________/          \_result->size_/ \__pkt->size__/
 /// ```
 pub fn foo() {}
+
+/// ```
+///    |
+/// LL | use foobar::Baz;
+///    |     ^^^^^^ did you mean `baz::foobar`?
+/// ```
+pub fn bar() {}
+
+/// ```
+/// valid
+/// ```
+///
+/// ```
+/// \_
+/// ```
+///
+/// ```text
+/// "invalid
+/// ```
+pub fn valid_and_invalid() {}
+
+/// This is a normal doc comment, but...
+///
+/// There's a code block with bad syntax in it:
+///
+/// ```rust
+/// \_
+/// ```
+///
+/// Good thing we tested it!
+pub fn baz() {}
+
+/// Indented block start
+///
+///     code with bad syntax
+///     \_
+///
+/// Indented block end
+pub fn quux() {}
+
+/// Unclosed fence
+///
+/// ```
+/// slkdjf
+pub fn xyzzy() {}
+
+/// Indented code that contains a fence
+///
+///     ```
+pub fn blah() {}
+
+/// ```edition2018
+/// \_
+/// ```
+pub fn blargh() {}
+
+#[doc = "```"]
+/// \_
+#[doc = "```"]
+pub fn crazy_attrs() {}
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index b566133..1080038 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -1,10 +1,97 @@
-Output from rustc:
-error: unknown start of token: /
- --> <stdin>:1:1
-  |
-1 | /__________pkt->size___________/          /_result->size_/ /__pkt->size__/
-  | ^
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:3:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | /// /__________pkt->size___________/          /_result->size_/ /__pkt->size__/
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
 
-warning: Invalid doc comment starting with: `/__________pkt->size___________/          /_result->size_/ /__pkt->size__/`
-(Ignoring this codeblock)
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:8:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | ///    |
+LL | | /// LL | use foobar::Baz;
+LL | | ///    |     ^^^^^^ did you mean `baz::foobar`?
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: `
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:19:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | /// /_
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:32:5
+   |
+LL |   /// ```rust
+   |  _____^
+LL | | /// /_
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:41:9
+   |
+LL |   ///     code with bad syntax
+   |  _________^
+LL | | ///     /_
+   | |__________^
+   |
+   = note: error from rustc: unknown start of token: /
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:55:9
+   |
+LL | ///     ```
+   |         ^^^
+   |
+   = note: error from rustc: unknown start of token: `
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:58:5
+   |
+LL |   /// ```edition2018
+   |  _____^
+LL | | /// /_
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unknown start of token: /
+
+warning: doc comment contains an invalid Rust code block
+  --> $DIR/invalid-syntax.rs:63:1
+   |
+LL | / #[doc = "```"]
+LL | | /// /_
+LL | | #[doc = "```"]
+   | |______________^
+   |
+   = help: mark blocks that do not contain Rust code as text: ```text
 
diff --git a/src/test/rustdoc/bad-codeblock-syntax.rs b/src/test/rustdoc/bad-codeblock-syntax.rs
new file mode 100644
index 0000000..0ab2f68
--- /dev/null
+++ b/src/test/rustdoc/bad-codeblock-syntax.rs
@@ -0,0 +1,27 @@
+// @has bad_codeblock_syntax/fn.foo.html
+// @has - '//*[@class="docblock"]/pre/code' '\_'
+/// ```
+/// \_
+/// ```
+pub fn foo() {}
+
+// @has bad_codeblock_syntax/fn.bar.html
+// @has - '//*[@class="docblock"]/pre/code' '`baz::foobar`'
+/// ```
+/// `baz::foobar`
+/// ```
+pub fn bar() {}
+
+// @has bad_codeblock_syntax/fn.quux.html
+// @has - '//*[@class="docblock"]/pre/code' '\_'
+/// ```rust
+/// \_
+/// ```
+pub fn quux() {}
+
+// @has bad_codeblock_syntax/fn.ok.html
+// @has - '//*[@class="docblock"]/pre/code[@class="language-text"]' '\_'
+/// ```text
+/// \_
+/// ```
+pub fn ok() {}
diff --git a/src/test/rustdoc/issue-56701.rs b/src/test/rustdoc/issue-56701.rs
new file mode 100644
index 0000000..6fb30a4
--- /dev/null
+++ b/src/test/rustdoc/issue-56701.rs
@@ -0,0 +1,34 @@
+// This shouldn't cause a stack overflow when rustdoc is run
+
+use std::ops::Deref;
+use std::ops::DerefMut;
+
+pub trait SimpleTrait {
+    type SimpleT;
+}
+
+impl<Inner: SimpleTrait, Outer: Deref<Target = Inner>> SimpleTrait for Outer {
+    type SimpleT = Inner::SimpleT;
+}
+
+pub trait AnotherTrait {
+    type AnotherT;
+}
+
+impl<T, Simple: SimpleTrait<SimpleT = Vec<T>>> AnotherTrait for Simple {
+    type AnotherT = T;
+}
+
+pub struct Unrelated<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>>(UnrelatedT);
+
+impl<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>> Deref for Unrelated<Inner, UnrelatedT> {
+    type Target = Vec<Inner>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+
+pub fn main() { }
+
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
index 08947fd..0738c3f 100644
--- a/src/test/ui/did_you_mean/recursion_limit.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -1,11 +1,10 @@
-error[E0275]: overflow evaluating the requirement `K: std::marker::Send`
+error[E0275]: overflow evaluating the requirement `J: std::marker::Send`
   --> $DIR/recursion_limit.rs:34:5
    |
 LL |     is_send::<A>(); //~ ERROR overflow evaluating the requirement
    |     ^^^^^^^^^^^^
    |
    = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
-   = note: required because it appears within the type `J`
    = note: required because it appears within the type `I`
    = note: required because it appears within the type `H`
    = note: required because it appears within the type `G`
diff --git a/src/test/ui/error-codes/E0055.rs b/src/test/ui/error-codes/E0055.rs
index a3ade92..b525575 100644
--- a/src/test/ui/error-codes/E0055.rs
+++ b/src/test/ui/error-codes/E0055.rs
@@ -1,4 +1,4 @@
-#![recursion_limit="2"]
+#![recursion_limit="5"]
 struct Foo;
 
 impl Foo {
@@ -7,7 +7,7 @@
 
 fn main() {
     let foo = Foo;
-    let ref_foo = &&Foo;
+    let ref_foo = &&&&&Foo;
     ref_foo.foo();
     //~^ ERROR E0055
 }
diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr
index cd2bd92..d06566f 100644
--- a/src/test/ui/error-codes/E0055.stderr
+++ b/src/test/ui/error-codes/E0055.stderr
@@ -4,7 +4,7 @@
 LL |     ref_foo.foo();
    |             ^^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="4"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="10"]` attribute to your crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
index 817b482..f2b0f39 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -1,11 +1,10 @@
-error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: std::marker::Sized`
+error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/E0275.rs:5:1
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
-   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index c422a1e..d0deb8c 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -29,19 +29,25 @@
   --> $DIR/E0423.rs:12:32
    |
 LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
-   |                                ^ did you mean `(S { /* fields */ })`?
+   |                                ^---------------
+   |                                |
+   |                                help: surround the struct literal with parenthesis: `(S { x: 1, y: 2 })`
 
 error[E0423]: expected value, found struct `T`
   --> $DIR/E0423.rs:15:8
    |
 LL |     if T {} == T {} { println!("Ok"); }
-   |        ^ did you mean `(T { /* fields */ })`?
+   |        ^---
+   |        |
+   |        help: surround the struct literal with parenthesis: `(T {})`
 
 error[E0423]: expected value, found struct `std::ops::Range`
   --> $DIR/E0423.rs:21:14
    |
 LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
-   |              ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`?
+   |              ^^^^^^^^^^^^^^^----------------------
+   |              |
+   |              help: surround the struct literal with parenthesis: `(std::ops::Range { start: 0, end: 10 })`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
new file mode 100644
index 0000000..92844f9
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
@@ -0,0 +1,6 @@
+//~ ERROR kind="static-nobundle" is feature gated
+// Test the behavior of rustc when non-existent library is statically linked
+
+// compile-flags: -l static-nobundle=nonexistent
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
new file mode 100644
index 0000000..419c219
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
@@ -0,0 +1,7 @@
+error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
+   |
+   = help: add #![feature(static_nobundle)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
index 9a33d29..47bb5e4 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/fully-qualified-type-name2.rs:12:12
    |
+LL | fn bar(x: x::Foo) -> y::Foo {
+   |                      ------ expected `y::Foo` because of return type
 LL |     return x;
    |            ^ expected enum `y::Foo`, found enum `x::Foo`
    |
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
index f03aaa6..b341879 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/fully-qualified-type-name4.rs:6:12
    |
+LL | fn bar(x: usize) -> Option<usize> {
+   |                     ------------- expected `std::option::Option<usize>` because of return type
 LL |     return x;
    |            ^ expected enum `std::option::Option`, found usize
    |
diff --git a/src/test/ui/huge-enum.rs b/src/test/ui/huge-enum.rs
index 18ef457..71c8fd5 100644
--- a/src/test/ui/huge-enum.rs
+++ b/src/test/ui/huge-enum.rs
@@ -1,7 +1,5 @@
-// error-pattern: Option
-// normalize-stderr-test "<\[u32; \d+\]>" -> "<[u32; N]>"
-
-// FIXME: work properly with higher limits
+// normalize-stderr-test "std::option::Option<\[u32; \d+\]>" -> "TYPE"
+// normalize-stderr-test "\[u32; \d+\]" -> "TYPE"
 
 #[cfg(target_pointer_width = "32")]
 fn main() {
diff --git a/src/test/ui/huge-enum.stderr b/src/test/ui/huge-enum.stderr
index b7cf255..67cae3d 100644
--- a/src/test/ui/huge-enum.stderr
+++ b/src/test/ui/huge-enum.stderr
@@ -1,4 +1,4 @@
-error: the type `std::option::Option<[u32; N]>` is too big for the current architecture
+error: the type `TYPE` is too big for the current architecture
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/issue-57539.rs b/src/test/ui/imports/issue-57539.rs
new file mode 100644
index 0000000..90b74eb
--- /dev/null
+++ b/src/test/ui/imports/issue-57539.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+mod core {
+    use core; //~ ERROR `core` is ambiguous
+    use crate::*;
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-57539.stderr b/src/test/ui/imports/issue-57539.stderr
new file mode 100644
index 0000000..3f745fd
--- /dev/null
+++ b/src/test/ui/imports/issue-57539.stderr
@@ -0,0 +1,18 @@
+error[E0659]: `core` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/issue-57539.rs:4:9
+   |
+LL |     use core; //~ ERROR `core` is ambiguous
+   |         ^^^^ ambiguous name
+   |
+   = note: `core` could refer to a built-in extern crate
+   = help: use `::core` to refer to this extern crate unambiguously
+note: `core` could also refer to the module imported here
+  --> $DIR/issue-57539.rs:5:9
+   |
+LL |     use crate::*;
+   |         ^^^^^^^^
+   = help: use `self::core` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/issue-53787-inline-assembler-macro.rs b/src/test/ui/issue-53787-inline-assembler-macro.rs
new file mode 100644
index 0000000..937bce1
--- /dev/null
+++ b/src/test/ui/issue-53787-inline-assembler-macro.rs
@@ -0,0 +1,23 @@
+// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
+
+#![feature(asm)]
+
+macro_rules! fake_jump {
+    ($id:expr) => {
+        unsafe {
+            asm!(
+            "
+            jmp $0
+            lea eax, [ebx]
+            xor eax, 0xDEADBEEF
+            retn
+            $0:
+            "::"0"($id)::"volatile", "intel");
+        }
+    };
+}
+
+fn main() {
+    fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/issue-53787-inline-assembler-macro.stderr b/src/test/ui/issue-53787-inline-assembler-macro.stderr
new file mode 100644
index 0000000..69f380b
--- /dev/null
+++ b/src/test/ui/issue-53787-inline-assembler-macro.stderr
@@ -0,0 +1,9 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/issue-53787-inline-assembler-macro.rs:21:16
+   |
+LL |     fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+   |                ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index 20e5758..1c353fe 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -6,7 +6,7 @@
    |
    = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
 
-error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: std::marker::Sized`
+error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/issue-20413.rs:8:1
    |
 LL | / impl<T> Foo for T where NoData<T>: Foo {
@@ -18,7 +18,6 @@
    | |_^
    |
    = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
-   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs
index 526a683..616fd09 100644
--- a/src/test/ui/issues/issue-5067.rs
+++ b/src/test/ui/issues/issue-5067.rs
@@ -1,37 +1,59 @@
 #![allow(unused_macros)]
 
+// Tests that repetition matchers cannot match the empty token tree (since that would be
+// ambiguous).
+
+// edition:2018
+
 macro_rules! foo {
     ( $()* ) => {};
     //~^ ERROR repetition matches empty token tree
     ( $()+ ) => {};
     //~^ ERROR repetition matches empty token tree
-
+    ( $()? ) => {};
+    //~^ ERROR repetition matches empty token tree
     ( $(),* ) => {}; // PASS
     ( $(),+ ) => {}; // PASS
-
+    // `?` cannot have a separator...
     ( [$()*] ) => {};
     //~^ ERROR repetition matches empty token tree
     ( [$()+] ) => {};
     //~^ ERROR repetition matches empty token tree
-
+    ( [$()?] ) => {};
+    //~^ ERROR repetition matches empty token tree
     ( [$(),*] ) => {}; // PASS
     ( [$(),+] ) => {}; // PASS
-
+    // `?` cannot have a separator...
     ( $($()* $(),* $(a)* $(a),* )* ) => {};
     //~^ ERROR repetition matches empty token tree
     ( $($()* $(),* $(a)* $(a),* )+ ) => {};
     //~^ ERROR repetition matches empty token tree
-
+    ( $($()* $(),* $(a)* $(a),* )? ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()? $(),* $(a)? $(a),* )* ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()? $(),* $(a)? $(a),* )+ ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $($()? $(),* $(a)? $(a),* )? ) => {};
+    //~^ ERROR repetition matches empty token tree
     ( $(a     $(),* $(a)* $(a),* )* ) => {}; // PASS
     ( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS
+    ( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS
+
+    ( $(a     $(),* $(a)? $(a),* )* ) => {}; // PASS
+    ( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS
+    ( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS
 
     ( $(a $()+)* ) => {};
     //~^ ERROR repetition matches empty token tree
     ( $(a $()*)+ ) => {};
     //~^ ERROR repetition matches empty token tree
+    ( $(a $()+)? ) => {};
+    //~^ ERROR repetition matches empty token tree
+    ( $(a $()?)+ ) => {};
+    //~^ ERROR repetition matches empty token tree
 }
 
-
 // --- Original Issue --- //
 
 macro_rules! make_vec {
@@ -43,11 +65,10 @@
     let _ = make_vec![a 1, a 2, a 3];
 }
 
-
 // --- Minified Issue --- //
 
 macro_rules! m {
-    ( $()* ) => {}
+    ( $()* ) => {};
     //~^ ERROR repetition matches empty token tree
 }
 
diff --git a/src/test/ui/issues/issue-5067.stderr b/src/test/ui/issues/issue-5067.stderr
index 433b7c8..7ffc607 100644
--- a/src/test/ui/issues/issue-5067.stderr
+++ b/src/test/ui/issues/issue-5067.stderr
@@ -1,62 +1,110 @@
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:4:8
+  --> $DIR/issue-5067.rs:9:8
    |
 LL |     ( $()* ) => {};
    |        ^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:6:8
+  --> $DIR/issue-5067.rs:11:8
    |
 LL |     ( $()+ ) => {};
    |        ^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:12:9
+  --> $DIR/issue-5067.rs:13:8
+   |
+LL |     ( $()? ) => {};
+   |        ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:18:9
    |
 LL |     ( [$()*] ) => {};
    |         ^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:14:9
+  --> $DIR/issue-5067.rs:20:9
    |
 LL |     ( [$()+] ) => {};
    |         ^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:20:8
+  --> $DIR/issue-5067.rs:22:9
+   |
+LL |     ( [$()?] ) => {};
+   |         ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:27:8
    |
 LL |     ( $($()* $(),* $(a)* $(a),* )* ) => {};
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:22:8
+  --> $DIR/issue-5067.rs:29:8
    |
 LL |     ( $($()* $(),* $(a)* $(a),* )+ ) => {};
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:28:12
+  --> $DIR/issue-5067.rs:31:8
+   |
+LL |     ( $($()* $(),* $(a)* $(a),* )? ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:33:8
+   |
+LL |     ( $($()? $(),* $(a)? $(a),* )* ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:35:8
+   |
+LL |     ( $($()? $(),* $(a)? $(a),* )+ ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:37:8
+   |
+LL |     ( $($()? $(),* $(a)? $(a),* )? ) => {};
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:47:12
    |
 LL |     ( $(a $()+)* ) => {};
    |            ^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:30:12
+  --> $DIR/issue-5067.rs:49:12
    |
 LL |     ( $(a $()*)+ ) => {};
    |            ^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:38:18
+  --> $DIR/issue-5067.rs:51:12
+   |
+LL |     ( $(a $()+)? ) => {};
+   |            ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:53:12
+   |
+LL |     ( $(a $()?)+ ) => {};
+   |            ^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-5067.rs:60:18
    |
 LL |     (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]);
    |                  ^^^^^^^^^^^^^^^^^^
 
 error: repetition matches empty token tree
-  --> $DIR/issue-5067.rs:50:8
+  --> $DIR/issue-5067.rs:71:8
    |
-LL |     ( $()* ) => {}
+LL |     ( $()* ) => {};
    |        ^^
 
-error: aborting due to 10 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/issues/issue-56488.rs b/src/test/ui/issues/issue-56488.rs
new file mode 100644
index 0000000..e2f3996
--- /dev/null
+++ b/src/test/ui/issues/issue-56488.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+mod alpha {
+    pub trait A {}
+    pub trait C = A;
+}
+
+#[allow(unused_imports)]
+use alpha::C;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs
new file mode 100644
index 0000000..ebeb3fe
--- /dev/null
+++ b/src/test/ui/issues/issue-57597.rs
@@ -0,0 +1,80 @@
+// Regression test for #57597.
+//
+// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
+
+// edition:2018
+
+macro_rules! foo1 {
+    ($($($i:ident)?)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo2 {
+    ($($($i:ident)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo3 {
+    ($($($i:ident)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo4 {
+    ($($($($i:ident)?)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo5 {
+    ($($($($i:ident)*)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo6 {
+    ($($($($i:ident)?)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo7 {
+    ($($($($i:ident)?)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo8 {
+    ($($($($i:ident)*)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo9 {
+    ($($($($i:ident)?)*)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo10 {
+    ($($($($i:ident)?)*)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo11 {
+    ($($($($i:ident)+)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo12 {
+    ($($($($i:ident)+)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+fn main() {
+    foo1!();
+    foo2!();
+    foo3!();
+    foo4!();
+    foo5!();
+    foo6!();
+    foo7!();
+    foo8!();
+    foo9!();
+    foo10!();
+    foo11!();
+    foo12!();
+}
diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr
new file mode 100644
index 0000000..0a02ac8
--- /dev/null
+++ b/src/test/ui/issues/issue-57597.stderr
@@ -0,0 +1,74 @@
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:8:7
+   |
+LL |     ($($($i:ident)?)+) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:13:7
+   |
+LL |     ($($($i:ident)?)*) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:18:7
+   |
+LL |     ($($($i:ident)?)?) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:23:7
+   |
+LL |     ($($($($i:ident)?)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:28:7
+   |
+LL |     ($($($($i:ident)*)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:33:7
+   |
+LL |     ($($($($i:ident)?)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:38:7
+   |
+LL |     ($($($($i:ident)?)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:43:7
+   |
+LL |     ($($($($i:ident)*)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:48:7
+   |
+LL |     ($($($($i:ident)?)*)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:53:7
+   |
+LL |     ($($($($i:ident)?)*)+) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:58:7
+   |
+LL |     ($($($($i:ident)+)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:63:7
+   |
+LL |     ($($($($i:ident)+)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs
new file mode 100644
index 0000000..9b905d4
--- /dev/null
+++ b/src/test/ui/lifetime-before-type-params.rs
@@ -0,0 +1,9 @@
+#![allow(unused)]
+fn first<T, 'a, 'b>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn second<'a, T, 'b>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn third<T, U, 'a>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn fourth<'a, T, 'b, U, 'c, V>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr
new file mode 100644
index 0000000..7ac8dff
--- /dev/null
+++ b/src/test/ui/lifetime-before-type-params.stderr
@@ -0,0 +1,47 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:2:13
+   |
+LL | fn first<T, 'a, 'b>() {}
+   |             ^^  ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | fn first<'a, 'b, T>() {}
+   |          ^^^ ^^^ --
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:4:18
+   |
+LL | fn second<'a, T, 'b>() {}
+   |                  ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | fn second<'a, 'b, T>() {}
+   |               ^^^ --
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:6:16
+   |
+LL | fn third<T, U, 'a>() {}
+   |                ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | fn third<'a, T, U>() {}
+   |          ^^^    --
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/lifetime-before-type-params.rs:8:18
+   |
+LL | fn fourth<'a, T, 'b, U, 'c, V>() {}
+   |                  ^^     ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | fn fourth<'a, 'b, 'c, T, U, V>() {}
+   |               ^^^ ^^^ -- --
+
+error[E0601]: `main` function not found in crate `lifetime_before_type_params`
+   |
+   = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
new file mode 100644
index 0000000..0d18965
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+trait Foo {}
+
+impl Foo for dyn Send {}
+
+impl Foo for dyn Send + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync {}
+
+impl Foo for dyn Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
new file mode 100644
index 0000000..928c92e
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
@@ -0,0 +1,39 @@
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:7:1
+   |
+LL | impl Foo for dyn Send {}
+   | --------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Send + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+   |
+   = note: #[deny(order_dependent_trait_objects)] 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:13:1
+   |
+LL | impl Foo for dyn Send + Sync {}
+   | ---------------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:17:1
+   |
+LL | impl Foo for dyn Sync + Send {}
+   | ---------------------------- first implementation here
+...
+LL | impl Foo for dyn Send + Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/liveness/liveness-dead.rs b/src/test/ui/liveness/liveness-dead.rs
index 7d420af..004663c 100644
--- a/src/test/ui/liveness/liveness-dead.rs
+++ b/src/test/ui/liveness/liveness-dead.rs
@@ -27,4 +27,13 @@
     x = 4; //~ ERROR: value assigned to `x` is never read
 }
 
+// #22630
+fn f6() {
+    let mut done = false;
+    while !done {
+        done = true; // no error
+        continue;
+    }
+}
+
 fn main() {}
diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr
index bbcbbdb..a970b80 100644
--- a/src/test/ui/liveness/liveness-forgot-ret.stderr
+++ b/src/test/ui/liveness/liveness-forgot-ret.stderr
@@ -2,7 +2,7 @@
   --> $DIR/liveness-forgot-ret.rs:3:19
    |
 LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
-   |    -              ^^^^^ expected isize, found ()    - expected because of this statement
+   |    -              ^^^^^ expected isize, found ()
    |    |
    |    this function's body doesn't return
    |
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 66f8791..8e40707 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -9,7 +9,7 @@
                for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32))
            ]
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/escape-argument-callee.rs:26:45
    |
 LL |         let mut closure = expect_sig(|p, y| *p = y);
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 5594271..55e4573 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -16,7 +16,7 @@
    = note: late-bound region is '_#5r
    = note: late-bound region is '_#6r
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/propagate-approximated-fail-no-postdom.rs:46:13
    |
 LL |         |_outlives1, _outlives2, _outlives3, x, y| {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
index 7296bba..1c409a1 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
@@ -41,10 +41,9 @@
 #[rustc_regions]
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ ERROR unsatisfied lifetime constraints
+        //~^ ERROR lifetime may not live long enough
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index a827b85..5863b9b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -3,10 +3,9 @@
    |
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
    |  _______________________________________________^
-LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
-LL | |         //~^ ERROR unsatisfied lifetime constraints
+LL | |         //~^ ERROR lifetime may not live long enough
 LL | |     });
    | |_____^
    |
@@ -24,17 +23,17 @@
    |
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-LL | |
 LL | |         // Only works if 'x: 'y:
-...  |
+LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR lifetime may not live long enough
 LL | |     });
 LL | | }
    | |_^
    |
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
 
-error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-ref.rs:46:9
+error: lifetime may not live long enough
+  --> $DIR/propagate-approximated-ref.rs:45:9
    |
 LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |           --  -- lifetime `'b` defined here
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
index eb6159c..233a5dc 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
@@ -34,10 +34,9 @@
 #[rustc_regions]
 fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-
         // Only works if 'x: 'y:
         demand_y(outlives1, outlives2, x.get())
-        //~^ ERROR unsatisfied lifetime constraints
+        //~^ ERROR lifetime may not live long enough
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 1f9d1d7..b6d9d85 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -3,10 +3,9 @@
    |
 LL |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
    |  _____________________________________________^
-LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(outlives1, outlives2, x.get())
-LL | |         //~^ ERROR unsatisfied lifetime constraints
+LL | |         //~^ ERROR lifetime may not live long enough
 LL | |     });
    | |_____^
    |
@@ -24,17 +23,17 @@
    |
 LL | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-LL | |
 LL | |         // Only works if 'x: 'y:
-...  |
+LL | |         demand_y(outlives1, outlives2, x.get())
+LL | |         //~^ ERROR lifetime may not live long enough
 LL | |     });
 LL | | }
    | |_^
    |
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs []
 
-error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-val.rs:39:9
+error: lifetime may not live long enough
+  --> $DIR/propagate-approximated-val.rs:38:9
    |
 LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |         --  -- lifetime `'b` defined here
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index 1a8988f..93eb93b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -16,7 +16,7 @@
    = note: late-bound region is '_#2r
    = note: late-bound region is '_#3r
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9
    |
 LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index d0492bd..c7809de 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -16,7 +16,7 @@
    = note: late-bound region is '_#3r
    = note: late-bound region is '_#4r
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
    |
 LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
index 0bc0592..d0a24a2 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/region-lbr-named-does-not-outlive-static.rs:9:5
    |
 LL | fn foo<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
index 1be27ae..4d864c6 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
@@ -7,7 +7,7 @@
 
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
     &*x
-        //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
index 2332332..6dc98a9 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:9:5
    |
 LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 26243f9..4a035d0 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -9,7 +9,7 @@
                for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32
            ]
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/return-wrong-bound-region.rs:11:23
    |
 LL |     expect_sig(|a, b| b); // ought to return `a`
diff --git a/src/test/ui/nll/issue-48238.stderr b/src/test/ui/nll/issue-48238.stderr
index 913effa..7cb5eb7 100644
--- a/src/test/ui/nll/issue-48238.stderr
+++ b/src/test/ui/nll/issue-48238.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/issue-48238.rs:11:13
    |
 LL |     move || use_val(&orig); //~ ERROR
diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr
index fa893df..229bb17 100644
--- a/src/test/ui/nll/issue-50716.stderr
+++ b/src/test/ui/nll/issue-50716.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/issue-50716.rs:16:14
    |
 LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs
index 8428e55..795f4f4 100644
--- a/src/test/ui/nll/issue-52113.rs
+++ b/src/test/ui/nll/issue-52113.rs
@@ -3,8 +3,8 @@
 #![allow(warnings)]
 #![feature(nll)]
 
-trait Bazinga { }
-impl<F> Bazinga for F { }
+trait Bazinga {}
+impl<F> Bazinga for F {}
 
 fn produce1<'a>(data: &'a u32) -> impl Bazinga + 'a {
     let x = move || {
@@ -21,7 +21,6 @@
     x
 }
 
-
 fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazinga + 'a {
     let x = move || {
         let value: &'a u32 = value;
@@ -35,7 +34,7 @@
         let value: &'a u32 = value;
         data.push(value);
     };
-    x   //~ ERROR unsatisfied lifetime constraints
+    x //~ ERROR lifetime may not live long enough
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr
index 873612d..ceae161 100644
--- a/src/test/ui/nll/issue-52113.stderr
+++ b/src/test/ui/nll/issue-52113.stderr
@@ -1,12 +1,12 @@
-error: unsatisfied lifetime constraints
-  --> $DIR/issue-52113.rs:38:5
+error: lifetime may not live long enough
+  --> $DIR/issue-52113.rs:37:5
    |
 LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
    |                --  -- lifetime `'b` defined here
    |                |
    |                lifetime `'a` defined here
 ...
-LL |     x   //~ ERROR unsatisfied lifetime constraints
+LL |     x //~ ERROR lifetime may not live long enough
    |     ^ returning this value requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
diff --git a/src/test/ui/nll/issue-52742.rs b/src/test/ui/nll/issue-52742.rs
index d8251cb..150e67f 100644
--- a/src/test/ui/nll/issue-52742.rs
+++ b/src/test/ui/nll/issue-52742.rs
@@ -7,14 +7,14 @@
 }
 
 struct Bar<'b> {
-    z: &'b u32
+    z: &'b u32,
 }
 
 impl Foo<'_, '_> {
     fn take_bar(&mut self, b: Bar<'_>) {
         self.y = b.z
-        //~^ ERROR unsatisfied lifetime constraints
+        //~^ ERROR lifetime may not live long enough
     }
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr
index f733702..6b25296 100644
--- a/src/test/ui/nll/issue-52742.stderr
+++ b/src/test/ui/nll/issue-52742.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/issue-52742.rs:15:9
    |
 LL |     fn take_bar(&mut self, b: Bar<'_>) {
diff --git a/src/test/ui/nll/issue-55394.rs b/src/test/ui/nll/issue-55394.rs
index 4a83c33..deb1034 100644
--- a/src/test/ui/nll/issue-55394.rs
+++ b/src/test/ui/nll/issue-55394.rs
@@ -8,7 +8,7 @@
 
 impl Foo<'_> {
     fn new(bar: &mut Bar) -> Self {
-        Foo { bar } //~ ERROR unsatisfied lifetime constraints
+        Foo { bar } //~ERROR lifetime may not live long enough
     }
 }
 
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr
index a4c5160..bcdd782 100644
--- a/src/test/ui/nll/issue-55394.stderr
+++ b/src/test/ui/nll/issue-55394.stderr
@@ -1,11 +1,11 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/issue-55394.rs:11:9
    |
 LL |     fn new(bar: &mut Bar) -> Self {
    |                 -            ---- return type is Foo<'2>
    |                 |
    |                 let's call the lifetime of this reference `'1`
-LL |         Foo { bar } //~ ERROR unsatisfied lifetime constraints
+LL |         Foo { bar } //~ERROR lifetime may not live long enough
    |         ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr
index 9e50db7..952b544 100644
--- a/src/test/ui/nll/issue-55401.stderr
+++ b/src/test/ui/nll/issue-55401.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/issue-55401.rs:5:5
    |
 LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/mir_check_cast_closure.rs b/src/test/ui/nll/mir_check_cast_closure.rs
index 5298e84..0619ff3 100644
--- a/src/test/ui/nll/mir_check_cast_closure.rs
+++ b/src/test/ui/nll/mir_check_cast_closure.rs
@@ -5,7 +5,7 @@
 fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
     let g: fn(_, _) -> _ = |_x, y| y;
     g
-    //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_closure.stderr b/src/test/ui/nll/mir_check_cast_closure.stderr
index b883533..e14cb07 100644
--- a/src/test/ui/nll/mir_check_cast_closure.stderr
+++ b/src/test/ui/nll/mir_check_cast_closure.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/mir_check_cast_closure.rs:7:5
    |
 LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
diff --git a/src/test/ui/nll/mir_check_cast_reify.rs b/src/test/ui/nll/mir_check_cast_reify.rs
index b0ad8e3..be12e31 100644
--- a/src/test/ui/nll/mir_check_cast_reify.rs
+++ b/src/test/ui/nll/mir_check_cast_reify.rs
@@ -35,7 +35,7 @@
     // as part of checking the `ReifyFnPointer`.
     let f: fn(_) -> _ = foo;
     f(x)
-    //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr
index 2585486..4e8eec3 100644
--- a/src/test/ui/nll/mir_check_cast_reify.stderr
+++ b/src/test/ui/nll/mir_check_cast_reify.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/mir_check_cast_reify.rs:37:5
    |
 LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
index 29fbf46..9df9c05 100644
--- a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
@@ -7,7 +7,7 @@
     // in `g`. These are related via the `UnsafeFnPointer` cast.
     let g: unsafe fn(_) -> _ = f;
     unsafe { g(input) }
-    //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
index e7b945a..5295985 100644
--- a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/mir_check_cast_unsafe_fn.rs:9:14
    |
 LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/mir_check_cast_unsize.rs b/src/test/ui/nll/mir_check_cast_unsize.rs
index e98d5e1..d15c4e4 100644
--- a/src/test/ui/nll/mir_check_cast_unsize.rs
+++ b/src/test/ui/nll/mir_check_cast_unsize.rs
@@ -6,7 +6,7 @@
 
 fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
     x
-    //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr
index 189bb2d..364d6c1 100644
--- a/src/test/ui/nll/mir_check_cast_unsize.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsize.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/mir_check_cast_unsize.rs:8:5
    |
 LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index f2bfdae..e8283d1 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -40,7 +40,7 @@
    |
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/projection-one-region-closure.rs:45:39
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -94,7 +94,7 @@
    |
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/projection-one-region-closure.rs:56:39
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index fc59100..78a8c80 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -31,7 +31,7 @@
                T
            ]
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/projection-one-region-trait-bound-closure.rs:37:39
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -76,7 +76,7 @@
                T
            ]
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
index 25877e6..20edfb3 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
@@ -85,7 +85,7 @@
     T: Anything<'b, 'b>,
 {
     with_signature(cell, t, |cell, t| require(cell, t));
-    //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
 #[rustc_regions]
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index c2b54b6..d8725dc 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -217,7 +217,7 @@
 LL | |     T: Anything<'b, 'b>,
 LL | | {
 LL | |     with_signature(cell, t, |cell, t| require(cell, t));
-LL | |     //~^ ERROR unsatisfied lifetime constraints
+LL | |     //~^ ERROR lifetime may not live long enough
 LL | | }
    | |_^
    |
@@ -226,7 +226,7 @@
                T
            ]
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
    |
 LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr
index 6b3bb60..bcd141b 100644
--- a/src/test/ui/nll/type-alias-free-regions.stderr
+++ b/src/test/ui/nll/type-alias-free-regions.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/type-alias-free-regions.rs:19:9
    |
 LL | impl<'a> FromBox<'a> for C<'a> {
@@ -8,7 +8,7 @@
 LL |         C { f: b } //~ ERROR
    |         ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/type-alias-free-regions.rs:29:9
    |
 LL | impl<'a> FromTuple<'a> for C<'a> {
diff --git a/src/test/ui/nll/user-annotations/closure-substs.rs b/src/test/ui/nll/user-annotations/closure-substs.rs
index 9dc84aa..cafdd92 100644
--- a/src/test/ui/nll/user-annotations/closure-substs.rs
+++ b/src/test/ui/nll/user-annotations/closure-substs.rs
@@ -5,21 +5,21 @@
 fn foo<'a>() {
     // Here `x` is free in the closure sig:
     |x: &'a i32| -> &'static i32 {
-        return x; //~ ERROR unsatisfied lifetime constraints
+        return x; //~ ERROR lifetime may not live long enough
     };
 }
 
 fn foo1() {
     // Here `x` is bound in the closure sig:
     |x: &i32| -> &'static i32 {
-        return x; //~ ERROR unsatisfied lifetime constraints
+        return x; //~ ERROR lifetime may not live long enough
     };
 }
 
 fn bar<'a>() {
     // Here `x` is free in the closure sig:
     |x: &'a i32, b: fn(&'static i32)| {
-        b(x); //~ ERROR unsatisfied lifetime constraints
+        b(x); //~ ERROR lifetime may not live long enough
     };
 }
 
@@ -30,4 +30,4 @@
     };
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/closure-substs.stderr b/src/test/ui/nll/user-annotations/closure-substs.stderr
index ffc6e5a..a46ab61 100644
--- a/src/test/ui/nll/user-annotations/closure-substs.stderr
+++ b/src/test/ui/nll/user-annotations/closure-substs.stderr
@@ -1,27 +1,27 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/closure-substs.rs:8:16
    |
 LL | fn foo<'a>() {
    |        -- lifetime `'a` defined here
 ...
-LL |         return x; //~ ERROR unsatisfied lifetime constraints
+LL |         return x; //~ ERROR lifetime may not live long enough
    |                ^ returning this value requires that `'a` must outlive `'static`
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/closure-substs.rs:15:16
    |
 LL |     |x: &i32| -> &'static i32 {
    |         - let's call the lifetime of this reference `'1`
-LL |         return x; //~ ERROR unsatisfied lifetime constraints
+LL |         return x; //~ ERROR lifetime may not live long enough
    |                ^ returning this value requires that `'1` must outlive `'static`
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/closure-substs.rs:22:9
    |
 LL | fn bar<'a>() {
    |        -- lifetime `'a` defined here
 ...
-LL |         b(x); //~ ERROR unsatisfied lifetime constraints
+LL |         b(x); //~ ERROR lifetime may not live long enough
    |         ^^^^ argument requires that `'a` must outlive `'static`
 
 error[E0521]: borrowed data escapes outside of closure
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
index 94fbe01..541a711 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/constant-in-expr-inherent-1.rs:10:5
    |
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
index 7aeb276..5b97c12 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/constant-in-expr-normalize.rs:20:5
    |
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
index fee9abc..10e48b5 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/constant-in-expr-trait-item-1.rs:12:5
    |
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
index 047aad9..5bfa32e 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/constant-in-expr-trait-item-2.rs:12:5
    |
 LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
index b373ceb..a1e60db 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/constant-in-expr-trait-item-3.rs:12:5
    |
 LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/issue-54124.rs b/src/test/ui/nll/user-annotations/issue-54124.rs
index 042ad02..e1de67a 100644
--- a/src/test/ui/nll/user-annotations/issue-54124.rs
+++ b/src/test/ui/nll/user-annotations/issue-54124.rs
@@ -1,8 +1,8 @@
 #![feature(nll)]
 
 fn test<'a>() {
-    let _:fn(&()) = |_:&'a ()| {}; //~ ERROR unsatisfied lifetime constraints
-    //~^ ERROR unsatisfied lifetime constraints
+    let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {
diff --git a/src/test/ui/nll/user-annotations/issue-54124.stderr b/src/test/ui/nll/user-annotations/issue-54124.stderr
index 5b5afaee..b1c2411 100644
--- a/src/test/ui/nll/user-annotations/issue-54124.stderr
+++ b/src/test/ui/nll/user-annotations/issue-54124.stderr
@@ -1,19 +1,19 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/issue-54124.rs:4:22
    |
 LL | fn test<'a>() {
    |         -- lifetime `'a` defined here
-LL |     let _:fn(&()) = |_:&'a ()| {}; //~ ERROR unsatisfied lifetime constraints
+LL |     let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
    |                      ^ - let's call the lifetime of this reference `'1`
    |                      |
    |                      requires that `'1` must outlive `'a`
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/issue-54124.rs:4:22
    |
 LL | fn test<'a>() {
    |         -- lifetime `'a` defined here
-LL |     let _:fn(&()) = |_:&'a ()| {}; //~ ERROR unsatisfied lifetime constraints
+LL |     let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
    |                      ^ requires that `'a` must outlive `'static`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr
index b0c554e..476578e 100644
--- a/src/test/ui/nll/user-annotations/patterns.stderr
+++ b/src/test/ui/nll/user-annotations/patterns.stderr
@@ -148,7 +148,7 @@
 LL | }
    | - `x` dropped here while still borrowed
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/patterns.rs:113:5
    |
 LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
@@ -157,7 +157,7 @@
 LL |     y //~ ERROR
    |     ^ returning this value requires that `'a` must outlive `'static`
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/patterns.rs:125:5
    |
 LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
@@ -166,7 +166,7 @@
 LL |     y //~ ERROR
    |     ^ returning this value requires that `'a` must outlive `'static`
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/patterns.rs:130:5
    |
 LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
@@ -175,7 +175,7 @@
 LL |     y //~ ERROR
    |     ^ returning this value requires that `'a` must outlive `'static`
 
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/patterns.rs:134:18
    |
 LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/wf-self-type.rs b/src/test/ui/nll/user-annotations/wf-self-type.rs
index da9ef8c..d8caf46 100644
--- a/src/test/ui/nll/user-annotations/wf-self-type.rs
+++ b/src/test/ui/nll/user-annotations/wf-self-type.rs
@@ -9,7 +9,7 @@
 }
 
 pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
-    Foo::xmute(u) //~ ERROR unsatisfied lifetime constraints
+    Foo::xmute(u) //~ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/user-annotations/wf-self-type.stderr b/src/test/ui/nll/user-annotations/wf-self-type.stderr
index 401fe2a..00500c8 100644
--- a/src/test/ui/nll/user-annotations/wf-self-type.stderr
+++ b/src/test/ui/nll/user-annotations/wf-self-type.stderr
@@ -1,11 +1,11 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/wf-self-type.rs:12:5
    |
 LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
    |            --  -- lifetime `'b` defined here
    |            |
    |            lifetime `'a` defined here
-LL |     Foo::xmute(u) //~ ERROR unsatisfied lifetime constraints
+LL |     Foo::xmute(u) //~ ERROR lifetime may not live long enough
    |     ^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
 
 error: aborting due to previous error
diff --git a/src/test/ui/nll/where_clauses_in_functions.rs b/src/test/ui/nll/where_clauses_in_functions.rs
index 256ec60..0d35c09 100644
--- a/src/test/ui/nll/where_clauses_in_functions.rs
+++ b/src/test/ui/nll/where_clauses_in_functions.rs
@@ -11,7 +11,7 @@
 
 fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
     foo(x, y)
-    //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/where_clauses_in_functions.stderr b/src/test/ui/nll/where_clauses_in_functions.stderr
index 4419a19..f3b65ec 100644
--- a/src/test/ui/nll/where_clauses_in_functions.stderr
+++ b/src/test/ui/nll/where_clauses_in_functions.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/where_clauses_in_functions.rs:13:5
    |
 LL | fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
diff --git a/src/test/ui/nll/where_clauses_in_structs.rs b/src/test/ui/nll/where_clauses_in_structs.rs
index 1b02f26..8bc6b2e 100644
--- a/src/test/ui/nll/where_clauses_in_structs.rs
+++ b/src/test/ui/nll/where_clauses_in_structs.rs
@@ -11,7 +11,7 @@
 
 fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
     Foo { x, y };
-    //~^ ERROR unsatisfied lifetime constraints
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/where_clauses_in_structs.stderr b/src/test/ui/nll/where_clauses_in_structs.stderr
index 8704b0dc..e0feb40 100644
--- a/src/test/ui/nll/where_clauses_in_structs.stderr
+++ b/src/test/ui/nll/where_clauses_in_structs.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/where_clauses_in_structs.rs:13:11
    |
 LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/parser/lex-bad-char-literals-2.rs
index 7f85999..1e180f8 100644
--- a/src/test/ui/parser/lex-bad-char-literals-2.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-2.rs
@@ -1,4 +1,4 @@
 // This test needs to the last one appearing in this file as it kills the parser
 static c: char =
-    'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
+    'nope' //~ ERROR: character literal may only contain one codepoint
 ;
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr
index a7075b7..7eadb8e 100644
--- a/src/test/ui/parser/lex-bad-char-literals-2.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-2.stderr
@@ -1,8 +1,13 @@
-error: character literal may only contain one codepoint: 'nope'
+error: character literal may only contain one codepoint
   --> $DIR/lex-bad-char-literals-2.rs:3:5
    |
-LL |     'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
+LL |     'nope' //~ ERROR: character literal may only contain one codepoint
    |     ^^^^^^
 
-error: aborting due to previous error
+error[E0601]: `main` function not found in crate `lex_bad_char_literals_2`
+   |
+   = note: consider adding a `main` function to `$DIR/lex-bad-char-literals-2.rs`
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.rs b/src/test/ui/parser/lex-bad-char-literals-3.rs
index f874970..5194ff4 100644
--- a/src/test/ui/parser/lex-bad-char-literals-3.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-3.rs
@@ -1,7 +1,7 @@
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
-    '●●' //~ ERROR: character literal may only contain one codepoint
-         //~| ERROR: mismatched types
-;
+static c: char = '●●';
+//~^ ERROR: character literal may only contain one codepoint
 
-fn main() {}
+fn main() {
+    let ch: &str = '●●';
+    //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.stderr b/src/test/ui/parser/lex-bad-char-literals-3.stderr
index 89f18e3..6462a3c 100644
--- a/src/test/ui/parser/lex-bad-char-literals-3.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-3.stderr
@@ -1,22 +1,22 @@
 error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-3.rs:3:5
+  --> $DIR/lex-bad-char-literals-3.rs:1:18
    |
-LL |     '●●' //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^
+LL | static c: char = '●●';
+   |                  ^^^^
 help: if you meant to write a `str` literal, use double quotes
    |
-LL |     "●●" //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^
+LL | static c: char = "●●";
+   |                  ^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/lex-bad-char-literals-3.rs:3:5
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-3.rs:5:20
    |
-LL |     '●●' //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^ expected char, found reference
+LL |     let ch: &str = '●●';
+   |                    ^^^^
+help: if you meant to write a `str` literal, use double quotes
    |
-   = note: expected type `char`
-              found type `&'static str`
+LL |     let ch: &str = "●●";
+   |                    ^^^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.rs b/src/test/ui/parser/lex-bad-char-literals-4.rs
index 966e2bb..e13f11f 100644
--- a/src/test/ui/parser/lex-bad-char-literals-4.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-4.rs
@@ -1,5 +1,5 @@
 //
 // This test needs to the last one appearing in this file as it kills the parser
 static c: char =
-    '●  //~ ERROR: character literal may only contain one codepoint: '●
+    '●  //~ ERROR: character literal may only contain one codepoint
 ;
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.stderr b/src/test/ui/parser/lex-bad-char-literals-4.stderr
index 550cb54..881e3d5 100644
--- a/src/test/ui/parser/lex-bad-char-literals-4.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-4.stderr
@@ -1,7 +1,7 @@
 error: character literal may only contain one codepoint: '●
   --> $DIR/lex-bad-char-literals-4.rs:4:5
    |
-LL |     '●  //~ ERROR: character literal may only contain one codepoint: '●
+LL |     '●  //~ ERROR: character literal may only contain one codepoint
    |     ^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.rs b/src/test/ui/parser/lex-bad-char-literals-5.rs
index 247289e..0c4339e 100644
--- a/src/test/ui/parser/lex-bad-char-literals-5.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-5.rs
@@ -1,8 +1,7 @@
-//
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
-    '\x10\x10'  //~ ERROR: character literal may only contain one codepoint
-                //~| ERROR: mismatched types
-;
+static c: char = '\x10\x10';
+//~^ ERROR: character literal may only contain one codepoint
 
-fn main() {}
+fn main() {
+    let ch: &str = '\x10\x10';
+    //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.stderr b/src/test/ui/parser/lex-bad-char-literals-5.stderr
index 523d71f..ef02973 100644
--- a/src/test/ui/parser/lex-bad-char-literals-5.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-5.stderr
@@ -1,22 +1,22 @@
 error: character literal may only contain one codepoint
-  --> $DIR/lex-bad-char-literals-5.rs:4:5
+  --> $DIR/lex-bad-char-literals-5.rs:1:18
    |
-LL |     '/x10/x10'  //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^^^^^^^
+LL | static c: char = '/x10/x10';
+   |                  ^^^^^^^^^^
 help: if you meant to write a `str` literal, use double quotes
    |
-LL |     "/x10/x10"  //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^^^^^^^
+LL | static c: char = "/x10/x10";
+   |                  ^^^^^^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/lex-bad-char-literals-5.rs:4:5
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-5.rs:5:20
    |
-LL |     '/x10/x10'  //~ ERROR: character literal may only contain one codepoint
-   |     ^^^^^^^^^^ expected char, found reference
+LL |     let ch: &str = '/x10/x10';
+   |                    ^^^^^^^^^^
+help: if you meant to write a `str` literal, use double quotes
    |
-   = note: expected type `char`
-              found type `&'static str`
+LL |     let ch: &str = "/x10/x10";
+   |                    ^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.rs b/src/test/ui/parser/lex-bad-char-literals-6.rs
new file mode 100644
index 0000000..4379b4f
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-6.rs
@@ -0,0 +1,17 @@
+fn main() {
+    let x: &str = 'ab';
+    //~^ ERROR: character literal may only contain one codepoint
+    let y: char = 'cd';
+    //~^ ERROR: character literal may only contain one codepoint
+    let z = 'ef';
+    //~^ ERROR: character literal may only contain one codepoint
+
+    if x == y {}
+    //~^ ERROR: can't compare `&str` with `char`
+    if y == z {}  // no error here
+    if x == z {}
+    //~^ ERROR: can't compare `&str` with `char`
+
+    let a: usize = "";
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr
new file mode 100644
index 0000000..df99726
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-6.stderr
@@ -0,0 +1,47 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:2:19
+   |
+LL |     let x: &str = 'ab';
+   |                   ^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:4:19
+   |
+LL |     let y: char = 'cd';
+   |                   ^^^^
+
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-char-literals-6.rs:6:13
+   |
+LL |     let z = 'ef';
+   |             ^^^^
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:9:10
+   |
+LL |     if x == y {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/lex-bad-char-literals-6.rs:15:20
+   |
+LL |     let a: usize = "";
+   |                    ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error[E0277]: can't compare `&str` with `char`
+  --> $DIR/lex-bad-char-literals-6.rs:12:10
+   |
+LL |     if x == z {}
+   |          ^^ no implementation for `&str == char`
+   |
+   = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs
new file mode 100644
index 0000000..50f1fe8
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs
@@ -0,0 +1,17 @@
+fn unrelated() -> Result<(), std::string::ParseError> {  // #57664
+    let x = 0;
+
+    match x {
+        1 => {
+            let property_value_as_string = "a".parse()?;
+        }
+        2 => {
+            let value: &bool = unsafe { &42 };
+            //~^ ERROR mismatched types
+        }
+    };
+
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
new file mode 100644
index 0000000..edaa60e
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41
+   |
+LL |             let value: &bool = unsafe { &42 };
+   |                                         ^^^ expected bool, found integer
+   |
+   = note: expected type `&bool`
+              found type `&{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
new file mode 100644
index 0000000..95b4036
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
@@ -0,0 +1,36 @@
+fn foo() -> impl std::fmt::Display {
+    if false {
+        return 0i32;
+    }
+    1u32
+    //~^ ERROR mismatched types
+}
+
+fn bar() -> impl std::fmt::Display {
+    if false {
+        return 0i32;
+    } else {
+        return 1u32;
+        //~^ ERROR mismatched types
+    }
+}
+
+fn baz() -> impl std::fmt::Display {
+    if false {
+    //~^ ERROR mismatched types
+        return 0i32;
+    } else {
+        1u32
+    }
+}
+
+fn qux() -> impl std::fmt::Display {
+    if false {
+        0i32
+    } else {
+        1u32
+        //~^ ERROR if and else have incompatible types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
new file mode 100644
index 0000000..62da078
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -0,0 +1,58 @@
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
+   |
+LL |         return 0i32;
+   |                ---- expected because of this statement
+LL |     }
+LL |     1u32
+   |     ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
+   |
+LL |         return 0i32;
+   |                ---- expected because of this statement
+LL |     } else {
+LL |         return 1u32;
+   |                ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
+   |
+LL | /     if false {
+LL | |     //~^ ERROR mismatched types
+LL | |         return 0i32;
+   | |                ---- expected because of this statement
+LL | |     } else {
+LL | |         1u32
+LL | |     }
+   | |_____^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: if and else have incompatible types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
+   |
+LL | /     if false {
+LL | |         0i32
+   | |         ---- expected because of this
+LL | |     } else {
+LL | |         1u32
+   | |         ^^^^ expected i32, found u32
+LL | |         //~^ ERROR if and else have incompatible types
+LL | |     }
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index c6e86ed..81d2395 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -1,7 +1,7 @@
 // Private types and traits are not allowed in interfaces of associated types.
 // This test also ensures that the checks are performed even inside private modules.
 
-#![feature(associated_type_defaults)]
+#![feature(associated_type_defaults, existential_type)]
 
 mod m {
     struct Priv;
@@ -23,10 +23,17 @@
 
         type Alias4 = Priv;
         //~^ ERROR private type `m::Priv` in public interface
+
+        type Exist;
+        fn infer_exist() -> Self::Exist;
     }
     impl PubTr for u8 {
         type Alias1 = Priv;
         //~^ ERROR private type `m::Priv` in public interface
+
+        existential type Exist: PrivTr;
+        //~^ ERROR private trait `m::PrivTr` in public interface
+        fn infer_exist() -> Self::Exist { Priv }
     }
 }
 
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index 6740277..0e5dab1 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -6,7 +6,7 @@
 LL | |         //~| WARN this was previously accepted
 LL | |         //~| WARN private type `m::Priv` in public interface
 ...  |
-LL | |         //~^ ERROR private type `m::Priv` in public interface
+LL | |         fn infer_exist() -> Self::Exist;
 LL | |     }
    | |_____^
    |
@@ -22,7 +22,7 @@
 LL | |         //~| WARN this was previously accepted
 LL | |         //~| WARN private type `m::Priv` in public interface
 ...  |
-LL | |         //~^ ERROR private type `m::Priv` in public interface
+LL | |         fn infer_exist() -> Self::Exist;
 LL | |     }
    | |_____^
    |
@@ -39,7 +39,7 @@
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:28:9
+  --> $DIR/private-in-public-assoc-ty.rs:31:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -47,6 +47,16 @@
 LL |         type Alias1 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
-error: aborting due to 2 previous errors
+error[E0445]: private trait `m::PrivTr` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
+   |
+LL |     trait PrivTr {}
+   |     - `m::PrivTr` declared as private
+...
+LL |         existential type Exist: PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-For more information about this error, try `rustc --explain E0446`.
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0445, E0446.
+For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/privacy/private-in-public-existential.rs b/src/test/ui/privacy/private-in-public-existential.rs
index 95658f4..61c6130 100644
--- a/src/test/ui/privacy/private-in-public-existential.rs
+++ b/src/test/ui/privacy/private-in-public-existential.rs
@@ -12,4 +12,14 @@
     Priv
 }
 
+pub trait Trait {
+    type Pub: Default;
+    fn method() -> Self::Pub;
+}
+
+impl Trait for u8 {
+    existential type Pub: Default;
+    fn method() -> Self::Pub { Priv }
+}
+
 fn main() {}
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index 1f9103a..db52490 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -15,6 +15,9 @@
 error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:19:29
    |
+LL | fn b(x: Option<isize>) -> usize {
+   |                           ----- expected `usize` because of return type
+LL |     match x {
 LL |         Some(x) => { return x }, //~ ERROR mismatched types
    |                             ^ expected usize, found isize
 
diff --git a/src/test/ui/regions/regions-static-bound.nll.stderr b/src/test/ui/regions/regions-static-bound.nll.stderr
index f667afd..d6cec03 100644
--- a/src/test/ui/regions/regions-static-bound.nll.stderr
+++ b/src/test/ui/regions/regions-static-bound.nll.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
   --> $DIR/regions-static-bound.rs:9:5
    |
 LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
diff --git a/src/test/ui/regions/regions-static-bound.rs b/src/test/ui/regions/regions-static-bound.rs
index 3ee5187..c1a15e5 100644
--- a/src/test/ui/regions/regions-static-bound.rs
+++ b/src/test/ui/regions/regions-static-bound.rs
@@ -7,7 +7,7 @@
     where 'a: 'b, 'b: 'static { t }
 fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
     t //[ll]~ ERROR E0312
-        //[nll]~^ ERROR unsatisfied lifetime constraints
+        //[nll]~^ ERROR lifetime may not live long enough
 }
 
 fn error(u: &(), v: &()) {
diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr
index 4f6d0f6..ebe3c36 100644
--- a/src/test/ui/resolve/resolve-hint-macro.stderr
+++ b/src/test/ui/resolve/resolve-hint-macro.stderr
@@ -2,7 +2,7 @@
   --> $DIR/resolve-hint-macro.rs:2:5
    |
 LL |     assert(true);
-   |     ^^^^^^ did you mean `assert!(...)`?
+   |     ^^^^^^ help: use `!` to invoke the macro: `assert!`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
index 8a9426b..b7b158c 100644
--- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
@@ -4,15 +4,15 @@
 LL |     a.I
    |     ^--
    |     |
-   |     did you mean `a::I`?
+   |     help: use the path separator to refer to an item: `a::I`
 
 error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5
    |
 LL |     a.g()
-   |     ^----
+   |     ^--
    |     |
-   |     did you mean `a::g(...)`?
+   |     help: use the path separator to refer to an item: `a::g`
 
 error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
@@ -20,16 +20,21 @@
 LL |     a.b.J
    |     ^--
    |     |
-   |     did you mean `a::b`?
+   |     help: use the path separator to refer to an item: `a::b`
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5
    |
 LL |     a::b.J
-   |     ^^^---
-   |     |  |
-   |     |  help: a constant with a similar name exists: `I`
-   |     did you mean `a::b::J`?
+   |     ^^^^
+help: a constant with a similar name exists
+   |
+LL |     a::I.J
+   |        ^
+help: use the path separator to refer to an item
+   |
+LL |     a::b::J
+   |
 
 error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5
@@ -37,7 +42,7 @@
 LL |     a.b.f();
    |     ^--
    |     |
-   |     did you mean `a::b`?
+   |     help: use the path separator to refer to an item: `a::b`
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12
@@ -51,10 +56,15 @@
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
    |
 LL |     a::b.f()
-   |     ^^^-----
-   |     |  |
-   |     |  help: a constant with a similar name exists: `I`
-   |     did you mean `a::b::f(...)`?
+   |     ^^^^
+help: a constant with a similar name exists
+   |
+LL |     a::I.f()
+   |        ^
+help: use the path separator to refer to an item
+   |
+LL |     a::b::f()
+   |     ^^^^^^^
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5
diff --git a/src/test/ui/return/return-from-diverging.stderr b/src/test/ui/return/return-from-diverging.stderr
index c84dd19..2862ae6 100644
--- a/src/test/ui/return/return-from-diverging.stderr
+++ b/src/test/ui/return/return-from-diverging.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/return-from-diverging.rs:4:12
    |
+LL | fn fail() -> ! {
+   |              - expected `!` because of return type
 LL |     return "wow"; //~ ERROR mismatched types
    |            ^^^^^ expected !, found reference
    |
diff --git a/src/test/ui/str/str-as-char.fixed b/src/test/ui/str/str-as-char.fixed
index 9d4297b..accead5 100644
--- a/src/test/ui/str/str-as-char.fixed
+++ b/src/test/ui/str/str-as-char.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
 fn main() {
-    println!("●●");
-    //~^ ERROR character literal may only contain one codepoint
+    println!("{}", "●●"); //~ ERROR character literal may only contain one codepoint
+    //~^ ERROR format argument must be a string literal
 }
diff --git a/src/test/ui/str/str-as-char.rs b/src/test/ui/str/str-as-char.rs
index 710fa74..fb179ec 100644
--- a/src/test/ui/str/str-as-char.rs
+++ b/src/test/ui/str/str-as-char.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
 fn main() {
-    println!('●●');
-    //~^ ERROR character literal may only contain one codepoint
+    println!('●●'); //~ ERROR character literal may only contain one codepoint
+    //~^ ERROR format argument must be a string literal
 }
diff --git a/src/test/ui/str/str-as-char.stderr b/src/test/ui/str/str-as-char.stderr
index 540a1b5..4ca430a 100644
--- a/src/test/ui/str/str-as-char.stderr
+++ b/src/test/ui/str/str-as-char.stderr
@@ -1,12 +1,22 @@
 error: character literal may only contain one codepoint
   --> $DIR/str-as-char.rs:4:14
    |
-LL |     println!('●●');
+LL |     println!('●●'); //~ ERROR character literal may only contain one codepoint
    |              ^^^^
 help: if you meant to write a `str` literal, use double quotes
    |
-LL |     println!("●●");
+LL |     println!("●●"); //~ ERROR character literal may only contain one codepoint
    |              ^^^^
 
-error: aborting due to previous error
+error: format argument must be a string literal
+  --> $DIR/str-as-char.rs:4:14
+   |
+LL |     println!('●●'); //~ ERROR character literal may only contain one codepoint
+   |              ^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     println!("{}", '●●'); //~ ERROR character literal may only contain one codepoint
+   |              ^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
index 108096d..71b1747 100644
--- a/src/test/ui/str/str-idx.stderr
+++ b/src/test/ui/str/str-idx.stderr
@@ -5,6 +5,8 @@
    |                 ^^^^ `str` cannot be indexed by `{integer}`
    |
    = help: the trait `std::ops::Index<{integer}>` is not implemented for `str`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index a0c7c2c..a1212c5 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -29,6 +29,8 @@
    |     ^^^^^^^^^ `str` cannot be mutably indexed by `usize`
    |
    = help: the trait `std::ops::IndexMut<usize>` is not implemented for `str`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
index 72a2cbe..b36e927 100644
--- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
@@ -16,7 +16,7 @@
 help: move the lifetime parameter prior to the first type parameter
    |
 LL | struct B<'a, T, U> { //~ ERROR lifetime parameters must be declared
-   |          ^^^   --
+   |          ^^^ --
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/suggest-move-lifetimes.rs:10:16
@@ -36,7 +36,7 @@
 help: move the lifetime parameter prior to the first type parameter
    |
 LL | struct D<'a, 'b, 'c, T, U, V> { //~ ERROR lifetime parameters must be declared
-   |          ^^^ ^^^ ^^^      ---
+   |          ^^^ ^^^ ^^^    -- --
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr
index eadf3d6..1170f5c 100644
--- a/src/test/ui/tail-typeck.stderr
+++ b/src/test/ui/tail-typeck.stderr
@@ -2,7 +2,9 @@
   --> $DIR/tail-typeck.rs:3:26
    |
 LL | fn f() -> isize { return g(); }
-   |                          ^^^ expected isize, found usize
+   |           -----          ^^^ expected isize, found usize
+   |           |
+   |           expected `isize` because of return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/thread-local-mutation.nll.stderr b/src/test/ui/thread-local-mutation.nll.stderr
new file mode 100644
index 0000000..0a3664b
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.nll.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `S`
+  --> $DIR/thread-local-mutation.rs:11:5
+   |
+LL |     S = "after"; //~ ERROR cannot assign to immutable
+   |     ^^^^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/thread-local-mutation.rs b/src/test/ui/thread-local-mutation.rs
new file mode 100644
index 0000000..e738225
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.rs
@@ -0,0 +1,18 @@
+// Regression test for #54901: immutable thread locals could be mutated. See:
+// https://github.com/rust-lang/rust/issues/29594#issuecomment-328177697
+// https://github.com/rust-lang/rust/issues/54901
+
+#![feature(thread_local)]
+
+#[thread_local]
+static S: &str = "before";
+
+fn set_s() {
+    S = "after"; //~ ERROR cannot assign to immutable
+}
+
+fn main() {
+    println!("{}", S);
+    set_s();
+    println!("{}", S);
+}
diff --git a/src/test/ui/thread-local-mutation.stderr b/src/test/ui/thread-local-mutation.stderr
new file mode 100644
index 0000000..bf29852
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable thread-local static item
+  --> $DIR/thread-local-mutation.rs:11:5
+   |
+LL |     S = "after"; //~ ERROR cannot assign to immutable
+   |     ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/auxiliary/trait_alias.rs
new file mode 100644
index 0000000..9e56b87
--- /dev/null
+++ b/src/test/ui/traits/auxiliary/trait_alias.rs
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SendSync = Send + Sync;
diff --git a/src/test/ui/traits/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias-cross-crate.rs
new file mode 100644
index 0000000..259fc4f
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.rs
@@ -0,0 +1,17 @@
+// aux-build:trait_alias.rs
+
+#![feature(trait_alias)]
+
+extern crate trait_alias;
+
+use std::rc::Rc;
+use trait_alias::SendSync;
+
+fn use_alias<T: SendSync>() {}
+
+fn main() {
+    use_alias::<u32>();
+    use_alias::<Rc<u32>>();
+    //~^ ERROR `std::rc::Rc<u32>` cannot be sent between threads safely [E0277]
+    //~^^ ERROR `std::rc::Rc<u32>` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/traits/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias-cross-crate.stderr
new file mode 100644
index 0000000..972d213
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.stderr
@@ -0,0 +1,29 @@
+error[E0277]: `std::rc::Rc<u32>` cannot be sent between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<u32>` cannot be shared between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr
index 6365008..a7b8106 100644
--- a/src/test/ui/try-block/try-block-in-edition2015.stderr
+++ b/src/test/ui/try-block/try-block-in-edition2015.stderr
@@ -15,7 +15,7 @@
   --> $DIR/try-block-in-edition2015.rs:4:33
    |
 LL |     let try_result: Option<_> = try {
-   |                                 ^^^ did you mean `try!(...)`?
+   |                                 ^^^ help: use `!` to invoke the macro: `try!`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs
new file mode 100644
index 0000000..295f8ac
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-2.rs
@@ -0,0 +1,13 @@
+#![feature(type_alias_enum_variants)]
+
+enum E {
+    V(u8)
+}
+
+impl E {
+    fn V() {}
+}
+
+fn main() {
+    <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+}
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr
new file mode 100644
index 0000000..c6ec96e
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-2.stderr
@@ -0,0 +1,12 @@
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/type-alias-enum-variants-priority-2.rs:12:5
+   |
+LL |     V(u8)
+   |     ----- defined here
+...
+LL |     <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+   |     ^^^^^^^^ expected 1 parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.rs b/src/test/ui/type-alias-enum-variants-priority-3.rs
new file mode 100644
index 0000000..33f9655
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-3.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_enum_variants)]
+
+enum E {
+    V
+}
+
+fn check() -> <E>::V {}
+//~^ ERROR expected type, found variant `V`
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.stderr b/src/test/ui/type-alias-enum-variants-priority-3.stderr
new file mode 100644
index 0000000..b345154
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-3.stderr
@@ -0,0 +1,8 @@
+error: expected type, found variant `V`
+  --> $DIR/type-alias-enum-variants-priority-3.rs:7:15
+   |
+LL | fn check() -> <E>::V {}
+   |               ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs
new file mode 100644
index 0000000..db1da2b
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority.rs
@@ -0,0 +1,20 @@
+#![feature(type_alias_enum_variants)]
+#![deny(ambiguous_associated_items)]
+
+enum E {
+    V
+}
+
+trait Tr {
+    type V;
+    fn f() -> Self::V;
+}
+
+impl Tr for E {
+    type V = u8;
+    fn f() -> Self::V { 0 }
+    //~^ ERROR ambiguous associated item
+    //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants-priority.stderr
new file mode 100644
index 0000000..dcf7dc7
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority.stderr
@@ -0,0 +1,26 @@
+error: ambiguous associated item
+  --> $DIR/type-alias-enum-variants-priority.rs:15:15
+   |
+LL |     fn f() -> Self::V { 0 }
+   |               ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
+   |
+note: lint level defined here
+  --> $DIR/type-alias-enum-variants-priority.rs:2:9
+   |
+LL | #![deny(ambiguous_associated_items)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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 #57644 <https://github.com/rust-lang/rust/issues/57644>
+note: `V` could refer to variant defined here
+  --> $DIR/type-alias-enum-variants-priority.rs:5:5
+   |
+LL |     V
+   |     ^
+note: `V` could also refer to associated type defined here
+  --> $DIR/type-alias-enum-variants-priority.rs:9:5
+   |
+LL |     type V;
+   |     ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr
index 221806f..cf59f42 100644
--- a/src/test/ui/wrong-ret-type.stderr
+++ b/src/test/ui/wrong-ret-type.stderr
@@ -2,7 +2,9 @@
   --> $DIR/wrong-ret-type.rs:2:49
    |
 LL | fn mk_int() -> usize { let i: isize = 3; return i; }
-   |                                                 ^ expected usize, found isize
+   |                -----                            ^ expected usize, found isize
+   |                |
+   |                expected `usize` because of return type
 
 error: aborting due to previous error
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 8c1baa5..4ca285b 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -95,6 +95,7 @@
     "wasm32-unknown-unknown",
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
+    "x86_64-fortanix-unknown-sgx",
     "x86_64-fuchsia",
     "x86_64-linux-android",
     "x86_64-pc-windows-gnu",
diff --git a/src/tools/cargo b/src/tools/cargo
index 2b4a5f1..ffe6587 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 2b4a5f1f0bb6e13759e88ea9512527b0beba154f
+Subproject commit ffe65875fd05018599ad07e7389e99050c7915be