Auto merge of #56863 - arielb1:supertrait-self-4, r=nikomatsakis

fix trait objects with a Self-containing projection values

Fixes #56288.

This follows ALT2 in the issue.

beta-nominating since this is a regression.

r? @nikomatsakis
diff --git a/.travis.yml b/.travis.yml
index 3f2e43a..9e46e6b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,7 +16,7 @@
   fast_finish: true
   include:
     # Images used in testing PR and try-build should be run first.
-    - env: IMAGE=x86_64-gnu-llvm-5.0 RUST_BACKTRACE=1
+    - env: IMAGE=x86_64-gnu-llvm-6.0 RUST_BACKTRACE=1
       if: type = pull_request OR branch = auto
 
     - env: IMAGE=dist-x86_64-linux DEPLOY=1
diff --git a/Cargo.lock b/Cargo.lock
index be4a1c2..7e03474 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -87,7 +87,7 @@
  "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1813,7 +1813,7 @@
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1835,7 +1835,7 @@
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1860,7 +1860,7 @@
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2195,8 +2195,12 @@
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-std-workspace-core 1.0.0",
+]
 
 [[package]]
 name = "rustc-hash"
@@ -2315,7 +2319,7 @@
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_llvm 0.0.0",
 ]
 
@@ -2331,7 +2335,7 @@
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_codegen_utils 0.0.0",
@@ -2892,6 +2896,7 @@
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_asan 0.0.0",
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
@@ -3578,7 +3583,7 @@
 "checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737"
 "checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a"
 "checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652"
-"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
+"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
 "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
diff --git a/README.md b/README.md
index 3744266..dc013a1 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
 
 Read ["Installation"] from [The Book].
 
-["Installation"]: https://doc.rust-lang.org/book/second-edition/ch01-01-installation.html
+["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
 [The Book]: https://doc.rust-lang.org/book/index.html
 
 ## Building from Source
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 3e91c2b..0f7b6c2 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "bootstrap"
 version = "0.0.0"
+edition = "2018"
 
 [lib]
 name = "bootstrap"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c1d5686..405fc87 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -21,20 +21,20 @@
 use std::process::Command;
 use std::time::{Duration, Instant};
 
-use cache::{Cache, Interned, INTERNER};
-use check;
-use compile;
-use dist;
-use doc;
-use flags::Subcommand;
-use install;
-use native;
-use test;
-use tool;
-use util::{add_lib_path, exe, libdir};
-use {Build, DocTests, Mode, GitRepo};
+use crate::cache::{Cache, Interned, INTERNER};
+use crate::check;
+use crate::compile;
+use crate::dist;
+use crate::doc;
+use crate::flags::Subcommand;
+use crate::install;
+use crate::native;
+use crate::test;
+use crate::tool;
+use crate::util::{add_lib_path, exe, libdir};
+use crate::{Build, DocTests, Mode, GitRepo};
 
-pub use Compiler;
+pub use crate::Compiler;
 
 use petgraph::graph::NodeIndex;
 use petgraph::Graph;
@@ -1252,7 +1252,7 @@
 #[cfg(test)]
 mod __test {
     use super::*;
-    use config::Config;
+    use crate::config::Config;
     use std::thread;
 
     fn configure(host: &[&str], target: &[&str]) -> Config {
diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs
index 0b561a3..165cffa 100644
--- a/src/bootstrap/cache.rs
+++ b/src/bootstrap/cache.rs
@@ -23,7 +23,7 @@
 use std::sync::Mutex;
 use std::cmp::{PartialOrd, Ord, Ordering};
 
-use builder::Step;
+use crate::builder::Step;
 
 pub struct Interned<T>(usize, PhantomData<*const T>);
 
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index d5da0ca..3d2b3a2 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -39,9 +39,9 @@
 use build_helper::output;
 use cc;
 
-use {Build, GitRepo};
-use config::Target;
-use cache::Interned;
+use crate::{Build, GitRepo};
+use crate::config::Target;
+use crate::cache::Interned;
 
 // The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
 // so use some simplified logic here. First we respect the environment variable `AR`, then
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 878b6ed..8756ec9 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -20,8 +20,8 @@
 
 use build_helper::output;
 
-use Build;
-use config::Config;
+use crate::Build;
+use crate::config::Config;
 
 // The version number
 pub const CFG_RELEASE_NUM: &str = "1.33.0";
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 0c6dbb0..84e7c40 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -10,11 +10,12 @@
 
 //! Implementation of compiling the compiler and standard library, in "check" mode.
 
-use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot};
-use builder::{RunConfig, Builder, ShouldRun, Step};
-use tool::{prepare_tool_cargo, SourceType};
-use {Compiler, Mode};
-use cache::{INTERNER, Interned};
+use crate::compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env,
+                     add_to_sysroot};
+use crate::builder::{RunConfig, Builder, ShouldRun, Step};
+use crate::tool::{prepare_tool_cargo, SourceType};
+use crate::{Compiler, Mode};
+use crate::cache::{INTERNER, Interned};
 use std::path::PathBuf;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 87f194f..dc42159 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -19,7 +19,7 @@
 use std::io::{self, ErrorKind};
 use std::path::Path;
 
-use Build;
+use crate::Build;
 
 pub fn clean(build: &Build, all: bool) {
     rm_rf("tmp".as_ref());
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 689d053..61a04b9 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -29,12 +29,12 @@
 use filetime::FileTime;
 use serde_json;
 
-use util::{exe, libdir, is_dylib};
-use {Compiler, Mode, GitRepo};
-use native;
+use crate::util::{exe, libdir, is_dylib};
+use crate::{Compiler, Mode, GitRepo};
+use crate::native;
 
-use cache::{INTERNER, Interned};
-use builder::{Step, RunConfig, ShouldRun, Builder};
+use crate::cache::{INTERNER, Interned};
+use crate::builder::{Step, RunConfig, ShouldRun, Builder};
 
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 1dafbe1..2ae9da9 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -22,9 +22,9 @@
 
 use num_cpus;
 use toml;
-use cache::{INTERNER, Interned};
-use flags::Flags;
-pub use flags::Subcommand;
+use crate::cache::{INTERNER, Interned};
+use crate::flags::Flags;
+pub use crate::flags::Subcommand;
 
 /// Global configuration for the entire build and/or bootstrap.
 ///
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index f03eefb..927f9bf 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -26,13 +26,13 @@
 
 use build_helper::output;
 
-use {Compiler, Mode, LLVM_TOOLS};
-use channel;
-use util::{libdir, is_dylib, exe};
-use builder::{Builder, RunConfig, ShouldRun, Step};
-use compile;
-use tool::{self, Tool};
-use cache::{INTERNER, Interned};
+use crate::{Compiler, Mode, LLVM_TOOLS};
+use crate::channel;
+use crate::util::{libdir, is_dylib, exe};
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::compile;
+use crate::tool::{self, Tool};
+use crate::cache::{INTERNER, Interned};
 use time;
 
 pub fn pkgname(builder: &Builder, component: &str) -> String {
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 2d0625b..217328a 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -22,15 +22,15 @@
 use std::io;
 use std::path::{PathBuf, Path};
 
-use Mode;
+use crate::Mode;
 use build_helper::up_to_date;
 
-use util::symlink_dir;
-use builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
-use tool::{self, prepare_tool_cargo, Tool, SourceType};
-use compile;
-use cache::{INTERNER, Interned};
-use config::Config;
+use crate::util::symlink_dir;
+use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
+use crate::tool::{self, prepare_tool_cargo, Tool, SourceType};
+use crate::compile;
+use crate::cache::{INTERNER, Interned};
+use crate::config::Config;
 
 macro_rules! book {
     ($($name:ident, $path:expr, $book_name:expr;)+) => {
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index c49da8f..14e2f69 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -19,12 +19,12 @@
 
 use getopts::Options;
 
-use builder::Builder;
-use config::Config;
-use metadata;
-use {Build, DocTests};
+use crate::builder::Builder;
+use crate::config::Config;
+use crate::metadata;
+use crate::{Build, DocTests};
 
-use cache::{Interned, INTERNER};
+use crate::cache::{Interned, INTERNER};
 
 /// Deserialized version of all flags for this compile.
 pub struct Flags {
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index cb28698..aebcfb4 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -18,11 +18,11 @@
 use std::path::{Path, PathBuf, Component};
 use std::process::Command;
 
-use dist::{self, pkgname, sanitize_sh, tmpdir};
+use crate::dist::{self, pkgname, sanitize_sh, tmpdir};
 
-use builder::{Builder, RunConfig, ShouldRun, Step};
-use cache::Interned;
-use config::Config;
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::cache::Interned;
+use crate::config::Config;
 
 pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
     install_sh(builder, "docs", "rust-docs", stage, Some(host));
diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs
index f7b1c50..a9da2c4 100644
--- a/src/bootstrap/job.rs
+++ b/src/bootstrap/job.rs
@@ -42,7 +42,7 @@
 use std::env;
 use std::io;
 use std::mem;
-use Build;
+use crate::Build;
 
 type HANDLE = *mut u8;
 type BOOL = i32;
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index c879291..c5b8f19 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -159,7 +159,7 @@
 use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime};
 use filetime::FileTime;
 
-use util::{exe, libdir, OutputFolder, CiEnv};
+use crate::util::{exe, libdir, OutputFolder, CiEnv};
 
 mod cc_detect;
 mod channel;
@@ -188,7 +188,7 @@
 mod job {
     use libc;
 
-    pub unsafe fn setup(build: &mut ::Build) {
+    pub unsafe fn setup(build: &mut crate::Build) {
         if build.config.low_priority {
             libc::setpriority(libc::PRIO_PGRP as _, 0, 10);
         }
@@ -197,14 +197,14 @@
 
 #[cfg(any(target_os = "haiku", not(any(unix, windows))))]
 mod job {
-    pub unsafe fn setup(_build: &mut ::Build) {
+    pub unsafe fn setup(_build: &mut crate::Build) {
     }
 }
 
-pub use config::Config;
-use flags::Subcommand;
-use cache::{Interned, INTERNER};
-use toolstate::ToolState;
+pub use crate::config::Config;
+use crate::flags::Subcommand;
+use crate::cache::{Interned, INTERNER};
+use crate::toolstate::ToolState;
 
 const LLVM_TOOLS: &[&str] = &[
     "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index fa0b198..bb503e8 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -16,8 +16,8 @@
 use build_helper::output;
 use serde_json;
 
-use {Build, Crate};
-use cache::INTERNER;
+use crate::{Build, Crate};
+use crate::cache::INTERNER;
 
 #[derive(Deserialize)]
 struct Output {
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 8ff175b..d9f51f6 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -28,11 +28,11 @@
 use cmake;
 use cc;
 
-use util::{self, exe};
+use crate::util::{self, exe};
 use build_helper::up_to_date;
-use builder::{Builder, RunConfig, ShouldRun, Step};
-use cache::Interned;
-use GitRepo;
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::cache::Interned;
+use crate::GitRepo;
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Llvm {
@@ -278,11 +278,11 @@
     let mut parts = version.split('.').take(2)
         .filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
-        if major >= 5 {
+        if major >= 6 {
             return
         }
     }
-    panic!("\n\nbad LLVM version: {}, need >=5.0\n\n", version)
+    panic!("\n\nbad LLVM version: {}, need >=6.0\n\n", version)
 }
 
 fn configure_cmake(builder: &Builder,
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 7a9e6d4..f585495 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -27,7 +27,7 @@
 
 use build_helper::output;
 
-use Build;
+use crate::Build;
 
 struct Finder {
     cache: HashMap<OsString, Option<PathBuf>>,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 87d5737..11932d5 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -23,17 +23,17 @@
 
 use build_helper::{self, output};
 
-use builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
-use cache::{Interned, INTERNER};
-use compile;
-use dist;
-use flags::Subcommand;
-use native;
-use tool::{self, Tool, SourceType};
-use toolstate::ToolState;
-use util::{self, dylib_path, dylib_path_var};
-use Crate as CargoCrate;
-use {DocTests, Mode, GitRepo};
+use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
+use crate::cache::{Interned, INTERNER};
+use crate::compile;
+use crate::dist;
+use crate::flags::Subcommand;
+use crate::native;
+use crate::tool::{self, Tool, SourceType};
+use crate::toolstate::ToolState;
+use crate::util::{self, dylib_path, dylib_path_var};
+use crate::Crate as CargoCrate;
+use crate::{DocTests, Mode, GitRepo};
 
 const ADB_TEST_DIR: &str = "/data/tmp/work";
 
@@ -616,7 +616,7 @@
         if let Some(ref nodejs) = builder.config.nodejs {
             let mut command = Command::new(nodejs);
             command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]);
-            builder.ensure(::doc::Std {
+            builder.ensure(crate::doc::Std {
                 target: self.target,
                 stage: builder.top_stage,
             });
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 1bd4403..4335359 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -15,16 +15,16 @@
 use std::process::{Command, exit};
 use std::collections::HashSet;
 
-use Mode;
-use Compiler;
-use builder::{Step, RunConfig, ShouldRun, Builder};
-use util::{exe, add_lib_path};
-use compile;
-use native;
-use channel::GitInfo;
-use channel;
-use cache::Interned;
-use toolstate::ToolState;
+use crate::Mode;
+use crate::Compiler;
+use crate::builder::{Step, RunConfig, ShouldRun, Builder};
+use crate::util::{exe, add_lib_path};
+use crate::compile;
+use crate::native;
+use crate::channel::GitInfo;
+use crate::channel;
+use crate::cache::Interned;
+use crate::toolstate::ToolState;
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub enum SourceType {
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index be24ae0..b18e38e 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -21,8 +21,8 @@
 use std::process::Command;
 use std::time::{SystemTime, Instant};
 
-use config::Config;
-use builder::Builder;
+use crate::config::Config;
+use crate::builder::Builder;
 
 /// Returns the `name` as the filename of a static library for `target`.
 pub fn staticlib(name: &str, target: &str) -> String {
diff --git a/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
similarity index 89%
rename from src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile
rename to src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
index 4f90c50..160b23e 100644
--- a/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile
@@ -11,7 +11,7 @@
   cmake \
   sudo \
   gdb \
-  llvm-5.0-tools \
+  llvm-6.0-tools \
   libedit-dev \
   zlib1g-dev \
   xz-utils
@@ -22,6 +22,6 @@
 # using llvm-link-shared due to libffi issues -- see #34486
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-5.0 \
+      --llvm-root=/usr/lib/llvm-6.0 \
       --enable-llvm-link-shared
 ENV RUST_CHECK_TARGET check
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index 215689d..a2d2d3c 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -58,9 +58,34 @@
 /// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
 /// case.
 ///
-/// We put the metadata first so that its position is the same for every `K` and `V`, in order
-/// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
-/// prevent them from being reordered.
+/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in
+/// order to statically allocate a single dummy node to avoid allocations. This struct is
+/// `repr(C)` to prevent them from being reordered.  `LeafNode` does not just contain a
+/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
+/// Crucially, `NodeHeader` can be safely transmuted to different K and V.  (This is exploited
+/// by `as_header`.)
+/// See `into_key_slice` for an explanation of K2.  K2 cannot be safely transmuted around
+/// because the size of `NodeHeader` depends on its alignment!
+#[repr(C)]
+struct NodeHeader<K, V, K2 = ()> {
+    /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
+    /// This either points to an actual node or is null.
+    parent: *const InternalNode<K, V>,
+
+    /// This node's index into the parent node's `edges` array.
+    /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
+    /// This is only guaranteed to be initialized when `parent` is non-null.
+    parent_idx: MaybeUninit<u16>,
+
+    /// The number of keys and values this node stores.
+    ///
+    /// This next to `parent_idx` to encourage the compiler to join `len` and
+    /// `parent_idx` into the same 32-bit word, reducing space overhead.
+    len: u16,
+
+    /// See `into_key_slice`.
+    keys_start: [K2; 0],
+}
 #[repr(C)]
 struct LeafNode<K, V> {
     /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
@@ -98,24 +123,25 @@
             len: 0
         }
     }
+}
 
+impl<K, V> NodeHeader<K, V> {
     fn is_shared_root(&self) -> bool {
         ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
     }
 }
 
 // We need to implement Sync here in order to make a static instance.
-unsafe impl Sync for LeafNode<(), ()> {}
+unsafe impl Sync for NodeHeader<(), ()> {}
 
 // An empty node used as a placeholder for the root node, to avoid allocations.
-// We use () in order to save space, since no operation on an empty tree will
+// We use just a header in order to save space, since no operation on an empty tree will
 // ever take a pointer past the first key.
-static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
+static EMPTY_ROOT_NODE: NodeHeader<(), ()> = NodeHeader {
     parent: ptr::null(),
     parent_idx: MaybeUninit::uninitialized(),
     len: 0,
-    keys: MaybeUninit::uninitialized(),
-    vals: MaybeUninit::uninitialized(),
+    keys_start: [],
 };
 
 /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
@@ -281,7 +307,7 @@
                                     .node)
         };
         self.height -= 1;
-        self.as_mut().as_leaf_mut().parent = ptr::null();
+        unsafe { (*self.as_mut().as_leaf_mut()).parent = ptr::null(); }
 
         unsafe {
             Global.dealloc(NonNull::from(top).cast(), Layout::new::<InternalNode<K, V>>());
@@ -306,6 +332,11 @@
 ///   `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
 ///   `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
 ///   `NodeRef` could be pointing to either type of node.
+///   Note that in case of a leaf node, this might still be the shared root!  Only turn
+///   this into a `LeafNode` reference if you know it is not a root!  Shared references
+///   must be dereferencable *for the entire size of their pointee*, so `&InternalNode`
+///   pointing to the shared root is UB.
+///   Turning this into a `NodeHeader` is always safe.
 pub struct NodeRef<BorrowType, K, V, Type> {
     height: usize,
     node: NonNull<LeafNode<K, V>>,
@@ -352,7 +383,7 @@
     /// Finds the length of the node. This is the number of keys or values. In an
     /// internal node, the number of edges is `len() + 1`.
     pub fn len(&self) -> usize {
-        self.as_leaf().len as usize
+        self.as_header().len as usize
     }
 
     /// Returns the height of this node in the whole tree. Zero height denotes the
@@ -382,14 +413,19 @@
         }
     }
 
-    fn as_leaf(&self) -> &LeafNode<K, V> {
+    /// Assert that this is indeed a proper leaf node, and not the shared root.
+    unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
+        self.node.as_ref()
+    }
+
+    fn as_header(&self) -> &NodeHeader<K, V> {
         unsafe {
-            self.node.as_ref()
+            &*(self.node.as_ptr() as *const NodeHeader<K, V>)
         }
     }
 
     pub fn is_shared_root(&self) -> bool {
-        self.as_leaf().is_shared_root()
+        self.as_header().is_shared_root()
     }
 
     pub fn keys(&self) -> &[K] {
@@ -418,7 +454,7 @@
         >,
         Self
     > {
-        let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
+        let parent_as_leaf = self.as_header().parent as *const LeafNode<K, V>;
         if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
             Ok(Handle {
                 node: NodeRef {
@@ -427,7 +463,7 @@
                     root: self.root,
                     _marker: PhantomData
                 },
-                idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) },
+                idx: unsafe { usize::from(*self.as_header().parent_idx.get_ref()) },
                 _marker: PhantomData
             })
         } else {
@@ -534,10 +570,10 @@
         }
     }
 
-    fn as_leaf_mut(&mut self) -> &mut LeafNode<K, V> {
-        unsafe {
-            self.node.as_mut()
-        }
+    /// Returns a raw ptr to avoid asserting exclusive access to the entire node.
+    fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
+        // We are mutable, so we cannot be the root, so accessing this as a leaf is okay.
+        self.node.as_ptr()
     }
 
     fn keys_mut(&mut self) -> &mut [K] {
@@ -551,28 +587,50 @@
 
 impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
     fn into_key_slice(self) -> &'a [K] {
-        // When taking a pointer to the keys, if our key has a stricter
-        // alignment requirement than the shared root does, then the pointer
-        // would be out of bounds, which LLVM assumes will not happen. If the
-        // alignment is more strict, we need to make an empty slice that doesn't
-        // use an out of bounds pointer.
+        // We have to be careful here because we might be pointing to the shared root.
+        // In that case, we must not create an `&LeafNode`.  We could just return
+        // an empty slice whenever the length is 0 (this includes the shared root),
+        // but we want to avoid that run-time check.
+        // Instead, we create a slice pointing into the node whenever possible.
+        // We can sometimes do this even for the shared root, as the slice will be
+        // empty.  We cannot *always* do this because if the type is too highly
+        // aligned, the offset of `keys` in a "full node" might be outside the bounds
+        // of the header!  So we do an alignment check first, that will be
+        // evaluated at compile-time, and only do any run-time check in the rare case
+        // that the alignment is very big.
         if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() {
             &[]
         } else {
-            // Here either it's not the root, or the alignment is less strict,
-            // in which case the keys pointer will point "one-past-the-end" of
-            // the node, which is allowed by LLVM.
+            // Thanks to the alignment check above, we know that `keys` will be
+            // in-bounds of some allocation even if this is the shared root!
+            // (We might be one-past-the-end, but that is allowed by LLVM.)
+            // Getting the pointer is tricky though.  `NodeHeader` does not have a `keys`
+            // field because we want its size to not depend on the alignment of `K`
+            // (needed becuase `as_header` should be safe).  We cannot call `as_leaf`
+            // because we might be the shared root.
+            // For this reason, `NodeHeader` has this `K2` parameter (that's usually `()`
+            // and hence just adds a size-0-align-1 field, not affecting layout).
+            // We know that we can transmute `NodeHeader<K, V, ()>` to `NodeHeader<K, V, K>`
+            // because we did the alignment check above, and hence `NodeHeader<K, V, K>`
+            // is not bigger than `NodeHeader<K, V, ()>`!  Then we can use `NodeHeader<K, V, K>`
+            // to compute the pointer where the keys start.
+            // This entire hack will become unnecessary once
+            // <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw
+            // pointer to the `keys` field of `*const InternalNode<K, V>`.
+
+            // This is a non-debug-assert because it can be completely compile-time evaluated.
+            assert!(mem::size_of::<NodeHeader<K, V>>() == mem::size_of::<NodeHeader<K, V, K>>());
+            let header = self.as_header() as *const _ as *const NodeHeader<K, V, K>;
+            let keys = unsafe { &(*header).keys_start as *const _ as *const K };
             unsafe {
-                slice::from_raw_parts(
-                    self.as_leaf().keys.as_ptr() as *const K,
-                    self.len()
-                )
+                slice::from_raw_parts(keys, self.len())
             }
         }
     }
 
     fn into_val_slice(self) -> &'a [V] {
         debug_assert!(!self.is_shared_root());
+        // We cannot be the root, so `as_leaf` is okay
         unsafe {
             slice::from_raw_parts(
                 self.as_leaf().vals.as_ptr() as *const V,
@@ -602,7 +660,7 @@
         } else {
             unsafe {
                 slice::from_raw_parts_mut(
-                    self.as_leaf_mut().keys.as_mut_ptr() as *mut K,
+                    (*self.as_leaf_mut()).keys.as_mut_ptr() as *mut K,
                     self.len()
                 )
             }
@@ -613,7 +671,7 @@
         debug_assert!(!self.is_shared_root());
         unsafe {
             slice::from_raw_parts_mut(
-                self.as_leaf_mut().vals.as_mut_ptr() as *mut V,
+                (*self.as_leaf_mut()).vals.as_mut_ptr() as *mut V,
                 self.len()
             )
         }
@@ -637,9 +695,9 @@
         unsafe {
             ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
             ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
-        }
 
-        self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
+        }
     }
 
     /// Adds a key/value pair to the beginning of the node.
@@ -651,9 +709,9 @@
         unsafe {
             slice_insert(self.keys_mut(), 0, key);
             slice_insert(self.vals_mut(), 0, val);
-        }
 
-        self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
+        }
     }
 }
 
@@ -672,7 +730,7 @@
             ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
             ptr::write(self.as_internal_mut().edges.get_unchecked_mut(idx + 1), edge.node);
 
-            self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
 
             Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link();
         }
@@ -708,7 +766,7 @@
                 edge.node
             );
 
-            self.as_leaf_mut().len += 1;
+            (*self.as_leaf_mut()).len += 1;
 
             self.correct_all_childrens_parent_links();
         }
@@ -732,12 +790,12 @@
                 ForceResult::Internal(internal) => {
                     let edge = ptr::read(internal.as_internal().edges.get_unchecked(idx + 1));
                     let mut new_root = Root { node: edge, height: internal.height - 1 };
-                    new_root.as_mut().as_leaf_mut().parent = ptr::null();
+                    (*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
                     Some(new_root)
                 }
             };
 
-            self.as_leaf_mut().len -= 1;
+            (*self.as_leaf_mut()).len -= 1;
             (key, val, edge)
         }
     }
@@ -765,7 +823,7 @@
                     );
 
                     let mut new_root = Root { node: edge, height: internal.height - 1 };
-                    new_root.as_mut().as_leaf_mut().parent = ptr::null();
+                    (*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
 
                     for i in 0..old_len {
                         Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link();
@@ -775,7 +833,7 @@
                 }
             };
 
-            self.as_leaf_mut().len -= 1;
+            (*self.as_leaf_mut()).len -= 1;
 
             (key, val, edge)
         }
@@ -966,7 +1024,7 @@
             slice_insert(self.node.keys_mut(), self.idx, key);
             slice_insert(self.node.vals_mut(), self.idx, val);
 
-            self.node.as_leaf_mut().len += 1;
+            (*self.node.as_leaf_mut()).len += 1;
 
             self.node.vals_mut().get_unchecked_mut(self.idx)
         }
@@ -1009,8 +1067,10 @@
         let idx = self.idx as u16;
         let ptr = self.node.as_internal_mut() as *mut _;
         let mut child = self.descend();
-        child.as_leaf_mut().parent = ptr;
-        child.as_leaf_mut().parent_idx.set(idx);
+        unsafe {
+            (*child.as_leaf_mut()).parent = ptr;
+            (*child.as_leaf_mut()).parent_idx.set(idx);
+        }
     }
 
     /// Unsafely asserts to the compiler some static information about whether the underlying
@@ -1158,7 +1218,7 @@
                 new_len
             );
 
-            self.node.as_leaf_mut().len = self.idx as u16;
+            (*self.node.as_leaf_mut()).len = self.idx as u16;
             new_node.len = new_len as u16;
 
             (
@@ -1180,7 +1240,7 @@
         unsafe {
             let k = slice_remove(self.node.keys_mut(), self.idx);
             let v = slice_remove(self.node.vals_mut(), self.idx);
-            self.node.as_leaf_mut().len -= 1;
+            (*self.node.as_leaf_mut()).len -= 1;
             (self.left_edge(), k, v)
         }
     }
@@ -1221,7 +1281,7 @@
                 new_len + 1
             );
 
-            self.node.as_leaf_mut().len = self.idx as u16;
+            (*self.node.as_leaf_mut()).len = self.idx as u16;
             new_node.data.len = new_len as u16;
 
             let mut new_root = Root {
@@ -1295,9 +1355,9 @@
             for i in self.idx+1..self.node.len() {
                 Handle::new_edge(self.node.reborrow_mut(), i).correct_parent_link();
             }
-            self.node.as_leaf_mut().len -= 1;
+            (*self.node.as_leaf_mut()).len -= 1;
 
-            left_node.as_leaf_mut().len += right_len as u16 + 1;
+            (*left_node.as_leaf_mut()).len += right_len as u16 + 1;
 
             if self.node.height > 1 {
                 ptr::copy_nonoverlapping(
@@ -1407,8 +1467,8 @@
                 move_kv(left_kv, new_left_len, parent_kv, 0, 1);
             }
 
-            left_node.reborrow_mut().as_leaf_mut().len -= count as u16;
-            right_node.reborrow_mut().as_leaf_mut().len += count as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len += count as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@@ -1468,8 +1528,8 @@
                           new_right_len);
             }
 
-            left_node.reborrow_mut().as_leaf_mut().len += count as u16;
-            right_node.reborrow_mut().as_leaf_mut().len -= count as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len += count as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@@ -1560,8 +1620,8 @@
 
             move_kv(left_kv, left_new_len, right_kv, 0, right_new_len);
 
-            left_node.reborrow_mut().as_leaf_mut().len = left_new_len as u16;
-            right_node.reborrow_mut().as_leaf_mut().len = right_new_len as u16;
+            (*left_node.reborrow_mut().as_leaf_mut()).len = left_new_len as u16;
+            (*right_node.reborrow_mut().as_leaf_mut()).len = right_new_len as u16;
 
             match (left_node.force(), right_node.force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(right)) => {
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index 2ef84db..ba46faf 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -627,7 +627,9 @@
         self.pop_front_node().map(Node::into_element)
     }
 
-    /// Appends an element to the back of a list
+    /// Appends an element to the back of a list.
+    ///
+    /// This operation should compute in O(1) time.
     ///
     /// # Examples
     ///
@@ -647,6 +649,8 @@
     /// Removes the last element from a list and returns it, or `None` if
     /// it is empty.
     ///
+    /// This operation should compute in O(1) time.
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index e329b45..509195c 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -80,6 +80,11 @@
 }
 
 #[test]
+fn test_zst_capacity() {
+    assert_eq!(Vec::<()>::new().capacity(), usize::max_value());
+}
+
+#[test]
 fn test_extend() {
     let mut v = Vec::new();
     let mut w = Vec::new();
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 0c5256b..8e0caa5 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -609,10 +609,15 @@
 /// println!("The origin is: {}", origin);
 /// ```
 #[rustc_on_unimplemented(
+    on(
+        _Self="std::path::Path",
+        label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
+        note="call `.display()` or `.to_string_lossy()` to safely print paths, \
+              as they may contain non-Unicode data"
+    ),
     message="`{Self}` doesn't implement `{Display}`",
     label="`{Self}` cannot be formatted with the default formatter",
-    note="in format strings you may be able to use `{{:?}}` \
-          (or {{:#?}} for pretty-print) instead",
+    note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead",
 )]
 #[doc(alias = "{}")]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs
index 0c870f9..5dee1d6 100644
--- a/src/libcore/future/future.rs
+++ b/src/libcore/future/future.rs
@@ -33,6 +33,7 @@
 ///
 /// When using a future, you generally won't call `poll` directly, but instead
 /// `await!` the value.
+#[must_use]
 pub trait Future {
     /// The result of the `Future`.
     type Output;
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 92a4aed..c0b83a6 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -98,6 +98,7 @@
     message="`{Self}` is not an iterator"
 )]
 #[doc(spotlight)]
+#[must_use]
 pub trait Iterator {
     /// The type of the elements being iterated over.
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 7b273f7..aa23d49 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -649,19 +649,6 @@
             _ => (usize::MAX, None)
         }
     }
-
-    #[inline]
-    fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
-        Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
-    {
-        let mut accum = init;
-        while let Some(x) = self.iter.next() {
-            accum = f(accum, x)?;
-            accum = self.iter.try_fold(accum, &mut f)?;
-            self.iter = self.orig.clone();
-        }
-        Try::from_ok(accum)
-    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index a51674f..c8ad38c 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -121,7 +121,6 @@
 #![feature(const_slice_len)]
 #![feature(const_str_as_bytes)]
 #![feature(const_str_len)]
-#![feature(const_let)]
 #![feature(const_int_rotate)]
 #![feature(const_int_wrapping)]
 #![feature(const_int_sign)]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 4acf3a1..f1df1f2 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -70,7 +70,7 @@
                 #[stable(feature = "nonzero", since = "1.28.0")]
                 #[inline]
                 pub const unsafe fn new_unchecked(n: $Int) -> Self {
-                    $Ty(unsafe { NonZero(n) })
+                    $Ty(NonZero(n))
                 }
 
                 /// Create a non-zero if the given value is not zero.
@@ -2150,19 +2150,6 @@
          "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" }
 }
 
-// Emits the correct `cttz` call, depending on the size of the type.
-macro_rules! uint_cttz_call {
-    // As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
-    // emits two conditional moves on x86_64. By promoting the value to
-    // u16 and setting bit 8, we get better code without any conditional
-    // operations.
-    // FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
-    // pending, remove this workaround once LLVM generates better code
-    // for cttz8.
-    ($value:expr, 8) => { intrinsics::cttz($value as u16 | 0x100) };
-    ($value:expr, $_BITS:expr) => { intrinsics::cttz($value) }
-}
-
 // `Int` + `UnsignedInt` implemented for unsigned integers
 macro_rules! uint_impl {
     ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr,
@@ -2306,7 +2293,7 @@
             #[rustc_const_unstable(feature = "const_int_ops")]
             #[inline]
             pub const fn trailing_zeros(self) -> u32 {
-                unsafe { uint_cttz_call!(self, $BITS) as u32 }
+                unsafe { intrinsics::cttz(self) as u32 }
             }
         }
 
diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs
index d1be724..3b356b9 100644
--- a/src/libcore/ops/function.rs
+++ b/src/libcore/ops/function.rs
@@ -72,6 +72,7 @@
     label="expected an `Fn<{Args}>` closure, found `{Self}`",
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use]
 pub trait Fn<Args> : FnMut<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
@@ -150,6 +151,7 @@
     label="expected an `FnMut<{Args}>` closure, found `{Self}`",
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use]
 pub trait FnMut<Args> : FnOnce<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
@@ -228,6 +230,7 @@
     label="expected an `FnOnce<{Args}>` closure, found `{Self}`",
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use]
 pub trait FnOnce<Args> {
     /// The returned type after the call operator is used.
     #[stable(feature = "fn_once_output", since = "1.12.0")]
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 79ca600..b3c93ae 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2928,7 +2928,7 @@
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
-        NonNull { pointer: unsafe { NonZero(ptr as _) } }
+        NonNull { pointer: NonZero(ptr as _) }
     }
 
     /// Creates a new `NonNull` if `ptr` is non-null.
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 060983a..d2683e3 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -1072,6 +1072,15 @@
 #[cfg(target_has_atomic = "8")]
 #[stable(feature = "atomic_bool_from", since = "1.24.0")]
 impl From<bool> for AtomicBool {
+    /// Converts a `bool` into an `AtomicBool`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::atomic::AtomicBool;
+    /// let atomic_bool = AtomicBool::from(true);
+    /// assert_eq!(format!("{:?}", atomic_bool), "true")
+    /// ```
     #[inline]
     fn from(b: bool) -> Self { Self::new(b) }
 }
@@ -1126,8 +1135,12 @@
 
         #[$stable_from]
         impl From<$int_type> for $atomic_type {
-            #[inline]
-            fn from(v: $int_type) -> Self { Self::new(v) }
+            doc_comment! {
+                concat!(
+"Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`."),
+                #[inline]
+                fn from(v: $int_type) -> Self { Self::new(v) }
+            }
         }
 
         #[$stable_debug]
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 4efa013..00b4aa4 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1003,6 +1003,8 @@
     assert_eq!(it.next(), None);
 
     assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0);
+
+    assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4);
 }
 
 #[test]
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 8d2b1d7..43bc9d8 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -36,6 +36,7 @@
 use ty::fold::TypeFoldable;
 use ty::subst::{Kind, UnpackedKind};
 use ty::{self, BoundVar, Lift, Ty, TyCtxt};
+use util::captures::Captures;
 
 impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
     /// The "main method" for a canonicalized trait query. Given the
@@ -527,32 +528,30 @@
         param_env: ty::ParamEnv<'tcx>,
         unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
-        Box::new(
-            unsubstituted_region_constraints
-                .iter()
-                .map(move |constraint| {
-                    let constraint = substitute_value(self.tcx, result_subst, constraint);
-                    let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'gcx> {
+        unsubstituted_region_constraints
+            .iter()
+            .map(move |constraint| {
+                let constraint = substitute_value(self.tcx, result_subst, constraint);
+                let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
 
-                    Obligation::new(
-                        cause.clone(),
-                        param_env,
-                        match k1.unpack() {
-                            UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
-                                ty::Binder::bind(
-                                    ty::OutlivesPredicate(r1, r2)
-                                )
-                            ),
-                            UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
-                                ty::Binder::bind(
-                                    ty::OutlivesPredicate(t1, r2)
-                                )
-                            ),
-                        }
-                    )
-                })
-        ) as Box<dyn Iterator<Item = _>>
+                Obligation::new(
+                    cause.clone(),
+                    param_env,
+                    match k1.unpack() {
+                        UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
+                            ty::Binder::bind(
+                                ty::OutlivesPredicate(r1, r2)
+                            )
+                        ),
+                        UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
+                            ty::Binder::bind(
+                                ty::OutlivesPredicate(t1, r2)
+                            )
+                        ),
+                    }
+                )
+            })
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index f124623..833da67 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -347,6 +347,10 @@
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.infcx.trait_object_mode()
+    }
+
     fn tag(&self) -> &'static str {
         "Generalizer"
     }
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 27faa45..caa120f 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -39,6 +39,10 @@
 
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn a_is_expected(&self) -> bool { self.a_is_expected }
 
     fn relate_item_substs(&mut self,
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index 8968c59..ba21ebb 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -15,7 +15,7 @@
 
 use traits::ObligationCause;
 use ty::{self, Ty, TyCtxt};
-use ty::relate::{Relate, RelateResult, TypeRelation};
+use ty::relate::{self, Relate, RelateResult, TypeRelation};
 
 /// "Greatest lower bound" (common subtype)
 pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -36,6 +36,10 @@
 {
     fn tag(&self) -> &'static str { "Glb" }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.a_is_expected }
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index 8875b41..80fad44 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -15,7 +15,7 @@
 
 use traits::ObligationCause;
 use ty::{self, Ty, TyCtxt};
-use ty::relate::{Relate, RelateResult, TypeRelation};
+use ty::relate::{self, Relate, RelateResult, TypeRelation};
 
 /// "Least upper bound" (common supertype)
 pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -36,6 +36,10 @@
 {
     fn tag(&self) -> &'static str { "Lub" }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.a_is_expected }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index b1a1335..c961fd5 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -35,7 +35,7 @@
 use traits::{self, ObligationCause, PredicateObligations, TraitEngine};
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::TypeFoldable;
-use ty::relate::RelateResult;
+use ty::relate::{RelateResult, TraitObjectMode};
 use ty::subst::{Kind, Substs};
 use ty::{self, GenericParamDefKind, Ty, TyCtxt};
 use ty::{FloatVid, IntVid, TyVid};
@@ -182,6 +182,9 @@
     // This flag is true while there is an active snapshot.
     in_snapshot: Cell<bool>,
 
+    // The TraitObjectMode used here,
+    trait_object_mode: TraitObjectMode,
+
     // A set of constraints that regionck must validate. Each
     // constraint has the form `T:'a`, meaning "some type `T` must
     // outlive the lifetime 'a". These constraints derive from
@@ -472,6 +475,7 @@
     global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
     arena: SyncDroplessArena,
     fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
+    trait_object_mode: TraitObjectMode,
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
@@ -480,6 +484,7 @@
             global_tcx: self,
             arena: SyncDroplessArena::default(),
             fresh_tables: None,
+            trait_object_mode: TraitObjectMode::NoSquash,
         }
     }
 }
@@ -492,6 +497,12 @@
         self
     }
 
+    pub fn with_trait_object_mode(mut self, mode: TraitObjectMode) -> Self {
+        debug!("with_trait_object_mode: setting mode to {:?}", mode);
+        self.trait_object_mode = mode;
+        self
+    }
+
     /// Given a canonical value `C` as a starting point, create an
     /// inference context that contains each of the bound values
     /// within instantiated as a fresh variable. The `f` closure is
@@ -518,6 +529,7 @@
     pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R {
         let InferCtxtBuilder {
             global_tcx,
+            trait_object_mode,
             ref arena,
             ref fresh_tables,
         } = *self;
@@ -526,6 +538,7 @@
             f(InferCtxt {
                 tcx,
                 in_progress_tables,
+                trait_object_mode,
                 projection_cache: Default::default(),
                 type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
                 int_unification_table: RefCell::new(ut::UnificationTable::new()),
@@ -607,6 +620,10 @@
         self.in_snapshot.get()
     }
 
+    pub fn trait_object_mode(&self) -> TraitObjectMode {
+        self.trait_object_mode
+    }
+
     pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
     }
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index 773c712..0ce0eb9 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -382,6 +382,13 @@
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        // squashing should only be done in coherence, not NLL
+        assert_eq!(self.infcx.trait_object_mode(),
+                   relate::TraitObjectMode::NoSquash);
+        relate::TraitObjectMode::NoSquash
+    }
+
     fn tag(&self) -> &'static str {
         "nll::subtype"
     }
@@ -696,6 +703,13 @@
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        // squashing should only be done in coherence, not NLL
+        assert_eq!(self.infcx.trait_object_mode(),
+                   relate::TraitObjectMode::NoSquash);
+        relate::TraitObjectMode::NoSquash
+    }
+
     fn tag(&self) -> &'static str {
         "nll::generalizer"
     }
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index 3b0f9a5..ef2ef3f 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -15,7 +15,7 @@
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
 use ty::fold::TypeFoldable;
-use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
+use ty::relate::{self, Cause, Relate, RelateResult, TypeRelation};
 use std::mem;
 
 /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@@ -43,6 +43,10 @@
     for Sub<'combine, 'infcx, 'gcx, 'tcx>
 {
     fn tag(&self) -> &'static str { "Sub" }
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.fields.infcx.trait_object_mode()
+    }
+
     fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
     fn a_is_expected(&self) -> bool { self.a_is_expected }
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index b7759a8..cf43710 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -209,6 +209,12 @@
 }
 
 declare_lint! {
+    pub ORDER_DEPENDENT_TRAIT_OBJECTS,
+    Deny,
+    "trait-object types were treated as different depending on marker-trait order"
+}
+
+declare_lint! {
     pub BAD_REPR,
     Warn,
     "detects incorrect use of `repr` attribute"
@@ -365,6 +371,13 @@
     }
 }
 
+declare_lint! {
+    pub DEPRECATED_IN_FUTURE,
+    Allow,
+    "detects use of items that will be deprecated in a future version",
+    report_in_external_macro: true
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// that are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -405,6 +418,7 @@
             PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
             LATE_BOUND_LIFETIME_ARGUMENTS,
             INCOHERENT_FUNDAMENTAL_IMPLS,
+            ORDER_DEPENDENT_TRAIT_OBJECTS,
             DEPRECATED,
             UNUSED_UNSAFE,
             UNUSED_MUT,
@@ -427,6 +441,7 @@
             MACRO_USE_EXTERN_CRATE,
             MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
             parser::QUESTION_MARK_MACRO_SEP,
+            DEPRECATED_IN_FUTURE,
         )
     }
 }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index e576951..31a75bd 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1657,11 +1657,15 @@
     fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) {
         if let Some(name) = self.should_warn(var) {
             if is_argument {
-                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
-                    &format!("value passed to `{}` is never read", name));
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+                &format!("value passed to `{}` is never read", name))
+                .help("maybe it is overwritten before being read?")
+                .emit();
             } else {
-                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
-                    &format!("value assigned to `{}` is never read", name));
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+                &format!("value assigned to `{}` is never read", name))
+                .help("maybe it is overwritten before being read?")
+                .emit();
             }
         }
     }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index ab379c9..61341cb 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -13,7 +13,7 @@
 
 pub use self::StabilityLevel::*;
 
-use lint;
+use lint::{self, Lint};
 use hir::{self, Item, Generics, StructField, Variant, HirId};
 use hir::def::Def;
 use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
@@ -562,18 +562,20 @@
             return EvalResult::Allow;
         }
 
-        let lint_deprecated = |def_id: DefId, id: NodeId, note: Option<Symbol>| {
-            let path = self.item_path_str(def_id);
-
+        let lint_deprecated = |def_id: DefId,
+                               id: NodeId,
+                               note: Option<Symbol>,
+                               message: &str,
+                               lint: &'static Lint| {
             let msg = if let Some(note) = note {
-                format!("use of deprecated item '{}': {}", path, note)
+                format!("{}: {}", message, note)
             } else {
-                format!("use of deprecated item '{}'", path)
+                format!("{}", message)
             };
 
-            self.lint_node(lint::builtin::DEPRECATED, id, span, &msg);
+            self.lint_node(lint, id, span, &msg);
             if id == ast::DUMMY_NODE_ID {
-                span_bug!(span, "emitted a deprecated lint with dummy node id: {:?}", def_id);
+                span_bug!(span, "emitted a {} lint with dummy node id: {:?}", lint.name, def_id);
             }
         };
 
@@ -584,17 +586,39 @@
                 // version, then we should display no warning message.
                 let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since {
                     let since = sym.as_str();
-                    !deprecation_in_effect(&since)
+                    if !deprecation_in_effect(&since) {
+                        Some(since)
+                    } else {
+                        None
+                    }
                 } else {
-                    false
+                    None
                 };
 
                 let parent_def_id = self.hir().local_def_id(self.hir().get_parent(id));
-                let skip = deprecated_in_future_version ||
-                           self.lookup_deprecation_entry(parent_def_id)
+                let skip = self.lookup_deprecation_entry(parent_def_id)
                                .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
-                if !skip {
-                    lint_deprecated(def_id, id, depr_entry.attr.note);
+
+                if let Some(since) = deprecated_in_future_version {
+                    let path = self.item_path_str(def_id);
+                    let message = format!("use of item '{}' \
+                                           that will be deprecated in future version {}",
+                                          path,
+                                          since);
+
+                    lint_deprecated(def_id,
+                                    id,
+                                    depr_entry.attr.note,
+                                    &message,
+                                    lint::builtin::DEPRECATED_IN_FUTURE);
+                } else if !skip {
+                    let path = self.item_path_str(def_id);
+                    let message = format!("use of deprecated item '{}'", path);
+                    lint_deprecated(def_id,
+                                    id,
+                                    depr_entry.attr.note,
+                                    &message,
+                                    lint::builtin::DEPRECATED);
                 }
             };
         }
@@ -614,8 +638,24 @@
         if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..})
                 = stability {
             if let Some(id) = id {
+                let path = self.item_path_str(def_id);
                 if deprecation_in_effect(&since.as_str()) {
-                    lint_deprecated(def_id, id, Some(reason));
+                    let message = format!("use of deprecated item '{}'", path);
+                    lint_deprecated(def_id,
+                                    id,
+                                    Some(reason),
+                                    &message,
+                                    lint::builtin::DEPRECATED);
+                } else {
+                    let message = format!("use of item '{}' \
+                                           that will be deprecated in future version {}",
+                                          path,
+                                          since);
+                    lint_deprecated(def_id,
+                                    id,
+                                    Some(reason),
+                                    &message,
+                                    lint::builtin::DEPRECATED_IN_FUTURE);
                 }
             }
         }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 68b5c3e..9dff327 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -149,6 +149,14 @@
     /// This is used for the "rust-call" ABI.
     pub spread_arg: Option<Local>,
 
+    /// Mark this MIR of a const context other than const functions as having converted a `&&` or
+    /// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
+    /// this conversion from happening and use short circuiting, we will cause the following code
+    /// to change the value of `x`: `let mut x = 42; false && { x = 55; true };`
+    ///
+    /// List of places where control flow was destroyed. Used for error reporting.
+    pub control_flow_destroyed: Vec<(Span, String)>,
+
     /// A span representing this MIR, for error reporting
     pub span: Span,
 
@@ -167,6 +175,7 @@
         arg_count: usize,
         upvar_decls: Vec<UpvarDecl>,
         span: Span,
+        control_flow_destroyed: Vec<(Span, String)>,
     ) -> Self {
         // We need `arg_count` locals, and one for the return place
         assert!(
@@ -191,6 +200,7 @@
             spread_arg: None,
             span,
             cache: cache::Cache::new(),
+            control_flow_destroyed,
         }
     }
 
@@ -421,6 +431,7 @@
     arg_count,
     upvar_decls,
     spread_arg,
+    control_flow_destroyed,
     span,
     cache
 });
@@ -1748,6 +1759,9 @@
     /// (e.g., inspecting constants and discriminant values), and the
     /// kind of pattern it comes from. This is in order to adapt potential
     /// error messages to these specific patterns.
+    ///
+    /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
+    /// never accessed still get some sanity checks for e.g. `let x: ! = ..;`
     FakeRead(FakeReadCause, Place<'tcx>),
 
     /// Write the discriminant for a variant to the enum Place.
@@ -2984,6 +2998,7 @@
         arg_count,
         upvar_decls,
         spread_arg,
+        control_flow_destroyed,
         span,
         cache,
     }
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index f10f523..af338cd 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -20,6 +20,7 @@
 use traits::IntercrateMode;
 use traits::select::IntercrateAmbiguityCause;
 use ty::{self, Ty, TyCtxt};
+use ty::relate::TraitObjectMode;
 use ty::fold::TypeFoldable;
 use ty::subst::Subst;
 
@@ -52,6 +53,7 @@
     impl1_def_id: DefId,
     impl2_def_id: DefId,
     intercrate_mode: IntercrateMode,
+    trait_object_mode: TraitObjectMode,
     on_overlap: F1,
     no_overlap: F2,
 ) -> R
@@ -62,12 +64,14 @@
     debug!("overlapping_impls(\
            impl1_def_id={:?}, \
            impl2_def_id={:?},
-           intercrate_mode={:?})",
+           intercrate_mode={:?},
+           trait_object_mode={:?})",
            impl1_def_id,
            impl2_def_id,
-           intercrate_mode);
+           intercrate_mode,
+           trait_object_mode);
 
-    let overlaps = tcx.infer_ctxt().enter(|infcx| {
+    let overlaps = tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
         let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
         overlap(selcx, impl1_def_id, impl2_def_id).is_some()
     });
@@ -79,7 +83,7 @@
     // In the case where we detect an error, run the check again, but
     // this time tracking intercrate ambuiguity causes for better
     // diagnostics. (These take time and can lead to false errors.)
-    tcx.infer_ctxt().enter(|infcx| {
+    tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
         let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
         selcx.enable_tracking_intercrate_ambiguity_causes();
         on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap())
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 4ef4f45..373d665 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -459,7 +459,7 @@
     {
         let simp = fast_reject::simplify_type(self.tcx,
                                               trait_ref.skip_binder().self_ty(),
-                                              true);
+                                              true,);
         let all_impls = self.tcx.all_impls(trait_ref.def_id());
 
         match simp {
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 8d91132..cf37c3f 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -64,6 +64,8 @@
 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
 pub use self::specialize::find_associated_item;
+pub use self::specialize::specialization_graph::FutureCompatOverlapError;
+pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::engine::{TraitEngine, TraitEngineExt};
 pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
 pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index c438542..d46389b 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -44,7 +44,7 @@
 use middle::lang_items;
 use mir::interpret::GlobalId;
 use ty::fast_reject;
-use ty::relate::TypeRelation;
+use ty::relate::{TypeRelation, TraitObjectMode};
 use ty::subst::{Subst, Substs};
 use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
 
@@ -1501,6 +1501,13 @@
             return false;
         }
 
+        // Same idea as the above, but for alt trait object modes. These
+        // should only be used in intercrate mode - better safe than sorry.
+        if self.infcx.trait_object_mode() != TraitObjectMode::NoSquash {
+            bug!("using squashing TraitObjectMode outside of intercrate mode? param_env={:?}",
+                 param_env);
+        }
+
         // Otherwise, we can use the global cache.
         true
     }
@@ -3699,7 +3706,8 @@
         previous: &ty::PolyTraitRef<'tcx>,
         current: &ty::PolyTraitRef<'tcx>,
     ) -> bool {
-        let mut matcher = ty::_match::Match::new(self.tcx());
+        let mut matcher = ty::_match::Match::new(
+            self.tcx(), self.infcx.trait_object_mode());
         matcher.relate(previous, current).is_ok()
     }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 96bb545..70d36e9 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -24,10 +24,10 @@
 use hir::def_id::DefId;
 use infer::{InferCtxt, InferOk};
 use lint;
+use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use syntax_pos::DUMMY_SP;
-use traits::{self, ObligationCause, TraitEngine};
 use traits::select::IntercrateAmbiguityCause;
 use ty::{self, TyCtxt, TypeFoldable};
 use ty::subst::{Subst, Substs};
@@ -36,6 +36,7 @@
 use super::util::impl_trait_ref_and_oblig;
 
 /// Information pertinent to an overlapping impl error.
+#[derive(Debug)]
 pub struct OverlapError {
     pub with_impl: DefId,
     pub trait_desc: String,
@@ -318,8 +319,9 @@
             let insert_result = sg.insert(tcx, impl_def_id);
             // Report error if there was one.
             let (overlap, used_to_be_allowed) = match insert_result {
-                Err(overlap) => (Some(overlap), false),
-                Ok(opt_overlap) => (opt_overlap, true)
+                Err(overlap) => (Some(overlap), None),
+                Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)),
+                Ok(None) => (None, None)
             };
 
             if let Some(overlap) = overlap {
@@ -329,14 +331,20 @@
                         String::new(), |ty| {
                             format!(" for type `{}`", ty)
                         }),
-                    if used_to_be_allowed { " (E0119)" } else { "" }
+                    if used_to_be_allowed.is_some() { " (E0119)" } else { "" }
                 );
                 let impl_span = tcx.sess.source_map().def_span(
                     tcx.span_of_impl(impl_def_id).unwrap()
                 );
-                let mut err = if used_to_be_allowed {
+                let mut err = if let Some(kind) = used_to_be_allowed {
+                    let lint = match kind {
+                        FutureCompatOverlapErrorKind::Issue43355 =>
+                            lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                        FutureCompatOverlapErrorKind::Issue33140 =>
+                            lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
+                    };
                     tcx.struct_span_lint_node(
-                        lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                        lint,
                         tcx.hir().as_local_node_id(impl_def_id).unwrap(),
                         impl_span,
                         &msg)
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index b0ca2f6..1a22866 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -17,6 +17,7 @@
 use traits;
 use ty::{self, TyCtxt, TypeFoldable};
 use ty::fast_reject::{self, SimplifiedType};
+use ty::relate::TraitObjectMode;
 use rustc_data_structures::sync::Lrc;
 use syntax::ast::Ident;
 use util::captures::Captures;
@@ -68,10 +69,22 @@
     blanket_impls: Vec<DefId>,
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum FutureCompatOverlapErrorKind {
+    Issue43355,
+    Issue33140,
+}
+
+#[derive(Debug)]
+pub struct FutureCompatOverlapError {
+    pub error: OverlapError,
+    pub kind: FutureCompatOverlapErrorKind
+}
+
 /// The result of attempting to insert an impl into a group of children.
 enum Inserted {
     /// The impl was inserted as a new child in this group of children.
-    BecameNewSibling(Option<OverlapError>),
+    BecameNewSibling(Option<FutureCompatOverlapError>),
 
     /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
     ReplaceChildren(Vec<DefId>),
@@ -170,6 +183,7 @@
                 possible_sibling,
                 impl_def_id,
                 traits::IntercrateMode::Issue43355,
+                TraitObjectMode::NoSquash,
                 |overlap| {
                     if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
                         return Ok((false, false));
@@ -200,12 +214,36 @@
                 replace_children.push(possible_sibling);
             } else {
                 if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+                    // do future-compat checks for overlap. Have issue #43355
+                    // errors overwrite issue #33140 errors when both are present.
+
                     traits::overlapping_impls(
                         tcx,
                         possible_sibling,
                         impl_def_id,
                         traits::IntercrateMode::Fixed,
-                        |overlap| last_lint = Some(overlap_error(overlap)),
+                        TraitObjectMode::SquashAutoTraitsIssue33140,
+                        |overlap| {
+                            last_lint = Some(FutureCompatOverlapError {
+                                error: overlap_error(overlap),
+                                kind: FutureCompatOverlapErrorKind::Issue33140
+                            });
+                        },
+                        || (),
+                    );
+
+                    traits::overlapping_impls(
+                        tcx,
+                        possible_sibling,
+                        impl_def_id,
+                        traits::IntercrateMode::Fixed,
+                        TraitObjectMode::NoSquash,
+                        |overlap| {
+                            last_lint = Some(FutureCompatOverlapError {
+                                error: overlap_error(overlap),
+                                kind: FutureCompatOverlapErrorKind::Issue43355
+                            });
+                        },
                         || (),
                     );
                 }
@@ -272,7 +310,7 @@
     pub fn insert(&mut self,
                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
                   impl_def_id: DefId)
-                  -> Result<Option<OverlapError>, OverlapError> {
+                  -> Result<Option<FutureCompatOverlapError>, OverlapError> {
         assert!(impl_def_id.is_local());
 
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs
index d20b6d3..29067bf 100644
--- a/src/librustc/ty/_match.rs
+++ b/src/librustc/ty/_match.rs
@@ -29,17 +29,24 @@
 /// important thing about the result is Ok/Err. Also, matching never
 /// affects any type variables or unification state.
 pub struct Match<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'tcx>
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    trait_object_mode: relate::TraitObjectMode
 }
 
 impl<'a, 'gcx, 'tcx> Match<'a, 'gcx, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Match<'a, 'gcx, 'tcx> {
-        Match { tcx }
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+               trait_object_mode: relate::TraitObjectMode)
+               -> Match<'a, 'gcx, 'tcx> {
+        Match { tcx, trait_object_mode }
     }
 }
 
 impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> {
     fn tag(&self) -> &'static str { "Match" }
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.trait_object_mode
+    }
+
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx }
     fn a_is_expected(&self) -> bool { true } // irrelevant
 
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 7005e14..bd01dd8 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -43,6 +43,9 @@
     PtrSimplifiedType,
     NeverSimplifiedType,
     TupleSimplifiedType(usize),
+    /// A trait object, all of whose components are markers
+    /// (e.g., `dyn Send + Sync`).
+    MarkerTraitObjectSimplifiedType,
     TraitSimplifiedType(D),
     ClosureSimplifiedType(D),
     GeneratorSimplifiedType(D),
@@ -78,7 +81,12 @@
         ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
         ty::RawPtr(_) => Some(PtrSimplifiedType),
         ty::Dynamic(ref trait_info, ..) => {
-            Some(TraitSimplifiedType(trait_info.principal().def_id()))
+            let principal_def_id = trait_info.principal().def_id();
+            if tcx.trait_is_auto(principal_def_id) {
+                Some(MarkerTraitObjectSimplifiedType)
+            } else {
+                Some(TraitSimplifiedType(principal_def_id))
+            }
         }
         ty::Ref(_, ty, _) => {
             // since we introduce auto-refs during method lookup, we
@@ -144,6 +152,7 @@
             NeverSimplifiedType => NeverSimplifiedType,
             TupleSimplifiedType(n) => TupleSimplifiedType(n),
             TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
+            MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
             ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
             GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
             GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
@@ -170,7 +179,8 @@
             ArraySimplifiedType |
             PtrSimplifiedType |
             NeverSimplifiedType |
-            ParameterSimplifiedType => {
+            ParameterSimplifiedType |
+            MarkerTraitObjectSimplifiedType => {
                 // nothing to do
             }
             IntSimplifiedType(t) => t.hash_stable(hcx, hasher),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a1fc949..429b7f0 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1754,17 +1754,19 @@
     pub struct AdtFlags: u32 {
         const NO_ADT_FLAGS        = 0;
         const IS_ENUM             = 1 << 0;
-        const IS_PHANTOM_DATA     = 1 << 1;
-        const IS_FUNDAMENTAL      = 1 << 2;
-        const IS_UNION            = 1 << 3;
-        const IS_BOX              = 1 << 4;
+        const IS_UNION            = 1 << 1;
+        const IS_STRUCT           = 1 << 2;
+        const HAS_CTOR            = 1 << 3;
+        const IS_PHANTOM_DATA     = 1 << 4;
+        const IS_FUNDAMENTAL      = 1 << 5;
+        const IS_BOX              = 1 << 6;
         /// Indicates whether the type is an `Arc`.
-        const IS_ARC              = 1 << 5;
+        const IS_ARC              = 1 << 7;
         /// Indicates whether the type is an `Rc`.
-        const IS_RC               = 1 << 6;
+        const IS_RC               = 1 << 8;
         /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
         /// (i.e., this flag is never set unless this ADT is an enum).
-        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 7;
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
     }
 }
 
@@ -2079,31 +2081,43 @@
            repr: ReprOptions) -> Self {
         debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
-        let attrs = tcx.get_attrs(did);
-        if attr::contains_name(&attrs, "fundamental") {
-            flags = flags | AdtFlags::IS_FUNDAMENTAL;
-        }
-        if Some(did) == tcx.lang_items().phantom_data() {
-            flags = flags | AdtFlags::IS_PHANTOM_DATA;
-        }
-        if Some(did) == tcx.lang_items().owned_box() {
-            flags = flags | AdtFlags::IS_BOX;
-        }
-        if Some(did) == tcx.lang_items().arc() {
-            flags = flags | AdtFlags::IS_ARC;
-        }
-        if Some(did) == tcx.lang_items().rc() {
-            flags = flags | AdtFlags::IS_RC;
-        }
+
         if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
             debug!("found non-exhaustive variant list for {:?}", did);
             flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
         }
-        match kind {
-            AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
-            AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
-            AdtKind::Struct => {}
+        flags |= match kind {
+            AdtKind::Enum => AdtFlags::IS_ENUM,
+            AdtKind::Union => AdtFlags::IS_UNION,
+            AdtKind::Struct => AdtFlags::IS_STRUCT,
+        };
+
+        if let AdtKind::Struct = kind {
+            let variant_def = &variants[VariantIdx::new(0)];
+            let def_key = tcx.def_key(variant_def.did);
+            match def_key.disambiguated_data.data {
+                DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
+                _ => (),
+            }
         }
+
+        let attrs = tcx.get_attrs(did);
+        if attr::contains_name(&attrs, "fundamental") {
+            flags |= AdtFlags::IS_FUNDAMENTAL;
+        }
+        if Some(did) == tcx.lang_items().phantom_data() {
+            flags |= AdtFlags::IS_PHANTOM_DATA;
+        }
+        if Some(did) == tcx.lang_items().owned_box() {
+            flags |= AdtFlags::IS_BOX;
+        }
+        if Some(did) == tcx.lang_items().arc() {
+            flags |= AdtFlags::IS_ARC;
+        }
+        if Some(did) == tcx.lang_items().rc() {
+            flags |= AdtFlags::IS_RC;
+        }
+
         AdtDef {
             did,
             variants,
@@ -2114,25 +2128,25 @@
 
     #[inline]
     pub fn is_struct(&self) -> bool {
-        !self.is_union() && !self.is_enum()
+        self.flags.contains(AdtFlags::IS_STRUCT)
     }
 
     #[inline]
     pub fn is_union(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_UNION)
+        self.flags.contains(AdtFlags::IS_UNION)
     }
 
     #[inline]
     pub fn is_enum(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_ENUM)
+        self.flags.contains(AdtFlags::IS_ENUM)
     }
 
     #[inline]
     pub fn is_variant_list_non_exhaustive(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
+        self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
     }
 
-    /// Returns the kind of the ADT - Struct or Enum.
+    /// Returns the kind of the ADT.
     #[inline]
     pub fn adt_kind(&self) -> AdtKind {
         if self.is_enum() {
@@ -2161,33 +2175,39 @@
         }
     }
 
-    /// Returns whether this type is #[fundamental] for the purposes
+    /// If this function returns `true`, it implies that `is_struct` must return `true`.
+    #[inline]
+    pub fn has_ctor(&self) -> bool {
+        self.flags.contains(AdtFlags::HAS_CTOR)
+    }
+
+    /// Returns whether this type is `#[fundamental]` for the purposes
     /// of coherence checking.
     #[inline]
     pub fn is_fundamental(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
+        self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
     }
 
     /// Returns `true` if this is PhantomData<T>.
     #[inline]
     pub fn is_phantom_data(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
+        self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
     }
 
     /// Returns `true` if this is `Arc<T>`.
     pub fn is_arc(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_ARC)
+        self.flags.contains(AdtFlags::IS_ARC)
     }
 
     /// Returns `true` if this is `Rc<T>`.
     pub fn is_rc(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_RC)
+        self.flags.contains(AdtFlags::IS_RC)
     }
 
     /// Returns `true` if this is Box<T>.
     #[inline]
     pub fn is_box(&self) -> bool {
-        self.flags.intersects(AdtFlags::IS_BOX)
+        self.flags.contains(AdtFlags::IS_BOX)
     }
 
     /// Returns whether this type has a destructor.
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 7ad4fd5..88c3e5c 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -35,9 +35,20 @@
     ExistentialRegionBound, // relating an existential region bound
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum TraitObjectMode {
+    NoSquash,
+    /// A temporary mode to treat `Send + Sync = Sync + Send`, should be
+    /// used only in coherence.
+    SquashAutoTraitsIssue33140
+}
+
 pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized {
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx>;
 
+    /// Return the trait object mode to be used.
+    fn trait_object_mode(&self) -> TraitObjectMode;
+
     /// Returns a static string we can use for printouts.
     fn tag(&self) -> &'static str;
 
@@ -596,14 +607,44 @@
                            a: &Self,
                            b: &Self)
         -> RelateResult<'tcx, Self>
-            where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
+        where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
+        use ty::ExistentialPredicate::*;
 
-        if a.len() != b.len() {
+        let tcx = relation.tcx();
+        let (a_buf, b_buf);
+        let (a_norm, b_norm): (&[_], &[_]) = match relation.trait_object_mode() {
+            TraitObjectMode::NoSquash => {
+                (a, b)
+            }
+            TraitObjectMode::SquashAutoTraitsIssue33140 => {
+                // Treat auto-trait "principal" components as equal
+                // to the non-principal components, to make
+                // `dyn Send+Sync = dyn Sync+Send`.
+                let normalize = |d: &[ty::ExistentialPredicate<'tcx>]| {
+                    let mut result: Vec<_> = d.iter().map(|pi| match pi {
+                        Trait(ref a) if tcx.trait_is_auto(a.def_id) => {
+                            AutoTrait(a.def_id)
+                        },
+                        other => *other
+                    }).collect();
+
+                    result.sort_by(|a, b| a.stable_cmp(tcx, b));
+                    result.dedup();
+                    result
+                };
+
+                a_buf = normalize(a);
+                b_buf = normalize(b);
+
+                (&a_buf, &b_buf)
+            }
+        };
+
+        if a_norm.len() != b_norm.len() {
             return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
         }
 
-        let tcx = relation.tcx();
-        let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
+        let v = a_norm.iter().zip(b_norm.iter()).map(|(ep_a, ep_b)| {
             use ty::ExistentialPredicate::*;
             match (*ep_a, *ep_b) {
                 (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index d6aeb28..1d28c4f 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -35,6 +35,7 @@
     usize,
     ::ty::layout::VariantIdx,
     u64,
+    String,
     ::middle::region::Scope,
     ::syntax::ast::FloatTy,
     ::syntax::ast::NodeId,
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index a95ddef..01b1387 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -1024,17 +1024,11 @@
 
     fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("minnum");
-        unsafe {
-            let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs);
-            instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0")
-        }
+        unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
     }
     fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("maxnum");
-        unsafe {
-            let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs);
-            instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0")
-        }
+        unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
     }
 
     fn select(
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 0bd6146..b75cd8f 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -10,7 +10,6 @@
 
 use attributes;
 use llvm;
-use llvm_util;
 use rustc::dep_graph::DepGraphSafe;
 use rustc::hir;
 use debuginfo;
@@ -446,10 +445,6 @@
         attributes::apply_target_cpu_attr(self, llfn)
     }
 
-    fn closure_env_needs_indirect_debuginfo(&self) -> bool {
-        llvm_util::get_major_version() < 6
-    }
-
     fn create_used_variable(&self) {
         let name = const_cstr!("llvm.used");
         let section = const_cstr!("llvm.metadata");
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 8b26ada..e229f8d 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1192,7 +1192,7 @@
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
 
-    // every intrinsic takes a SIMD vector as its first argument
+    // every intrinsic below takes a SIMD vector as its first argument
     require_simd!(arg_tys[0], "input");
     let in_ty = arg_tys[0];
     let in_elem = arg_tys[0].simd_type(tcx);
@@ -1296,6 +1296,7 @@
     if name == "simd_select" {
         let m_elem_ty = in_elem;
         let m_len = in_len;
+        require_simd!(arg_tys[1], "argument");
         let v_len = arg_tys[1].simd_size(tcx);
         require!(m_len == v_len,
                  "mismatched lengths: mask length `{}` != other vector length `{}`",
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 127759a..4732db8 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -1222,12 +1222,12 @@
         B: &Builder<'a>,
         LHS: &'a Value,
         LHS: &'a Value,
-    ) -> Option<&'a Value>;
+    ) -> &'a Value;
     pub fn LLVMRustBuildMaxNum(
         B: &Builder<'a>,
         LHS: &'a Value,
         LHS: &'a Value,
-    ) -> Option<&'a Value>;
+    ) -> &'a Value;
 
     // Atomic Operations
     pub fn LLVMRustBuildAtomicLoad(B: &Builder<'a>,
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 12109ae..82b1d7e 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -140,6 +140,7 @@
     ("avx512vpopcntdq", Some("avx512_target_feature")),
     ("bmi1", None),
     ("bmi2", None),
+    ("cmpxchg16b", Some("cmpxchg16b_target_feature")),
     ("fma", None),
     ("fxsr", None),
     ("lzcnt", None),
@@ -212,6 +213,7 @@
         ("x86", "pclmulqdq") => "pclmul",
         ("x86", "rdrand") => "rdrnd",
         ("x86", "bmi1") => "bmi",
+        ("x86", "cmpxchg16b") => "cx16",
         ("aarch64", "fp") => "fp-armv8",
         ("aarch64", "fp16") => "fullfp16",
         (_, s) => s,
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 750de1c..d316b3e 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -610,35 +610,13 @@
             };
             let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
 
-            // Store the pointer to closure data in an alloca for debuginfo
-            // because that's what the llvm.dbg.declare intrinsic expects.
-
-            // FIXME(eddyb) this shouldn't be necessary but SROA seems to
-            // mishandle DW_OP_plus not preceded by DW_OP_deref, i.e., it
-            // doesn't actually strip the offset when splitting the closure
-            // environment into its components so it ends up out of bounds.
-            // (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
-            let env_alloca = !env_ref && bx.closure_env_needs_indirect_debuginfo();
-            let env_ptr = if env_alloca {
-                let scratch = PlaceRef::alloca(bx,
-                    bx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
-                    "__debuginfo_env_ptr");
-                bx.store(place.llval, scratch.llval, scratch.align);
-                scratch.llval
-            } else {
-                place.llval
-            };
-
             for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
                 let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes();
 
                 let ops = bx.debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env);
 
                 // The environment and the capture can each be indirect.
-
-                // FIXME(eddyb) see above why we sometimes have to keep
-                // a pointer in an alloca for debuginfo atm.
-                let mut ops = if env_ref || env_alloca { &ops[..] } else { &ops[1..] };
+                let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
 
                 let ty = if let (true, &ty::Ref(_, ty, _)) = (decl.by_ref, &ty.sty) {
                     ty
@@ -648,7 +626,7 @@
                 };
 
                 let variable_access = VariableAccess::IndirectVariable {
-                    alloca: env_ptr,
+                    alloca: place.llval,
                     address_operations: &ops
                 };
                 bx.declare_local(
diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs
index d8871dd..57afb80 100644
--- a/src/librustc_codegen_ssa/traits/misc.rs
+++ b/src/librustc_codegen_ssa/traits/misc.rs
@@ -32,7 +32,6 @@
     fn stats(&self) -> &RefCell<Stats>;
     fn consume_stats(self) -> RefCell<Stats>;
     fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
-    fn closure_env_needs_indirect_debuginfo(&self) -> bool;
     fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
     fn set_frame_pointer_elimination(&self, llfn: Self::Value);
     fn apply_target_cpu_attr(&self, llfn: Self::Value);
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 66364ff..3471218 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -294,6 +294,11 @@
             edition: None,
         },
         FutureIncompatibleInfo {
+            id: LintId::of(ORDER_DEPENDENT_TRAIT_OBJECTS),
+            reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
+            edition: None,
+        },
+        FutureIncompatibleInfo {
             id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
             reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
             edition: Some(Edition::Edition2018),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index e3029c6..5eca629 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -545,7 +545,7 @@
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     (place, span),
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                     flow_state,
                 );
@@ -782,7 +782,6 @@
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum ArtificialField {
-    Discriminant,
     ArrayLength,
     ShallowBorrow,
 }
@@ -1191,14 +1190,14 @@
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     (place, span),
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                     flow_state,
                 );
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 8af23a8..07bda8a 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -99,7 +99,7 @@
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     place,
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                 );
             }
@@ -360,14 +360,14 @@
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     place,
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                 );
             }
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index eeac915..e24586c 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -165,15 +165,12 @@
                 let base_ty = base.ty(mir, tcx).to_ty(tcx);
 
                 match (elem, &base_ty.sty, access) {
-                    (_, _, Shallow(Some(ArtificialField::Discriminant)))
-                    | (_, _, Shallow(Some(ArtificialField::ArrayLength)))
+                    (_, _, Shallow(Some(ArtificialField::ArrayLength)))
                     | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
-                        // The discriminant and array length are like
-                        // additional fields on the type; they do not
-                        // overlap any existing data there. Furthermore,
-                        // they cannot actually be a prefix of any
-                        // borrowed place (at least in MIR as it is
-                        // currently.)
+                        // The array length is like  additional fields on the
+                        // type; it does not overlap any existing data there.
+                        // Furthermore, if cannot actually be a prefix of any
+                        // borrowed place (at least in MIR as it is currently.)
                         //
                         // e.g., a (mutable) borrow of `a[5]` while we read the
                         // array length of `a`.
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 7e7c0b1..4d61bf8 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -19,7 +19,6 @@
 use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
 use hair::*;
 use hair::pattern::PatternTypeProjections;
-use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::VariantIdx;
@@ -100,7 +99,7 @@
             .collect();
 
         // create binding start block for link them by false edges
-        let candidate_count = arms.iter().fold(0, |ac, c| ac + c.patterns.len());
+        let candidate_count = arms.iter().map(|c| c.patterns.len()).sum::<usize>();
         let pre_binding_blocks: Vec<_> = (0..=candidate_count)
             .map(|_| self.cfg.start_new_block())
             .collect();
@@ -337,7 +336,7 @@
 
     pub fn place_into_pattern(
         &mut self,
-        mut block: BasicBlock,
+        block: BasicBlock,
         irrefutable_pat: Pattern<'tcx>,
         initializer: &Place<'tcx>,
         set_match_place: bool,
@@ -359,7 +358,7 @@
 
         // Simplify the candidate. Since the pattern is irrefutable, this should
         // always convert all match-pairs into bindings.
-        unpack!(block = self.simplify_candidate(block, &mut candidate));
+        self.simplify_candidate(&mut candidate);
 
         if !candidate.match_pairs.is_empty() {
             span_bug!(
@@ -681,12 +680,7 @@
     },
 
     // test whether the value falls within an inclusive or exclusive range
-    Range {
-        lo: &'tcx ty::Const<'tcx>,
-        hi: &'tcx ty::Const<'tcx>,
-        ty: Ty<'tcx>,
-        end: hir::RangeEnd,
-    },
+    Range(PatternRange<'tcx>),
 
     // test length of the slice is equal to len
     Len {
@@ -745,7 +739,7 @@
         // complete, all the match pairs which remain require some
         // form of test, whether it be a switch or pattern comparison.
         for candidate in &mut candidates {
-            unpack!(block = self.simplify_candidate(block, candidate));
+            self.simplify_candidate(candidate);
         }
 
         // The candidates are sorted by priority. Check to see
@@ -1035,7 +1029,7 @@
             test, match_pair
         );
         let target_blocks = self.perform_test(block, &match_pair.place, &test);
-        let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect();
+        let mut target_candidates = vec![vec![]; target_blocks.len()];
 
         // Sort the candidates into the appropriate vector in
         // `target_candidates`. Note that at some point we may
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index 328b330..0ce6428 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -22,10 +22,9 @@
 //! sort of test: for example, testing which variant an enum is, or
 //! testing a value against a constant.
 
-use build::{BlockAnd, BlockAndExtension, Builder};
+use build::Builder;
 use build::matches::{Ascription, Binding, MatchPair, Candidate};
 use hair::*;
-use rustc::mir::*;
 use rustc::ty;
 use rustc::ty::layout::{Integer, IntegerExt, Size};
 use syntax::attr::{SignedInt, UnsignedInt};
@@ -35,24 +34,23 @@
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub fn simplify_candidate<'pat>(&mut self,
-                                    block: BasicBlock,
-                                    candidate: &mut Candidate<'pat, 'tcx>)
-                                    -> BlockAnd<()> {
+                                    candidate: &mut Candidate<'pat, 'tcx>) {
         // repeatedly simplify match pairs until fixed point is reached
         loop {
             let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
-            let mut progress = match_pairs.len(); // count how many were simplified
+            let mut changed = false;
             for match_pair in match_pairs {
                 match self.simplify_match_pair(match_pair, candidate) {
-                    Ok(()) => {}
+                    Ok(()) => {
+                        changed = true;
+                    }
                     Err(match_pair) => {
                         candidate.match_pairs.push(match_pair);
-                        progress -= 1; // this one was not simplified
                     }
                 }
             }
-            if progress == 0 {
-                return block.unit(); // if we were not able to simplify any, done.
+            if !changed {
+                return; // if we were not able to simplify any, done.
             }
         }
     }
@@ -109,7 +107,7 @@
                 Err(match_pair)
             }
 
-            PatternKind::Range { lo, hi, ty, end } => {
+            PatternKind::Range(PatternRange { lo, hi, ty, end }) => {
                 let range = match ty.sty {
                     ty::Char => {
                         Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32)))
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 5d9cb01..c8dec6d 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -18,6 +18,7 @@
 use build::Builder;
 use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
+use hair::pattern::compare_const_vals;
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashMap;
 use rustc::ty::{self, Ty};
@@ -71,16 +72,11 @@
                 }
             }
 
-            PatternKind::Range { lo, hi, ty, end } => {
-                assert!(ty == match_pair.pattern.ty);
+            PatternKind::Range(range) => {
+                assert!(range.ty == match_pair.pattern.ty);
                 Test {
                     span: match_pair.pattern.span,
-                    kind: TestKind::Range {
-                        lo,
-                        hi,
-                        ty,
-                        end,
-                    },
+                    kind: TestKind::Range(range),
                 }
             }
 
@@ -136,7 +132,11 @@
             PatternKind::Variant { .. } => {
                 panic!("you should have called add_variants_to_switch instead!");
             }
-            PatternKind::Range { .. } |
+            PatternKind::Range(range) => {
+                // Check that none of the switch values are in the range.
+                self.values_not_contained_in_range(range, indices)
+                    .unwrap_or(false)
+            }
             PatternKind::Slice { .. } |
             PatternKind::Array { .. } |
             PatternKind::Wild |
@@ -200,20 +200,18 @@
                 for (idx, discr) in adt_def.discriminants(tcx) {
                     target_blocks.push(if variants.contains(idx) {
                         values.push(discr.val);
-                        targets.push(self.cfg.start_new_block());
-                        *targets.last().unwrap()
+                        let block = self.cfg.start_new_block();
+                        targets.push(block);
+                        block
                     } else {
-                        if otherwise_block.is_none() {
-                            otherwise_block = Some(self.cfg.start_new_block());
-                        }
-                        otherwise_block.unwrap()
+                        *otherwise_block
+                            .get_or_insert_with(|| self.cfg.start_new_block())
                     });
                 }
-                if let Some(otherwise_block) = otherwise_block {
-                    targets.push(otherwise_block);
-                } else {
-                    targets.push(self.unreachable_block());
-                }
+                targets.push(
+                    otherwise_block
+                        .unwrap_or_else(|| self.unreachable_block()),
+                );
                 debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}",
                        num_enum_variants, values, variants);
                 let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
@@ -378,7 +376,7 @@
                 }
             }
 
-            TestKind::Range { ref lo, ref hi, ty, ref end } => {
+            TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => {
                 // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
                 let lo = self.literal_operand(test.span, ty.clone(), lo.clone());
                 let hi = self.literal_operand(test.span, ty.clone(), hi.clone());
@@ -490,8 +488,7 @@
         // away.)
         let tested_match_pair = candidate.match_pairs.iter()
                                                      .enumerate()
-                                                     .filter(|&(_, mp)| mp.place == *test_place)
-                                                     .next();
+                                                     .find(|&(_, mp)| mp.place == *test_place);
         let (match_pair_index, match_pair) = match tested_match_pair {
             Some(pair) => pair,
             None => {
@@ -532,6 +529,24 @@
                 resulting_candidates[index].push(new_candidate);
                 true
             }
+
+            (&TestKind::SwitchInt { switch_ty: _, ref options, ref indices },
+             &PatternKind::Range(range)) => {
+                let not_contained = self
+                    .values_not_contained_in_range(range, indices)
+                    .unwrap_or(false);
+
+                if not_contained {
+                    // No switch values are contained in the pattern range,
+                    // so the pattern can be matched only if this test fails.
+                    let otherwise = options.len();
+                    resulting_candidates[otherwise].push(candidate.clone());
+                    true
+                } else {
+                    false
+                }
+            }
+
             (&TestKind::SwitchInt { .. }, _) => false,
 
 
@@ -610,8 +625,63 @@
                 }
             }
 
+            (&TestKind::Range(test),
+             &PatternKind::Range(pat)) => {
+                if test == pat {
+                    resulting_candidates[0]
+                        .push(self.candidate_without_match_pair(
+                            match_pair_index,
+                            candidate,
+                        ));
+                    return true;
+                }
+
+                let no_overlap = (|| {
+                    use std::cmp::Ordering::*;
+                    use rustc::hir::RangeEnd::*;
+
+                    let param_env = ty::ParamEnv::empty().and(test.ty);
+                    let tcx = self.hir.tcx();
+
+                    let lo = compare_const_vals(tcx, test.lo, pat.hi, param_env)?;
+                    let hi = compare_const_vals(tcx, test.hi, pat.lo, param_env)?;
+
+                    match (test.end, pat.end, lo, hi) {
+                        // pat < test
+                        (_, _, Greater, _) |
+                        (_, Excluded, Equal, _) |
+                        // pat > test
+                        (_, _, _, Less) |
+                        (Excluded, _, _, Equal) => Some(true),
+                        _ => Some(false),
+                    }
+                })();
+
+                if no_overlap == Some(true) {
+                    // Testing range does not overlap with pattern range,
+                    // so the pattern can be matched only if this test fails.
+                    resulting_candidates[1].push(candidate.clone());
+                    true
+                } else {
+                    false
+                }
+            }
+
+            (&TestKind::Range(range), &PatternKind::Constant { ref value }) => {
+                if self.const_range_contains(range, value) == Some(false) {
+                    // `value` is not contained in the testing range,
+                    // so `value` can be matched only if this test fails.
+                    resulting_candidates[1].push(candidate.clone());
+                    true
+                } else {
+                    false
+                }
+            }
+
+            (&TestKind::Range { .. }, _) => false,
+
+
             (&TestKind::Eq { .. }, _) |
-            (&TestKind::Range { .. }, _) |
             (&TestKind::Len { .. }, _) => {
                 // These are all binary tests.
                 //
@@ -722,6 +792,40 @@
                   "simplifyable pattern found: {:?}",
                   match_pair.pattern)
     }
+
+    fn const_range_contains(
+        &self,
+        range: PatternRange<'tcx>,
+        value: &'tcx ty::Const<'tcx>,
+    ) -> Option<bool> {
+        use std::cmp::Ordering::*;
+
+        let param_env = ty::ParamEnv::empty().and(range.ty);
+        let tcx = self.hir.tcx();
+
+        let a = compare_const_vals(tcx, range.lo, value, param_env)?;
+        let b = compare_const_vals(tcx, value, range.hi, param_env)?;
+
+        match (b, range.end) {
+            (Less, _) |
+            (Equal, RangeEnd::Included) if a != Greater => Some(true),
+            _ => Some(false),
+        }
+    }
+
+    fn values_not_contained_in_range(
+        &self,
+        range: PatternRange<'tcx>,
+        indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>,
+    ) -> Option<bool> {
+        for val in indices.keys() {
+            if self.const_range_contains(range, val)? {
+                return Some(false);
+            }
+        }
+
+        Some(true)
+    }
 }
 
 fn is_switch_ty<'tcx>(ty: Ty<'tcx>) -> bool {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index ab52d9b..d6af125 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -111,13 +111,6 @@
 
             let safety = match fn_sig.unsafety {
                 hir::Unsafety::Normal => Safety::Safe,
-                hir::Unsafety::Unsafe if tcx.is_min_const_fn(fn_def_id) => {
-                    // As specified in #55607, a `const unsafe fn` differs
-                    // from an `unsafe fn` in that its body is still considered
-                    // safe code by default.
-                    assert!(implicit_argument.is_none());
-                    Safety::Safe
-                },
                 hir::Unsafety::Unsafe => Safety::FnUnsafe,
             };
 
@@ -856,15 +849,17 @@
             }
         }
 
-        Mir::new(self.cfg.basic_blocks,
-                 self.source_scopes,
-                 ClearCrossCrate::Set(self.source_scope_local_data),
-                 IndexVec::new(),
-                 yield_ty,
-                 self.local_decls,
-                 self.arg_count,
-                 self.upvar_decls,
-                 self.fn_span
+        Mir::new(
+            self.cfg.basic_blocks,
+            self.source_scopes,
+            ClearCrossCrate::Set(self.source_scope_local_data),
+            IndexVec::new(),
+            yield_ty,
+            self.local_decls,
+            self.arg_count,
+            self.upvar_decls,
+            self.fn_span,
+            self.hir.control_flow_destroyed(),
         )
     }
 
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index a1471ad..f93dbce 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -372,6 +372,10 @@
                     // FIXME(eddyb) use logical ops in constants when
                     // they can handle that kind of control-flow.
                     (hir::BinOpKind::And, hir::Constness::Const) => {
+                        cx.control_flow_destroyed.push((
+                            op.span,
+                            "`&&` operator".into(),
+                        ));
                         ExprKind::Binary {
                             op: BinOp::BitAnd,
                             lhs: lhs.to_ref(),
@@ -379,6 +383,10 @@
                         }
                     }
                     (hir::BinOpKind::Or, hir::Constness::Const) => {
+                        cx.control_flow_destroyed.push((
+                            op.span,
+                            "`||` operator".into(),
+                        ));
                         ExprKind::Binary {
                             op: BinOp::BitOr,
                             lhs: lhs.to_ref(),
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index a0b2d99..5d8732b 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -56,6 +56,9 @@
 
     /// True if this constant/function needs overflow checks.
     check_overflow: bool,
+
+    /// See field with the same name on `Mir`
+    control_flow_destroyed: Vec<(Span, String)>,
 }
 
 impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
@@ -96,9 +99,13 @@
             constness,
             body_owner_kind,
             check_overflow,
+            control_flow_destroyed: Vec::new(),
         }
     }
 
+    pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
+        self.control_flow_destroyed
+    }
 }
 
 impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index e604b11..b254fce 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -29,7 +29,7 @@
 mod constant;
 
 pub mod pattern;
-pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
+pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern};
 pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
 
 mod util;
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 5cfcc16..7ec6bbf 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -173,7 +173,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::{FieldPattern, Pattern, PatternKind};
+use super::{FieldPattern, Pattern, PatternKind, PatternRange};
 use super::{PatternFoldable, PatternFolder, compare_const_vals};
 
 use rustc::hir::def_id::DefId;
@@ -604,12 +604,12 @@
                 _ => {
                     match *ctor {
                         ConstantValue(value) => PatternKind::Constant { value },
-                        ConstantRange(lo, hi, ty, end) => PatternKind::Range {
+                        ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange {
                             lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)),
                             hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
                             ty,
                             end,
-                        },
+                        }),
                         _ => PatternKind::Wild,
                     }
                 }
@@ -872,7 +872,7 @@
                 -> Option<IntRange<'tcx>> {
         Self::from_ctor(tcx, &match pat.kind {
             box PatternKind::Constant { value } => ConstantValue(value),
-            box PatternKind::Range { lo, hi, ty, end } => ConstantRange(
+            box PatternKind::Range(PatternRange { lo, hi, ty, end }) => ConstantRange(
                 lo.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
                 hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
                 ty,
@@ -1311,7 +1311,7 @@
             Some(vec![Variant(adt_def.variants[variant_index].did)])
         }
         PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
-        PatternKind::Range { lo, hi, ty, end } =>
+        PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
             Some(vec![ConstantRange(
                 lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
                 hi.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
@@ -1642,7 +1642,7 @@
 ) -> Result<bool, ErrorReported> {
     let (from, to, end, ty) = match pat.kind {
         box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty),
-        box PatternKind::Range { lo, hi, ty, end } => (lo, hi, end, ty),
+        box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty),
         _ => bug!("`constructor_covered_by_range` called with {:?}", pat),
     };
     trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index ddd6a70..f78a70f 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -24,7 +24,7 @@
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -219,12 +219,7 @@
         value: &'tcx ty::Const<'tcx>,
     },
 
-    Range {
-        lo: &'tcx ty::Const<'tcx>,
-        hi: &'tcx ty::Const<'tcx>,
-        ty: Ty<'tcx>,
-        end: RangeEnd,
-    },
+    Range(PatternRange<'tcx>),
 
     /// matches against a slice, checking the length and extracting elements.
     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
@@ -243,6 +238,14 @@
     },
 }
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct PatternRange<'tcx> {
+    pub lo: &'tcx ty::Const<'tcx>,
+    pub hi: &'tcx ty::Const<'tcx>,
+    pub ty: Ty<'tcx>,
+    pub end: RangeEnd,
+}
+
 impl<'tcx> fmt::Display for Pattern<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self.kind {
@@ -354,7 +357,7 @@
             PatternKind::Constant { value } => {
                 fmt_const_val(f, value)
             }
-            PatternKind::Range { lo, hi, ty: _, end } => {
+            PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
                 fmt_const_val(f, lo)?;
                 match end {
                     RangeEnd::Included => write!(f, "..=")?,
@@ -483,7 +486,7 @@
                         );
                         match (end, cmp) {
                             (RangeEnd::Excluded, Some(Ordering::Less)) =>
-                                PatternKind::Range { lo, hi, ty, end },
+                                PatternKind::Range(PatternRange { lo, hi, ty, end }),
                             (RangeEnd::Excluded, _) => {
                                 span_err!(
                                     self.tcx.sess,
@@ -497,7 +500,7 @@
                                 PatternKind::Constant { value: lo }
                             }
                             (RangeEnd::Included, Some(Ordering::Less)) => {
-                                PatternKind::Range { lo, hi, ty, end }
+                                PatternKind::Range(PatternRange { lo, hi, ty, end })
                             }
                             (RangeEnd::Included, _) => {
                                 let mut err = struct_span_err!(
@@ -1177,17 +1180,17 @@
             } => PatternKind::Constant {
                 value: value.fold_with(folder)
             },
-            PatternKind::Range {
+            PatternKind::Range(PatternRange {
                 lo,
                 hi,
                 ty,
                 end,
-            } => PatternKind::Range {
+            }) => PatternKind::Range(PatternRange {
                 lo: lo.fold_with(folder),
                 hi: hi.fold_with(folder),
                 ty: ty.fold_with(folder),
                 end,
-            },
+            }),
             PatternKind::Slice {
                 ref prefix,
                 ref slice,
@@ -1210,8 +1213,8 @@
     }
 }
 
-pub fn compare_const_vals<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn compare_const_vals<'a, 'gcx, 'tcx>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     a: &'tcx ty::Const<'tcx>,
     b: &'tcx ty::Const<'tcx>,
     ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
@@ -1233,6 +1236,9 @@
         return fallback();
     }
 
+    let tcx = tcx.global_tcx();
+    let (a, b, ty) = (a, b, ty).lift_to_tcx(tcx).unwrap();
+
     // FIXME: This should use assert_bits(ty) instead of use_bits
     // but triggers possibly bugs due to mismatching of arrays and slices
     if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 1a35f4d..983488d 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -37,7 +37,7 @@
 #![feature(if_while_or_patterns)]
 #![feature(try_from)]
 #![feature(reverse_bits)]
-#![feature(underscore_imports)]
+#![cfg_attr(stage0, feature(underscore_imports))]
 
 #![recursion_limit="256"]
 
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 1141629..2728833 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -219,7 +219,8 @@
         local_decls_for_sig(&sig, span),
         sig.inputs().len(),
         vec![],
-        span
+        span,
+        vec![],
     );
 
     if let Some(..) = ty {
@@ -396,7 +397,8 @@
             self.local_decls,
             self.sig.inputs().len(),
             vec![],
-            self.span
+            self.span,
+            vec![],
         )
     }
 
@@ -844,7 +846,8 @@
         local_decls,
         sig.inputs().len(),
         vec![],
-        span
+        span,
+        vec![],
     );
     if let Abi::RustCall = sig.abi {
         mir.spread_arg = Some(Local::new(sig.inputs().len()));
@@ -921,6 +924,7 @@
         local_decls,
         sig.inputs().len(),
         vec![],
-        span
+        span,
+        vec![],
     )
 }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 6af29b7..3607869 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -311,13 +311,9 @@
                            violations: &[UnsafetyViolation],
                            unsafe_blocks: &[(ast::NodeId, bool)]) {
         let safety = self.source_scope_local_data[self.source_info.scope].safety;
-        let within_unsafe = match (safety, self.min_const_fn) {
-            // Erring on the safe side, pun intended
-            (Safety::BuiltinUnsafe, true) |
-            // mir building encodes const fn bodies as safe, even for `const unsafe fn`
-            (Safety::FnUnsafe, true) => bug!("const unsafe fn body treated as inherently unsafe"),
+        let within_unsafe = match safety {
             // `unsafe` blocks are required in safe code
-            (Safety::Safe, _) => {
+            Safety::Safe => {
                 for violation in violations {
                     let mut violation = violation.clone();
                     match violation.kind {
@@ -342,9 +338,9 @@
                 }
                 false
             }
-            // regular `unsafe` function bodies allow unsafe without additional unsafe blocks
-            (Safety::BuiltinUnsafe, false) | (Safety::FnUnsafe, false) => true,
-            (Safety::ExplicitUnsafe(node_id), _) => {
+            // `unsafe` function bodies allow unsafe without additional unsafe blocks
+            Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
+            Safety::ExplicitUnsafe(node_id) => {
                 // mark unsafe block as used if there are any unsafe operations inside
                 if !violations.is_empty() {
                     self.used_unsafe.insert(node_id);
@@ -616,21 +612,6 @@
     } in violations.iter() {
         // Report an error.
         match kind {
-            UnsafetyViolationKind::General if tcx.is_min_const_fn(def_id) => {
-                let mut err = tcx.sess.struct_span_err(
-                    source_info.span,
-                    &format!("{} is unsafe and unsafe operations \
-                            are not allowed in const fn", description));
-                err.span_label(source_info.span, &description.as_str()[..])
-                    .note(&details.as_str()[..]);
-                if tcx.fn_sig(def_id).unsafety() == hir::Unsafety::Unsafe {
-                    err.note(
-                        "unsafe action within a `const unsafe fn` still require an `unsafe` \
-                        block in contrast to regular `unsafe fn`."
-                    );
-                }
-                err.emit();
-            }
             UnsafetyViolationKind::GeneralAndConstFn |
             UnsafetyViolationKind::General => {
                 struct_span_err!(
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 7f8dfc1..f5bf73b 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -412,7 +412,8 @@
                 initial_locals,
                 0,
                 vec![],
-                mir.span
+                mir.span,
+                vec![],
             ),
             tcx,
             source: mir,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 5f08dee..58a3cb9 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -553,7 +553,13 @@
                     this.super_place(place, context, location);
                     match proj.elem {
                         ProjectionElem::Deref => {
-                            this.add(Qualif::NOT_CONST);
+                            if context.is_mutating_use() {
+                                // `not_const` errors out in const contexts
+                                this.not_const()
+                            } else {
+                                // just make sure this doesn't get promoted
+                                this.add(Qualif::NOT_CONST);
+                            }
                             let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
                             match this.mode {
                                 Mode::Fn => {},
@@ -1178,7 +1184,6 @@
             if self.mir.local_kind(index) == LocalKind::Var &&
                self.const_fn_arg_vars.insert(index) &&
                !self.tcx.features().const_let {
-
                 // Direct use of an argument is permitted.
                 match *rvalue {
                     Rvalue::Use(Operand::Copy(Place::Local(local))) |
@@ -1189,7 +1194,6 @@
                     }
                     _ => {}
                 }
-
                 // Avoid a generic error for other uses of arguments.
                 if self.qualif.contains(Qualif::FN_ARGUMENT) {
                     let decl = &self.mir.local_decls[index];
@@ -1348,6 +1352,37 @@
             // Do the actual promotion, now that we know what's viable.
             promote_consts::promote_candidates(mir, tcx, temps, candidates);
         } else {
+            if !mir.control_flow_destroyed.is_empty() {
+                let mut locals = mir.vars_iter();
+                if let Some(local) = locals.next() {
+                    let span = mir.local_decls[local].source_info.span;
+                    let mut error = tcx.sess.struct_span_err(
+                        span,
+                        &format!(
+                            "new features like let bindings are not permitted in {}s \
+                            which also use short circuiting operators",
+                            mode,
+                        ),
+                    );
+                    for (span, kind) in mir.control_flow_destroyed.iter() {
+                        error.span_note(
+                            *span,
+                            &format!("use of {} here does not actually short circuit due to \
+                            the const evaluator presently not being able to do control flow. \
+                            See https://github.com/rust-lang/rust/issues/49146 for more \
+                            information.", kind),
+                        );
+                    }
+                    for local in locals {
+                        let span = mir.local_decls[local].source_info.span;
+                        error.span_note(
+                            span,
+                            "more locals defined here",
+                        );
+                    }
+                    error.emit();
+                }
+            }
             let promoted_temps = if mode == Mode::Const {
                 // Already computed by `mir_const_qualif`.
                 const_promoted_temps.unwrap()
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 3c1b9db..eee167c 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -230,7 +230,7 @@
             check_rvalue(tcx, mir, rval, span)
         }
 
-        StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())),
+        StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read),
 
         // just an assignment
         StatementKind::SetDiscriminant { .. } => Ok(()),
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index f643870..592f721 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -108,10 +108,14 @@
     pub fn simplify(mut self) {
         self.strip_nops();
 
+        let mut start = START_BLOCK;
+
         loop {
             let mut changed = false;
 
-            for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) {
+            self.collapse_goto_chain(&mut start, &mut changed);
+
+            for bb in self.basic_blocks.indices() {
                 if self.pred_count[bb] == 0 {
                     continue
                 }
@@ -142,6 +146,27 @@
 
             if !changed { break }
         }
+
+        if start != START_BLOCK {
+            debug_assert!(self.pred_count[START_BLOCK] == 0);
+            self.basic_blocks.swap(START_BLOCK, start);
+            self.pred_count.swap(START_BLOCK, start);
+
+            // pred_count == 1 if the start block has no predecessor _blocks_.
+            if self.pred_count[START_BLOCK] > 1 {
+                for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
+                    if self.pred_count[bb] == 0 {
+                        continue;
+                    }
+
+                    for target in data.terminator_mut().successors_mut() {
+                        if *target == start {
+                            *target = START_BLOCK;
+                        }
+                    }
+                }
+            }
+        }
     }
 
     // Collapse a goto chain starting from `start`
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 42ead92..a5d2edb 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -41,7 +41,6 @@
 pub mod rvalue_promotion;
 pub mod hir_stats;
 pub mod loops;
-mod mir_stats;
 
 __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
 
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
deleted file mode 100644
index fb37f03..0000000
--- a/src/librustc_passes/mir_stats.rs
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// The visitors in this module collect sizes and counts of the most important
-// pieces of MIR. The resulting numbers are good approximations but not
-// completely accurate (some things might be counted twice, others missed).
-
-use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
-use rustc::mir::{Constant, Location, Local, LocalDecl};
-use rustc::mir::{Place, PlaceElem, PlaceProjection};
-use rustc::mir::{Mir, Operand, ProjectionElem};
-use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
-use rustc::mir::{Terminator, TerminatorKind, SourceScope, SourceScopeData};
-use rustc::mir::interpret::EvalErrorKind;
-use rustc::mir::visit as mir_visit;
-use rustc::ty::{self, ClosureSubsts, TyCtxt};
-use rustc::util::nodemap::{FxHashMap};
-
-struct NodeData {
-    count: usize,
-    size: usize,
-}
-
-struct StatCollector<'a, 'tcx: 'a> {
-    _tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    data: FxHashMap<&'static str, NodeData>,
-}
-
-impl<'a, 'tcx> StatCollector<'a, 'tcx> {
-
-    fn record_with_size(&mut self, label: &'static str, node_size: usize) {
-        let entry = self.data.entry(label).or_insert(NodeData {
-            count: 0,
-            size: 0,
-        });
-
-        entry.count += 1;
-        entry.size = node_size;
-    }
-
-    fn record<T>(&mut self, label: &'static str, node: &T) {
-        self.record_with_size(label, ::std::mem::size_of_val(node));
-    }
-}
-
-impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
-    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
-        self.record("Mir", mir);
-
-        // since the `super_mir` method does not traverse the MIR of
-        // promoted rvalues, (but we still want to gather statistics
-        // on the structures represented there) we manually traverse
-        // the promoted rvalues here.
-        for promoted_mir in &mir.promoted {
-            self.visit_mir(promoted_mir);
-        }
-
-        self.super_mir(mir);
-    }
-
-    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
-        self.record("BasicBlockData", data);
-        self.super_basic_block_data(block, data);
-    }
-
-    fn visit_source_scope_data(&mut self, scope_data: &SourceScopeData) {
-        self.record("SourceScopeData", scope_data);
-        self.super_source_scope_data(scope_data);
-    }
-
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &Statement<'tcx>,
-                       location: Location) {
-        self.record("Statement", statement);
-        self.record(match statement.kind {
-            StatementKind::Assign(..) => "StatementKind::Assign",
-            StatementKind::FakeRead(..) => "StatementKind::FakeRead",
-            StatementKind::Retag { .. } => "StatementKind::Retag",
-            StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw",
-            StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
-            StatementKind::StorageLive(..) => "StatementKind::StorageLive",
-            StatementKind::StorageDead(..) => "StatementKind::StorageDead",
-            StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
-            StatementKind::AscribeUserType(..) => "StatementKind::AscribeUserType",
-            StatementKind::Nop => "StatementKind::Nop",
-        }, &statement.kind);
-        self.super_statement(block, statement, location);
-    }
-
-    fn visit_terminator(&mut self,
-                        block: BasicBlock,
-                        terminator: &Terminator<'tcx>,
-                        location: Location) {
-        self.record("Terminator", terminator);
-        self.super_terminator(block, terminator, location);
-    }
-
-    fn visit_terminator_kind(&mut self,
-                             block: BasicBlock,
-                             kind: &TerminatorKind<'tcx>,
-                             location: Location) {
-        self.record("TerminatorKind", kind);
-        self.record(match *kind {
-            TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
-            TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
-            TerminatorKind::Resume => "TerminatorKind::Resume",
-            TerminatorKind::Abort => "TerminatorKind::Abort",
-            TerminatorKind::Return => "TerminatorKind::Return",
-            TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
-            TerminatorKind::Drop { .. } => "TerminatorKind::Drop",
-            TerminatorKind::DropAndReplace { .. } => "TerminatorKind::DropAndReplace",
-            TerminatorKind::Call { .. } => "TerminatorKind::Call",
-            TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
-            TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
-            TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
-            TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
-            TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
-        }, kind);
-        self.super_terminator_kind(block, kind, location);
-    }
-
-    fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>, location: Location) {
-        self.record("AssertMessage", msg);
-        self.record(match *msg {
-            EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
-            EvalErrorKind::Overflow(..) => "AssertMessage::Overflow",
-            EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg",
-            EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero",
-            EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero",
-            EvalErrorKind::GeneratorResumedAfterReturn => {
-                "AssertMessage::GeneratorResumedAfterReturn"
-            }
-            EvalErrorKind::GeneratorResumedAfterPanic => {
-                "AssertMessage::GeneratorResumedAfterPanic"
-            }
-            _ => bug!(),
-        }, msg);
-        self.super_assert_message(msg, location);
-    }
-
-    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        self.record("Rvalue", rvalue);
-        let rvalue_kind = match *rvalue {
-            Rvalue::Use(..) => "Rvalue::Use",
-            Rvalue::Repeat(..) => "Rvalue::Repeat",
-            Rvalue::Ref(..) => "Rvalue::Ref",
-            Rvalue::Len(..) => "Rvalue::Len",
-            Rvalue::Cast(..) => "Rvalue::Cast",
-            Rvalue::BinaryOp(..) => "Rvalue::BinaryOp",
-            Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp",
-            Rvalue::UnaryOp(..) => "Rvalue::UnaryOp",
-            Rvalue::Discriminant(..) => "Rvalue::Discriminant",
-            Rvalue::NullaryOp(..) => "Rvalue::NullaryOp",
-            Rvalue::Aggregate(ref kind, ref _operands) => {
-                // AggregateKind is not distinguished by visit API, so
-                // record it. (`super_rvalue` handles `_operands`.)
-                self.record(match **kind {
-                    AggregateKind::Array(_) => "AggregateKind::Array",
-                    AggregateKind::Tuple => "AggregateKind::Tuple",
-                    AggregateKind::Adt(..) => "AggregateKind::Adt",
-                    AggregateKind::Closure(..) => "AggregateKind::Closure",
-                    AggregateKind::Generator(..) => "AggregateKind::Generator",
-                }, kind);
-
-                "Rvalue::Aggregate"
-            }
-        };
-        self.record(rvalue_kind, rvalue);
-        self.super_rvalue(rvalue, location);
-    }
-
-    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
-        self.record("Operand", operand);
-        self.record(match *operand {
-            Operand::Copy(..) => "Operand::Copy",
-            Operand::Move(..) => "Operand::Move",
-            Operand::Constant(..) => "Operand::Constant",
-        }, operand);
-        self.super_operand(operand, location);
-    }
-
-    fn visit_place(&mut self,
-                    place: &Place<'tcx>,
-                    context: mir_visit::PlaceContext<'tcx>,
-                    location: Location) {
-        self.record("Place", place);
-        self.record(match *place {
-            Place::Local(..) => "Place::Local",
-            Place::Static(..) => "Place::Static",
-            Place::Promoted(..) => "Place::Promoted",
-            Place::Projection(..) => "Place::Projection",
-        }, place);
-        self.super_place(place, context, location);
-    }
-
-    fn visit_projection(&mut self,
-                        place: &PlaceProjection<'tcx>,
-                        context: mir_visit::PlaceContext<'tcx>,
-                        location: Location) {
-        self.record("PlaceProjection", place);
-        self.super_projection(place, context, location);
-    }
-
-    fn visit_projection_elem(&mut self,
-                             place: &PlaceElem<'tcx>,
-                             location: Location) {
-        self.record("PlaceElem", place);
-        self.record(match *place {
-            ProjectionElem::Deref => "PlaceElem::Deref",
-            ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
-            ProjectionElem::Field(..) => "PlaceElem::Field",
-            ProjectionElem::Index(..) => "PlaceElem::Index",
-            ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
-            ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
-        }, place);
-        self.super_projection_elem(place, location);
-    }
-
-    fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
-        self.record("Constant", constant);
-        self.super_constant(constant, location);
-    }
-
-    fn visit_source_info(&mut self, source_info: &SourceInfo) {
-        self.record("SourceInfo", source_info);
-        self.super_source_info(source_info);
-    }
-
-    fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, _: Location) {
-        self.record("ClosureSubsts", substs);
-        self.super_closure_substs(substs);
-    }
-
-    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
-        self.record("Const", constant);
-        self.super_const(constant);
-    }
-
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        self.record("LocalDecl", local_decl);
-        self.super_local_decl(local, local_decl);
-    }
-
-    fn visit_source_scope(&mut self, scope: &SourceScope) {
-        self.record("VisiblityScope", scope);
-        self.super_source_scope(scope);
-    }
-}
diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs
index e926e49..ef41ea3 100644
--- a/src/librustc_target/spec/apple_ios_base.rs
+++ b/src/librustc_target/spec/apple_ios_base.rs
@@ -74,6 +74,8 @@
     args.insert(LinkerFlavor::Gcc,
                 vec!["-arch".to_string(),
                      arch_name.to_string(),
+                     "-isysroot".to_string(),
+                     sdk_root.clone(),
                      "-Wl,-syslibroot".to_string(),
                      sdk_root]);
 
diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
index 07383b3..5b6d8ab 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -49,6 +49,7 @@
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         cpu: "x86-64".into(),
+        features: "+rdrnd,+rdseed".into(),
         position_independent_executables: true,
         pre_link_args: iter::once(
                 (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect())
diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs
index df6458a..73aa8a1 100644
--- a/src/librustc_traits/chalk_context/resolvent_ops.rs
+++ b/src/librustc_traits/chalk_context/resolvent_ops.rs
@@ -17,7 +17,7 @@
 };
 use rustc::ty::{self, Ty};
 use rustc::ty::subst::Kind;
-use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
+use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use syntax_pos::DUMMY_SP;
 
 use super::{ChalkInferenceContext, ChalkArenas, ChalkExClause, ConstrainedSubst};
@@ -137,6 +137,10 @@
         self.infcx.tcx
     }
 
+    fn trait_object_mode(&self) -> relate::TraitObjectMode {
+        self.infcx.trait_object_mode()
+    }
+
     fn tag(&self) -> &'static str {
         "chalk_context::answer_substitutor"
     }
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index e4ce049..75ae868 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -280,7 +280,7 @@
                         Def::Local(id) | Def::Upvar(id, ..) => {
                             Some(self.tcx.hir().span(id))
                         }
-                        _ => self.tcx.hir().span_if_local(def.def_id())
+                        _ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)),
                     };
                     if let Some(span) = def_span {
                         let label = match (unit_variant, inner_callee_path) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 8901f4b..957c8d9 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -95,7 +95,7 @@
 
 use astconv::AstConv;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc::hir::{self, GenericArg, Node, ItemKind, PatKind};
+use rustc::hir::{self, GenericArg, ItemKind, Node, PatKind};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -113,7 +113,8 @@
 use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
                        UserSelfTy, UserSubsts};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
-use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
+use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate,
+                RegionKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::query::Providers;
@@ -3217,8 +3218,8 @@
                             return_expr_ty);
     }
 
-    // A generic function for checking the then and else in an if
-    // or if-else.
+    // A generic function for checking the 'then' and 'else' clauses in an 'if'
+    // or 'if-else' expression.
     fn check_then_else(&self,
                        cond_expr: &'gcx hir::Expr,
                        then_expr: &'gcx hir::Expr,
@@ -3544,7 +3545,7 @@
                 // We don't look at stability attributes on
                 // struct-like enums (yet...), but it's definitely not
                 // a bug to have constructed one.
-                if adt_kind != ty::AdtKind::Enum {
+                if adt_kind != AdtKind::Enum {
                     tcx.check_stability(v_field.did, Some(expr_id), field.span);
                 }
 
@@ -5156,26 +5157,48 @@
         }).unwrap_or(false);
 
         let mut new_def = def;
-        let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
-            let ty = self.impl_self_ty(span, impl_def_id).ty;
+        let (def_id, ty) = match def {
+            Def::SelfCtor(impl_def_id) => {
+                let ty = self.impl_self_ty(span, impl_def_id).ty;
+                let adt_def = ty.ty_adt_def();
 
-            match ty.ty_adt_def() {
-                Some(adt_def) if adt_def.is_struct() => {
-                    let variant = adt_def.non_enum_variant();
-                    new_def = Def::StructCtor(variant.did, variant.ctor_kind);
-                    (variant.did, self.tcx.type_of(variant.did))
-                }
-                _ => {
-                    (impl_def_id, self.tcx.types.err)
+                match adt_def {
+                    Some(adt_def) if adt_def.has_ctor() => {
+                        let variant = adt_def.non_enum_variant();
+                        new_def = Def::StructCtor(variant.did, variant.ctor_kind);
+                        (variant.did, self.tcx.type_of(variant.did))
+                    }
+                    _ => {
+                        let mut err = self.tcx.sess.struct_span_err(span,
+                            "the `Self` constructor can only be used with tuple or unit structs");
+                        if let Some(adt_def) = adt_def {
+                            match adt_def.adt_kind() {
+                                AdtKind::Enum => {
+                                    err.note("did you mean to use one of the enum's variants?");
+                                },
+                                AdtKind::Struct |
+                                AdtKind::Union => {
+                                    err.span_label(
+                                        span,
+                                        format!("did you mean `Self {{ /* fields */ }}`?"),
+                                    );
+                                }
+                            }
+                        }
+                        err.emit();
+
+                        (impl_def_id, self.tcx.types.err)
+                    }
                 }
             }
-        } else {
-            let def_id = def.def_id();
+            _ => {
+                let def_id = def.def_id();
 
-            // The things we are substituting into the type should not contain
-            // escaping late-bound regions, and nor should the base type scheme.
-            let ty = self.tcx.type_of(def_id);
-            (def_id, ty)
+                // The things we are substituting into the type should not contain
+                // escaping late-bound regions, and nor should the base type scheme.
+                let ty = self.tcx.type_of(def_id);
+                (def_id, ty)
+            }
         };
 
         let substs = AstConv::create_substs_for_generic_args(
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index ec1a439..c273c8f 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -12,8 +12,9 @@
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::traits::{self, IntercrateMode};
+use rustc::traits::{self, IntercrateMode, FutureCompatOverlapErrorKind};
 use rustc::ty::TyCtxt;
+use rustc::ty::relate::TraitObjectMode;
 
 use lint;
 
@@ -29,9 +30,11 @@
 }
 
 impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
-    fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId,
-                                       overlap: traits::OverlapResult,
-                                       used_to_be_allowed: bool) {
+    fn check_for_common_items_in_impls(
+        &self, impl1: DefId, impl2: DefId,
+        overlap: traits::OverlapResult,
+        used_to_be_allowed: Option<FutureCompatOverlapErrorKind>)
+    {
 
         let name_and_namespace = |def_id| {
             let item = self.tcx.associated_item(def_id);
@@ -47,19 +50,28 @@
             for &item2 in &impl_items2[..] {
                 if (name, namespace) == name_and_namespace(item2) {
                     let node_id = self.tcx.hir().as_local_node_id(impl1);
-                    let mut err = if used_to_be_allowed && node_id.is_some() {
-                        self.tcx.struct_span_lint_node(
-                            lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
-                            node_id.unwrap(),
-                            self.tcx.span_of_impl(item1).unwrap(),
-                            &format!("duplicate definitions with name `{}` (E0592)", name)
-                        )
-                    } else {
-                        struct_span_err!(self.tcx.sess,
-                                         self.tcx.span_of_impl(item1).unwrap(),
-                                         E0592,
-                                         "duplicate definitions with name `{}`",
-                                         name)
+                    let mut err = match used_to_be_allowed {
+                        Some(kind) if node_id.is_some() => {
+                            let lint = match kind {
+                                FutureCompatOverlapErrorKind::Issue43355 =>
+                                    lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                                FutureCompatOverlapErrorKind::Issue33140 =>
+                                    lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
+                            };
+                            self.tcx.struct_span_lint_node(
+                                lint,
+                                node_id.unwrap(),
+                                self.tcx.span_of_impl(item1).unwrap(),
+                                &format!("duplicate definitions with name `{}` (E0592)", name)
+                            )
+                        }
+                        _ => {
+                            struct_span_err!(self.tcx.sess,
+                                             self.tcx.span_of_impl(item1).unwrap(),
+                                             E0592,
+                                             "duplicate definitions with name `{}`",
+                                             name)
+                        }
                     };
 
                     err.span_label(self.tcx.span_of_impl(item1).unwrap(),
@@ -82,38 +94,73 @@
 
         for (i, &impl1_def_id) in impls.iter().enumerate() {
             for &impl2_def_id in &impls[(i + 1)..] {
+                // First, check if the impl was forbidden under the
+                // old rules. In that case, just have an error.
                 let used_to_be_allowed = traits::overlapping_impls(
                     self.tcx,
                     impl1_def_id,
                     impl2_def_id,
                     IntercrateMode::Issue43355,
+                    TraitObjectMode::NoSquash,
                     |overlap| {
                         self.check_for_common_items_in_impls(
                             impl1_def_id,
                             impl2_def_id,
                             overlap,
-                            false,
+                            None,
                         );
                         false
                     },
                     || true,
                 );
 
-                if used_to_be_allowed {
-                    traits::overlapping_impls(
-                        self.tcx,
-                        impl1_def_id,
-                        impl2_def_id,
-                        IntercrateMode::Fixed,
-                        |overlap| self.check_for_common_items_in_impls(
+                if !used_to_be_allowed {
+                    continue;
+                }
+
+                // Then, check if the impl was forbidden under only
+                // #43355. In that case, emit an #43355 error.
+                let used_to_be_allowed = traits::overlapping_impls(
+                    self.tcx,
+                    impl1_def_id,
+                    impl2_def_id,
+                    IntercrateMode::Fixed,
+                    TraitObjectMode::NoSquash,
+                    |overlap| {
+                        self.check_for_common_items_in_impls(
                             impl1_def_id,
                             impl2_def_id,
                             overlap,
-                            true,
-                        ),
-                        || (),
-                    );
+                            Some(FutureCompatOverlapErrorKind::Issue43355),
+                        );
+                        false
+                    },
+                    || true,
+                );
+
+                if !used_to_be_allowed {
+                    continue;
                 }
+
+                // Then, check if the impl was forbidden under
+                // #33140. In that case, emit a #33140 error.
+                traits::overlapping_impls(
+                    self.tcx,
+                    impl1_def_id,
+                    impl2_def_id,
+                    IntercrateMode::Fixed,
+                    TraitObjectMode::SquashAutoTraitsIssue33140,
+                    |overlap| {
+                        self.check_for_common_items_in_impls(
+                            impl1_def_id,
+                            impl2_def_id,
+                            overlap,
+                            Some(FutureCompatOverlapErrorKind::Issue33140),
+                        );
+                        false
+                    },
+                    || true,
+                );
             }
         }
     }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index c9f3aa0..46002c0 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -868,10 +868,10 @@
     }
 
     {
-        let mut data = static_files::STORAGE_JS.to_owned();
-        data.push_str(&format!("var resourcesSuffix = \"{}\";", cx.shared.resource_suffix));
         write_minify(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)),
-                     &data,
+                     &format!("var resourcesSuffix = \"{}\";{}",
+                              cx.shared.resource_suffix,
+                              static_files::STORAGE_JS),
                      options.enable_minification)?;
     }
 
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 51714c3..d5b8ecd 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -213,9 +213,9 @@
     function expandSection(id) {
         var elem = document.getElementById(id);
         if (elem && isHidden(elem)) {
-            var h3 = elem.parentNode.previousSibling;
+            var h3 = elem.parentNode.previousElementSibling;
             if (h3 && h3.tagName !== "H3") {
-                h3 = h3.previousSibling; // skip div.docblock
+                h3 = h3.previousElementSibling; // skip div.docblock
             }
 
             if (h3) {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index d1336b1..01d2cbe 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -305,7 +305,7 @@
 	overflow-x: auto;
 }
 
-body:not(.source) .example-wrap > pre {
+.rustdoc:not(.source) .example-wrap > pre {
 	margin: 0;
 }
 
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
index d1c377b..22ac52f 100644
--- a/src/librustdoc/html/static/storage.js
+++ b/src/librustdoc/html/static/storage.js
@@ -111,7 +111,7 @@
 
     var found = false;
     if (savedHref.length === 0) {
-        onEach(document.getElementsByTagName("link"), function(el) {
+        onEachLazy(document.getElementsByTagName("link"), function(el) {
             savedHref.push(el.href);
         });
     }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 50acde6..84ce9f6 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -395,6 +395,7 @@
     // Now push any outer attributes from the example, assuming they
     // are intended to be crate attributes.
     prog.push_str(&crate_attrs);
+    prog.push_str(&crates);
 
     // Uses libsyntax to parse the doctest and find if there's a main fn and the extern
     // crate already is included.
@@ -488,37 +489,78 @@
         prog.push_str("\n}");
     }
 
+    debug!("final doctest:\n{}", prog);
+
     (prog, line_offset)
 }
 
 // FIXME(aburka): use a real parser to deal with multiline attributes
 fn partition_source(s: &str) -> (String, String, String) {
-    let mut after_header = false;
+    #[derive(Copy, Clone, PartialEq)]
+    enum PartitionState {
+        Attrs,
+        Crates,
+        Other,
+    }
+    let mut state = PartitionState::Attrs;
     let mut before = String::new();
     let mut crates = String::new();
     let mut after = String::new();
 
     for line in s.lines() {
         let trimline = line.trim();
-        let header = trimline.chars().all(|c| c.is_whitespace()) ||
-            trimline.starts_with("#![") ||
-            trimline.starts_with("#[macro_use] extern crate") ||
-            trimline.starts_with("extern crate");
-        if !header || after_header {
-            after_header = true;
-            after.push_str(line);
-            after.push_str("\n");
-        } else {
-            if trimline.starts_with("#[macro_use] extern crate")
-                || trimline.starts_with("extern crate") {
+
+        // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
+        // shunted into "everything else"
+        match state {
+            PartitionState::Attrs => {
+                state = if trimline.starts_with("#![") ||
+                    trimline.chars().all(|c| c.is_whitespace()) ||
+                    (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Attrs
+                } else if trimline.starts_with("extern crate") ||
+                    trimline.starts_with("#[macro_use] extern crate")
+                {
+                    PartitionState::Crates
+                } else {
+                    PartitionState::Other
+                };
+            }
+            PartitionState::Crates => {
+                state = if trimline.starts_with("extern crate") ||
+                    trimline.starts_with("#[macro_use] extern crate") ||
+                    trimline.chars().all(|c| c.is_whitespace()) ||
+                    (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Crates
+                } else {
+                    PartitionState::Other
+                };
+            }
+            PartitionState::Other => {}
+        }
+
+        match state {
+            PartitionState::Attrs => {
+                before.push_str(line);
+                before.push_str("\n");
+            }
+            PartitionState::Crates => {
                 crates.push_str(line);
                 crates.push_str("\n");
             }
-            before.push_str(line);
-            before.push_str("\n");
+            PartitionState::Other => {
+                after.push_str(line);
+                after.push_str("\n");
+            }
         }
     }
 
+    debug!("before:\n{}", before);
+    debug!("crates:\n{}", crates);
+    debug!("after:\n{}", after);
+
     (before, after, crates)
 }
 
@@ -1035,8 +1077,8 @@
 assert_eq!(2+2, 4);";
         let expected =
 "#![allow(unused)]
-fn main() {
 //Ceci n'est pas une `fn main`
+fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
         let output = make_test(input, None, false, &opts);
@@ -1083,8 +1125,8 @@
 
         let expected =
 "#![allow(unused)]
-fn main() {
 // fn main
+fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
 
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 41e778b..9cee00b 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -21,6 +21,7 @@
 compiler_builtins = { version = "0.1.1" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
+rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = "0.6.1"
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 7d17aaf..d0dd4d4 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -550,7 +550,8 @@
     #[inline]
     #[rustc_deprecated(since = "1.10.0",
                        reason = "you probably meant `(self - other).abs()`: \
-                                 this operation is `(self - other).max(0.0)` (also \
+                                 this operation is `(self - other).max(0.0)` \
+                                 except that `abs_sub` also propagates NaNs (also \
                                  known as `fdimf` in C). If you truly need the positive \
                                  difference, consider using that expression or the C function \
                                  `fdimf`, depending on how you wish to handle NaN (please consider \
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index c800763..9e627ec 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -491,7 +491,8 @@
     #[inline]
     #[rustc_deprecated(since = "1.10.0",
                        reason = "you probably meant `(self - other).abs()`: \
-                                 this operation is `(self - other).max(0.0)` (also \
+                                 this operation is `(self - other).max(0.0)` \
+                                 except that `abs_sub` also propagates NaNs (also \
                                  known as `fdim` in C). If you truly need the positive \
                                  difference, consider using that expression or the C function \
                                  `fdim`, depending on how you wish to handle NaN (please consider \
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index edcfdd9..35ae493 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1729,7 +1729,7 @@
 /// limited to just these cases:
 ///
 /// * `path` does not exist.
-/// * A component in path is not a directory.
+/// * A non-final component in path is not a directory.
 ///
 /// # Examples
 ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 0febbe5..ead38f2 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -339,6 +339,7 @@
 extern crate alloc as alloc_crate;
 #[doc(masked)]
 extern crate libc;
+extern crate rustc_demangle;
 
 // We always need an unwinder currently for backtraces
 #[doc(masked)]
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index 95faf3a..05f30f2 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -27,6 +27,10 @@
           all(target_os = "android", any(target_arch = "aarch64",
                                          target_arch = "arm")),
           all(target_os = "l4re", target_arch = "x86_64"),
+          all(target_os = "freebsd", any(target_arch = "aarch64",
+                                         target_arch = "arm",
+                                         target_arch = "powerpc",
+                                         target_arch = "powerpc64")),
           all(target_os = "netbsd", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc")),
@@ -42,6 +46,10 @@
               all(target_os = "android", any(target_arch = "aarch64",
                                              target_arch = "arm")),
               all(target_os = "l4re", target_arch = "x86_64"),
+              all(target_os = "freebsd", any(target_arch = "aarch64",
+                                             target_arch = "arm",
+                                             target_arch = "powerpc",
+                                             target_arch = "powerpc64")),
               all(target_os = "netbsd", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc")),
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 7737178..e44113f 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -14,11 +14,12 @@
 use env;
 use io::prelude::*;
 use io;
+use path::{self, Path};
+use ptr;
+use rustc_demangle::demangle;
 use str;
 use sync::atomic::{self, Ordering};
-use path::{self, Path};
 use sys::mutex::Mutex;
-use ptr;
 
 pub use sys::backtrace::{
     unwind_backtrace,
@@ -191,7 +192,14 @@
         PrintFormat::Short => write!(w, "  {:2}: ", idx)?,
     }
     match s {
-        Some(string) => demangle(w, string, format)?,
+        Some(string) => {
+            let symbol = demangle(string);
+            match format {
+                PrintFormat::Full => write!(w, "{}", symbol)?,
+                // strip the trailing hash if short mode
+                PrintFormat::Short => write!(w, "{:#}", symbol)?,
+            }
+        }
         None => w.write_all(b"<unknown>")?,
     }
     w.write_all(b"\n")
@@ -235,228 +243,3 @@
     w.write_all(b"\n")
 }
 
-
-// All rust symbols are in theory lists of "::"-separated identifiers. Some
-// assemblers, however, can't handle these characters in symbol names. To get
-// around this, we use C++-style mangling. The mangling method is:
-//
-// 1. Prefix the symbol with "_ZN"
-// 2. For each element of the path, emit the length plus the element
-// 3. End the path with "E"
-//
-// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar".
-//
-// We're the ones printing our backtraces, so we can't rely on anything else to
-// demangle our symbols. It's *much* nicer to look at demangled symbols, so
-// this function is implemented to give us nice pretty output.
-//
-// Note that this demangler isn't quite as fancy as it could be. We have lots
-// of other information in our symbols like hashes, version, type information,
-// etc. Additionally, this doesn't handle glue symbols at all.
-pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
-    // During ThinLTO LLVM may import and rename internal symbols, so strip out
-    // those endings first as they're one of the last manglings applied to
-    // symbol names.
-    let llvm = ".llvm.";
-    if let Some(i) = s.find(llvm) {
-        let candidate = &s[i + llvm.len()..];
-        let all_hex = candidate.chars().all(|c| {
-            match c {
-                'A' ..= 'F' | '0' ..= '9' => true,
-                _ => false,
-            }
-        });
-
-        if all_hex {
-            s = &s[..i];
-        }
-    }
-
-    // Validate the symbol. If it doesn't look like anything we're
-    // expecting, we just print it literally. Note that we must handle non-rust
-    // symbols because we could have any function in the backtrace.
-    let mut valid = true;
-    let mut inner = s;
-    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
-        inner = &s[3 .. s.len() - 1];
-    // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
-    } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
-        inner = &s[2 .. s.len() - 1];
-    } else {
-        valid = false;
-    }
-
-    if valid {
-        let mut chars = inner.chars();
-        while valid {
-            let mut i = 0;
-            for c in chars.by_ref() {
-                if c.is_numeric() {
-                    i = i * 10 + c as usize - '0' as usize;
-                } else {
-                    break
-                }
-            }
-            if i == 0 {
-                valid = chars.next().is_none();
-                break
-            } else if chars.by_ref().take(i - 1).count() != i - 1 {
-                valid = false;
-            }
-        }
-    }
-
-    // Alright, let's do this.
-    if !valid {
-        writer.write_all(s.as_bytes())?;
-    } else {
-        // remove the `::hfc2edb670e5eda97` part at the end of the symbol.
-        if format == PrintFormat::Short {
-            // The symbol in still mangled.
-            let mut split = inner.rsplitn(2, "17h");
-            match (split.next(), split.next()) {
-                (Some(addr), rest) => {
-                    if addr.len() == 16 &&
-                       addr.chars().all(|c| c.is_digit(16))
-                    {
-                        inner = rest.unwrap_or("");
-                    }
-                }
-                _ => (),
-            }
-        }
-
-        let mut first = true;
-        while !inner.is_empty() {
-            if !first {
-                writer.write_all(b"::")?;
-            } else {
-                first = false;
-            }
-            let mut rest = inner;
-            while rest.chars().next().unwrap().is_numeric() {
-                rest = &rest[1..];
-            }
-            let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap();
-            inner = &rest[i..];
-            rest = &rest[..i];
-            if rest.starts_with("_$") {
-                rest = &rest[1..];
-            }
-            while !rest.is_empty() {
-                if rest.starts_with(".") {
-                    if let Some('.') = rest[1..].chars().next() {
-                        writer.write_all(b"::")?;
-                        rest = &rest[2..];
-                    } else {
-                        writer.write_all(b".")?;
-                        rest = &rest[1..];
-                    }
-                } else if rest.starts_with("$") {
-                    macro_rules! demangle {
-                        ($($pat:expr => $demangled:expr),*) => ({
-                            $(if rest.starts_with($pat) {
-                                writer.write_all($demangled)?;
-                                rest = &rest[$pat.len()..];
-                              } else)*
-                            {
-                                writer.write_all(rest.as_bytes())?;
-                                break;
-                            }
-
-                        })
-                    }
-
-                    // see src/librustc/back/link.rs for these mappings
-                    demangle! (
-                        "$SP$" => b"@",
-                        "$BP$" => b"*",
-                        "$RF$" => b"&",
-                        "$LT$" => b"<",
-                        "$GT$" => b">",
-                        "$LP$" => b"(",
-                        "$RP$" => b")",
-                        "$C$" => b",",
-
-                        // in theory we can demangle any Unicode code point, but
-                        // for simplicity we just catch the common ones.
-                        "$u7e$" => b"~",
-                        "$u20$" => b" ",
-                        "$u27$" => b"'",
-                        "$u5b$" => b"[",
-                        "$u5d$" => b"]",
-                        "$u7b$" => b"{",
-                        "$u7d$" => b"}",
-                        "$u3b$" => b";",
-                        "$u2b$" => b"+",
-                        "$u22$" => b"\""
-                    )
-                } else {
-                    let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') {
-                        None => rest.len(),
-                        Some((i, _)) => i,
-                    };
-                    writer.write_all(rest[..idx].as_bytes())?;
-                    rest = &rest[idx..];
-                }
-            }
-        }
-    }
-
-    Ok(())
-}
-
-#[cfg(test)]
-mod tests {
-    use sys_common;
-    macro_rules! t { ($a:expr, $b:expr) => ({
-        let mut m = Vec::new();
-        sys_common::backtrace::demangle(&mut m,
-                                        $a,
-                                        super::PrintFormat::Full).unwrap();
-        assert_eq!(String::from_utf8(m).unwrap(), $b);
-    }) }
-
-    #[test]
-    fn demangle() {
-        t!("test", "test");
-        t!("_ZN4testE", "test");
-        t!("_ZN4test", "_ZN4test");
-        t!("_ZN4test1a2bcE", "test::a::bc");
-    }
-
-    #[test]
-    fn demangle_dollars() {
-        t!("_ZN4$RP$E", ")");
-        t!("_ZN8$RF$testE", "&test");
-        t!("_ZN8$BP$test4foobE", "*test::foob");
-        t!("_ZN9$u20$test4foobE", " test::foob");
-        t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>");
-    }
-
-    #[test]
-    fn demangle_many_dollars() {
-        t!("_ZN13test$u20$test4foobE", "test test::foob");
-        t!("_ZN12test$BP$test4foobE", "test*test::foob");
-    }
-
-    #[test]
-    fn demangle_windows() {
-        t!("ZN4testE", "test");
-        t!("ZN13test$u20$test4foobE", "test test::foob");
-        t!("ZN12test$RF$test4foobE", "test&test::foob");
-    }
-
-    #[test]
-    fn demangle_elements_beginning_with_underscore() {
-        t!("_ZN13_$LT$test$GT$E", "<test>");
-        t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}");
-        t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR");
-    }
-
-    #[test]
-    fn demangle_trait_impls() {
-        t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE",
-           "<Test + 'static as foo::Bar<Test>>::bar");
-    }
-}
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 7723c15..73cbe49 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -483,7 +483,7 @@
             last_pos = segment.ident.span.hi();
         }
         idents.push(self.node.tokens(self.span));
-        TokenStream::concat(idents)
+        TokenStream::new(idents)
     }
 
     fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
@@ -539,7 +539,7 @@
         match *self {
             MetaItemKind::Word => TokenStream::empty(),
             MetaItemKind::NameValue(ref lit) => {
-                TokenStream::concat(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()])
+                TokenStream::new(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()])
             }
             MetaItemKind::List(ref list) => {
                 let mut tokens = Vec::new();
@@ -552,7 +552,7 @@
                 TokenTree::Delimited(
                     DelimSpan::from_single(span),
                     token::Paren,
-                    TokenStream::concat(tokens).into(),
+                    TokenStream::new(tokens).into(),
                 ).into()
             }
         }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index f4e9a7e..03c7aa9 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{self, Block, Ident, NodeId, PatKind, Path};
+use ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path};
 use ast::{MacStmtStyle, StmtKind, ItemKind};
 use attr::{self, HasAttrs};
 use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
@@ -1535,21 +1535,65 @@
                             let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info);
                             items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item)));
                         }
-                        Err(ref e) if e.kind() == ErrorKind::InvalidData => {
-                            self.cx.span_err(
-                                at.span,
-                                &format!("{} wasn't a utf-8 file", filename.display()),
-                            );
-                        }
                         Err(e) => {
-                            self.cx.span_err(
-                                at.span,
-                                &format!("couldn't read {}: {}", filename.display(), e),
-                            );
+                            let lit = it
+                                .meta_item()
+                                .and_then(|item| item.name_value_literal())
+                                .unwrap();
+
+                            if e.kind() == ErrorKind::InvalidData {
+                                self.cx
+                                    .struct_span_err(
+                                        lit.span,
+                                        &format!("{} wasn't a utf-8 file", filename.display()),
+                                    )
+                                    .span_label(lit.span, "contains invalid utf-8")
+                                    .emit();
+                            } else {
+                                let mut err = self.cx.struct_span_err(
+                                    lit.span,
+                                    &format!("couldn't read {}: {}", filename.display(), e),
+                                );
+                                err.span_label(lit.span, "couldn't read file");
+
+                                if e.kind() == ErrorKind::NotFound {
+                                    err.help("external doc paths are relative to the crate root");
+                                }
+
+                                err.emit();
+                            }
                         }
                     }
                 } else {
-                    items.push(noop_fold_meta_list_item(it, self));
+                    let mut err = self.cx.struct_span_err(
+                        it.span,
+                        &format!("expected path to external documentation"),
+                    );
+
+                    // Check if the user erroneously used `doc(include(...))` syntax.
+                    let literal = it.meta_item_list().and_then(|list| {
+                        if list.len() == 1 {
+                            list[0].literal().map(|literal| &literal.node)
+                        } else {
+                            None
+                        }
+                    });
+
+                    let (path, applicability) = match &literal {
+                        Some(LitKind::Str(path, ..)) => {
+                            (path.to_string(), Applicability::MachineApplicable)
+                        }
+                        _ => (String::from("<path>"), Applicability::HasPlaceholders),
+                    };
+
+                    err.span_suggestion_with_applicability(
+                        it.span,
+                        "provide a file path with `=`",
+                        format!("include = \"{}\"", path),
+                        applicability,
+                    );
+
+                    err.emit();
                 }
             }
 
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index c3497a1..5820b49 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -247,7 +247,7 @@
 
             let delim_span = DelimSpan::from_single(self.span);
             r.push(TokenTree::Delimited(
-                delim_span, token::Bracket, TokenStream::concat(inner).into()
+                delim_span, token::Bracket, TokenStream::new(inner).into()
             ));
             r
         }
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index a76779f..a63abd4 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -103,12 +103,12 @@
                 }
                 Frame::Delimited { forest, span, .. } => {
                     if result_stack.is_empty() {
-                        return TokenStream::concat(result);
+                        return TokenStream::new(result);
                     }
                     let tree = TokenTree::Delimited(
                         span,
                         forest.delim,
-                        TokenStream::concat(result).into(),
+                        TokenStream::new(result).into(),
                     );
                     result = result_stack.pop().unwrap();
                     result.push(tree.into());
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 1a4de59..4eca0c9 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -400,9 +400,6 @@
     // Allows `#[repr(packed)]` attribute on structs.
     (active, repr_packed, "1.26.0", Some(33158), None),
 
-    // Allows `use path as _;` and `extern crate c as _;`.
-    (active, underscore_imports, "1.26.0", Some(48216), None),
-
     // Allows macro invocations in `extern {}` blocks.
     (active, macros_in_extern, "1.27.0", Some(49476), None),
 
@@ -694,6 +691,8 @@
     (accepted, self_struct_ctor, "1.32.0", Some(51994), None),
     // `Self` in type definitions (RFC 2300)
     (accepted, self_in_typedefs, "1.32.0", Some(49303), None),
+    // `use path as _;` and `extern crate c as _;`
+    (accepted, underscore_imports, "1.33.0", Some(48216), None),
 );
 
 // If you change this, please modify `src/doc/unstable-book` as well. You must
@@ -1547,26 +1546,8 @@
         }
     }
 
-    fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) {
-        if let ast::UseTreeKind::Simple(Some(ident), ..) = use_tree.kind {
-            if ident.name == "_" {
-                gate_feature_post!(&self, underscore_imports, use_tree.span,
-                                   "renaming imports with `_` is unstable");
-            }
-        }
-
-        visit::walk_use_tree(self, use_tree, id);
-    }
-
     fn visit_item(&mut self, i: &'a ast::Item) {
         match i.node {
-            ast::ItemKind::ExternCrate(_) => {
-                if i.ident.name == "_" {
-                    gate_feature_post!(&self, underscore_imports, i.span,
-                                       "renaming extern crates with `_` is unstable");
-                }
-            }
-
             ast::ItemKind::Static(..) |
             ast::ItemKind::Const(_,_) => {
                 if i.ident.name == "_" {
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 0c24c20..1fa11a4 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -145,12 +145,6 @@
     #[cfg(test)]
     pub mod parser_testing;
     pub mod move_map;
-
-    mod rc_slice;
-    pub use self::rc_slice::RcSlice;
-
-    mod rc_vec;
-    pub use self::rc_vec::RcVec;
 }
 
 pub mod json;
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 4ff6048..1bd0656 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -170,7 +170,7 @@
                     token::CloseDelim(_) | token::Eof => self.unexpected()?,
                     _ => self.parse_token_tree(),
                 };
-                TokenStream::concat(vec![eq.into(), tree.into()])
+                TokenStream::new(vec![eq.into(), tree.into()])
             } else {
                 TokenStream::empty()
             };
diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs
index 86c87cf..0906c25c 100644
--- a/src/libsyntax/parse/lexer/tokentrees.rs
+++ b/src/libsyntax/parse/lexer/tokentrees.rs
@@ -22,7 +22,7 @@
             tts.push(self.parse_token_tree()?);
         }
 
-        Ok(TokenStream::concat(tts))
+        Ok(TokenStream::new(tts))
     }
 
     // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
@@ -30,14 +30,14 @@
         let mut tts = vec![];
         loop {
             if let token::CloseDelim(..) = self.token {
-                return TokenStream::concat(tts);
+                return TokenStream::new(tts);
             }
 
             match self.parse_token_tree() {
                 Ok(tree) => tts.push(tree),
                 Err(mut e) => {
                     e.emit();
-                    return TokenStream::concat(tts);
+                    return TokenStream::new(tts);
                 }
             }
         }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 10c451e..e3cccac 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -863,13 +863,13 @@
         with_globals(|| {
             let tts = string_to_stream("fn a (b : i32) { b; }".to_string());
 
-            let expected = TokenStream::concat(vec![
+            let expected = TokenStream::new(vec![
                 TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"), false)).into(),
                 TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"), false)).into(),
                 TokenTree::Delimited(
                     DelimSpan::from_pair(sp(5, 6), sp(13, 14)),
                     token::DelimToken::Paren,
-                    TokenStream::concat(vec![
+                    TokenStream::new(vec![
                         TokenTree::Token(sp(6, 7),
                                          token::Ident(Ident::from_str("b"), false)).into(),
                         TokenTree::Token(sp(8, 9), token::Colon).into(),
@@ -880,7 +880,7 @@
                 TokenTree::Delimited(
                     DelimSpan::from_pair(sp(15, 16), sp(20, 21)),
                     token::DelimToken::Brace,
-                    TokenStream::concat(vec![
+                    TokenStream::new(vec![
                         TokenTree::Token(sp(17, 18),
                                          token::Ident(Ident::from_str("b"), false)).into(),
                         TokenTree::Token(sp(18, 19), token::Semi).into(),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a4326d9..a672a08 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2939,7 +2939,7 @@
                 _ => result.push(self.parse_token_tree().into()),
             }
         }
-        TokenStream::concat(result)
+        TokenStream::new(result)
     }
 
     /// Parse a prefix-unary-operator expr
@@ -4635,7 +4635,7 @@
                         self.unexpected()?;
                         unreachable!()
                     };
-                    TokenStream::concat(vec![
+                    TokenStream::new(vec![
                         args.into(),
                         TokenTree::Token(token_lo.to(self.prev_span), token::FatArrow).into(),
                         body.into(),
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 90191c5..c11ef33 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -28,8 +28,8 @@
 use parse::Directory;
 use parse::token::{self, DelimToken, Token};
 use print::pprust;
+use rustc_data_structures::sync::Lrc;
 use serialize::{Decoder, Decodable, Encoder, Encodable};
-use util::RcVec;
 
 use std::borrow::Cow;
 use std::{fmt, iter, mem};
@@ -123,7 +123,7 @@
     }
 
     pub fn joint(self) -> TokenStream {
-        TokenStream { kind: TokenStreamKind::JointTree(self) }
+        TokenStream::JointTree(self)
     }
 
     /// Returns the opening delimiter as a token tree.
@@ -154,65 +154,57 @@
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat.
 #[derive(Clone, Debug)]
-pub struct TokenStream {
-    kind: TokenStreamKind,
+pub enum TokenStream {
+    Empty,
+    Tree(TokenTree),
+    JointTree(TokenTree),
+    Stream(Lrc<Vec<TokenStream>>),
 }
 
 // `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>() == 40);
+static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
 
 impl TokenStream {
     /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
     /// 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 TokenStreamKind::Stream(ref slice) = self.kind {
+        if let TokenStream::Stream(ref stream) = self {
             let mut suggestion = None;
-            let mut iter = slice.iter().enumerate().peekable();
+            let mut iter = stream.iter().enumerate().peekable();
             while let Some((pos, ts)) = iter.next() {
                 if let Some((_, next)) = iter.peek() {
-                    let sp = match (&ts.kind, &next.kind) {
-                        (TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma)), _) |
-                        (_, TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma))) => {
+                    let sp = match (&ts, &next) {
+                        (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma)), _) |
+                        (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma))) => {
                             continue;
                         }
-                        (TokenStreamKind::Tree(TokenTree::Token(sp, _)), _) => *sp,
-                        (TokenStreamKind::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(),
+                        (TokenStream::Tree(TokenTree::Token(sp, _)), _) => *sp,
+                        (TokenStream::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(),
                         _ => continue,
                     };
                     let sp = sp.shrink_to_hi();
-                    let comma = TokenStream {
-                        kind: TokenStreamKind::Tree(TokenTree::Token(sp, token::Comma)),
-                    };
+                    let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma));
                     suggestion = Some((pos, comma, sp));
                 }
             }
             if let Some((pos, comma, sp)) = suggestion {
-                let mut new_slice = vec![];
-                let parts = slice.split_at(pos + 1);
-                new_slice.extend_from_slice(parts.0);
-                new_slice.push(comma);
-                new_slice.extend_from_slice(parts.1);
-                let slice = RcVec::new(new_slice);
-                return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, sp));
+                let mut new_stream = vec![];
+                let parts = stream.split_at(pos + 1);
+                new_stream.extend_from_slice(parts.0);
+                new_stream.push(comma);
+                new_stream.extend_from_slice(parts.1);
+                return Some((TokenStream::new(new_stream), sp));
             }
         }
         None
     }
 }
 
-#[derive(Clone, Debug)]
-enum TokenStreamKind {
-    Empty,
-    Tree(TokenTree),
-    JointTree(TokenTree),
-    Stream(RcVec<TokenStream>),
-}
-
 impl From<TokenTree> for TokenStream {
     fn from(tt: TokenTree) -> TokenStream {
-        TokenStream { kind: TokenStreamKind::Tree(tt) }
+        TokenStream::Tree(tt)
     }
 }
 
@@ -224,29 +216,29 @@
 
 impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
-        TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>())
+        TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<_>>())
     }
 }
 
 impl Extend<TokenStream> for TokenStream {
     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, iter: I) {
         let iter = iter.into_iter();
-        let kind = mem::replace(&mut self.kind, TokenStreamKind::Empty);
+        let this = mem::replace(self, TokenStream::Empty);
 
         // Vector of token streams originally in self.
-        let tts: Vec<TokenStream> = match kind {
-            TokenStreamKind::Empty => {
+        let tts: Vec<TokenStream> = match this {
+            TokenStream::Empty => {
                 let mut vec = Vec::new();
                 vec.reserve(iter.size_hint().0);
                 vec
             }
-            TokenStreamKind::Tree(_) | TokenStreamKind::JointTree(_) => {
+            TokenStream::Tree(_) | TokenStream::JointTree(_) => {
                 let mut vec = Vec::new();
                 vec.reserve(1 + iter.size_hint().0);
-                vec.push(TokenStream { kind });
+                vec.push(this);
                 vec
             }
-            TokenStreamKind::Stream(rc_vec) => match RcVec::try_unwrap(rc_vec) {
+            TokenStream::Stream(rc_vec) => match Lrc::try_unwrap(rc_vec) {
                 Ok(mut vec) => {
                     // Extend in place using the existing capacity if possible.
                     // This is the fast path for libraries like `quote` that
@@ -273,12 +265,7 @@
         // Build the resulting token stream. If it contains more than one token,
         // preserve capacity in the vector in anticipation of the caller
         // performing additional calls to extend.
-        let mut tts = builder.0;
-        *self = match tts.len() {
-            0 => TokenStream::empty(),
-            1 => tts.pop().unwrap(),
-            _ => TokenStream::concat_rc_vec(RcVec::new_preserving_capacity(tts)),
-        };
+        *self = TokenStream::new(builder.0);
     }
 }
 
@@ -292,7 +279,7 @@
 
 impl TokenStream {
     pub fn len(&self) -> usize {
-        if let TokenStreamKind::Stream(ref slice) = self.kind {
+        if let TokenStream::Stream(ref slice) = self {
             slice.len()
         } else {
             0
@@ -300,28 +287,24 @@
     }
 
     pub fn empty() -> TokenStream {
-        TokenStream { kind: TokenStreamKind::Empty }
+        TokenStream::Empty
     }
 
     pub fn is_empty(&self) -> bool {
-        match self.kind {
-            TokenStreamKind::Empty => true,
+        match self {
+            TokenStream::Empty => true,
             _ => false,
         }
     }
 
-    pub fn concat(mut streams: Vec<TokenStream>) -> TokenStream {
+    pub fn new(mut streams: Vec<TokenStream>) -> TokenStream {
         match streams.len() {
             0 => TokenStream::empty(),
             1 => streams.pop().unwrap(),
-            _ => TokenStream::concat_rc_vec(RcVec::new(streams)),
+            _ => TokenStream::Stream(Lrc::new(streams)),
         }
     }
 
-    fn concat_rc_vec(streams: RcVec<TokenStream>) -> TokenStream {
-        TokenStream { kind: TokenStreamKind::Stream(streams) }
-    }
-
     pub fn trees(&self) -> Cursor {
         self.clone().into_trees()
     }
@@ -383,9 +366,9 @@
     /// Precondition: `self` consists of a single token tree.
     /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`.
     pub fn as_tree(self) -> (TokenTree, bool /* joint? */) {
-        match self.kind {
-            TokenStreamKind::Tree(tree) => (tree, false),
-            TokenStreamKind::JointTree(tree) => (tree, true),
+        match self {
+            TokenStream::Tree(tree) => (tree, false),
+            TokenStream::JointTree(tree) => (tree, true),
             _ => unreachable!(),
         }
     }
@@ -395,43 +378,43 @@
         let mut result = Vec::new();
         let mut i = 0;
         while let Some(stream) = trees.next_as_stream() {
-            result.push(match stream.kind {
-                TokenStreamKind::Tree(tree) => f(i, tree).into(),
-                TokenStreamKind::JointTree(tree) => f(i, tree).joint(),
+            result.push(match stream {
+                TokenStream::Tree(tree) => f(i, tree).into(),
+                TokenStream::JointTree(tree) => f(i, tree).joint(),
                 _ => unreachable!()
             });
             i += 1;
         }
-        TokenStream::concat(result)
+        TokenStream::new(result)
     }
 
     pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
         let mut trees = self.into_trees();
         let mut result = Vec::new();
         while let Some(stream) = trees.next_as_stream() {
-            result.push(match stream.kind {
-                TokenStreamKind::Tree(tree) => f(tree).into(),
-                TokenStreamKind::JointTree(tree) => f(tree).joint(),
+            result.push(match stream {
+                TokenStream::Tree(tree) => f(tree).into(),
+                TokenStream::JointTree(tree) => f(tree).joint(),
                 _ => unreachable!()
             });
         }
-        TokenStream::concat(result)
+        TokenStream::new(result)
     }
 
     fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> {
-        match self.kind {
-            TokenStreamKind::Empty => None,
-            TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)),
-            TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)),
-            TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
+        match self {
+            TokenStream::Empty => None,
+            TokenStream::Tree(ref tree) => Some((tree.clone(), false)),
+            TokenStream::JointTree(ref tree) => Some((tree.clone(), true)),
+            TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
         }
     }
 
     fn last_tree_if_joint(&self) -> Option<TokenTree> {
-        match self.kind {
-            TokenStreamKind::Empty | TokenStreamKind::Tree(..) => None,
-            TokenStreamKind::JointTree(ref tree) => Some(tree.clone()),
-            TokenStreamKind::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(),
+        match self {
+            TokenStream::Empty | TokenStream::Tree(..) => None,
+            TokenStream::JointTree(ref tree) => Some(tree.clone()),
+            TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(),
         }
     }
 }
@@ -474,28 +457,28 @@
     }
 
     pub fn build(self) -> TokenStream {
-        TokenStream::concat(self.0)
+        TokenStream::new(self.0)
     }
 
     fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
-        if let TokenStreamKind::Stream(ref streams) = stream.kind {
+        if let TokenStream::Stream(ref streams) = stream {
             let len = streams.len();
             match len {
                 1 => {}
                 2 => self.0.push(streams[0].clone().into()),
-                _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(0 .. len - 1))),
+                _ => self.0.push(TokenStream::new(streams[0 .. len - 1].to_vec())),
             }
             self.push_all_but_last_tree(&streams[len - 1])
         }
     }
 
     fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
-        if let TokenStreamKind::Stream(ref streams) = stream.kind {
+        if let TokenStream::Stream(ref streams) = stream {
             let len = streams.len();
             match len {
                 1 => {}
                 2 => self.0.push(streams[1].clone().into()),
-                _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(1 .. len))),
+                _ => self.0.push(TokenStream::new(streams[1 .. len].to_vec())),
             }
             self.push_all_but_first_tree(&streams[0])
         }
@@ -515,13 +498,13 @@
 
 #[derive(Clone)]
 struct StreamCursor {
-    stream: RcVec<TokenStream>,
+    stream: Lrc<Vec<TokenStream>>,
     index: usize,
-    stack: Vec<(RcVec<TokenStream>, usize)>,
+    stack: Vec<(Lrc<Vec<TokenStream>>, usize)>,
 }
 
 impl StreamCursor {
-    fn new(stream: RcVec<TokenStream>) -> Self {
+    fn new(stream: Lrc<Vec<TokenStream>>) -> Self {
         StreamCursor { stream: stream, index: 0, stack: Vec::new() }
     }
 
@@ -530,10 +513,10 @@
             if self.index < self.stream.len() {
                 self.index += 1;
                 let next = self.stream[self.index - 1].clone();
-                match next.kind {
-                    TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => return Some(next),
-                    TokenStreamKind::Stream(stream) => self.insert(stream),
-                    TokenStreamKind::Empty => {}
+                match next {
+                    TokenStream::Tree(..) | TokenStream::JointTree(..) => return Some(next),
+                    TokenStream::Stream(stream) => self.insert(stream),
+                    TokenStream::Empty => {}
                 }
             } else if let Some((stream, index)) = self.stack.pop() {
                 self.stream = stream;
@@ -544,7 +527,7 @@
         }
     }
 
-    fn insert(&mut self, stream: RcVec<TokenStream>) {
+    fn insert(&mut self, stream: Lrc<Vec<TokenStream>>) {
         self.stack.push((mem::replace(&mut self.stream, stream),
                          mem::replace(&mut self.index, 0)));
     }
@@ -554,8 +537,8 @@
     type Item = TokenTree;
 
     fn next(&mut self) -> Option<TokenTree> {
-        self.next_as_stream().map(|stream| match stream.kind {
-            TokenStreamKind::Tree(tree) | TokenStreamKind::JointTree(tree) => tree,
+        self.next_as_stream().map(|stream| match stream {
+            TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree,
             _ => unreachable!()
         })
     }
@@ -563,11 +546,11 @@
 
 impl Cursor {
     fn new(stream: TokenStream) -> Self {
-        Cursor(match stream.kind {
-            TokenStreamKind::Empty => CursorKind::Empty,
-            TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false),
-            TokenStreamKind::JointTree(tree) => CursorKind::JointTree(tree, false),
-            TokenStreamKind::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)),
+        Cursor(match stream {
+            TokenStream::Empty => CursorKind::Empty,
+            TokenStream::Tree(tree) => CursorKind::Tree(tree, false),
+            TokenStream::JointTree(tree) => CursorKind::JointTree(tree, false),
+            TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)),
         })
     }
 
@@ -590,7 +573,7 @@
             _ if stream.is_empty() => return,
             CursorKind::Empty => *self = stream.trees(),
             CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => {
-                *self = TokenStream::concat(vec![self.original_stream(), stream]).trees();
+                *self = TokenStream::new(vec![self.original_stream(), stream]).trees();
                 if consumed {
                     self.next();
                 }
@@ -606,21 +589,21 @@
             CursorKind::Empty => TokenStream::empty(),
             CursorKind::Tree(ref tree, _) => tree.clone().into(),
             CursorKind::JointTree(ref tree, _) => tree.clone().joint(),
-            CursorKind::Stream(ref cursor) => TokenStream::concat_rc_vec({
+            CursorKind::Stream(ref cursor) => TokenStream::Stream(
                 cursor.stack.get(0).cloned().map(|(stream, _)| stream)
                     .unwrap_or_else(|| cursor.stream.clone())
-            }),
+            ),
         }
     }
 
     pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
         fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize> {
             for stream in streams {
-                n = match stream.kind {
-                    TokenStreamKind::Tree(ref tree) | TokenStreamKind::JointTree(ref tree)
+                n = match stream {
+                    TokenStream::Tree(ref tree) | TokenStream::JointTree(ref tree)
                         if n == 0 => return Ok(tree.clone()),
-                    TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => n - 1,
-                    TokenStreamKind::Stream(ref stream) => match look_ahead(stream, n) {
+                    TokenStream::Tree(..) | TokenStream::JointTree(..) => n - 1,
+                    TokenStream::Stream(ref stream) => match look_ahead(stream, n) {
                         Ok(tree) => return Ok(tree),
                         Err(n) => n,
                     },
@@ -656,7 +639,7 @@
 /// `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<RcVec<TokenStream>>);
+pub struct ThinTokenStream(Option<Lrc<Vec<TokenStream>>>);
 
 impl ThinTokenStream {
     pub fn stream(&self) -> TokenStream {
@@ -666,18 +649,18 @@
 
 impl From<TokenStream> for ThinTokenStream {
     fn from(stream: TokenStream) -> ThinTokenStream {
-        ThinTokenStream(match stream.kind {
-            TokenStreamKind::Empty => None,
-            TokenStreamKind::Tree(tree) => Some(RcVec::new(vec![tree.into()])),
-            TokenStreamKind::JointTree(tree) => Some(RcVec::new(vec![tree.joint()])),
-            TokenStreamKind::Stream(stream) => Some(stream),
+        ThinTokenStream(match stream {
+            TokenStream::Empty => None,
+            TokenStream::Tree(tree) => Some(Lrc::new(vec![tree.into()])),
+            TokenStream::JointTree(tree) => Some(Lrc::new(vec![tree.joint()])),
+            TokenStream::Stream(stream) => Some(stream),
         })
     }
 }
 
 impl From<ThinTokenStream> for TokenStream {
     fn from(stream: ThinTokenStream) -> TokenStream {
-        stream.0.map(TokenStream::concat_rc_vec).unwrap_or_else(TokenStream::empty)
+        stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty)
     }
 }
 
@@ -776,7 +759,7 @@
             let test_res = string_to_ts("foo::bar::baz");
             let test_fst = string_to_ts("foo::bar");
             let test_snd = string_to_ts("::baz");
-            let eq_res = TokenStream::concat(vec![test_fst, test_snd]);
+            let eq_res = TokenStream::new(vec![test_fst, test_snd]);
             assert_eq!(test_res.trees().count(), 5);
             assert_eq!(eq_res.trees().count(), 5);
             assert_eq!(test_res.eq_unspanned(&eq_res), true);
diff --git a/src/libsyntax/util/rc_slice.rs b/src/libsyntax/util/rc_slice.rs
deleted file mode 100644
index 520b7a4..0000000
--- a/src/libsyntax/util/rc_slice.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt;
-use std::ops::{Deref, Range};
-use rustc_data_structures::sync::Lrc;
-
-use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
-                                           HashStable};
-
-#[derive(Clone)]
-pub struct RcSlice<T> {
-    data: Lrc<Box<[T]>>,
-    offset: u32,
-    len: u32,
-}
-
-impl<T> RcSlice<T> {
-    pub fn new(vec: Vec<T>) -> Self {
-        RcSlice {
-            offset: 0,
-            len: vec.len() as u32,
-            data: Lrc::new(vec.into_boxed_slice()),
-        }
-    }
-
-    pub fn sub_slice(&self, range: Range<usize>) -> Self {
-        RcSlice {
-            data: self.data.clone(),
-            offset: self.offset + range.start as u32,
-            len: (range.end - range.start) as u32,
-        }
-    }
-}
-
-impl<T> Deref for RcSlice<T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        &self.data[self.offset as usize .. (self.offset + self.len) as usize]
-    }
-}
-
-impl<T: fmt::Debug> fmt::Debug for RcSlice<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self.deref(), f)
-    }
-}
-
-impl<CTX, T> HashStable<CTX> for RcSlice<T>
-    where T: HashStable<CTX>
-{
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut CTX,
-                                          hasher: &mut StableHasher<W>) {
-        (**self).hash_stable(hcx, hasher);
-    }
-}
diff --git a/src/libsyntax/util/rc_vec.rs b/src/libsyntax/util/rc_vec.rs
deleted file mode 100644
index 99fbce1..0000000
--- a/src/libsyntax/util/rc_vec.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt;
-use std::ops::{Deref, Range};
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
-use rustc_data_structures::sync::Lrc;
-
-#[derive(Clone)]
-pub struct RcVec<T> {
-    data: Lrc<Vec<T>>,
-    offset: u32,
-    len: u32,
-}
-
-impl<T> RcVec<T> {
-    pub fn new(mut vec: Vec<T>) -> Self {
-        // By default, constructing RcVec from Vec gives it just enough capacity
-        // to hold the initial elements. Callers that anticipate needing to
-        // extend the vector may prefer RcVec::new_preserving_capacity.
-        vec.shrink_to_fit();
-        Self::new_preserving_capacity(vec)
-    }
-
-    pub fn new_preserving_capacity(vec: Vec<T>) -> Self {
-        RcVec {
-            offset: 0,
-            len: vec.len() as u32,
-            data: Lrc::new(vec),
-        }
-    }
-
-    pub fn sub_slice(&self, range: Range<usize>) -> Self {
-        RcVec {
-            data: self.data.clone(),
-            offset: self.offset + range.start as u32,
-            len: (range.end - range.start) as u32,
-        }
-    }
-
-    /// If this RcVec has exactly one strong reference, returns ownership of the
-    /// underlying vector. Otherwise returns self unmodified.
-    pub fn try_unwrap(self) -> Result<Vec<T>, Self> {
-        match Lrc::try_unwrap(self.data) {
-            // If no other RcVec shares ownership of this data.
-            Ok(mut vec) => {
-                // Drop any elements after our view of the data.
-                vec.truncate(self.offset as usize + self.len as usize);
-                // Drop any elements before our view of the data. Do this after
-                // the `truncate` so that elements past the end of our view do
-                // not need to be copied around.
-                vec.drain(..self.offset as usize);
-                Ok(vec)
-            }
-
-            // If the data is shared.
-            Err(data) => Err(RcVec { data, ..self }),
-        }
-    }
-}
-
-impl<T> Deref for RcVec<T> {
-    type Target = [T];
-    fn deref(&self) -> &[T] {
-        &self.data[self.offset as usize..(self.offset + self.len) as usize]
-    }
-}
-
-impl<T: fmt::Debug> fmt::Debug for RcVec<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self.deref(), f)
-    }
-}
-
-impl<CTX, T> HashStable<CTX> for RcVec<T>
-where
-    T: HashStable<CTX>,
-{
-    fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) {
-        (**self).hash_stable(hcx, hasher);
-    }
-}
diff --git a/src/llvm b/src/llvm
index a784eca..95185c8 160000
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit a784eca10d2c1f09e65d67e16eca266485e1eac3
+Subproject commit 95185c8c801c765ac1072392d081d265af9fb310
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 1355c03..2f8dc0d 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -216,16 +216,11 @@
       Members.push_back(std::move(*MOrErr));
     }
   }
+
   auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
-#if LLVM_VERSION_GE(6, 0)
   if (!Result)
     return LLVMRustResult::Success;
   LLVMRustSetLastError(toString(std::move(Result)).c_str());
-#else
-  if (!Result.second)
-    return LLVMRustResult::Success;
-  LLVMRustSetLastError(Result.second.message().c_str());
-#endif
 
   return LLVMRustResult::Failure;
 }
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index aa420bf..4d95368 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -17,21 +17,15 @@
 
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
+#include "llvm/IR/IntrinsicInst.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
-
-#if LLVM_VERSION_GE(6, 0)
-#include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/IR/IntrinsicInst.h"
-#else
-#include "llvm/Target/TargetSubtargetInfo.h"
-#endif
-
 #include "llvm/Transforms/IPO/AlwaysInliner.h"
 #include "llvm/Transforms/IPO/FunctionImport.h"
 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
@@ -198,13 +192,9 @@
 
 extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
                                    const char *Feature) {
-#if LLVM_VERSION_GE(6, 0)
   TargetMachine *Target = unwrap(TM);
   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
   return MCInfo->checkFeatures(std::string("+") + Feature);
-#else
-  return false;
-#endif
 }
 
 enum class LLVMRustCodeModel {
@@ -392,13 +382,9 @@
     Options.ThreadModel = ThreadModel::Single;
   }
 
-#if LLVM_VERSION_GE(6, 0)
   Options.EmitStackSizeSection = EmitStackSizeSection;
 
   Optional<CodeModel::Model> CM;
-#else
-  CodeModel::Model CM = CodeModel::Model::Default;
-#endif
   if (RustCM != LLVMRustCodeModel::None)
     CM = fromRust(RustCM);
   TargetMachine *TM = TheTarget->createTargetMachine(
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index b9a0b43..86c5dfc 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -297,11 +297,7 @@
 // enable fpmath flag UnsafeAlgebra
 extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) {
   if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
-#if LLVM_VERSION_GE(6, 0)
     I->setFast(true);
-#else
-    I->setHasUnsafeAlgebra(true);
-#endif
   }
 }
 
@@ -1437,7 +1433,6 @@
   return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
 }
 
-#if LLVM_VERSION_GE(6, 0)
 extern "C" LLVMValueRef
 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
     return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
@@ -1446,13 +1441,3 @@
 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
     return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
 }
-#else
-extern "C" LLVMValueRef
-LLVMRustBuildMinNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
-   return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildMaxNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
-   return nullptr;
-}
-#endif
diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger
index 9cf17c4..a268838 100644
--- a/src/rustllvm/llvm-rebuild-trigger
+++ b/src/rustllvm/llvm-rebuild-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-11-28
+2018-12-13
diff --git a/src/stdsimd b/src/stdsimd
index 5e628c5..3c0503d 160000
--- a/src/stdsimd
+++ b/src/stdsimd
@@ -1 +1 @@
-Subproject commit 5e628c5120c619a22799187371f057ec41e06f87
+Subproject commit 3c0503db8439928e42c1175f0009c506fc874ae9
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index 5061d9a..52bdb1b 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -10,7 +10,6 @@
 
 // compile-flags: -C no-prepopulate-passes
 // ignore-tidy-linelength
-// min-llvm-version 6.0
 
 #![crate_type = "lib"]
 #![feature(custom_attribute)]
diff --git a/src/test/codegen/issue-44056-macos-tls-align.rs b/src/test/codegen/issue-44056-macos-tls-align.rs
index b146e10..ebd436c 100644
--- a/src/test/codegen/issue-44056-macos-tls-align.rs
+++ b/src/test/codegen/issue-44056-macos-tls-align.rs
@@ -11,7 +11,6 @@
 // ignore-tidy-linelength
 // only-macos
 // no-system-llvm
-// min-llvm-version 6.0
 // compile-flags: -O
 
 #![crate_type = "rlib"]
diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs
index 3544786..a6e633b 100644
--- a/src/test/codegen/issue-45222.rs
+++ b/src/test/codegen/issue-45222.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // compile-flags: -O
-// min-llvm-version 6.0
 
 #![crate_type = "lib"]
 
diff --git a/src/test/codegen/issue-45466.rs b/src/test/codegen/issue-45466.rs
index 1495476..f916c1a 100644
--- a/src/test/codegen/issue-45466.rs
+++ b/src/test/codegen/issue-45466.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // compile-flags: -O
-// min-llvm-version 6.0
 
 #![crate_type="rlib"]
 
diff --git a/src/test/codegen/simd-intrinsic-generic-gather.rs b/src/test/codegen/simd-intrinsic-generic-gather.rs
index 6c47bf3..605a952 100644
--- a/src/test/codegen/simd-intrinsic-generic-gather.rs
+++ b/src/test/codegen/simd-intrinsic-generic-gather.rs
@@ -10,7 +10,6 @@
 
 // ignore-emscripten
 // ignore-tidy-linelength
-// min-llvm-version 6.0
 
 // compile-flags: -C no-prepopulate-passes
 
diff --git a/src/test/codegen/simd-intrinsic-generic-scatter.rs b/src/test/codegen/simd-intrinsic-generic-scatter.rs
index 7b5b2e5..6645778 100644
--- a/src/test/codegen/simd-intrinsic-generic-scatter.rs
+++ b/src/test/codegen/simd-intrinsic-generic-scatter.rs
@@ -10,7 +10,6 @@
 
 // ignore-emscripten
 // ignore-tidy-linelength
-// min-llvm-version 6.0
 
 // compile-flags: -C no-prepopulate-passes
 
diff --git a/src/test/codegen/vtabletype.rs b/src/test/codegen/vtabletype.rs
index abd1eb3..cb96a84 100644
--- a/src/test/codegen/vtabletype.rs
+++ b/src/test/codegen/vtabletype.rs
@@ -14,7 +14,6 @@
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
-// min-llvm-version 6.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
diff --git a/src/test/compile-fail/const-fn-error.rs b/src/test/compile-fail/const-fn-error.rs
index 17dc9f9..397bc7e 100644
--- a/src/test/compile-fail/const-fn-error.rs
+++ b/src/test/compile-fail/const-fn-error.rs
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_fn, const_let)]
 
 const X : usize = 2;
 
 const fn f(x: usize) -> usize {
     let mut sum = 0;
-    //~^ let bindings in constant functions are unstable
-    //~| statements in constant functions are unstable
     for i in 0..x {
         //~^ ERROR E0015
         //~| ERROR E0019
diff --git a/src/test/compile-fail/must_use-in-stdlib-traits.rs b/src/test/compile-fail/must_use-in-stdlib-traits.rs
new file mode 100644
index 0000000..4bb5c59
--- /dev/null
+++ b/src/test/compile-fail/must_use-in-stdlib-traits.rs
@@ -0,0 +1,47 @@
+#![deny(unused_must_use)]
+#![feature(futures_api, pin, arbitrary_self_types)]
+
+use std::iter::Iterator;
+use std::future::Future;
+
+use std::task::{Poll, LocalWaker};
+use std::pin::Pin;
+use std::unimplemented;
+
+struct MyFuture;
+
+impl Future for MyFuture {
+   type Output = u32;
+
+   fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<u32> {
+      Poll::Pending
+   }
+}
+
+fn iterator() -> impl Iterator {
+   std::iter::empty::<u32>()
+}
+
+fn future() -> impl Future {
+   MyFuture
+}
+
+fn square_fn_once() -> impl FnOnce(u32) -> u32 {
+   |x| x * x
+}
+
+fn square_fn_mut() -> impl FnMut(u32) -> u32 {
+   |x| x * x
+}
+
+fn square_fn() -> impl Fn(u32) -> u32 {
+   |x| x * x
+}
+
+fn main() {
+   iterator(); //~ ERROR unused implementer of `std::iter::Iterator` that must be used
+   future(); //~ ERROR unused implementer of `std::future::Future` that must be used
+   square_fn_once(); //~ ERROR unused implementer of `std::ops::FnOnce` that must be used
+   square_fn_mut(); //~ ERROR unused implementer of `std::ops::FnMut` that must be used
+   square_fn(); //~ ERROR unused implementer of `std::ops::Fn` that must be used
+}
diff --git a/src/test/mir-opt/match_test.rs b/src/test/mir-opt/match_test.rs
new file mode 100644
index 0000000..9bfb728
--- /dev/null
+++ b/src/test/mir-opt/match_test.rs
@@ -0,0 +1,85 @@
+// Make sure redundant testing paths in `match` expressions are sorted out.
+
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let x = 3;
+    let b = true;
+
+    // When `(0..=10).contains(x) && !b`, we should jump to the last arm
+    // without testing two other candidates.
+    match x {
+        0..10 if b => 0,
+        10..=20 => 1,
+        -1 => 2,
+        _ => 3,
+    };
+}
+
+// END RUST SOURCE
+// START rustc.main.SimplifyCfg-initial.after.mir
+//    bb0: {
+//        ...
+//        _4 = Le(const 0i32, _1);
+//        switchInt(move _4) -> [false: bb10, otherwise: bb11];
+//    }
+//    bb1: {
+//        _3 = const 0i32;
+//        goto -> bb16;
+//    }
+//    bb2: {
+//        _3 = const 1i32;
+//        goto -> bb16;
+//    }
+//    bb3: {
+//        _3 = const 2i32;
+//        goto -> bb16;
+//    }
+//    bb4: {
+//        _3 = const 3i32;
+//        goto -> bb16;
+//    }
+//    bb5: {
+//        falseEdges -> [real: bb12, imaginary: bb6];
+//    }
+//    bb6: {
+//        falseEdges -> [real: bb2, imaginary: bb7];
+//    }
+//    bb7: {
+//        falseEdges -> [real: bb3, imaginary: bb8];
+//    }
+//    bb8: {
+//        falseEdges -> [real: bb4, imaginary: bb9];
+//    }
+//    bb9: {
+//        unreachable;
+//    }
+//    bb10: {
+//        _7 = Le(const 10i32, _1);
+//        switchInt(move _7) -> [false: bb14, otherwise: bb15];
+//    }
+//    bb11: {
+//        _5 = Lt(_1, const 10i32);
+//        switchInt(move _5) -> [false: bb10, otherwise: bb5];
+//    }
+//    bb12: {
+//        StorageLive(_6);
+//        _6 = _2;
+//        switchInt(move _6) -> [false: bb13, otherwise: bb1];
+//    }
+//    bb13: {
+//        falseEdges -> [real: bb8, imaginary: bb6];
+//    }
+//    bb14: {
+//        switchInt(_1) -> [-1i32: bb7, otherwise: bb8];
+//    }
+//    bb15: {
+//        _8 = Le(_1, const 20i32);
+//        switchInt(move _8) -> [false: bb14, otherwise: bb6];
+//    }
+//    bb16: {
+//        StorageDead(_6);
+//        ...
+//        return;
+//    }
+// END rustc.main.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/simplify_cfg.rs b/src/test/mir-opt/simplify_cfg.rs
new file mode 100644
index 0000000..ef843f7
--- /dev/null
+++ b/src/test/mir-opt/simplify_cfg.rs
@@ -0,0 +1,54 @@
+// Test that the goto chain starting from bb0 is collapsed.
+
+fn main() {
+    loop {
+        if bar() {
+            break;
+        }
+    }
+}
+
+#[inline(never)]
+fn bar() -> bool {
+    true
+}
+
+// END RUST SOURCE
+// START rustc.main.SimplifyCfg-initial.before.mir
+//     bb0: {
+//         goto -> bb1;
+//     }
+//     bb1: {
+//         falseUnwind -> [real: bb3, cleanup: bb4];
+//     }
+//     ...
+//     bb11: {
+//         ...
+//         goto -> bb1;
+//     }
+// END rustc.main.SimplifyCfg-initial.before.mir
+// START rustc.main.SimplifyCfg-initial.after.mir
+//     bb0: {
+//         falseUnwind -> [real: bb1, cleanup: bb2];
+//     }
+//     ...
+//     bb5: {
+//         ...
+//         goto -> bb0;
+//     }
+// END rustc.main.SimplifyCfg-initial.after.mir
+// START rustc.main.SimplifyCfg-early-opt.before.mir
+//     bb0: {
+//         goto -> bb1;
+//     }
+//     bb1: {
+//         StorageLive(_2);
+//         _2 = const bar() -> bb3;
+//     }
+// END rustc.main.SimplifyCfg-early-opt.before.mir
+// START rustc.main.SimplifyCfg-early-opt.after.mir
+//     bb0: {
+//         StorageLive(_2);
+//         _2 = const bar() -> bb1;
+//     }
+// END rustc.main.SimplifyCfg-early-opt.after.mir
diff --git a/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs b/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
deleted file mode 100644
index 88f0d07..0000000
--- a/src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// run-pass
-#![allow(dead_code)]
-
-// test that certain things are disallowed in constant functions
-
-#![feature(const_fn, const_let)]
-
-// no destructuring
-const fn i((
-            a,
-            b
-           ): (u32, u32)) -> u32 {
-    a + b
-}
-
-fn main() {}
diff --git a/src/test/run-pass/issues/issue-33140.rs b/src/test/run-pass/issues/issue-33140.rs
new file mode 100644
index 0000000..08c6945
--- /dev/null
+++ b/src/test/run-pass/issues/issue-33140.rs
@@ -0,0 +1,57 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(order_dependent_trait_objects)]
+
+trait Trait {
+    fn xyz() -> bool;
+}
+
+impl Trait for dyn Send + Sync {
+    fn xyz() -> bool { false }
+}
+
+impl Trait for dyn Sync + Send {
+    fn xyz() -> bool { true }
+}
+
+trait Trait2 {
+    fn uvw() -> bool;
+}
+
+impl Trait2 for dyn Send + Sync {
+    fn uvw() -> bool { false }
+}
+
+impl Trait2 for dyn Sync + Send + Sync {
+    fn uvw() -> bool { true }
+}
+
+struct Foo<T: ?Sized>(T);
+impl Foo<dyn Send + Sync> {
+    fn abc() -> bool {
+        false
+    }
+}
+
+impl Foo<dyn Sync + Send> {
+    fn abc() -> bool {
+        true
+    }
+}
+
+fn main() {
+    assert_eq!(<dyn Send+Sync>::xyz(), false);
+    assert_eq!(<dyn Sync+Send>::xyz(), true);
+    assert_eq!(<dyn Send+Sync>::uvw(), false);
+    assert_eq!(<dyn Sync+Send+Sync>::uvw(), true);
+    assert_eq!(<Foo<dyn Send+Sync>>::abc(), false);
+    assert_eq!(<Foo<dyn Sync+Send>>::abc(), true);
+}
diff --git a/src/test/run-pass/mir/mir_match_test.rs b/src/test/run-pass/mir/mir_match_test.rs
new file mode 100644
index 0000000..1f96d67
--- /dev/null
+++ b/src/test/run-pass/mir/mir_match_test.rs
@@ -0,0 +1,83 @@
+#![feature(exclusive_range_pattern)]
+
+// run-pass
+
+fn main() {
+    let incl_range = |x, b| {
+        match x {
+            0..=5 if b => 0,
+            5..=10 if b => 1,
+            1..=4 if !b => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(incl_range(3, false), 2);
+    assert_eq!(incl_range(3, true), 0);
+    assert_eq!(incl_range(5, false), 3);
+    assert_eq!(incl_range(5, true), 0);
+
+    let excl_range = |x, b| {
+        match x {
+            0..5 if b => 0,
+            5..10 if b => 1,
+            1..4 if !b => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(excl_range(3, false), 2);
+    assert_eq!(excl_range(3, true), 0);
+    assert_eq!(excl_range(5, false), 3);
+    assert_eq!(excl_range(5, true), 1);
+
+    let incl_range_vs_const = |x, b| {
+        match x {
+            0..=5 if b => 0,
+            7 => 1,
+            3 => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(incl_range_vs_const(5, false), 3);
+    assert_eq!(incl_range_vs_const(5, true), 0);
+    assert_eq!(incl_range_vs_const(3, false), 2);
+    assert_eq!(incl_range_vs_const(3, true), 0);
+    assert_eq!(incl_range_vs_const(7, false), 1);
+    assert_eq!(incl_range_vs_const(7, true), 1);
+
+    let excl_range_vs_const = |x, b| {
+        match x {
+            0..5 if b => 0,
+            7 => 1,
+            3 => 2,
+            _ => 3,
+        }
+    };
+    assert_eq!(excl_range_vs_const(5, false), 3);
+    assert_eq!(excl_range_vs_const(5, true), 3);
+    assert_eq!(excl_range_vs_const(3, false), 2);
+    assert_eq!(excl_range_vs_const(3, true), 0);
+    assert_eq!(excl_range_vs_const(7, false), 1);
+    assert_eq!(excl_range_vs_const(7, true), 1);
+
+    let const_vs_incl_range = |x, b| {
+        match x {
+            3 if b => 0,
+            5..=7 => 2,
+            1..=4 => 1,
+            _ => 3,
+        }
+    };
+    assert_eq!(const_vs_incl_range(3, false), 1);
+    assert_eq!(const_vs_incl_range(3, true), 0);
+
+    let const_vs_excl_range = |x, b| {
+        match x {
+            3 if b => 0,
+            5..7 => 2,
+            1..4 => 1,
+            _ => 3,
+        }
+    };
+    assert_eq!(const_vs_excl_range(3, false), 1);
+    assert_eq!(const_vs_excl_range(3, true), 0);
+}
diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs b/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs
index 5f6a72a..e5ac577 100644
--- a/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs
+++ b/src/test/run-pass/simd/simd-intrinsic-generic-gather.rs
@@ -10,7 +10,6 @@
 
 // run-pass
 // ignore-emscripten
-// min-llvm-version 6.0
 
 // Test that the simd_{gather,scatter} intrinsics produce the correct results.
 
diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs
index 041286f..779c72b 100644
--- a/src/test/run-pass/sse2.rs
+++ b/src/test/run-pass/sse2.rs
@@ -8,11 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(stable_features)]
-// min-llvm-version 6.0
-// ^ needs MCSubtargetInfo::checkFeatures()
 // ignore-cloudabi no std::env
 
+#![allow(stable_features)]
 #![feature(cfg_target_feature)]
 
 use std::env;
diff --git a/src/test/rustdoc/comment-in-doctest.rs b/src/test/rustdoc/comment-in-doctest.rs
new file mode 100644
index 0000000..3468bb7
--- /dev/null
+++ b/src/test/rustdoc/comment-in-doctest.rs
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:--test
+
+// comments, both doc comments and regular ones, used to trick rustdoc's doctest parser into
+// thinking that everything after it was part of the regular program. combined with the libsyntax
+// parser loop failing to detect the manual main function, it would wrap everything in `fn main`,
+// which would cause the doctest to fail as the "extern crate" declaration was no longer valid.
+// oddly enough, it would pass in 2018 if a crate was in the extern prelude. see
+// https://github.com/rust-lang/rust/issues/56727
+
+//! ```
+//! // crate: proc-macro-test
+//! //! this is a test
+//!
+//! // used to pull in proc-macro specific items
+//! extern crate proc_macro;
+//!
+//! use proc_macro::TokenStream;
+//!
+//! # fn main() {}
+//! ```
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
index 17722bf..6f72de0 100644
--- a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
@@ -1,3 +1,31 @@
+warning[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:27:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(_, ref mut b) => b,
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+   |
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+error[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:44:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+
 error[E0499]: cannot borrow `y.0` as mutable more than once at a time
   --> $DIR/borrowck-anon-fields-variant.rs:44:14
    |
@@ -10,6 +38,7 @@
 LL |     *a += 1;
    |     ------- first borrow later used here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0499`.
+Some errors occurred: E0499, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
index ef0de61..63e5bcc 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
@@ -24,7 +24,7 @@
 static FOO: Foo = Foo(UnsafeCell::new(42));
 
 static BAR: () = unsafe {
-    *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer
+    *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
index 0892b05..740954c 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
@@ -1,9 +1,9 @@
-error[E0080]: could not evaluate static initializer
+error[E0019]: static contains unimplemented expression type
   --> $DIR/assign-to-static-within-other-static-2.rs:27:5
    |
-LL |     *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer
-   |     ^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+LL |     *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
index 01fcc83..6c2fdcc 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
@@ -27,9 +27,7 @@
 
 static BAR: () = unsafe {
     *FOO.0.get() = 5;
-    // we do not error on the above access, because that is not detectable statically. Instead,
-    // const evaluation will error when trying to evaluate it. Due to the error below, we never even
-    // attempt to const evaluate `BAR`, so we don't see the error
+    //~^ contains unimplemented expression
 
     foo();
     //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
index 01ad1fc..49b39e2 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
@@ -1,9 +1,16 @@
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/mod-static-with-const-fn.rs:29:5
+   |
+LL |     *FOO.0.get() = 5;
+   |     ^^^^^^^^^^^^^^^^
+
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/mod-static-with-const-fn.rs:34:5
+  --> $DIR/mod-static-with-const-fn.rs:32:5
    |
 LL |     foo();
    |     ^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0015`.
+Some errors occurred: E0015, E0019.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs
index 30a738a..2f7e2ec 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.rs
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs
@@ -37,15 +37,13 @@
 }
 
 const fn get() -> u32 {
-    let x = 22;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
-    let y = 44;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
+    let x = 22; //~ ERROR let bindings in constant functions are unstable
+//~^ ERROR statements in constant functions
+    let y = 44; //~ ERROR let bindings in constant functions are unstable
+//~^ ERROR statements in constant functions
     x + y
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR let bindings in constant functions are unstable
+//~^ ERROR let bindings in constant functions are unstable
+//~| ERROR let bindings in constant functions are unstable
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
index 613670a..1a8c5f5 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
@@ -19,7 +19,7 @@
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
   --> $DIR/const-fn-not-safe-for-const.rs:40:13
    |
-LL |     let x = 22;
+LL |     let x = 22; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
@@ -27,29 +27,29 @@
 error[E0658]: statements in constant functions are unstable (see issue #48821)
   --> $DIR/const-fn-not-safe-for-const.rs:40:13
    |
-LL |     let x = 22;
+LL |     let x = 22; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:43:13
+  --> $DIR/const-fn-not-safe-for-const.rs:42:13
    |
-LL |     let y = 44;
+LL |     let y = 44; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:43:13
+  --> $DIR/const-fn-not-safe-for-const.rs:42:13
    |
-LL |     let y = 44;
+LL |     let y = 44; //~ ERROR let bindings in constant functions are unstable
    |             ^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:46:5
+  --> $DIR/const-fn-not-safe-for-const.rs:44:5
    |
 LL |     x + y
    |     ^
@@ -57,7 +57,7 @@
    = help: add #![feature(const_let)] to the crate attributes to enable
 
 error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:46:9
+  --> $DIR/const-fn-not-safe-for-const.rs:44:9
    |
 LL |     x + y
    |         ^
diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs
index 8382545..c2ed6cd 100644
--- a/src/test/ui/consts/const_let_assign3.rs
+++ b/src/test/ui/consts/const_let_assign3.rs
@@ -8,6 +8,7 @@
 impl S {
     const fn foo(&mut self, x: u32) {
         self.state = x;
+        //~^ contains unimplemented expression
     }
 }
 
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index 7f9a953..0f29461 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -1,9 +1,16 @@
+error[E0019]: constant function contains unimplemented expression type
+  --> $DIR/const_let_assign3.rs:10:9
+   |
+LL |         self.state = x;
+   |         ^^^^^^^^^^^^^^
+
 error[E0017]: references in constants may only refer to immutable values
-  --> $DIR/const_let_assign3.rs:16:5
+  --> $DIR/const_let_assign3.rs:17:5
    |
 LL |     s.foo(3); //~ ERROR references in constants may only refer to immutable values
    |     ^ constants require immutable values
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0017`.
+Some errors occurred: E0017, E0019.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/const_let_eq.rs b/src/test/ui/consts/const_let_eq.rs
new file mode 100644
index 0000000..8739cb8
--- /dev/null
+++ b/src/test/ui/consts/const_let_eq.rs
@@ -0,0 +1,470 @@
+#![feature(const_let, const_fn)]
+
+// run-pass
+
+struct Foo<T>(T);
+struct Bar<T> { x: T }
+struct W(u32);
+struct A { a: u32 }
+
+const fn basics((a,): (u32,)) -> u32 {
+    // Deferred assignment:
+    let b: u32;
+    b = a + 1;
+
+    // Immediate assignment:
+    let c: u32 = b + 1;
+
+    // Mutables:
+    let mut d: u32 = c + 1;
+    d = d + 1;
+    // +4 so far.
+
+    // No effect statements work:
+    ; ;
+    1;
+
+    // Array projection
+    let mut arr: [u32; 1] = [0];
+    arr[0] = 1;
+    d = d + arr[0];
+    // +5
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(0);
+    let mut bar: Bar<u32> = Bar { x: 0 };
+    foo.0 = 1;
+    bar.x = 1;
+    d = d + foo.0 + bar.x;
+    // +7
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(0)];
+    arr[0].0 = 1;
+    d = d + arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
+    arr[0].x = 1;
+    d = d + arr[0].x;
+    // +9
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([0]);
+    (arr.0)[0] = 1;
+    d = d + (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
+    arr.x[0] = 1;
+    d = d + arr.x[0];
+    // +11
+
+    d
+}
+
+const fn add_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a + 1;
+    d += 1;
+    // +2 so far.
+
+    // Array projection
+    let mut arr: [u32; 1] = [0];
+    arr[0] += 1;
+    d += arr[0];
+    // +3
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(0);
+    let mut bar: Bar<u32> = Bar { x: 0 };
+    foo.0 += 1;
+    bar.x += 1;
+    d += foo.0 + bar.x;
+    // +5
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(0)];
+    arr[0].0 += 1;
+    d += arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
+    arr[0].x += 1;
+    d += arr[0].x;
+    // +7
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([0]);
+    (arr.0)[0] += 1;
+    d += (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
+    arr.x[0] += 1;
+    d += arr.x[0];
+    // +9
+
+    d
+}
+
+const fn mul_assign(A { a }: A) -> u32 {
+    // Mutables:
+    let mut d: u32 = a + 1;
+    d *= 2;
+    // 2^1 * (a + 1)
+
+    // Array projection
+    let mut arr: [u32; 1] = [1];
+    arr[0] *= 2;
+    d *= arr[0];
+    // 2^2 * (a + 1)
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(1);
+    let mut bar: Bar<u32> = Bar { x: 1 };
+    foo.0 *= 2;
+    bar.x *= 2;
+    d *= foo.0 + bar.x;
+    // 2^4 * (a + 1)
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(1)];
+    arr[0].0 *= 2;
+    d *= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
+    arr[0].x *= 2;
+    d *= arr[0].x;
+    // 2^6 * (a + 1)
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([1]);
+    (arr.0)[0] *= 2;
+    d *= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
+    arr.x[0] *= 2;
+    d *= arr.x[0];
+    // 2^8 * (a + 1)
+
+    d
+}
+
+const fn div_assign(a: [u32; 1]) -> u32 {
+    let a = a[0];
+    // Mutables:
+    let mut d: u32 = 1024 * a;
+    d /= 2;
+    // 512
+
+    // Array projection
+    let mut arr: [u32; 1] = [4];
+    arr[0] /= 2;
+    d /= arr[0];
+    // 256
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(4);
+    let mut bar: Bar<u32> = Bar { x: 4 };
+    foo.0 /= 2;
+    bar.x /= 2;
+    d /= foo.0;
+    d /= bar.x;
+    // 64
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(4)];
+    arr[0].0 /= 2;
+    d /= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 4 }];
+    arr[0].x /= 2;
+    d /= arr[0].x;
+    // 16
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([4]);
+    (arr.0)[0] /= 2;
+    d /= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [4] };
+    arr.x[0] /= 2;
+    d /= arr.x[0];
+    // 4
+
+    d
+}
+
+const fn rem_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d %= 10;
+    d += 10;
+
+    // Array projection
+    let mut arr: [u32; 1] = [3];
+    arr[0] %= 2;
+    d %= 9 + arr[0];
+    d += 10;
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(5);
+    let mut bar: Bar<u32> = Bar { x: 7 };
+    foo.0 %= 2;
+    bar.x %= 2;
+    d %= 8 + foo.0 + bar.x;
+    d += 10;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(4)];
+    arr[0].0 %= 3;
+    d %= 9 + arr[0].0;
+    d += 10;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 7 }];
+    arr[0].x %= 3;
+    d %= 9 + arr[0].x;
+    d += 10;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([6]);
+    (arr.0)[0] %= 5;
+    d %= 9 + (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [11] };
+    arr.x[0] %= 5;
+    d %= 9 + arr.x[0];
+
+    d
+}
+
+const fn sub_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d -= 1;
+
+    // Array projection
+    let mut arr: [u32; 1] = [2];
+    arr[0] -= 1;
+    d -= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(2);
+    let mut bar: Bar<u32> = Bar { x: 2 };
+    foo.0 -= 1;
+    bar.x -= 1;
+    d -= foo.0 + bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(2)];
+    arr[0].0 -= 1;
+    d -= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
+    arr[0].x -= 1;
+    d -= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([2]);
+    (arr.0)[0] -= 1;
+    d -= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
+    arr.x[0] -= 1;
+    d -= arr.x[0];
+
+    d
+}
+
+const fn shl_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d <<= 1; // 10
+
+    // Array projection
+    let mut arr: [u32; 1] = [1];
+    arr[0] <<= 1;
+    d <<= arr[0]; // 10 << 2
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(1);
+    let mut bar: Bar<u32> = Bar { x: 1 };
+    foo.0 <<= 1;
+    bar.x <<= 1;
+    d <<= foo.0 + bar.x; // 1000 << 4
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(1)];
+    arr[0].0 <<= 1;
+    d <<= arr[0].0; // 1000_0000 << 2
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
+    arr[0].x <<= 1;
+    d <<= arr[0].x; // 1000_0000_00 << 2
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([1]);
+    (arr.0)[0] <<= 1;
+    d <<= (arr.0)[0]; // 1000_0000_0000 << 2
+    let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
+    arr.x[0] <<= 1;
+    d <<= arr.x[0]; // 1000_0000_0000_00 << 2
+
+    d
+}
+
+const fn shr_assign(W(a): W) -> u32 {
+    // Mutables:
+    let mut d: u32 = a;
+    d >>= 1; // /= 2
+
+    // Array projection
+    let mut arr: [u32; 1] = [2];
+    arr[0] >>= 1;
+    d >>= arr[0]; // /= 4
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(2);
+    let mut bar: Bar<u32> = Bar { x: 2 };
+    foo.0 >>= 1;
+    bar.x >>= 1;
+    d >>= foo.0 + bar.x; // /= 16
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(2)];
+    arr[0].0 >>= 1;
+    d >>= arr[0].0; // /= 32
+    let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
+    arr[0].x >>= 1;
+    d >>= arr[0].x; // /= 64
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([2]);
+    (arr.0)[0] >>= 1;
+    d >>= (arr.0)[0]; // /= 128
+    let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
+    arr.x[0] >>= 1;
+    d >>= arr.x[0]; // /= 256
+
+    d
+}
+
+const fn bit_and_assign(W(a): W) -> u32 {
+    let f = 0b1111_1111_1111_1111;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d &= 0b1111_1111_1111_1110;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] &= 0b1111_1111_1111_1101;
+    d &= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 &= 0b1111_1111_1111_0111;
+    bar.x &= 0b1111_1111_1101_1111;
+    d &= foo.0 & bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 &= 0b1111_1110_1111_1111;
+    d &= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x &= 0b1111_1101_1111_1111;
+    d &= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] &= 0b1011_1111_1111_1111;
+    d &= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] &= 0b0111_1111_1111_1111;
+    d &= arr.x[0];
+
+    d
+}
+
+const fn bit_or_assign(W(a): W) -> u32 {
+    let f = 0b0000_0000_0000_0000;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d |= 0b0000_0000_0000_0001;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] |= 0b0000_0000_0000_1001;
+    d |= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 |= 0b0000_0000_0001_0000;
+    bar.x |= 0b0000_0000_0100_0000;
+    d |= foo.0 | bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 |= 0b0000_0001_0000_0000;
+    d |= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x |= 0b0000_0010_0000_0000;
+    d |= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] |= 0b1000_0000_0000_0000;
+    d |= (arr.0)[0]; // /= 128
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] |= 0b1100_0000_0000_0000;
+    d |= arr.x[0]; // /= 256
+
+    d
+}
+
+const fn bit_xor_assign(W(a): W) -> u32 {
+    let f = 0b0000_0000_0000_0000;
+
+    // Mutables:
+    let mut d: u32 = a;
+    d ^= 0b0000_0000_0000_0001;
+
+    // Array projection
+    let mut arr: [u32; 1] = [f];
+    arr[0] ^= 0b0000_0000_0000_0010;
+    d ^= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<u32> = Foo(f);
+    let mut bar: Bar<u32> = Bar { x: f };
+    foo.0 ^= 0b0000_0000_0001_0000;
+    bar.x ^= 0b0000_0000_1000_0000;
+    d ^= foo.0 ^ bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<u32>; 1] = [Foo(f)];
+    arr[0].0 ^= 0b0000_0001_0000_0000;
+    d ^= arr[0].0;
+    let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
+    arr[0].x ^= 0b0000_0010_0000_0000;
+    d ^= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[u32; 1]> = Foo([f]);
+    (arr.0)[0] ^= 0b0100_0000_0000_0000;
+    d ^= (arr.0)[0];
+    let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
+    arr.x[0] ^= 0b1000_0000_0000_0000;
+    d ^= arr.x[0];
+
+    d
+}
+
+macro_rules! test {
+    ($c:ident, $e:expr, $r:expr) => {
+        const $c: u32 = $e;
+        assert_eq!($c, $r);
+        assert_eq!($e, $r);
+    }
+}
+
+fn main() {
+    test!(BASICS, basics((2,)), 13);
+    test!(ADD, add_assign(W(1)), 10);
+    test!(MUL, mul_assign(A { a: 0 }), 256);
+    test!(DIV, div_assign([1]), 4);
+    test!(REM, rem_assign(W(5)), 5);
+    test!(SUB, sub_assign(W(8)), 0);
+    test!(SHL, shl_assign(W(1)), 0b1000_0000_0000_0000);
+    test!(SHR, shr_assign(W(256)), 1);
+    test!(AND, bit_and_assign(W(0b1011_1111_1111_1111_1111)), 0b0011_1100_1101_0100);
+    test!(OR, bit_or_assign(W(0b1011_0000_0000_0000)), 0b1111_0011_0101_1001);
+    test!(XOR, bit_xor_assign(W(0b0000_0000_0000_0000)), 0b1100_0011_1001_0011);
+}
diff --git a/src/test/ui/consts/const_let_eq_float.rs b/src/test/ui/consts/const_let_eq_float.rs
new file mode 100644
index 0000000..2c7262d
--- /dev/null
+++ b/src/test/ui/consts/const_let_eq_float.rs
@@ -0,0 +1,279 @@
+// compile-pass
+
+#![feature(const_let, const_fn)]
+
+struct Foo<T>(T);
+struct Bar<T> { x: T }
+struct W(f32);
+struct A { a: f32 }
+
+const fn basics((a,): (f32,)) -> f32 {
+    // Deferred assignment:
+    let b: f32;
+    b = a + 1.0;
+
+    // Immediate assignment:
+    let c: f32 = b + 1.0;
+
+    // Mutables:
+    let mut d: f32 = c + 1.0;
+    d = d + 1.0;
+    // +4 so far.
+
+    // No effect statements work:
+    ; ;
+    1;
+
+    // Array projection
+    let mut arr: [f32; 1] = [0.0];
+    arr[0] = 1.0;
+    d = d + arr[0];
+    // +5
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(0.0);
+    let mut bar: Bar<f32> = Bar { x: 0.0 };
+    foo.0 = 1.0;
+    bar.x = 1.0;
+    d = d + foo.0 + bar.x;
+    // +7
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
+    arr[0].0 = 1.0;
+    d = d + arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
+    arr[0].x = 1.0;
+    d = d + arr[0].x;
+    // +9
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([0.0]);
+    (arr.0)[0] = 1.0;
+    d = d + (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
+    arr.x[0] = 1.0;
+    d = d + arr.x[0];
+    // +11
+
+    d
+}
+
+const fn add_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a + 1.0;
+    d += 1.0;
+    // +2 so far.
+
+    // Array projection
+    let mut arr: [f32; 1] = [0.0];
+    arr[0] += 1.0;
+    d += arr[0];
+    // +3
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(0.0);
+    let mut bar: Bar<f32> = Bar { x: 0.0 };
+    foo.0 += 1.0;
+    bar.x += 1.0;
+    d += foo.0 + bar.x;
+    // +5
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
+    arr[0].0 += 1.0;
+    d += arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
+    arr[0].x += 1.0;
+    d += arr[0].x;
+    // +7
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([0.0]);
+    (arr.0)[0] += 1.0;
+    d += (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
+    arr.x[0] += 1.0;
+    d += arr.x[0];
+    // +9
+
+    d
+}
+
+const fn mul_assign(A { a }: A) -> f32 {
+    // Mutables:
+    let mut d: f32 = a + 1.0;
+    d *= 2.0;
+    // 2^1 * (a + 1)
+
+    // Array projection
+    let mut arr: [f32; 1] = [1.0];
+    arr[0] *= 2.0;
+    d *= arr[0];
+    // 2^2 * (a + 1)
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(1.0);
+    let mut bar: Bar<f32> = Bar { x: 1.0 };
+    foo.0 *= 2.0;
+    bar.x *= 2.0;
+    d *= foo.0 + bar.x;
+    // 2^4 * (a + 1)
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(1.0)];
+    arr[0].0 *= 2.0;
+    d *= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 1.0 }];
+    arr[0].x *= 2.0;
+    d *= arr[0].x;
+    // 2^6 * (a + 1)
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([1.0]);
+    (arr.0)[0] *= 2.0;
+    d *= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [1.0] };
+    arr.x[0] *= 2.0;
+    d *= arr.x[0];
+    // 2^8 * (a + 1)
+
+    d
+}
+
+const fn div_assign(a: [f32; 1]) -> f32 {
+    let a = a[0];
+    // Mutables:
+    let mut d: f32 = 1024.0 * a;
+    d /= 2.0;
+    // 512
+
+    // Array projection
+    let mut arr: [f32; 1] = [4.0];
+    arr[0] /= 2.0;
+    d /= arr[0];
+    // 256
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(4.0);
+    let mut bar: Bar<f32> = Bar { x: 4.0 };
+    foo.0 /= 2.0;
+    bar.x /= 2.0;
+    d /= foo.0;
+    d /= bar.x;
+    // 64
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
+    arr[0].0 /= 2.0;
+    d /= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 4.0 }];
+    arr[0].x /= 2.0;
+    d /= arr[0].x;
+    // 16
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([4.0]);
+    (arr.0)[0] /= 2.0;
+    d /= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [4.0] };
+    arr.x[0] /= 2.0;
+    d /= arr.x[0];
+    // 4
+
+    d
+}
+
+const fn rem_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a;
+    d %= 10.0;
+    d += 10.0;
+
+    // Array projection
+    let mut arr: [f32; 1] = [3.0];
+    arr[0] %= 2.0;
+    d %= 9.0 + arr[0];
+    d += 10.0;
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(5.0);
+    let mut bar: Bar<f32> = Bar { x: 7.0 };
+    foo.0 %= 2.0;
+    bar.x %= 2.0;
+    d %= 8.0 + foo.0 + bar.x;
+    d += 10.0;
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
+    arr[0].0 %= 3.0;
+    d %= 9.0 + arr[0].0;
+    d += 10.0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 7.0 }];
+    arr[0].x %= 3.0;
+    d %= 9.0 + arr[0].x;
+    d += 10.0;
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([6.0]);
+    (arr.0)[0] %= 5.0;
+    d %= 9.0 + (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [11.0] };
+    arr.x[0] %= 5.0;
+    d %= 9.0 + arr.x[0];
+
+    d
+}
+
+const fn sub_assign(W(a): W) -> f32 {
+    // Mutables:
+    let mut d: f32 = a;
+    d -= 1.0;
+
+    // Array projection
+    let mut arr: [f32; 1] = [2.0];
+    arr[0] -= 1.0;
+    d -= arr[0];
+
+    // Field projection:
+    let mut foo: Foo<f32> = Foo(2.0);
+    let mut bar: Bar<f32> = Bar { x: 2.0 };
+    foo.0 -= 1.0;
+    bar.x -= 1.0;
+    d -= foo.0 + bar.x;
+
+    // Array + Field projection:
+    let mut arr: [Foo<f32>; 1] = [Foo(2.0)];
+    arr[0].0 -= 1.0;
+    d -= arr[0].0;
+    let mut arr: [Bar<f32>; 1] = [Bar { x: 2.0 }];
+    arr[0].x -= 1.0;
+    d -= arr[0].x;
+
+    // Field + Array projection:
+    let mut arr: Foo<[f32; 1]> = Foo([2.0]);
+    (arr.0)[0] -= 1.0;
+    d -= (arr.0)[0];
+    let mut arr: Bar<[f32; 1]> = Bar { x: [2.0] };
+    arr.x[0] -= 1.0;
+    d -= arr.x[0];
+
+    d
+}
+
+macro_rules! test {
+    ($c:ident, $e:expr, $r:expr) => {
+        const $c: f32 = $e;
+        assert_eq!($c, $r);
+        assert_eq!($e, $r);
+    }
+}
+
+fn main() {
+    test!(BASICS, basics((2.0,)), 13.0);
+    test!(ADD, add_assign(W(1.0)), 10.0);
+    test!(MUL, mul_assign(A { a: 0.0 }), 256.0);
+    test!(DIV, div_assign([1.0]), 4.0);
+    test!(REM, rem_assign(W(5.0)), 5.0);
+    test!(SUB, sub_assign(W(8.0)), 0.0);
+}
diff --git a/src/test/ui/consts/const_short_circuit.rs b/src/test/ui/consts/const_short_circuit.rs
new file mode 100644
index 0000000..cc49e46
--- /dev/null
+++ b/src/test/ui/consts/const_short_circuit.rs
@@ -0,0 +1,16 @@
+#![feature(underscore_const_names, const_let)]
+
+const _: bool = false && false;
+const _: bool = true && false;
+const _: bool = {
+    let mut x = true && false;
+    //~^ ERROR new features like let bindings are not permitted
+    x
+};
+const _: bool = {
+    let x = true && false;
+    //~^ ERROR new features like let bindings are not permitted
+    x
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const_short_circuit.stderr b/src/test/ui/consts/const_short_circuit.stderr
new file mode 100644
index 0000000..a67bb0b
--- /dev/null
+++ b/src/test/ui/consts/const_short_circuit.stderr
@@ -0,0 +1,26 @@
+error: new features like let bindings are not permitted in constants which also use short circuiting operators
+  --> $DIR/const_short_circuit.rs:6:9
+   |
+LL |     let mut x = true && false;
+   |         ^^^^^
+   |
+note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
+  --> $DIR/const_short_circuit.rs:6:22
+   |
+LL |     let mut x = true && false;
+   |                      ^^
+
+error: new features like let bindings are not permitted in constants which also use short circuiting operators
+  --> $DIR/const_short_circuit.rs:11:9
+   |
+LL |     let x = true && false;
+   |         ^
+   |
+note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
+  --> $DIR/const_short_circuit.rs:11:18
+   |
+LL |     let x = true && false;
+   |                  ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index f43befb..6c4e9e0 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -115,7 +115,7 @@
 error: local variables in const fn are unstable
   --> $DIR/min_const_fn.rs:109:34
    |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
    |                                  ^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
index 43ca9e7..ad983da 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -106,7 +106,7 @@
 const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
-const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
 const fn foo36(a: bool, b: bool) -> bool { a && b }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo37(a: bool, b: bool) -> bool { a || b }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index bcb9be6..a93a4f8 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -115,7 +115,7 @@
 error: local variables in const fn are unstable
   --> $DIR/min_const_fn.rs:109:34
    |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
    |                                  ^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
index f11b43d..92e99c6 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
@@ -28,13 +28,13 @@
     unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
     //~^ ERROR calls to `const unsafe fn` in const fns
 }
-const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
 //~^ dereferencing raw pointers in constant functions
 
 fn main() {}
 
 const unsafe fn no_union() {
     union Foo { x: (), y: () }
-    Foo { x: () }.y //~ ERROR not allowed in const fn
+    Foo { x: () }.y
     //~^ unions in const fn
 }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
index 922a788..fafc89d 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
@@ -1,7 +1,7 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
   --> $DIR/min_const_fn_unsafe.rs:31:59
    |
-LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
    |                                                           ^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
@@ -9,7 +9,7 @@
 error[E0658]: unions in const fn are unstable (see issue #51909)
   --> $DIR/min_const_fn_unsafe.rs:38:5
    |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+LL |     Foo { x: () }.y
    |     ^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
@@ -38,24 +38,6 @@
    |
    = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
 
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe.rs:31:59
-   |
-LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
-   |                                                           ^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: access to union field is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe.rs:38:5
-   |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
index 8a6884b..67a4820 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
@@ -34,29 +34,28 @@
 const unsafe fn foo10_3() -> *const Vec<std::cell::Cell<u32>> {
     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
 }
-// not ok
 const unsafe fn foo8_2() -> i32 {
-    foo4() //~ ERROR not allowed in const fn
+    foo4()
 }
 const unsafe fn foo9_2() -> *const String {
-    foo5::<String>() //~ ERROR not allowed in const fn
+    foo5::<String>()
 }
 const unsafe fn foo10_2() -> *const Vec<std::cell::Cell<u32>> {
-    foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
+    foo6::<Vec<std::cell::Cell<u32>>>()
 }
-const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
 //~^ dereferencing raw pointers in constant functions
 
-const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
+const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
 //~^ dereferencing raw pointers in constant functions
 
-const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
 //~^ dereferencing raw pointers in constant functions
 
 fn main() {}
 
 const unsafe fn no_union() {
     union Foo { x: (), y: () }
-    Foo { x: () }.y //~ ERROR not allowed in const fn
+    Foo { x: () }.y
     //~^ unions in const fn
 }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
index 20c75af..63bf9a5 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
@@ -1,97 +1,44 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:46:51
    |
-LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
    |                                                   ^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:49:60
    |
-LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
+LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
    |                                                            ^^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
    |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
    |                                                              ^^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error[E0658]: unions in const fn are unstable (see issue #51909)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:59:5
    |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
+LL |     Foo { x: () }.y
    |     ^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
 
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:39:5
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
    |
-LL |     foo4() //~ ERROR not allowed in const fn
-   |     ^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:42:5
-   |
-LL |     foo5::<String>() //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:45:5
-   |
-LL |     foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
-   |
-LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
-   |                                                   ^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
-   |
-LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
-   |                                                            ^^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
-
-error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
-   |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
+LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
    |                                                              ^^^ dereference of raw pointer
    |
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: access to union field is unsafe and unsafe operations are not allowed in const fn
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
-   |
-LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
-   |     ^^^^^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
+error: aborting due to 5 previous errors
 
-error: aborting due to 11 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
+Some errors occurred: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.rs b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
new file mode 100644
index 0000000..3dd76b6
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
@@ -0,0 +1,17 @@
+const fn mutable_ref_in_const() -> u8 {
+    let mut a = 0; //~ ERROR local variables in const fn
+    let b = &mut a;
+    *b
+}
+
+struct X;
+
+impl X {
+    const fn inherent_mutable_ref_in_const() -> u8 {
+        let mut a = 0; //~ ERROR local variables in const fn
+        let b = &mut a;
+        *b
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
new file mode 100644
index 0000000..fa46f5c
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
@@ -0,0 +1,14 @@
+error: local variables in const fn are unstable
+  --> $DIR/mutable_borrow.rs:2:9
+   |
+LL |     let mut a = 0; //~ ERROR local variables in const fn
+   |         ^^^^^
+
+error: local variables in const fn are unstable
+  --> $DIR/mutable_borrow.rs:11:13
+   |
+LL |         let mut a = 0; //~ ERROR local variables in const fn
+   |             ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
index 34e8eab..5863429 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -7,6 +7,7 @@
     {
         let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
+        //~^ contains unimplemented expression
     }
     &{a}
 };
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
index d5252f1..cc3635a 100644
--- a/src/test/ui/consts/projection_qualif.stderr
+++ b/src/test/ui/consts/projection_qualif.stderr
@@ -4,6 +4,12 @@
 LL |         let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
    |                           ^^^^^^ constants require immutable values
 
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/projection_qualif.rs:9:18
+   |
+LL |         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
+   |                  ^^^^^^
+
 error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
   --> $DIR/projection_qualif.rs:9:18
    |
@@ -12,7 +18,7 @@
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-Some errors occurred: E0017, E0658.
+Some errors occurred: E0017, E0019, E0658.
 For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/single_variant_match_ice.rs b/src/test/ui/consts/single_variant_match_ice.rs
index 67a41bc..79dde3c 100644
--- a/src/test/ui/consts/single_variant_match_ice.rs
+++ b/src/test/ui/consts/single_variant_match_ice.rs
@@ -2,6 +2,14 @@
     Prob,
 }
 
+const FOO: u32 = match Foo::Prob {
+    Foo::Prob => 42, //~ ERROR unimplemented expression type
+};
+
+const BAR: u32 = match Foo::Prob {
+    x => 42, //~ ERROR unimplemented expression type
+};
+
 impl Foo {
     pub const fn as_val(&self) -> u8 {
         use self::Foo::*;
diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr
index a0222b0..f5c2cb5 100644
--- a/src/test/ui/consts/single_variant_match_ice.stderr
+++ b/src/test/ui/consts/single_variant_match_ice.stderr
@@ -1,8 +1,21 @@
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/single_variant_match_ice.rs:6:5
+   |
+LL |     Foo::Prob => 42, //~ ERROR unimplemented expression type
+   |     ^^^^^^^^^
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/single_variant_match_ice.rs:10:5
+   |
+LL |     x => 42, //~ ERROR unimplemented expression type
+   |     ^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/single_variant_match_ice.rs:10:13
+  --> $DIR/single_variant_match_ice.rs:18:13
    |
 LL |             Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
    |             ^^^^
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0019`.
diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs
new file mode 100644
index 0000000..c6c6017
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-future.rs
@@ -0,0 +1,12 @@
+// ignore-tidy-linelength
+
+#![deny(deprecated_in_future)]
+
+#[deprecated(since = "99.99.99", note = "text")]
+pub fn deprecated_future() {}
+
+fn test() {
+    deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecation/deprecation-in-future.stderr b/src/test/ui/deprecation/deprecation-in-future.stderr
new file mode 100644
index 0000000..38392cf
--- /dev/null
+++ b/src/test/ui/deprecation/deprecation-in-future.stderr
@@ -0,0 +1,14 @@
+error: use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+  --> $DIR/deprecation-in-future.rs:9:5
+   |
+LL |     deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/deprecation-in-future.rs:3:9
+   |
+LL | #![deny(deprecated_in_future)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/extern/auxiliary/invalid-utf8.txt b/src/test/ui/extern/auxiliary/invalid-utf8.txt
new file mode 100644
index 0000000..dc1115b
--- /dev/null
+++ b/src/test/ui/extern/auxiliary/invalid-utf8.txt
@@ -0,0 +1 @@
+Ã(
\ No newline at end of file
diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs
index 5c6f6e4..e17dda6 100644
--- a/src/test/ui/extern/external-doc-error.rs
+++ b/src/test/ui/extern/external-doc-error.rs
@@ -2,7 +2,31 @@
 
 #![feature(external_doc)]
 
-#[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
-pub struct SomeStruct;
+#[doc(include = "not-a-file.md")]
+pub struct SomeStruct; //~^ ERROR couldn't read
+                       //~| HELP external doc paths are relative to the crate root
+
+#[doc(include = "auxiliary/invalid-utf8.txt")]
+pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
+
+#[doc(include)]
+pub struct MissingPath; //~^ ERROR expected path
+                        //~| HELP provide a file path with `=`
+                        //~| SUGGESTION include = "<path>"
+
+#[doc(include("../README.md"))]
+pub struct InvalidPathSyntax; //~^ ERROR expected path
+                              //~| HELP provide a file path with `=`
+                              //~| SUGGESTION include = "../README.md"
+
+#[doc(include = 123)]
+pub struct InvalidPathType; //~^ ERROR expected path
+                            //~| HELP provide a file path with `=`
+                            //~| SUGGESTION include = "<path>"
+
+#[doc(include(123))]
+pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path
+                                     //~| HELP provide a file path with `=`
+                                     //~| SUGGESTION include = "<path>"
 
 fn main() {}
diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr
index 5cc7551..a3be327 100644
--- a/src/test/ui/extern/external-doc-error.stderr
+++ b/src/test/ui/extern/external-doc-error.stderr
@@ -1,8 +1,40 @@
 error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/external-doc-error.rs:5:1
+  --> $DIR/external-doc-error.rs:5:17
    |
-LL | #[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[doc(include = "not-a-file.md")]
+   |                 ^^^^^^^^^^^^^^^ couldn't read file
+   |
+   = help: external doc paths are relative to the crate root
 
-error: aborting due to previous error
+error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
+  --> $DIR/external-doc-error.rs:9:17
+   |
+LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:12:7
+   |
+LL | #[doc(include)]
+   |       ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:17:7
+   |
+LL | #[doc(include("../README.md"))]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:22:7
+   |
+LL | #[doc(include = 123)]
+   |       ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: expected path to external documentation
+  --> $DIR/external-doc-error.rs:27:7
+   |
+LL | #[doc(include(123))]
+   |       ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-const_let.rs b/src/test/ui/feature-gates/feature-gate-const_let.rs
index 05d02e6..9bf957a 100644
--- a/src/test/ui/feature-gates/feature-gate-const_let.rs
+++ b/src/test/ui/feature-gates/feature-gate-const_let.rs
@@ -10,13 +10,22 @@
 
 // Test use of const let without feature gate.
 
-#![feature(const_fn)]
-
-const fn foo() -> usize {
+const FOO: usize = {
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
     let x = 42;
-    //~^ ERROR statements in constant functions are unstable
-    //~| ERROR: let bindings in constant functions are unstable
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
     42
-}
+};
+
+static BAR: usize = {
+    //~^ ERROR statements in statics are unstable
+    //~| ERROR: let bindings in statics are unstable
+    let x = 42;
+    //~^ ERROR statements in statics are unstable
+    //~| ERROR: let bindings in statics are unstable
+    42
+};
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_let.stderr b/src/test/ui/feature-gates/feature-gate-const_let.stderr
index 6a7f625..acb5165 100644
--- a/src/test/ui/feature-gates/feature-gate-const_let.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_let.stderr
@@ -1,4 +1,4 @@
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+error[E0658]: let bindings in constants are unstable (see issue #48821)
   --> $DIR/feature-gate-const_let.rs:16:13
    |
 LL |     let x = 42;
@@ -6,7 +6,7 @@
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
-error[E0658]: statements in constant functions are unstable (see issue #48821)
+error[E0658]: statements in constants are unstable (see issue #48821)
   --> $DIR/feature-gate-const_let.rs:16:13
    |
 LL |     let x = 42;
@@ -14,6 +14,78 @@
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:13:1
+   |
+LL | / const FOO: usize = {
+LL | |     //~^ ERROR statements in constants are unstable
+LL | |     //~| ERROR: let bindings in constants are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:13:1
+   |
+LL | / const FOO: usize = {
+LL | |     //~^ ERROR statements in constants are unstable
+LL | |     //~| ERROR: let bindings in constants are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:25:13
+   |
+LL |     let x = 42;
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:25:13
+   |
+LL |     let x = 42;
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:22:1
+   |
+LL | / static BAR: usize = {
+LL | |     //~^ ERROR statements in statics are unstable
+LL | |     //~| ERROR: let bindings in statics are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:22:1
+   |
+LL | / static BAR: usize = {
+LL | |     //~^ ERROR statements in statics are unstable
+LL | |     //~| ERROR: let bindings in statics are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-underscore-imports.rs b/src/test/ui/feature-gates/feature-gate-underscore-imports.rs
deleted file mode 100644
index ceb8afe..0000000
--- a/src/test/ui/feature-gates/feature-gate-underscore-imports.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable
-use std::vec as _; //~ ERROR renaming imports with `_` is unstable
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr b/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr
deleted file mode 100644
index 2eea952..0000000
--- a/src/test/ui/feature-gates/feature-gate-underscore-imports.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0658]: renaming extern crates with `_` is unstable (see issue #48216)
-  --> $DIR/feature-gate-underscore-imports.rs:11:1
-   |
-LL | extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable
-   | ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(underscore_imports)] to the crate attributes to enable
-
-error[E0658]: renaming imports with `_` is unstable (see issue #48216)
-  --> $DIR/feature-gate-underscore-imports.rs:12:5
-   |
-LL | use std::vec as _; //~ ERROR renaming imports with `_` is unstable
-   |     ^^^^^^^^^^^^^
-   |
-   = help: add #![feature(underscore_imports)] to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-33140.rs b/src/test/ui/issues/issue-33140.rs
new file mode 100644
index 0000000..fef5a82
--- /dev/null
+++ b/src/test/ui/issues/issue-33140.rs
@@ -0,0 +1,62 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(order_dependent_trait_objects)]
+
+trait Trait {
+    fn xyz() -> bool;
+}
+
+impl Trait for dyn Send + Sync {
+    fn xyz() -> bool { false }
+}
+
+impl Trait for dyn Sync + Send {
+//~^ ERROR conflicting implementations
+//~| hard error
+    fn xyz() -> bool { true }
+}
+
+trait Trait2 {
+    fn uvw() -> bool;
+}
+
+impl Trait2 for dyn Send + Sync {
+    fn uvw() -> bool { false }
+}
+
+impl Trait2 for dyn Sync + Send + Sync {
+//~^ ERROR conflicting implementations
+//~| hard error
+    fn uvw() -> bool { true }
+}
+
+struct Foo<T: ?Sized>(T);
+impl Foo<dyn Send + Sync> {
+    fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
+                       //~| hard error
+        false
+    }
+}
+
+impl Foo<dyn Sync + Send> {
+    fn abc() -> bool {
+        true
+    }
+}
+
+fn main() {
+    assert_eq!(<Send+Sync>::xyz(), false);
+    assert_eq!(<Sync+Send>::xyz(), true);
+    assert_eq!(<Send+Sync>::uvw(), false);
+    assert_eq!(<Sync+Send+Sync>::uvw(), true);
+    assert_eq!(<Foo<Send+Sync>>::abc(), false);
+    assert_eq!(<Foo<Sync+Send>>::abc(), true);
+}
diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/issues/issue-33140.stderr
new file mode 100644
index 0000000..240137f
--- /dev/null
+++ b/src/test/ui/issues/issue-33140.stderr
@@ -0,0 +1,48 @@
+error: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140.rs:21:1
+   |
+LL | impl Trait for dyn Send + Sync {
+   | ------------------------------ first implementation here
+...
+LL | impl Trait for dyn Sync + Send {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+note: lint level defined here
+  --> $DIR/issue-33140.rs:11:9
+   |
+LL | #![deny(order_dependent_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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 `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/issue-33140.rs:35:1
+   |
+LL | impl Trait2 for dyn Send + Sync {
+   | ------------------------------- first implementation here
+...
+LL | impl Trait2 for dyn Sync + Send + Sync {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: duplicate definitions with name `abc` (E0592)
+  --> $DIR/issue-33140.rs:43:5
+   |
+LL | /     fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
+LL | |                        //~| hard error
+LL | |         false
+LL | |     }
+   | |_____^ duplicate definitions for `abc`
+...
+LL | /     fn abc() -> bool {
+LL | |         true
+LL | |     }
+   | |_____- other definition for `abc`
+   |
+   = 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/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs
index af1f6ef..a2f40b3 100644
--- a/src/test/ui/issues/issue-37550.rs
+++ b/src/test/ui/issues/issue-37550.rs
@@ -8,15 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
-
 const fn x() {
-    let t = true;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
+    let t = true; //~ ERROR local variables in const fn
     let x = || t;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr
index 7468510..5a7d1ad 100644
--- a/src/test/ui/issues/issue-37550.stderr
+++ b/src/test/ui/issues/issue-37550.stderr
@@ -1,35 +1,8 @@
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:14:13
+error: local variables in const fn are unstable
+  --> $DIR/issue-37550.rs:12:9
    |
-LL |     let t = true;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
+LL |     let t = true; //~ ERROR local variables in const fn
+   |         ^
 
-error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:14:13
-   |
-LL |     let t = true;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
+error: aborting due to previous error
 
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:17:13
-   |
-LL |     let x = || t;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/issue-37550.rs:17:13
-   |
-LL |     let x = || t;
-   |             ^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-56199.rs b/src/test/ui/issues/issue-56199.rs
new file mode 100644
index 0000000..83d4e31
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.rs
@@ -0,0 +1,23 @@
+
+enum Foo {}
+struct Bar {}
+
+impl Foo {
+    fn foo() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+impl Bar {
+    fn bar() {
+        let _ = Self;
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+        let _ = Self();
+        //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr
new file mode 100644
index 0000000..6e3c7fd
--- /dev/null
+++ b/src/test/ui/issues/issue-56199.stderr
@@ -0,0 +1,30 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:7:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^
+   |
+   = note: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:9:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^
+   |
+   = note: did you mean to use one of the enum's variants?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:16:17
+   |
+LL |         let _ = Self;
+   |                 ^^^^ did you mean `Self { /* fields */ }`?
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56199.rs:18:17
+   |
+LL |         let _ = Self();
+   |                 ^^^^ did you mean `Self { /* fields */ }`?
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-56835.rs b/src/test/ui/issues/issue-56835.rs
new file mode 100644
index 0000000..c16550e
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.rs
@@ -0,0 +1,10 @@
+
+pub struct Foo {}
+
+impl Foo {
+    fn bar(Self(foo): Self) {}
+    //~^ ERROR the `Self` constructor can only be used with tuple or unit structs
+    //~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164]
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr
new file mode 100644
index 0000000..b7c3b14
--- /dev/null
+++ b/src/test/ui/issues/issue-56835.stderr
@@ -0,0 +1,15 @@
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-56835.rs:5:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ did you mean `Self { /* fields */ }`?
+
+error[E0164]: expected tuple struct/variant, found self constructor `Self`
+  --> $DIR/issue-56835.rs:5:12
+   |
+LL |     fn bar(Self(foo): Self) {}
+   |            ^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
index a8b0e3e..6b9e1dc 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -55,6 +55,7 @@
 LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    |         ^^^^^^
    = note: #[warn(unused_assignments)] implied by #[warn(unused)]
+   = help: maybe it is overwritten before being read?
 
 warning: unused variable: `fire`
   --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:54:32
diff --git a/src/test/ui/liveness/liveness-dead.stderr b/src/test/ui/liveness/liveness-dead.stderr
index 6709fee..6e43ccc 100644
--- a/src/test/ui/liveness/liveness-dead.stderr
+++ b/src/test/ui/liveness/liveness-dead.stderr
@@ -9,24 +9,31 @@
    |
 LL | #![deny(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
 
 error: value assigned to `x` is never read
   --> $DIR/liveness-dead.rs:27:5
    |
 LL |     x = 4; //~ ERROR: value assigned to `x` is never read
    |     ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: value passed to `x` is never read
   --> $DIR/liveness-dead.rs:30:11
    |
 LL | fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read
    |           ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: value assigned to `x` is never read
   --> $DIR/liveness-dead.rs:37:5
    |
 LL |     x = 4; //~ ERROR: value assigned to `x` is never read
    |     ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr
index 2846f24..35ccc79 100644
--- a/src/test/ui/liveness/liveness-unused.stderr
+++ b/src/test/ui/liveness/liveness-unused.stderr
@@ -60,6 +60,7 @@
    |
 LL | #![deny(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
+   = help: maybe it is overwritten before being read?
 
 error: variable `z` is assigned to, but never used
   --> $DIR/liveness-unused.rs:47:13
@@ -106,6 +107,8 @@
    |
 LL |         x = 0;  //~ ERROR value assigned to `x` is never read
    |         ^
+   |
+   = help: maybe it is overwritten before being read?
 
 error: aborting due to 13 previous errors
 
diff --git a/src/test/ui/nll/match-on-borrowed.rs b/src/test/ui/nll/match-on-borrowed.rs
index 6a8ce03..edce2b1 100644
--- a/src/test/ui/nll/match-on-borrowed.rs
+++ b/src/test/ui/nll/match-on-borrowed.rs
@@ -46,9 +46,9 @@
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match e { // OK, no access of borrowed data
+    match e { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
@@ -59,9 +59,9 @@
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match f { // OK, no access of borrowed data
+    match f { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index cdff29d4..2d34dd7 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -1,3 +1,27 @@
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:51:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `e.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `e.0`
+...
+LL |     x;
+   |     - borrow later used here
+
+error[E0503]: cannot use `*f` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:64:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `f.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `f.0`
+...
+LL |     x;
+   |     - borrow later used here
+
 error[E0503]: cannot use `t` because it was mutably borrowed
   --> $DIR/match-on-borrowed.rs:82:9
    |
@@ -16,7 +40,7 @@
 LL |     match n {} //~ ERROR
    |           ^ use of possibly uninitialized `n`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 Some errors occurred: E0381, E0503.
 For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
index 70de916..c335336 100644
--- a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
@@ -1,5 +1,3 @@
-#![feature(underscore_imports)]
-
 #[macro_export]
 macro_rules! do_nothing {
     () => ()
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/rfc-2166-underscore-imports/basic.rs
index 64a8d07..93b246f 100644
--- a/src/test/ui/rfc-2166-underscore-imports/basic.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.rs
@@ -11,7 +11,6 @@
 // compile-pass
 // aux-build:underscore-imports.rs
 
-#![feature(underscore_imports)]
 #![warn(unused_imports, unused_extern_crates)]
 
 #[macro_use]
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
index e1fe5cc..f2b8cc4 100644
--- a/src/test/ui/rfc-2166-underscore-imports/basic.stderr
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
@@ -1,17 +1,17 @@
 warning: unused import: `m::Tr1 as _`
-  --> $DIR/basic.rs:37:9
+  --> $DIR/basic.rs:36:9
    |
 LL |     use m::Tr1 as _; //~ WARN unused import
    |         ^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/basic.rs:15:9
+  --> $DIR/basic.rs:14:9
    |
 LL | #![warn(unused_imports, unused_extern_crates)]
    |         ^^^^^^^^^^^^^^
 
 warning: unused import: `S as _`
-  --> $DIR/basic.rs:38:9
+  --> $DIR/basic.rs:37:9
    |
 LL |     use S as _; //~ WARN unused import
    |         ^^^^^^
diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
index 92615c4..95f7cae 100644
--- a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
@@ -1,8 +1,6 @@
 // compile-pass
 // aux-build:duplicate.rs
 
-#![feature(underscore_imports)]
-
 extern crate duplicate;
 
 #[duplicate::duplicate]
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
index 611eb3c..d06a26a 100644
--- a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
@@ -1,6 +1,5 @@
 // edition:2018
 
-#![feature(underscore_imports)]
 #![deny(unused_imports)]
 
 mod multi_segment {
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
index 02b29b3..4163c28 100644
--- a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
+++ b/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
@@ -1,17 +1,17 @@
 error: unused import: `core::any`
-  --> $DIR/unused-2018.rs:7:9
+  --> $DIR/unused-2018.rs:6:9
    |
 LL |     use core::any; //~ ERROR unused import: `core::any`
    |         ^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/unused-2018.rs:4:9
+  --> $DIR/unused-2018.rs:3:9
    |
 LL | #![deny(unused_imports)]
    |         ^^^^^^^^^^^^^^
 
 error: unused import: `core`
-  --> $DIR/unused-2018.rs:11:9
+  --> $DIR/unused-2018.rs:10:9
    |
 LL |     use core; //~ ERROR unused import: `core`
    |         ^^^^
diff --git a/src/test/ui/rust-2018/future-proofing-locals.rs b/src/test/ui/rust-2018/future-proofing-locals.rs
index d2e6dbb..4f0cada 100644
--- a/src/test/ui/rust-2018/future-proofing-locals.rs
+++ b/src/test/ui/rust-2018/future-proofing-locals.rs
@@ -1,6 +1,6 @@
 // edition:2018
 
-#![feature(uniform_paths, underscore_imports)]
+#![feature(uniform_paths)]
 
 mod T {
     pub struct U;
diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
index e8098a4..fc433c2 100644
--- a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
+++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs
@@ -2,7 +2,7 @@
 
 // For the time being `macro_rules` items are treated as *very* private...
 
-#![feature(underscore_imports, decl_macro, uniform_paths)]
+#![feature(decl_macro, uniform_paths)]
 
 mod m1 {
     macro_rules! legacy_macro { () => () }
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
index 2a2d35e..31ec8a7 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -54,8 +54,14 @@
         simd_select(z, z, z);
         //~^ ERROR mask element type is `f32`, expected `i_`
 
+        simd_select(m4, 0u32, 1u32);
+        //~^ ERROR found non-SIMD `u32`
+
         simd_select_bitmask(0u8, x, x);
         //~^ ERROR mask length `8` != other vector length `4`
+        //
+        simd_select_bitmask(0u8, 1u32, 2u32);
+        //~^ ERROR found non-SIMD `u32`
 
         simd_select_bitmask(0.0f32, x, x);
         //~^ ERROR `f32` is not an integral type
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
index 584f3d5..05317da 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
@@ -16,24 +16,36 @@
 LL |         simd_select(z, z, z);
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
   --> $DIR/simd-intrinsic-generic-select.rs:57:9
    |
+LL |         simd_select(m4, 0u32, 1u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+  --> $DIR/simd-intrinsic-generic-select.rs:60:9
+   |
 LL |         simd_select_bitmask(0u8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
+  --> $DIR/simd-intrinsic-generic-select.rs:63:9
+   |
+LL |         simd_select_bitmask(0u8, 1u32, 2u32);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:60:9
+  --> $DIR/simd-intrinsic-generic-select.rs:66:9
    |
 LL |         simd_select_bitmask(0.0f32, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:63:9
+  --> $DIR/simd-intrinsic-generic-select.rs:69:9
    |
 LL |         simd_select_bitmask("x", x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/suggestions/path-display.rs b/src/test/ui/suggestions/path-display.rs
new file mode 100644
index 0000000..62fc9e7
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.rs
@@ -0,0 +1,7 @@
+use std::path::Path;
+
+fn main() {
+    let path = Path::new("/tmp/foo/bar.txt");
+    println!("{}", path);
+    //~^ ERROR E0277
+}
diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr
new file mode 100644
index 0000000..39d236a
--- /dev/null
+++ b/src/test/ui/suggestions/path-display.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `std::path::Path` doesn't implement `std::fmt::Display`
+  --> $DIR/path-display.rs:5:20
+   |
+LL |     println!("{}", path);
+   |                    ^^^^ `std::path::Path` cannot be formatted with the default formatter; call `.display()` on it
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `std::path::Path`
+   = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
+   = note: required because of the requirements on the impl of `std::fmt::Display` for `&std::path::Path`
+   = note: required by `std::fmt::Display::fmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs
index 8a04588..2d0fb78 100644
--- a/src/test/ui/target-feature-gate.rs
+++ b/src/test/ui/target-feature-gate.rs
@@ -24,7 +24,6 @@
 // gate-test-mips_target_feature
 // gate-test-mmx_target_feature
 // gate-test-wasm_target_feature
-// min-llvm-version 6.0
 
 #[target_feature(enable = "avx512bw")]
 //~^ ERROR: currently unstable
diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr
index f18bebc..24141d0 100644
--- a/src/test/ui/target-feature-gate.stderr
+++ b/src/test/ui/target-feature-gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
-  --> $DIR/target-feature-gate.rs:29:18
+  --> $DIR/target-feature-gate.rs:28:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy b/src/tools/clippy
index b7a431e..a416c5e 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit b7a431ea1ddb96a396921bf9b5f2f6d8690cd474
+Subproject commit a416c5e0f7c4c9473069a58410d3ec3e86b1ac0d
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 0038399..8b3023e 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -873,3 +873,29 @@
     *line = &line[end + 1..];
     Some(result)
 }
+
+#[test]
+fn test_parse_normalization_string() {
+    let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, Some("something (32 bits)".to_owned()));
+    assert_eq!(s, " -> \"something ($WORD bits)\".");
+
+    // Nothing to normalize (No quotes)
+    let mut s = "normalize-stderr-32bit: something (32 bits) -> something ($WORD bits).";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, None);
+    assert_eq!(s, r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)."#);
+
+    // Nothing to normalize (Only a single quote)
+    let mut s = "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, None);
+    assert_eq!(s, "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).");
+
+    // Nothing to normalize (Three quotes)
+    let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits).";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, Some("something (32 bits)".to_owned()));
+    assert_eq!(s, " -> \"something ($WORD bits).");
+}
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 2a71697..381d808 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -86,6 +86,8 @@
     }
     panic!("Cannot determine OS from triple");
 }
+
+/// Determine the architecture from `triple`
 pub fn get_arch(triple: &str) -> &'static str {
     let triple: Vec<_> = triple.split('-').collect();
     for &(triple_arch, arch) in ARCH_TABLE {
@@ -151,3 +153,29 @@
         }
     }
 }
+
+#[test]
+#[should_panic(expected = "Cannot determine Architecture from triple")]
+fn test_get_arch_failure() {
+    get_arch("abc");
+}
+
+#[test]
+fn test_get_arch() {
+    assert_eq!("x86_64", get_arch("x86_64-unknown-linux-gnu"));
+    assert_eq!("x86_64", get_arch("amd64"));
+}
+
+#[test]
+#[should_panic(expected = "Cannot determine OS from triple")]
+fn test_matches_os_failure() {
+    matches_os("abc", "abc");
+}
+
+#[test]
+fn test_matches_os() {
+    assert!(matches_os("x86_64-unknown-linux-gnu", "linux"));
+    assert!(matches_os("wasm32-unknown-unknown", "emscripten"));
+    assert!(matches_os("wasm32-unknown-unknown", "wasm32-bare"));
+    assert!(!matches_os("wasm32-unknown-unknown", "windows"));
+}
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index e6bf9a2..1aa647a 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -137,7 +137,6 @@
        file.ends_with("symbol/struct.InternedString.html") ||
        file.ends_with("ast/struct.ThinVec.html") ||
        file.ends_with("util/struct.ThinVec.html") ||
-       file.ends_with("util/struct.RcSlice.html") ||
        file.ends_with("layout/struct.TyLayout.html") ||
        file.ends_with("humantime/struct.Timestamp.html") ||
        file.ends_with("log/index.html") ||
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index a65d263..4ade87f 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -34,16 +34,6 @@
     'rust-by-example': '@steveklabnik @marioidival @projektir',
 }
 
-EMOJI = {
-    'miri': '🛰️',
-    'clippy-driver': '📎',
-    'rls': '💻',
-    'rustfmt': '📝',
-    'book': '📖',
-    'nomicon': '👿',
-    'reference': '📚',
-    'rust-by-example': '👩‍🏫',
-}
 
 def read_current_status(current_commit, path):
     '''Reads build status of `current_commit` from content of `history/*.tsv`
@@ -73,12 +63,13 @@
         }
 
         slug = 'rust-lang/rust'
-        long_message = textwrap.dedent('''\
+        message = textwrap.dedent('''\
+            📣 Toolstate changed by {}!
+
             Tested on commit {}@{}.
             Direct link to PR: <{}>
 
-        ''').format(slug, current_commit, relevant_pr_url)
-        emoji_status = []
+        ''').format(relevant_pr_number, slug, current_commit, relevant_pr_url)
         anything_changed = False
         for status in latest:
             tool = status['tool']
@@ -90,18 +81,12 @@
                 status[os] = new
                 if new > old:
                     changed = True
-                    long_message += '🎉 {} on {}: {} → {}.\n' \
-                        .format(tool, os, old, new)
-                    emoji = "{}🎉".format(EMOJI.get(tool))
-                    if msg not in emoji_status:
-                        emoji_status += [msg]
+                    message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
+                        .format(tool, os, old, new, MAINTAINERS.get(tool))
                 elif new < old:
                     changed = True
-                    long_message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
+                    message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
                         .format(tool, os, old, new, MAINTAINERS.get(tool))
-                    emoji = "{}💔".format(EMOJI.get(tool))
-                    if msg not in emoji_status:
-                        emoji_status += [msg]
 
             if changed:
                 status['commit'] = current_commit
@@ -111,9 +96,6 @@
         if not anything_changed:
             return ''
 
-        short_message = "📣 Toolstate changed by {}! ({})"
-            .format(relevant_pr_number, '/'.join(emoji_status))
-        message = short_message + "\n\n" + long_message
         f.seek(0)
         f.truncate(0)
         json.dump(latest, f, indent=4, separators=(',', ': '))
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 2b5cff6..d1e4387 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -79,6 +79,7 @@
     Crate("chalk-macros"),
     Crate("cloudabi"),
     Crate("cmake"),
+    Crate("compiler_builtins"),
     Crate("crc"),
     Crate("crc32fast"),
     Crate("crossbeam-deque"),