Auto merge of #56481 - arielb1:dynamic-order, r=nikomatsakis

add coherence future-compat warnings for marker-only trait objects

The future-compat warnings break code that assumes that `dyn Send + Sync !=
dyn Sync + Send`, and are the first step in making them equal. cc #33140.

Note: this lint should be made to default-warn before we merge. It is deny only for the crater run.

r? @nikomatsakis / @scalexm . cc @Centril & @alexreg.
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 d22a910..7e03474 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -81,13 +81,13 @@
 
 [[package]]
 name = "backtrace"
-version = "0.3.9"
+version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "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)",
 ]
 
@@ -728,7 +728,7 @@
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -736,7 +736,7 @@
 version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -751,7 +751,7 @@
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (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]]
@@ -2060,7 +2060,7 @@
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -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",
@@ -3380,7 +3385,7 @@
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
 "checksum assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98589b0e465a6c510d95fceebd365bb79bedece7f6e18a480897f2015f85ec51"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
-"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
+"checksum backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "18b65ea1161bfb2dd6da6fade5edd4dbd08fba85012123dd333d2fd1b90b2782"
 "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
 "checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a"
 "checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"
@@ -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 32f3e57..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;
@@ -416,6 +416,7 @@
                 test::Rustfmt,
                 test::Miri,
                 test::Clippy,
+                test::CompiletestTest,
                 test::RustdocJS,
                 test::RustdocTheme,
                 // Run bootstrap close to the end as it's unlikely to fail
@@ -1251,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 c84abe42..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 {
@@ -155,7 +155,9 @@
         cargo
             .args(&["-p", "alloc"])
             .arg("--manifest-path")
-            .arg(builder.src.join("src/liballoc/Cargo.toml"));
+            .arg(builder.src.join("src/liballoc/Cargo.toml"))
+            .arg("--features")
+            .arg("compiler-builtins-mem");
     } else {
         let features = builder.std_features();
 
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 dc061fe..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";
 
@@ -430,6 +430,45 @@
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct CompiletestTest {
+    stage: u32,
+    host: Interned<String>,
+}
+
+impl Step for CompiletestTest {
+    type Output = ();
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/tools/compiletest")
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(CompiletestTest {
+            stage: run.builder.top_stage,
+            host: run.target,
+        });
+    }
+
+    /// Runs `cargo test` for compiletest.
+    fn run(self, builder: &Builder) {
+        let stage = self.stage;
+        let host = self.host;
+        let compiler = builder.compiler(stage, host);
+
+        let mut cargo = tool::prepare_tool_cargo(builder,
+                                                 compiler,
+                                                 Mode::ToolBootstrap,
+                                                 host,
+                                                 "test",
+                                                 "src/tools/compiletest",
+                                                 SourceType::InTree,
+                                                 &[]);
+
+        try_run(builder, &mut cargo);
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Clippy {
     stage: u32,
     host: Interned<String>,
@@ -577,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/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index c7e6af2..4f8a3c0 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -52,8 +52,8 @@
     CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv6 -marm" \
     bash musl.sh arm && \
     env \
-    CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv6 -marm" \
-    CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm" \
+    CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv6 -marm -mfpu=vfp" \
+    CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm -mfpu=vfp" \
     bash musl.sh armhf && \
     env \
     CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a" \
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/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md
index 8620346..2e94ebe 100644
--- a/src/doc/rustc/src/targets/built-in.md
+++ b/src/doc/rustc/src/targets/built-in.md
@@ -6,5 +6,5 @@
 
 To see the list of built-in targets, you can run `rustc --print target-list`,
 or look at [the API
-docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/#modules).
+docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/index.html#modules).
 Each module there defines a builder for a particular target.
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md
index 07e3a79..3d63d07 100644
--- a/src/doc/rustc/src/targets/index.md
+++ b/src/doc/rustc/src/targets/index.md
@@ -4,7 +4,7 @@
 architecture. The list of *targets* are the possible architectures that you can build for.
 
 To see all the options that you can set with a target, see the docs
-[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html).
+[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.Target.html).
 
 To compile to a particular target, use the `--target` flag:
 
diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md
index 1165ab9..edc039f 100644
--- a/src/doc/unstable-book/src/language-features/unsized-locals.md
+++ b/src/doc/unstable-book/src/language-features/unsized-locals.md
@@ -8,7 +8,7 @@
 
 This implements [RFC1909]. When turned on, you can have unsized arguments and locals:
 
-[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-coercions.md
+[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md
 
 ```rust
 #![feature(unsized_locals)]
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
index a376c85..f02c7d8 100755
--- a/src/etc/gdb_rust_pretty_printing.py
+++ b/src/etc/gdb_rust_pretty_printing.py
@@ -9,6 +9,7 @@
 # except according to those terms.
 
 import gdb
+import re
 import sys
 import debugger_pretty_printers_common as rustpp
 
@@ -20,6 +21,16 @@
 
 rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True)
 
+# The btree pretty-printers fail in a confusing way unless
+# https://sourceware.org/bugzilla/show_bug.cgi?id=21763 is fixed.
+# This fix went in 8.1, so check for that.
+# See https://github.com/rust-lang/rust/issues/56730
+gdb_81 = False
+_match = re.match('([0-9]+)\\.([0-9]+)', gdb.VERSION)
+if _match:
+    if int(_match.group(1)) > 8 or (int(_match.group(1)) == 8 and int(_match.group(2)) >= 1):
+        gdb_81 = True
+
 #===============================================================================
 # GDB Pretty Printing Module for Rust
 #===============================================================================
@@ -110,10 +121,10 @@
     if type_kind == rustpp.TYPE_KIND_STD_VECDEQUE:
         return RustStdVecDequePrinter(val)
 
-    if type_kind == rustpp.TYPE_KIND_STD_BTREESET:
+    if type_kind == rustpp.TYPE_KIND_STD_BTREESET and gdb_81:
         return RustStdBTreeSetPrinter(val)
 
-    if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP:
+    if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP and gdb_81:
         return RustStdBTreeMapPrinter(val)
 
     if type_kind == rustpp.TYPE_KIND_STD_STRING:
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
index b7faee1..b2eb356 100644
--- a/src/liballoc/Cargo.toml
+++ b/src/liballoc/Cargo.toml
@@ -28,3 +28,6 @@
 name = "vec_deque_append_bench"
 path = "../liballoc/benches/vec_deque_append.rs"
 harness = false
+
+[features]
+compiler-builtins-mem = ['compiler_builtins/mem']
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/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 f61e582..b3c93ae 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2544,7 +2544,7 @@
 /// assert_eq!(actual, expected);
 /// ```
 #[unstable(feature = "ptr_hash", reason = "newly added", issue = "56286")]
-pub fn hash<T, S: hash::Hasher>(hashee: *const T, into: &mut S) {
+pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
     use hash::Hash;
     hashee.hash(into);
 }
@@ -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/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 7d997a0..d213a5c 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -1095,7 +1095,8 @@
                             let sp = hir.span(id);
                             // `sp` only covers `T`, change it so that it covers
                             // `T:` when appropriate
-                            let sp = if has_bounds {
+                            let is_impl_trait = bound_kind.to_string().starts_with("impl ");
+                            let sp = if has_bounds && !is_impl_trait {
                                 sp.to(self.tcx
                                     .sess
                                     .source_map()
@@ -1103,7 +1104,7 @@
                             } else {
                                 sp
                             };
-                            (sp, has_bounds)
+                            (sp, has_bounds, is_impl_trait)
                         })
                     } else {
                         None
@@ -1136,25 +1137,33 @@
 
         fn binding_suggestion<'tcx, S: fmt::Display>(
             err: &mut DiagnosticBuilder<'tcx>,
-            type_param_span: Option<(Span, bool)>,
+            type_param_span: Option<(Span, bool, bool)>,
             bound_kind: GenericKind<'tcx>,
             sub: S,
         ) {
-            let consider = &format!(
-                "consider adding an explicit lifetime bound `{}: {}`...",
-                bound_kind, sub
+            let consider = format!(
+                "consider adding an explicit lifetime bound {}",
+                if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
+                    format!(" `{}` to `{}`...", sub, bound_kind)
+                } else {
+                    format!("`{}: {}`...", bound_kind, sub)
+                },
             );
-            if let Some((sp, has_lifetimes)) = type_param_span {
-                let tail = if has_lifetimes { " + " } else { "" };
-                let suggestion = format!("{}: {}{}", bound_kind, sub, tail);
+            if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
+                let suggestion = if is_impl_trait {
+                    format!("{} + {}", bound_kind, sub)
+                } else {
+                    let tail = if has_lifetimes { " + " } else { "" };
+                    format!("{}: {}{}", bound_kind, sub, tail)
+                };
                 err.span_suggestion_short_with_applicability(
                     sp,
-                    consider,
+                    &consider,
                     suggestion,
                     Applicability::MaybeIncorrect, // Issue #41966
                 );
             } else {
-                err.help(consider);
+                err.help(&consider);
             }
         }
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index bd2b995..cf43710 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -371,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)]
@@ -434,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/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 289f693..8b16aaf 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -183,50 +183,14 @@
 impl<'tcx> EvalError<'tcx> {
     pub fn print_backtrace(&mut self) {
         if let Some(ref mut backtrace) = self.backtrace {
-            eprintln!("{}", print_backtrace(&mut *backtrace));
+            print_backtrace(&mut *backtrace);
         }
     }
 }
 
-fn print_backtrace(backtrace: &mut Backtrace) -> String {
-    use std::fmt::Write;
-
+fn print_backtrace(backtrace: &mut Backtrace) {
     backtrace.resolve();
-
-    let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
-    write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
-    'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
-        if frame.symbols().is_empty() {
-            write!(trace_text, "  {}: no symbols\n", i).unwrap();
-        }
-        let mut first = true;
-        for symbol in frame.symbols() {
-            if first {
-                write!(trace_text, "  {}: ", i).unwrap();
-                first = false;
-            } else {
-                let len = i.to_string().len();
-                write!(trace_text, "  {}  ", " ".repeat(len)).unwrap();
-            }
-            if let Some(name) = symbol.name() {
-                write!(trace_text, "{}\n", name).unwrap();
-            } else {
-                write!(trace_text, "<unknown>\n").unwrap();
-            }
-            write!(trace_text, "           at ").unwrap();
-            if let Some(file_path) = symbol.filename() {
-                write!(trace_text, "{}", file_path.display()).unwrap();
-            } else {
-                write!(trace_text, "<unknown_file>").unwrap();
-            }
-            if let Some(line) = symbol.lineno() {
-                write!(trace_text, ":{}\n", line).unwrap();
-            } else {
-                write!(trace_text, "\n").unwrap();
-            }
-        }
-    }
-    trace_text
+    eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
 }
 
 impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
@@ -238,7 +202,7 @@
 
                 if val == "immediate" {
                     // Print it now
-                    eprintln!("{}", print_backtrace(&mut backtrace));
+                    print_backtrace(&mut backtrace);
                     None
                 } else {
                     Some(Box::new(backtrace))
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 54901bc..1a22866 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -145,10 +145,12 @@
             simplified_self,
         );
 
-        for possible_sibling in match simplified_self {
-            Some(sty) => self.filtered(sty),
-            None => self.iter(),
-        } {
+        let possible_siblings = match simplified_self {
+            Some(sty) => PotentialSiblings::Filtered(self.filtered(sty)),
+            None => PotentialSiblings::Unfiltered(self.iter()),
+        };
+
+        for possible_sibling in possible_siblings {
             debug!(
                 "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}",
                 impl_def_id,
@@ -260,14 +262,37 @@
         Ok(Inserted::BecameNewSibling(last_lint))
     }
 
-    fn iter(&mut self) -> Box<dyn Iterator<Item = DefId> + '_> {
+    fn iter(&mut self) -> impl Iterator<Item = DefId> + '_ {
         let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter());
-        Box::new(self.blanket_impls.iter().chain(nonblanket).cloned())
+        self.blanket_impls.iter().chain(nonblanket).cloned()
     }
 
-    fn filtered(&mut self, sty: SimplifiedType) -> Box<dyn Iterator<Item = DefId> + '_> {
+    fn filtered(&mut self, sty: SimplifiedType) -> impl Iterator<Item = DefId> + '_ {
         let nonblanket = self.nonblanket_impls.entry(sty).or_default().iter();
-        Box::new(self.blanket_impls.iter().chain(nonblanket).cloned())
+        self.blanket_impls.iter().chain(nonblanket).cloned()
+    }
+}
+
+// A custom iterator used by Children::insert
+enum PotentialSiblings<I, J>
+    where I: Iterator<Item = DefId>,
+          J: Iterator<Item = DefId>
+{
+    Unfiltered(I),
+    Filtered(J)
+}
+
+impl<I, J> Iterator for PotentialSiblings<I, J>
+    where I: Iterator<Item = DefId>,
+          J: Iterator<Item = DefId>
+{
+    type Item = DefId;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match *self {
+            PotentialSiblings::Unfiltered(ref mut iter) => iter.next(),
+            PotentialSiblings::Filtered(ref mut iter) => iter.next()
+        }
     }
 }
 
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/util/profiling.rs b/src/librustc/util/profiling.rs
index 1e648c4..c2bfa62 100644
--- a/src/librustc/util/profiling.rs
+++ b/src/librustc/util/profiling.rs
@@ -62,11 +62,15 @@
             }
 
             fn print(&self, lock: &mut StderrLock<'_>) {
-                writeln!(lock, "| Phase            | Time (ms)      | Queries        | Hits (%) |")
+                writeln!(lock, "| Phase            | Time (ms)      \
+                                | Time (%) | Queries        | Hits (%)")
                     .unwrap();
-                writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
+                writeln!(lock, "| ---------------- | -------------- \
+                                | -------- | -------------- | --------")
                     .unwrap();
 
+                let total_time = ($(self.times.$name + )* 0) as f32;
+
                 $(
                     let (hits, total) = self.query_counts.$name;
                     let (hits, total) = if total > 0 {
@@ -78,11 +82,12 @@
 
                     writeln!(
                         lock,
-                        "| {0: <16} | {1: <14} | {2: <14} | {3: <8} |",
+                        "| {0: <16} | {1: <14} | {2: <8.2} | {3: <14} | {4: <8}",
                         stringify!($name),
                         self.times.$name / 1_000_000,
+                        ((self.times.$name as f32) / total_time) * 100.0,
                         total,
-                        hits
+                        hits,
                     ).unwrap();
                 )*
             }
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 30edc47..48e0a3a 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -18,6 +18,7 @@
 use rustc::ty::{self, TyCtxt, PolyFnSig};
 use rustc::ty::layout::HasTyCtxt;
 use rustc::ty::query::Providers;
+use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_target::spec::PanicStrategy;
@@ -130,8 +131,7 @@
 }
 
 pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
-    let cpu = llvm_util::target_cpu(cx.tcx.sess);
-    let target_cpu = CString::new(cpu).unwrap();
+    let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess));
     llvm::AddFunctionAttrStringValue(
             llfn,
             llvm::AttributePlace::Function,
@@ -231,11 +231,7 @@
     // Always annotate functions with the target-cpu they are compiled for.
     // Without this, ThinLTO won't inline Rust functions into Clang generated
     // functions (because Clang annotates functions this way too).
-    // NOTE: For now we just apply this if -Zcross-lang-lto is specified, since
-    //       it introduce a little overhead and isn't really necessary otherwise.
-    if cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() {
-        apply_target_cpu_attr(cx, llfn);
-    }
+    apply_target_cpu_attr(cx, llfn);
 
     let features = llvm_target_features(cx.tcx.sess)
         .map(|s| s.to_string())
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 2b82ebe..e229f8d 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1171,7 +1171,28 @@
     );
     let arg_tys = sig.inputs();
 
-    // every intrinsic takes a SIMD vector as its first argument
+    if name == "simd_select_bitmask" {
+        let in_ty = arg_tys[0];
+        let m_len = match in_ty.sty {
+            // Note that this `.unwrap()` crashes for isize/usize, that's sort
+            // of intentional as there's not currently a use case for that.
+            ty::Int(i) => i.bit_width().unwrap(),
+            ty::Uint(i) => i.bit_width().unwrap(),
+            _ => return_error!("`{}` is not an integral type", in_ty),
+        };
+        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 `{}`",
+                 m_len, v_len
+        );
+        let i1 = bx.type_i1();
+        let i1xn = bx.type_vector(i1, m_len as u64);
+        let m_i1s = bx.bitcast(args[0].immediate(), i1xn);
+        return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
+    }
+
+    // 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);
@@ -1275,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 fdb6373..82b1d7e 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -124,6 +124,7 @@
 ];
 
 const X86_WHITELIST: &[(&str, Option<&str>)] = &[
+    ("adx", Some("adx_target_feature")),
     ("aes", None),
     ("avx", None),
     ("avx2", None),
@@ -139,6 +140,7 @@
     ("avx512vpopcntdq", Some("avx512_target_feature")),
     ("bmi1", None),
     ("bmi2", None),
+    ("cmpxchg16b", Some("cmpxchg16b_target_feature")),
     ("fma", None),
     ("fxsr", None),
     ("lzcnt", None),
@@ -211,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/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index 7b1c7cf..5099449 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -16,7 +16,7 @@
 rustc-demangle = "0.1.4"
 memmap = "0.6"
 log = "0.4.5"
-libc = "0.2.43"
+libc = "0.2.44"
 jobserver = "0.1.11"
 
 serialize = { path = "../libserialize" }
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 7f4c496..3471218 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -381,7 +381,7 @@
     store.register_removed("resolve_trait_on_defaulted_unit",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/48950");
     store.register_removed("private_no_mangle_fns",
-        "no longer an warning, #[no_mangle] functions always exported");
+        "no longer a warning, #[no_mangle] functions always exported");
     store.register_removed("private_no_mangle_statics",
-        "no longer an warning, #[no_mangle] statics always exported");
+        "no longer a warning, #[no_mangle] statics always exported");
 }
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 cfea357..0ce6428 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -22,33 +22,35 @@
 //! 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};
+use rustc::hir::RangeEnd;
 
 use std::mem;
 
 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.
             }
         }
     }
@@ -62,6 +64,7 @@
                                  match_pair: MatchPair<'pat, 'tcx>,
                                  candidate: &mut Candidate<'pat, 'tcx>)
                                  -> Result<(), MatchPair<'pat, 'tcx>> {
+        let tcx = self.hir.tcx();
         match *match_pair.pattern.kind {
             PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => {
                 candidate.ascriptions.push(Ascription {
@@ -104,7 +107,34 @@
                 Err(match_pair)
             }
 
-            PatternKind::Range { .. } => {
+            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)))
+                    }
+                    ty::Int(ity) => {
+                        // FIXME(49937): refactor these bit manipulations into interpret.
+                        let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
+                        let min = 1u128 << (size.bits() - 1);
+                        let max = (1u128 << (size.bits() - 1)) - 1;
+                        Some((min, max, size))
+                    }
+                    ty::Uint(uty) => {
+                        // FIXME(49937): refactor these bit manipulations into interpret.
+                        let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
+                        let max = !0u128 >> (128 - size.bits());
+                        Some((0, max, size))
+                    }
+                    _ => None,
+                };
+                if let Some((min, max, sz)) = range {
+                    if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) {
+                        if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) {
+                            // Irrefutable pattern match.
+                            return Ok(());
+                        }
+                    }
+                }
                 Err(match_pair)
             }
 
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..451034f 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,
             };
 
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 4c77350..7ec6bbf 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -173,16 +173,16 @@
 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;
 use rustc::hir::RangeEnd;
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::layout::{Integer, IntegerExt, VariantIdx};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
+use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
 
 use rustc::mir::Field;
-use rustc::mir::interpret::ConstValue;
+use rustc::mir::interpret::{ConstValue, Pointer, Scalar};
 use rustc::util::common::ErrorReported;
 
 use syntax::attr::{SignedInt, UnsignedInt};
@@ -200,14 +200,60 @@
 pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>)
                                 -> &'a Pattern<'tcx>
 {
-    cx.pattern_arena.alloc(LiteralExpander.fold_pattern(&pat))
+    cx.pattern_arena.alloc(LiteralExpander { tcx: cx.tcx }.fold_pattern(&pat))
 }
 
-struct LiteralExpander;
-impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
+struct LiteralExpander<'a, 'tcx> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
+}
+
+impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
+    /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice.
+    ///
+    /// `crty` and `rty` can differ because you can use array constants in the presence of slice
+    /// patterns. So the pattern may end up being a slice, but the constant is an array. We convert
+    /// the array to a slice in that case.
+    fn fold_const_value_deref(
+        &mut self,
+        val: ConstValue<'tcx>,
+        // the pattern's pointee type
+        rty: Ty<'tcx>,
+        // the constant's pointee type
+        crty: Ty<'tcx>,
+    ) -> ConstValue<'tcx> {
+        match (val, &crty.sty, &rty.sty) {
+            // the easy case, deref a reference
+            (ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => ConstValue::ByRef(
+                p.alloc_id,
+                self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id),
+                p.offset,
+            ),
+            // unsize array to slice if pattern is array but match value or other patterns are slice
+            (ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
+                assert_eq!(t, u);
+                ConstValue::ScalarPair(
+                    Scalar::Ptr(p),
+                    n.val.try_to_scalar().unwrap(),
+                )
+            },
+            // fat pointers stay the same
+            (ConstValue::ScalarPair(..), _, _) => val,
+            // FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used
+            _ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
+        }
+    }
+}
+
+impl<'a, 'tcx> PatternFolder<'tcx> for LiteralExpander<'a, 'tcx> {
     fn fold_pattern(&mut self, pat: &Pattern<'tcx>) -> Pattern<'tcx> {
         match (&pat.ty.sty, &*pat.kind) {
-            (&ty::Ref(_, rty, _), &PatternKind::Constant { ref value }) => {
+            (
+                &ty::Ref(_, rty, _),
+                &PatternKind::Constant { value: Const {
+                    val,
+                    ty: ty::TyS { sty: ty::Ref(_, crty, _), .. },
+                } },
+            ) => {
                 Pattern {
                     ty: pat.ty,
                     span: pat.span,
@@ -215,7 +261,11 @@
                         subpattern: Pattern {
                             ty: rty,
                             span: pat.span,
-                            kind: box PatternKind::Constant { value: value.clone() },
+                            kind: box PatternKind::Constant { value: Const::from_const_value(
+                                self.tcx,
+                                self.fold_const_value_deref(*val, rty, crty),
+                                rty,
+                            ) },
                         }
                     }
                 }
@@ -554,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,
                     }
                 }
@@ -732,15 +782,17 @@
     for row in patterns {
         match *row.kind {
             PatternKind::Constant { value } => {
-                if let Some(ptr) = value.to_ptr() {
-                    let is_array_ptr = value.ty
-                        .builtin_deref(true)
-                        .and_then(|t| t.ty.builtin_index())
-                        .map_or(false, |t| t == cx.tcx.types.u8);
-                    if is_array_ptr {
-                        let alloc = cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
-                        max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64);
-                    }
+                // extract the length of an array/slice from a constant
+                match (value.val, &value.ty.sty) {
+                    (_, ty::Array(_, n)) => max_fixed_len = cmp::max(
+                        max_fixed_len,
+                        n.unwrap_usize(cx.tcx),
+                    ),
+                    (ConstValue::ScalarPair(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
+                        max_fixed_len,
+                        n.to_usize(&cx.tcx).unwrap(),
+                    ),
+                    _ => {},
                 }
             }
             PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
@@ -820,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,
@@ -1259,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(),
@@ -1348,28 +1400,62 @@
     }
 }
 
-fn slice_pat_covered_by_constructor<'tcx>(
+// checks whether a constant is equal to a user-written slice pattern. Only supports byte slices,
+// meaning all other types will compare unequal and thus equal patterns often do not cause the
+// second pattern to lint about unreachable match arms.
+fn slice_pat_covered_by_const<'tcx>(
     tcx: TyCtxt<'_, 'tcx, '_>,
     _span: Span,
-    ctor: &Constructor,
+    const_val: &ty::Const<'tcx>,
     prefix: &[Pattern<'tcx>],
     slice: &Option<Pattern<'tcx>>,
     suffix: &[Pattern<'tcx>]
 ) -> Result<bool, ErrorReported> {
-    let data: &[u8] = match *ctor {
-        ConstantValue(const_val) => {
-            let val = match const_val.val {
-                ConstValue::Unevaluated(..) |
-                ConstValue::ByRef(..) => bug!("unexpected ConstValue: {:?}", const_val),
-                ConstValue::Scalar(val) | ConstValue::ScalarPair(val, _) => val,
-            };
-            if let Ok(ptr) = val.to_ptr() {
-                tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id).bytes.as_ref()
-            } else {
-                bug!("unexpected non-ptr ConstantValue")
+    let data: &[u8] = match (const_val.val, &const_val.ty.sty) {
+        (ConstValue::ByRef(id, alloc, offset), ty::Array(t, n)) => {
+            if *t != tcx.types.u8 {
+                // FIXME(oli-obk): can't mix const patterns with slice patterns and get
+                // any sort of exhaustiveness/unreachable check yet
+                // This solely means that we don't lint about unreachable patterns, even if some
+                // are definitely unreachable.
+                return Ok(false);
             }
-        }
-        _ => bug!()
+            let ptr = Pointer::new(id, offset);
+            let n = n.assert_usize(tcx).unwrap();
+            alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
+        },
+        // a slice fat pointer to a zero length slice
+        (ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(t)) => {
+            if *t != tcx.types.u8 {
+                // FIXME(oli-obk): can't mix const patterns with slice patterns and get
+                // any sort of exhaustiveness/unreachable check yet
+                // This solely means that we don't lint about unreachable patterns, even if some
+                // are definitely unreachable.
+                return Ok(false);
+            }
+            assert_eq!(n.to_usize(&tcx).unwrap(), 0);
+            &[]
+        },
+        //
+        (ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
+            if *t != tcx.types.u8 {
+                // FIXME(oli-obk): can't mix const patterns with slice patterns and get
+                // any sort of exhaustiveness/unreachable check yet
+                // This solely means that we don't lint about unreachable patterns, even if some
+                // are definitely unreachable.
+                return Ok(false);
+            }
+            let n = n.to_usize(&tcx).unwrap();
+            tcx.alloc_map
+                .lock()
+                .unwrap_memory(ptr.alloc_id)
+                .get_bytes(&tcx, ptr, Size::from_bytes(n))
+                .unwrap()
+        },
+        _ => bug!(
+            "slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}",
+            const_val, prefix, slice, suffix,
+        ),
     };
 
     let pat_len = prefix.len() + suffix.len();
@@ -1556,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);
@@ -1675,22 +1761,23 @@
                     // necessarily point to memory, they are usually just integers. The only time
                     // they should be pointing to memory is when they are subslices of nonzero
                     // slices
-                    let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty {
-                        ty::TyKind::Array(t, n) => (value.to_ptr(), n.unwrap_usize(cx.tcx), t),
-                        ty::TyKind::Slice(t) => {
-                            match value.val {
-                                ConstValue::ScalarPair(ptr, n) => (
-                                    ptr.to_ptr().ok(),
-                                    n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64,
-                                    t,
-                                ),
-                                _ => span_bug!(
-                                    pat.span,
-                                    "slice pattern constant must be scalar pair but is {:?}",
-                                    value,
-                                ),
-                            }
-                        },
+                    let (opt_ptr, n, ty) = match (value.val, &value.ty.sty) {
+                        (ConstValue::ByRef(id, alloc, offset), ty::TyKind::Array(t, n)) => (
+                            Some((
+                                Pointer::new(id, offset),
+                                alloc,
+                            )),
+                            n.unwrap_usize(cx.tcx),
+                            t,
+                        ),
+                        (ConstValue::ScalarPair(ptr, n), ty::TyKind::Slice(t)) => (
+                            ptr.to_ptr().ok().map(|ptr| (
+                                ptr,
+                                cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
+                            )),
+                            n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64,
+                            t,
+                        ),
                         _ => span_bug!(
                             pat.span,
                             "unexpected const-val {:?} with ctor {:?}",
@@ -1702,8 +1789,7 @@
                         // convert a constant slice/array pattern to a list of patterns.
                         match (n, opt_ptr) {
                             (0, _) => Some(SmallVec::new()),
-                            (_, Some(ptr)) => {
-                                let alloc = cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
+                            (_, Some((ptr, alloc))) => {
                                 let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
                                 (0..n).map(|i| {
                                     let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
@@ -1766,10 +1852,8 @@
                         None
                     }
                 }
-                ConstantValue(..) => {
-                    match slice_pat_covered_by_constructor(
-                        cx.tcx, pat.span, constructor, prefix, slice, suffix
-                            ) {
+                ConstantValue(cv) => {
+                    match slice_pat_covered_by_const(cx.tcx, pat.span, cv, prefix, slice, suffix) {
                         Ok(true) => Some(smallvec![]),
                         Ok(false) => None,
                         Err(ErrorReported) => None
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index d695a64..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)) {
@@ -1259,34 +1265,32 @@
         }
     }
 
-    if let ty::Ref(_, rty, _) = ty.value.sty {
-        if let ty::Str = rty.sty {
-            match (a.val, b.val) {
-                (
-                    ConstValue::ScalarPair(
-                        Scalar::Ptr(ptr_a),
-                        len_a,
-                    ),
-                    ConstValue::ScalarPair(
-                        Scalar::Ptr(ptr_b),
-                        len_b,
-                    ),
-                ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
-                    if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
-                        if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
-                            if len_a == len_b {
-                                let map = tcx.alloc_map.lock();
-                                let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
-                                let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
-                                if alloc_a.bytes.len() as u128 == len_a {
-                                    return from_bool(alloc_a == alloc_b);
-                                }
+    if let ty::Str = ty.value.sty {
+        match (a.val, b.val) {
+            (
+                ConstValue::ScalarPair(
+                    Scalar::Ptr(ptr_a),
+                    len_a,
+                ),
+                ConstValue::ScalarPair(
+                    Scalar::Ptr(ptr_b),
+                    len_b,
+                ),
+            ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
+                if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
+                    if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
+                        if len_a == len_b {
+                            let map = tcx.alloc_map.lock();
+                            let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
+                            let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
+                            if alloc_a.bytes.len() as u128 == len_a {
+                                return from_bool(alloc_a == alloc_b);
                             }
                         }
                     }
                 }
-                _ => (),
             }
+            _ => (),
         }
     }
 
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/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/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_resolve/lib.rs b/src/librustc_resolve/lib.rs
index ebd2c87..e449fec 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3010,6 +3010,7 @@
         // Visit all direct subpatterns of this pattern.
         let outer_pat_id = pat.id;
         pat.walk(&mut |pat| {
+            debug!("resolve_pattern pat={:?} node={:?}", pat, pat.node);
             match pat.node {
                 PatKind::Ident(bmode, ident, ref opt_pat) => {
                     // First try to resolve the identifier as some existing
@@ -3166,6 +3167,7 @@
                  format!("not found in {}", mod_str),
                  item_span)
             };
+
             let code = DiagnosticId::Error(code.into());
             let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
 
@@ -3189,11 +3191,22 @@
                 return (err, Vec::new());
             }
             if is_self_value(path, ns) {
+                debug!("smart_resolve_path_fragment E0424 source:{:?}", source);
+
                 __diagnostic_used!(E0424);
                 err.code(DiagnosticId::Error("E0424".into()));
-                err.span_label(span, format!("`self` value is a keyword \
-                                               only available in \
-                                               methods with `self` parameter"));
+                err.span_label(span, match source {
+                    PathSource::Pat => {
+                        format!("`self` value is a keyword \
+                                and may not be bound to \
+                                variables or shadowed")
+                    }
+                    _ => {
+                        format!("`self` value is a keyword \
+                                only available in methods \
+                                with `self` parameter")
+                    }
+                });
                 return (err, Vec::new());
             }
 
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/mod.rs b/src/librustc_target/spec/mod.rs
index d8e8477..aef8770 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -68,6 +68,7 @@
 mod openbsd_base;
 mod netbsd_base;
 mod solaris_base;
+mod uefi_base;
 mod windows_base;
 mod windows_msvc_base;
 mod thumb_base;
@@ -254,12 +255,12 @@
             }
         }
 
-        pub fn get_targets() -> Box<dyn Iterator<Item=String>> {
-            Box::new(TARGETS.iter().filter_map(|t| -> Option<String> {
+        pub fn get_targets() -> impl Iterator<Item = String> {
+            TARGETS.iter().filter_map(|t| -> Option<String> {
                 load_specific(t)
                     .and(Ok(t.to_string()))
                     .ok()
-            }))
+            })
         }
 
         #[cfg(test)]
@@ -419,6 +420,8 @@
     ("aarch64-unknown-none", aarch64_unknown_none),
 
     ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
+
+    ("x86_64-unknown-uefi", x86_64_unknown_uefi),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
diff --git a/src/librustc_target/spec/uefi_base.rs b/src/librustc_target/spec/uefi_base.rs
new file mode 100644
index 0000000..9b05158
--- /dev/null
+++ b/src/librustc_target/spec/uefi_base.rs
@@ -0,0 +1,74 @@
+// 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.
+
+// This defines a base target-configuration for native UEFI systems. The UEFI specification has
+// quite detailed sections on the ABI of all the supported target architectures. In almost all
+// cases it simply follows what Microsoft Windows does. Hence, whenever in doubt, see the MSDN
+// documentation.
+// UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic
+// linker is supported. As native to COFF, binaries are position-dependent, but will be relocated
+// by the loader if the pre-chosen memory location is already in use.
+// UEFI forbids running code on anything but the boot-CPU. Not interrupts are allowed other than
+// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
+// code runs in the same environment, no process separation is supported.
+
+use spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    let mut pre_link_args = LinkArgs::new();
+
+    pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), vec![
+            // Suppress the verbose logo and authorship debugging output, which would needlessly
+            // clog any log files.
+            "/NOLOGO".to_string(),
+
+            // UEFI is fully compatible to non-executable data pages. Tell the compiler that
+            // non-code sections can be marked as non-executable, including stack pages.
+            "/NXCOMPAT".to_string(),
+
+            // There is no runtime for UEFI targets, prevent them from being linked. UEFI targets
+            // must be freestanding.
+            "/nodefaultlib".to_string(),
+
+            // Non-standard subsystems have no default entry-point in PE+ files. We have to define
+            // one. "efi_main" seems to be a common choice amongst other implementations and the
+            // spec.
+            "/entry:efi_main".to_string(),
+
+            // COFF images have a "Subsystem" field in their header, which defines what kind of
+            // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
+            // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
+            // which is very likely the most common option. Individual projects can override this
+            // with custom linker flags.
+            // The subsystem-type only has minor effects on the application. It defines the memory
+            // regions the application is loaded into (runtime-drivers need to be put into
+            // reserved areas), as well as whether a return from the entry-point is treated as
+            // exit (default for applications).
+            "/subsystem:efi_application".to_string(),
+        ]);
+
+    TargetOptions {
+        dynamic_linking: false,
+        executables: true,
+        disable_redzone: true,
+        exe_suffix: ".efi".to_string(),
+        allows_weak_linkage: false,
+        panic_strategy: PanicStrategy::Abort,
+        singlethread: true,
+        emit_debug_gdb_scripts: false,
+
+        linker: Some("lld-link".to_string()),
+        lld_flavor: LldFlavor::Link,
+        pre_link_args,
+
+        .. Default::default()
+    }
+}
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_target/spec/x86_64_unknown_uefi.rs b/src/librustc_target/spec/x86_64_unknown_uefi.rs
new file mode 100644
index 0000000..ea68afa
--- /dev/null
+++ b/src/librustc_target/spec/x86_64_unknown_uefi.rs
@@ -0,0 +1,58 @@
+// 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.
+
+// This defines the amd64 target for UEFI systems as described in the UEFI specification. See the
+// uefi-base module for generic UEFI options. On x86_64 systems (mostly called "x64" in the spec)
+// UEFI systems always run in long-mode, have the interrupt-controller pre-configured and force a
+// single-CPU execution.
+// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
+// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
+
+use spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::uefi_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.max_atomic_width = Some(64);
+
+    // We disable MMX and SSE for now. UEFI does not prevent these from being used, but there have
+    // been reports to GRUB that some firmware does not initialize the FP exception handlers
+    // properly. Therefore, using FP coprocessors will end you up at random memory locations when
+    // you throw FP exceptions.
+    // To be safe, we disable them for now and force soft-float. This can be revisited when we
+    // have more test coverage. Disabling FP served GRUB well so far, so it should be good for us
+    // as well.
+    base.features = "-mmx,-sse,+soft-float".to_string();
+
+    // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell
+    // LLVM to expect code to reference any address in the address-space. The "large" code-model
+    // places no locality-restrictions, so it fits well here.
+    base.code_model = Some("large".to_string());
+
+    // UEFI mostly mirrors the calling-conventions used on windows. In case of x86-64 this means
+    // small structs will be returned as int. This shouldn't matter much, since the restrictions
+    // placed by the UEFI specifications forbid any ABI to return structures.
+    base.abi_return_struct_as_int = true;
+
+    Ok(Target {
+        llvm_target: "x86_64-unknown-windows".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        target_os: "uefi".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        arch: "x86_64".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+
+        options: base,
+    })
+}
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/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 5c0eef5..a40e56d 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -435,7 +435,8 @@
         "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
         "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)),
         "simd_cast" => (2, vec![param(0)], param(1)),
-        "simd_select" => (2, vec![param(0), param(1), param(1)], param(1)),
+        "simd_select" |
+        "simd_select_bitmask" => (2, vec![param(0), param(1), param(1)], param(1)),
         "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool),
         "simd_reduce_add_ordered" | "simd_reduce_mul_ordered"
             => (2, vec![param(0), param(1)], param(1)),
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index b76c910..0906357 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -424,10 +424,12 @@
                 }
 
                 if !unsatisfied_predicates.is_empty() {
-                    let bound_list = unsatisfied_predicates.iter()
+                    let mut bound_list = unsatisfied_predicates.iter()
                         .map(|p| format!("`{} : {}`", p.self_ty(), p))
-                        .collect::<Vec<_>>()
-                        .join("\n");
+                        .collect::<Vec<_>>();
+                    bound_list.sort();
+                    bound_list.dedup();  // #35677
+                    let bound_list = bound_list.join("\n");
                     err.note(&format!("the method `{}` exists but the following trait bounds \
                                        were not satisfied:\n{}",
                                       item_name,
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/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 6ce02c3..37ff693 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -54,6 +54,7 @@
     <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}light{suffix}.css\" \
           id=\"themeStyle\">\
     <script src=\"{root_path}storage{suffix}.js\"></script>\
+    <noscript><link rel=\"stylesheet\" href=\"{root_path}noscript{suffix}.css\"></noscript>\
     {css_extension}\
     {favicon}\
     {in_header}\
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 00ca4fe..536ea39 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -806,6 +806,10 @@
 }
 
 pub fn plain_summary_line(md: &str) -> String {
+    plain_summary_line_full(md, false)
+}
+
+pub fn plain_summary_line_full(md: &str, limit_length: bool) -> String {
     struct ParserWrapper<'a> {
         inner: Parser<'a>,
         is_in: isize,
@@ -852,7 +856,21 @@
             s.push_str(&t);
         }
     }
-    s
+    if limit_length && s.chars().count() > 60 {
+        let mut len = 0;
+        let mut ret = s.split_whitespace()
+                       .take_while(|p| {
+                           // + 1 for the added character after the word.
+                           len += p.chars().count() + 1;
+                           len < 60
+                       })
+                       .collect::<Vec<_>>()
+                       .join(" ");
+        ret.push('…');
+        ret
+    } else {
+        s
+    }
 }
 
 pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 8d7942a..46002c0 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -698,7 +698,7 @@
                 ty: item.type_(),
                 name: item.name.clone().unwrap(),
                 path: fqp[..fqp.len() - 1].join("::"),
-                desc: plain_summary_line(item.doc_value()),
+                desc: plain_summary_line_short(item.doc_value()),
                 parent: Some(did),
                 parent_idx: None,
                 search_type: get_index_search_type(&item),
@@ -736,7 +736,7 @@
     }
 
     let crate_doc = krate.module.as_ref().map(|module| {
-        plain_summary_line(module.doc_value())
+        plain_summary_line_short(module.doc_value())
     }).unwrap_or(String::new());
 
     let mut crate_data = BTreeMap::new();
@@ -772,6 +772,9 @@
     write_minify(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
                  static_files::SETTINGS_CSS,
                  options.enable_minification)?;
+    write_minify(cx.dst.join(&format!("noscript{}.css", cx.shared.resource_suffix)),
+                 static_files::NOSCRIPT_CSS,
+                 options.enable_minification)?;
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
     // then we'll run over the "official" styles.
@@ -865,11 +868,10 @@
     }
 
     {
-        let mut data = format!("var resourcesSuffix = \"{}\";\n",
-                               cx.shared.resource_suffix);
-        data.push_str(static_files::STORAGE_JS);
         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)?;
     }
 
@@ -1481,7 +1483,7 @@
                             ty: item.type_(),
                             name: s.to_string(),
                             path: path.join("::"),
-                            desc: plain_summary_line(item.doc_value()),
+                            desc: plain_summary_line_short(item.doc_value()),
                             parent,
                             parent_idx: None,
                             search_type: get_index_search_type(&item),
@@ -1512,7 +1514,8 @@
             clean::FunctionItem(..) | clean::ModuleItem(..) |
             clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) |
             clean::ConstantItem(..) | clean::StaticItem(..) |
-            clean::UnionItem(..) | clean::ForeignTypeItem | clean::MacroItem(..)
+            clean::UnionItem(..) | clean::ForeignTypeItem |
+            clean::MacroItem(..) | clean::ProcMacroItem(..)
             if !self.stripped_mod => {
                 // Re-exported items mean that the same id can show up twice
                 // in the rustdoc ast that we're looking at. We know,
@@ -1673,7 +1676,7 @@
                                 ty: item.type_(),
                                 name: item_name.to_string(),
                                 path: path.clone(),
-                                desc: plain_summary_line(item.doc_value()),
+                                desc: plain_summary_line_short(item.doc_value()),
                                 parent: None,
                                 parent_idx: None,
                                 search_type: get_index_search_type(&item),
@@ -2388,7 +2391,13 @@
 #[inline]
 fn plain_summary_line(s: Option<&str>) -> String {
     let line = shorter(s).replace("\n", " ");
-    markdown::plain_summary_line(&line[..])
+    markdown::plain_summary_line_full(&line[..], false)
+}
+
+#[inline]
+fn plain_summary_line_short(s: Option<&str>) -> String {
+    let line = shorter(s).replace("\n", " ");
+    markdown::plain_summary_line_full(&line[..], true)
 }
 
 fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
@@ -3006,6 +3015,22 @@
     // Trait documentation
     document(w, cx, it)?;
 
+    fn write_small_section_header(
+        w: &mut fmt::Formatter,
+        id: &str,
+        title: &str,
+        extra_content: &str,
+    ) -> fmt::Result {
+        write!(w, "
+            <h2 id='{0}' class='small-section-header'>\
+              {1}<a href='#{0}' class='anchor'></a>\
+            </h2>{2}", id, title, extra_content)
+    }
+
+    fn write_loading_content(w: &mut fmt::Formatter, extra_content: &str) -> fmt::Result {
+        write!(w, "{}<span class='loading-content'>Loading content...</span>", extra_content)
+    }
+
     fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item)
                   -> fmt::Result {
         let name = m.name.as_ref().unwrap();
@@ -3026,74 +3051,45 @@
     }
 
     if !types.is_empty() {
-        write!(w, "
-            <h2 id='associated-types' class='small-section-header'>
-              Associated Types<a href='#associated-types' class='anchor'></a>
-            </h2>
-            <div class='methods'>
-        ")?;
+        write_small_section_header(w, "associated-types", "Associated Types",
+                                   "<div class='methods'>")?;
         for t in &types {
             trait_item(w, cx, *t, it)?;
         }
-        write!(w, "</div>")?;
+        write_loading_content(w, "</div>")?;
     }
 
     if !consts.is_empty() {
-        write!(w, "
-            <h2 id='associated-const' class='small-section-header'>
-              Associated Constants<a href='#associated-const' class='anchor'></a>
-            </h2>
-            <div class='methods'>
-        ")?;
+        write_small_section_header(w, "associated-const", "Associated Constants",
+                                   "<div class='methods'>")?;
         for t in &consts {
             trait_item(w, cx, *t, it)?;
         }
-        write!(w, "</div>")?;
+        write_loading_content(w, "</div>")?;
     }
 
     // Output the documentation for each function individually
     if !required.is_empty() {
-        write!(w, "
-            <h2 id='required-methods' class='small-section-header'>
-              Required Methods<a href='#required-methods' class='anchor'></a>
-            </h2>
-            <div class='methods'>
-        ")?;
+        write_small_section_header(w, "required-methods", "Required methods",
+                                   "<div class='methods'>")?;
         for m in &required {
             trait_item(w, cx, *m, it)?;
         }
-        write!(w, "</div>")?;
+        write_loading_content(w, "</div>")?;
     }
     if !provided.is_empty() {
-        write!(w, "
-            <h2 id='provided-methods' class='small-section-header'>
-              Provided Methods<a href='#provided-methods' class='anchor'></a>
-            </h2>
-            <div class='methods'>
-        ")?;
+        write_small_section_header(w, "provided-methods", "Provided methods",
+                                   "<div class='methods'>")?;
         for m in &provided {
             trait_item(w, cx, *m, it)?;
         }
-        write!(w, "</div>")?;
+        write_loading_content(w, "</div>")?;
     }
 
     // If there are methods directly on this trait object, render them here.
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?;
 
     let cache = cache();
-    let impl_header = "\
-        <h2 id='implementors' class='small-section-header'>\
-          Implementors<a href='#implementors' class='anchor'></a>\
-        </h2>\
-        <div class='item-list' id='implementors-list'>\
-    ";
-
-    let synthetic_impl_header = "\
-        <h2 id='synthetic-implementors' class='small-section-header'>\
-          Auto implementors<a href='#synthetic-implementors' class='anchor'></a>\
-        </h2>\
-        <div class='item-list' id='synthetic-implementors-list'>\
-    ";
 
     let mut synthetic_types = Vec::new();
 
@@ -3130,11 +3126,7 @@
         concrete.sort_by(compare_impl);
 
         if !foreign.is_empty() {
-            write!(w, "
-                <h2 id='foreign-impls' class='small-section-header'>
-                  Implementations on Foreign Types<a href='#foreign-impls' class='anchor'></a>
-                </h2>
-            ")?;
+            write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "")?;
 
             for implementor in foreign {
                 let assoc_link = AssocItemLink::GotoSource(
@@ -3145,33 +3137,38 @@
                             RenderMode::Normal, implementor.impl_item.stable_since(), false,
                             None)?;
             }
+            write_loading_content(w, "")?;
         }
 
-        write!(w, "{}", impl_header)?;
+        write_small_section_header(w, "implementors", "Implementors",
+                                   "<div class='item-list' id='implementors-list'>")?;
         for implementor in concrete {
             render_implementor(cx, implementor, w, &implementor_dups)?;
         }
-        write!(w, "</div>")?;
+        write_loading_content(w, "</div>")?;
 
         if t.auto {
-            write!(w, "{}", synthetic_impl_header)?;
+            write_small_section_header(w, "synthetic-implementors", "Auto implementors",
+                                       "<div class='item-list' id='synthetic-implementors-list'>")?;
             for implementor in synthetic {
                 synthetic_types.extend(
                     collect_paths_for_type(implementor.inner_impl().for_.clone())
                 );
                 render_implementor(cx, implementor, w, &implementor_dups)?;
             }
-            write!(w, "</div>")?;
+            write_loading_content(w, "</div>")?;
         }
     } else {
         // even without any implementations to write in, we still want the heading and list, so the
         // implementors javascript file pulled in below has somewhere to write the impls into
-        write!(w, "{}", impl_header)?;
-        write!(w, "</div>")?;
+        write_small_section_header(w, "implementors", "Implementors",
+                                   "<div class='item-list' id='implementors-list'>")?;
+        write_loading_content(w, "</div>")?;
 
         if t.auto {
-            write!(w, "{}", synthetic_impl_header)?;
-            write!(w, "</div>")?;
+            write_small_section_header(w, "synthetic-implementors", "Auto implementors",
+                                       "<div class='item-list' id='synthetic-implementors-list'>")?;
+            write_loading_content(w, "</div>")?;
         }
     }
     write!(w, r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 1869969..d5b8ecd 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -30,6 +30,27 @@
     };
 }
 
+if (!DOMTokenList.prototype.add) {
+    DOMTokenList.prototype.add = function(className) {
+        if (className && !hasClass(this, className)) {
+            if (this.className && this.className.length > 0) {
+                this.className += " " + className;
+            } else {
+                this.className = className;
+            }
+        }
+    };
+}
+
+if (!DOMTokenList.prototype.remove) {
+    DOMTokenList.prototype.remove = function(className) {
+        if (className && this.className) {
+            this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
+                                                         .trim();
+        }
+    };
+}
+
 (function() {
     "use strict";
 
@@ -61,7 +82,7 @@
                      "attr",
                      "derive"];
 
-    var search_input = document.getElementsByClassName('search-input')[0];
+    var search_input = document.getElementsByClassName("search-input")[0];
 
     // On the search screen, so you remain on the last tab you opened.
     //
@@ -75,9 +96,9 @@
     var titleBeforeSearch = document.title;
 
     function getPageId() {
-        var id = document.location.href.split('#')[1];
+        var id = document.location.href.split("#")[1];
         if (id) {
-            return id.split('?')[0].split('&')[0];
+            return id.split("?")[0].split("&")[0];
         }
         return null;
     }
@@ -87,9 +108,9 @@
         if (elems) {
             addClass(elems, "show-it");
         }
-        var sidebar = document.getElementsByClassName('sidebar')[0];
+        var sidebar = document.getElementsByClassName("sidebar")[0];
         if (sidebar) {
-            addClass(sidebar, 'mobile');
+            addClass(sidebar, "mobile");
             var filler = document.getElementById("sidebar-filler");
             if (!filler) {
                 var div = document.createElement("div");
@@ -108,13 +129,13 @@
         if (elems) {
             removeClass(elems, "show-it");
         }
-        var sidebar = document.getElementsByClassName('sidebar')[0];
-        removeClass(sidebar, 'mobile');
+        var sidebar = document.getElementsByClassName("sidebar")[0];
+        removeClass(sidebar, "mobile");
         var filler = document.getElementById("sidebar-filler");
         if (filler) {
             filler.remove();
         }
-        document.getElementsByTagName("body")[0].style.marginTop = '';
+        document.getElementsByTagName("body")[0].style.marginTop = "";
         var themePicker = document.getElementsByClassName("theme-picker");
         if (themePicker && themePicker.length > 0) {
             themePicker[0].style.display = null;
@@ -125,8 +146,8 @@
     var TY_PRIMITIVE = itemTypes.indexOf("primitive");
     var TY_KEYWORD = itemTypes.indexOf("keyword");
 
-    onEach(document.getElementsByClassName('js-only'), function(e) {
-        removeClass(e, 'js-only');
+    onEachLazy(document.getElementsByClassName("js-only"), function(e) {
+        removeClass(e, "js-only");
     });
 
     function getQueryStringParams() {
@@ -145,16 +166,19 @@
           window.history && typeof window.history.pushState === "function";
     }
 
+    var main = document.getElementById("main");
+
     function highlightSourceLines(ev) {
         // If we're in mobile mode, we should add the sidebar in any case.
         hideSidebar();
+        var elem;
         var search = document.getElementById("search");
         var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
         if (match) {
             from = parseInt(match[1], 10);
             to = Math.min(50000, parseInt(match[2] || match[1], 10));
             from = Math.min(from, to);
-            var elem = document.getElementById(from);
+            elem = document.getElementById(from);
             if (!elem) {
                 return;
             }
@@ -164,22 +188,22 @@
                     x.scrollIntoView();
                 }
             }
-            onEach(document.getElementsByClassName('line-numbers'), function(e) {
-                onEach(e.getElementsByTagName('span'), function(i_e) {
-                    removeClass(i_e, 'line-highlighted');
+            onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
+                onEachLazy(e.getElementsByTagName("span"), function(i_e) {
+                    removeClass(i_e, "line-highlighted");
                 });
             });
             for (i = from; i <= to; ++i) {
-                addClass(document.getElementById(i), 'line-highlighted');
+                addClass(document.getElementById(i), "line-highlighted");
             }
         } else if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
             addClass(search, "hidden");
-            removeClass(document.getElementById("main"), "hidden");
-            var hash = ev.newURL.slice(ev.newURL.indexOf('#') + 1);
+            removeClass(main, "hidden");
+            var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
             if (browserSupportsHistoryApi()) {
                 history.replaceState(hash, "", "?search=#" + hash);
             }
-            var elem = document.getElementById(hash);
+            elem = document.getElementById(hash);
             if (elem) {
                 elem.scrollIntoView();
             }
@@ -189,9 +213,9 @@
     function expandSection(id) {
         var elem = document.getElementById(id);
         if (elem && isHidden(elem)) {
-            var h3 = elem.parentNode.previousSibling;
-            if (h3 && h3.tagName !== 'H3') {
-                h3 = h3.previousSibling; // skip div.docblock
+            var h3 = elem.parentNode.previousElementSibling;
+            if (h3 && h3.tagName !== "H3") {
+                h3 = h3.previousElementSibling; // skip div.docblock
             }
 
             if (h3) {
@@ -236,7 +260,7 @@
                 removeClass(help, "hidden");
                 addClass(document.body, "blur");
             }
-        } else if (!hasClass(help, "hidden")) {
+        } else if (hasClass(help, "hidden") === false) {
             ev.preventDefault();
             addClass(help, "hidden");
             removeClass(document.body, "blur");
@@ -246,12 +270,12 @@
     function handleEscape(ev, help) {
         hideModal();
         var search = document.getElementById("search");
-        if (!hasClass(help, "hidden")) {
+        if (hasClass(help, "hidden") === false) {
             displayHelp(false, ev);
-        } else if (!hasClass(search, "hidden")) {
+        } else if (hasClass(search, "hidden") === false) {
             ev.preventDefault();
             addClass(search, "hidden");
-            removeClass(document.getElementById("main"), "hidden");
+            removeClass(main, "hidden");
             document.title = titleBeforeSearch;
         }
         defocusSearchBar();
@@ -305,26 +329,27 @@
             if (elem && elem.tagName === tagName) {
                 return elem;
             }
-        } while (elem = elem.parentNode);
+            elem = elem.parentNode;
+        } while (elem);
         return null;
     }
 
     document.onkeypress = handleShortcut;
     document.onkeydown = handleShortcut;
     document.onclick = function(ev) {
-        if (hasClass(ev.target, 'collapse-toggle')) {
+        if (hasClass(ev.target, "collapse-toggle")) {
             collapseDocs(ev.target, "toggle");
-        } else if (hasClass(ev.target.parentNode, 'collapse-toggle')) {
+        } else if (hasClass(ev.target.parentNode, "collapse-toggle")) {
             collapseDocs(ev.target.parentNode, "toggle");
-        } else if (ev.target.tagName === 'SPAN' && hasClass(ev.target.parentNode, 'line-numbers')) {
+        } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) {
             var prev_id = 0;
 
             var set_fragment = function(name) {
                 if (browserSupportsHistoryApi()) {
-                    history.replaceState(null, null, '#' + name);
+                    history.replaceState(null, null, "#" + name);
                     window.hashchange();
                 } else {
-                    location.replace('#' + name);
+                    location.replace("#" + name);
                 }
             };
 
@@ -337,31 +362,31 @@
                     cur_id = tmp;
                 }
 
-                set_fragment(prev_id + '-' + cur_id);
+                set_fragment(prev_id + "-" + cur_id);
             } else {
                 prev_id = cur_id;
 
                 set_fragment(cur_id);
             }
-        } else if (!hasClass(document.getElementById("help"), "hidden")) {
+        } else if (hasClass(document.getElementById("help"), "hidden") === false) {
             addClass(document.getElementById("help"), "hidden");
             removeClass(document.body, "blur");
         } else {
             // Making a collapsed element visible on onhashchange seems
             // too late
-            var a = findParentElement(ev.target, 'A');
+            var a = findParentElement(ev.target, "A");
             if (a && a.hash) {
-                expandSection(a.hash.replace(/^#/, ''));
+                expandSection(a.hash.replace(/^#/, ""));
             }
         }
     };
 
-    var x = document.getElementsByClassName('version-selector');
+    var x = document.getElementsByClassName("version-selector");
     if (x.length > 0) {
         x[0].onchange = function() {
             var i, match,
                 url = document.location.href,
-                stripped = '',
+                stripped = "",
                 len = rootPath.match(/\.\.\//g).length + 1;
 
             for (i = 0; i < len; ++i) {
@@ -372,7 +397,7 @@
                 url = url.substring(0, url.length - match[0].length);
             }
 
-            url += '/' + document.getElementsByClassName('version-selector')[0].value + stripped;
+            url += "/" + document.getElementsByClassName("version-selector")[0].value + stripped;
 
             document.location.href = url;
         };
@@ -428,7 +453,7 @@
         // where you start trying to do a search, and the index loads, and
         // suddenly your search is gone!
         if (search_input.value === "") {
-            search_input.value = params.search || '';
+            search_input.value = params.search || "";
         }
 
         /**
@@ -441,7 +466,8 @@
          */
         function execQuery(query, searchWords, filterCrates) {
             function itemTypeFromName(typename) {
-                for (var i = 0; i < itemTypes.length; ++i) {
+                var length = itemTypes.length;
+                for (var i = 0; i < length; ++i) {
                     if (itemTypes[i] === typename) {
                         return i;
                     }
@@ -455,7 +481,8 @@
                 results = {}, results_in_args = {}, results_returned = {},
                 split = valLower.split("::");
 
-            for (var z = 0; z < split.length; ++z) {
+            var length = split.length;
+            for (var z = 0; z < length; ++z) {
                 if (split[z] === "") {
                     split.splice(z, 1);
                     z -= 1;
@@ -464,7 +491,8 @@
 
             function transformResults(results, isType) {
                 var out = [];
-                for (i = 0; i < results.length; ++i) {
+                var length = results.length;
+                for (var i = 0; i < length; ++i) {
                     if (results[i].id > -1) {
                         var obj = searchIndex[results[i].id];
                         obj.lev = results[i].lev;
@@ -473,7 +501,7 @@
                             obj.displayPath = pathSplitter(res[0]);
                             obj.fullPath = obj.displayPath + obj.name;
                             // To be sure than it some items aren't considered as duplicate.
-                            obj.fullPath += '|' + obj.ty;
+                            obj.fullPath += "|" + obj.ty;
                             obj.href = res[1];
                             out.push(obj);
                             if (out.length >= MAX_RESULTS) {
@@ -493,8 +521,9 @@
                     }
                 }
                 results = ar;
+                var i;
                 var nresults = results.length;
-                for (var i = 0; i < nresults; ++i) {
+                for (i = 0; i < nresults; ++i) {
                     results[i].word = searchWords[results[i].id];
                     results[i].item = searchIndex[results[i].id] || {};
                 }
@@ -552,8 +581,8 @@
                     }
 
                     // sort by description (no description goes later)
-                    a = (aaa.item.desc === '');
-                    b = (bbb.item.desc === '');
+                    a = (aaa.item.desc === "");
+                    b = (bbb.item.desc === "");
                     if (a !== b) { return a - b; }
 
                     // sort by type (later occurrence in `itemTypes` goes later)
@@ -570,7 +599,8 @@
                     return 0;
                 });
 
-                for (var i = 0; i < results.length; ++i) {
+                var length = results.length;
+                for (i = 0; i < length; ++i) {
                     var result = results[i];
 
                     // this validation does not make sense when searching by types
@@ -592,10 +622,10 @@
 
             function extractGenerics(val) {
                 val = val.toLowerCase();
-                if (val.indexOf('<') !== -1) {
-                    var values = val.substring(val.indexOf('<') + 1, val.lastIndexOf('>'));
+                if (val.indexOf("<") !== -1) {
+                    var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
                     return {
-                        name: val.substring(0, val.indexOf('<')),
+                        name: val.substring(0, val.indexOf("<")),
                         generics: values.split(/\s*,\s*/),
                     };
                 }
@@ -617,9 +647,11 @@
                         var done = 0;
                         // We need to find the type that matches the most to remove it in order
                         // to move forward.
-                        for (var y = 0; y < val.generics.length; ++y) {
+                        var vlength = val.generics.length;
+                        for (var y = 0; y < vlength; ++y) {
                             var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
-                            for (var x = 0; x < elems.length; ++x) {
+                            var elength = elems.length;
+                            for (var x = 0; x < elength; ++x) {
                                 var tmp_lev = levenshtein(elems[x], val.generics[y]);
                                 if (tmp_lev < lev.lev) {
                                     lev.lev = tmp_lev;
@@ -644,6 +676,7 @@
             // Check for type name and type generics (if any).
             function checkType(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
+                var x;
                 if (obj[NAME] === val.name) {
                     if (literalSearch === true) {
                         if (val.generics && val.generics.length !== 0) {
@@ -651,7 +684,6 @@
                                   obj[GENERICS_DATA].length >= val.generics.length) {
                                 var elems = obj[GENERICS_DATA].slice(0);
                                 var allFound = true;
-                                var x;
 
                                 for (var y = 0; allFound === true && y < val.generics.length; ++y) {
                                     allFound = false;
@@ -685,7 +717,8 @@
                 // Names didn't match so let's check if one of the generic types could.
                 if (literalSearch === true) {
                      if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
-                        for (var x = 0; x < obj[GENERICS_DATA].length; ++x) {
+                        var length = obj[GENERICS_DATA].length;
+                        for (x = 0; x < length; ++x) {
                             if (obj[GENERICS_DATA][x] === val.name) {
                                 return true;
                             }
@@ -693,13 +726,13 @@
                     }
                     return false;
                 }
-                var lev_distance = Math.min(levenshtein(obj[NAME], val.name),
-                                            lev_distance);
+                lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
                 if (lev_distance <= MAX_LEV_DISTANCE) {
                     lev_distance = Math.min(checkGenerics(obj, val), lev_distance);
                 } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
                     // We can check if the type we're looking for is inside the generics!
-                    for (var x = 0; x < obj[GENERICS_DATA].length; ++x) {
+                    var olength = obj[GENERICS_DATA].length;
+                    for (x = 0; x < olength; ++x) {
                         lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
                                                 lev_distance);
                     }
@@ -714,7 +747,8 @@
 
                 if (obj && obj.type && obj.type[INPUTS_DATA] &&
                       obj.type[INPUTS_DATA].length > 0) {
-                    for (var i = 0; i < obj.type[INPUTS_DATA].length; i++) {
+                    var length = obj.type[INPUTS_DATA].length;
+                    for (var i = 0; i < length; i++) {
                         var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch);
                         if (literalSearch === true && tmp === true) {
                             return true;
@@ -755,16 +789,18 @@
                     path.push(ty.parent.name.toLowerCase());
                 }
 
-                if (contains.length > path.length) {
+                var length = path.length;
+                var clength = contains.length;
+                if (clength > length) {
                     return MAX_LEV_DISTANCE + 1;
                 }
-                for (var i = 0; i < path.length; ++i) {
-                    if (i + contains.length > path.length) {
+                for (var i = 0; i < length; ++i) {
+                    if (i + clength > length) {
                         break;
                     }
                     var lev_total = 0;
                     var aborted = false;
-                    for (var x = 0; x < contains.length; ++x) {
+                    for (var x = 0; x < clength; ++x) {
                         var lev = levenshtein(path[i + x], contains[x]);
                         if (lev > MAX_LEV_DISTANCE) {
                             aborted = true;
@@ -773,7 +809,7 @@
                         lev_total += lev;
                     }
                     if (aborted === false) {
-                        ret_lev = Math.min(ret_lev, Math.round(lev_total / contains.length));
+                        ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
                     }
                 }
                 return ret_lev;
@@ -810,18 +846,23 @@
 
             // quoted values mean literal search
             var nSearchWords = searchWords.length;
+            var i;
+            var ty;
+            var fullId;
+            var returned;
+            var in_args;
             if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
                 val.charAt(val.length - 1) === val.charAt(0))
             {
                 val = extractGenerics(val.substr(1, val.length - 2));
-                for (var i = 0; i < nSearchWords; ++i) {
+                for (i = 0; i < nSearchWords; ++i) {
                     if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
                         continue;
                     }
-                    var in_args = findArg(searchIndex[i], val, true);
-                    var returned = checkReturned(searchIndex[i], val, true);
-                    var ty = searchIndex[i];
-                    var fullId = generateId(ty);
+                    in_args = findArg(searchIndex[i], val, true);
+                    returned = checkReturned(searchIndex[i], val, true);
+                    ty = searchIndex[i];
+                    fullId = generateId(ty);
 
                     if (searchWords[i] === val.name) {
                         // filter type: ... queries
@@ -866,27 +907,27 @@
                 var input = parts[0];
                 // sort inputs so that order does not matter
                 var inputs = input.split(",").map(trimmer).sort();
-                for (var i = 0; i < inputs.length; ++i) {
+                for (i = 0; i < inputs.length; ++i) {
                     inputs[i] = extractGenerics(inputs[i]);
                 }
                 var output = extractGenerics(parts[1]);
 
-                for (var i = 0; i < nSearchWords; ++i) {
+                for (i = 0; i < nSearchWords; ++i) {
                     if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
                         continue;
                     }
                     var type = searchIndex[i].type;
-                    var ty = searchIndex[i];
+                    ty = searchIndex[i];
                     if (!type) {
                         continue;
                     }
-                    var fullId = generateId(ty);
+                    fullId = generateId(ty);
 
                     // allow searching for void (no output) functions as well
                     var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : "";
-                    var returned = checkReturned(ty, output, true);
+                    returned = checkReturned(ty, output, true);
                     if (output.name === "*" || returned === true) {
-                        var in_args = false;
+                        in_args = false;
                         var module = false;
 
                         if (input === "*") {
@@ -946,14 +987,16 @@
                 var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
 
                 for (j = 0; j < nSearchWords; ++j) {
-                    var ty = searchIndex[j];
+                    var lev;
+                    var lev_distance;
+                    ty = searchIndex[j];
                     if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
                         continue;
                     }
                     var lev_distance;
                     var lev_add = 0;
                     if (paths.length > 1) {
-                        var lev = checkPath(contains, paths[paths.length - 1], ty);
+                        lev = checkPath(contains, paths[paths.length - 1], ty);
                         if (lev > MAX_LEV_DISTANCE) {
                             continue;
                         } else if (lev > 0) {
@@ -961,12 +1004,12 @@
                         }
                     }
 
-                    var returned = MAX_LEV_DISTANCE + 1;
-                    var in_args = MAX_LEV_DISTANCE + 1;
+                    returned = MAX_LEV_DISTANCE + 1;
+                    in_args = MAX_LEV_DISTANCE + 1;
                     var index = -1;
                     // we want lev results to go lower than others
-                    var lev = MAX_LEV_DISTANCE + 1;
-                    var fullId = generateId(ty);
+                    lev = MAX_LEV_DISTANCE + 1;
+                    fullId = generateId(ty);
 
                     if (searchWords[j].indexOf(split[i]) > -1 ||
                         searchWords[j].indexOf(val) > -1 ||
@@ -1042,14 +1085,14 @@
             }
 
             var ret = {
-                'in_args': sortResults(results_in_args, true),
-                'returned': sortResults(results_returned, true),
-                'others': sortResults(results),
+                "in_args": sortResults(results_in_args, true),
+                "returned": sortResults(results_returned, true),
+                "others": sortResults(results),
             };
             if (ALIASES && ALIASES[window.currentCrate] &&
                     ALIASES[window.currentCrate][query.raw]) {
                 var aliases = ALIASES[window.currentCrate][query.raw];
-                for (var i = 0; i < aliases.length; ++i) {
+                for (i = 0; i < aliases.length; ++i) {
                     aliases[i].is_alias = true;
                     aliases[i].alias = query.raw;
                     aliases[i].path = aliases[i].p;
@@ -1057,9 +1100,9 @@
                     aliases[i].displayPath = pathSplitter(res[0]);
                     aliases[i].fullPath = aliases[i].displayPath + aliases[i].name;
                     aliases[i].href = res[1];
-                    ret['others'].unshift(aliases[i]);
-                    if (ret['others'].length > MAX_RESULTS) {
-                        ret['others'].pop();
+                    ret.others.unshift(aliases[i]);
+                    if (ret.others.length > MAX_RESULTS) {
+                        ret.others.pop();
                     }
                 }
             }
@@ -1106,7 +1149,7 @@
 
             matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
             if (matches) {
-                type = matches[1].replace(/^const$/, 'constant');
+                type = matches[1].replace(/^const$/, "constant");
                 query = query.substring(matches[0].length);
             }
 
@@ -1124,38 +1167,38 @@
             var click_func = function(e) {
                 var el = e.target;
                 // to retrieve the real "owner" of the event.
-                while (el.tagName !== 'TR') {
+                while (el.tagName !== "TR") {
                     el = el.parentNode;
                 }
-                var dst = e.target.getElementsByTagName('a');
+                var dst = e.target.getElementsByTagName("a");
                 if (dst.length < 1) {
                     return;
                 }
                 dst = dst[0];
                 if (window.location.pathname === dst.pathname) {
-                    addClass(document.getElementById('search'), 'hidden');
-                    removeClass(document.getElementById('main'), 'hidden');
+                    addClass(document.getElementById("search"), "hidden");
+                    removeClass(main, "hidden");
                     document.location.href = dst.href;
                 }
             };
             var mouseover_func = function(e) {
                 var el = e.target;
                 // to retrieve the real "owner" of the event.
-                while (el.tagName !== 'TR') {
+                while (el.tagName !== "TR") {
                     el = el.parentNode;
                 }
                 clearTimeout(hoverTimeout);
                 hoverTimeout = setTimeout(function() {
-                    onEach(document.getElementsByClassName('search-results'), function(e) {
-                        onEach(e.getElementsByClassName('result'), function(i_e) {
-                            removeClass(i_e, 'highlighted');
+                    onEachLazy(document.getElementsByClassName("search-results"), function(e) {
+                        onEachLazy(e.getElementsByClassName("result"), function(i_e) {
+                            removeClass(i_e, "highlighted");
                         });
                     });
-                    addClass(el, 'highlighted');
+                    addClass(el, "highlighted");
                 }, 20);
             };
-            onEach(document.getElementsByClassName('search-results'), function(e) {
-                onEach(e.getElementsByClassName('result'), function(i_e) {
+            onEachLazy(document.getElementsByClassName("search-results"), function(e) {
+                onEachLazy(e.getElementsByClassName("result"), function(i_e) {
                     i_e.onclick = click_func;
                     i_e.onmouseover = mouseover_func;
                 });
@@ -1167,8 +1210,8 @@
                 var actives = [[], [], []];
                 // "current" is used to know which tab we're looking into.
                 var current = 0;
-                onEach(document.getElementsByClassName('search-results'), function(e) {
-                    onEach(e.getElementsByClassName('highlighted'), function(e) {
+                onEachLazy(document.getElementsByClassName("search-results"), function(e) {
+                    onEachLazy(e.getElementsByClassName("highlighted"), function(e) {
                         actives[current].push(e);
                     });
                     current += 1;
@@ -1180,25 +1223,25 @@
                         return;
                     }
 
-                    addClass(actives[currentTab][0].previousElementSibling, 'highlighted');
-                    removeClass(actives[currentTab][0], 'highlighted');
+                    addClass(actives[currentTab][0].previousElementSibling, "highlighted");
+                    removeClass(actives[currentTab][0], "highlighted");
                 } else if (e.which === 40) { // down
                     if (!actives[currentTab].length) {
-                        var results = document.getElementsByClassName('search-results');
+                        var results = document.getElementsByClassName("search-results");
                         if (results.length > 0) {
-                            var res = results[currentTab].getElementsByClassName('result');
+                            var res = results[currentTab].getElementsByClassName("result");
                             if (res.length > 0) {
-                                addClass(res[0], 'highlighted');
+                                addClass(res[0], "highlighted");
                             }
                         }
                     } else if (actives[currentTab][0].nextElementSibling) {
-                        addClass(actives[currentTab][0].nextElementSibling, 'highlighted');
-                        removeClass(actives[currentTab][0], 'highlighted');
+                        addClass(actives[currentTab][0].nextElementSibling, "highlighted");
+                        removeClass(actives[currentTab][0], "highlighted");
                     }
                 } else if (e.which === 13) { // return
                     if (actives[currentTab].length) {
                         document.location.href =
-                            actives[currentTab][0].getElementsByTagName('a')[0].href;
+                            actives[currentTab][0].getElementsByTagName("a")[0].href;
                     }
                 } else if (e.which === 9) { // tab
                     if (e.shiftKey) {
@@ -1210,11 +1253,11 @@
                 } else if (e.which === 16) { // shift
                     // Does nothing, it's just to avoid losing "focus" on the highlighted element.
                 } else if (e.which === 27) { // escape
-                    removeClass(actives[currentTab][0], 'highlighted');
-                    search_input.value = '';
+                    removeClass(actives[currentTab][0], "highlighted");
+                    search_input.value = "";
                     defocusSearchBar();
                 } else if (actives[currentTab].length > 0) {
-                    removeClass(actives[currentTab][0], 'highlighted');
+                    removeClass(actives[currentTab][0], "highlighted");
                 }
             };
         }
@@ -1225,46 +1268,46 @@
             var type = itemTypes[item.ty];
             var name = item.name;
 
-            if (type === 'mod') {
-                displayPath = item.path + '::';
-                href = rootPath + item.path.replace(/::/g, '/') + '/' +
-                       name + '/index.html';
+            if (type === "mod") {
+                displayPath = item.path + "::";
+                href = rootPath + item.path.replace(/::/g, "/") + "/" +
+                       name + "/index.html";
             } else if (type === "primitive" || type === "keyword") {
                 displayPath = "";
-                href = rootPath + item.path.replace(/::/g, '/') +
-                       '/' + type + '.' + name + '.html';
+                href = rootPath + item.path.replace(/::/g, "/") +
+                       "/" + type + "." + name + ".html";
             } else if (type === "externcrate") {
                 displayPath = "";
-                href = rootPath + name + '/index.html';
+                href = rootPath + name + "/index.html";
             } else if (item.parent !== undefined) {
                 var myparent = item.parent;
-                var anchor = '#' + type + '.' + name;
+                var anchor = "#" + type + "." + name;
                 var parentType = itemTypes[myparent.ty];
                 if (parentType === "primitive") {
-                    displayPath = myparent.name + '::';
+                    displayPath = myparent.name + "::";
                 } else {
-                    displayPath = item.path + '::' + myparent.name + '::';
+                    displayPath = item.path + "::" + myparent.name + "::";
                 }
-                href = rootPath + item.path.replace(/::/g, '/') +
-                       '/' + parentType +
-                       '.' + myparent.name +
-                       '.html' + anchor;
+                href = rootPath + item.path.replace(/::/g, "/") +
+                       "/" + parentType +
+                       "." + myparent.name +
+                       ".html" + anchor;
             } else {
-                displayPath = item.path + '::';
-                href = rootPath + item.path.replace(/::/g, '/') +
-                       '/' + type + '.' + name + '.html';
+                displayPath = item.path + "::";
+                href = rootPath + item.path.replace(/::/g, "/") +
+                       "/" + type + "." + name + ".html";
             }
             return [displayPath, href];
         }
 
         function escape(content) {
-            var h1 = document.createElement('h1');
+            var h1 = document.createElement("h1");
             h1.textContent = content;
             return h1.innerHTML;
         }
 
         function pathSplitter(path) {
-            var tmp = '<span>' + path.replace(/::/g, '::</span><span>');
+            var tmp = "<span>" + path.replace(/::/g, "::</span><span>");
             if (tmp.endsWith("<span>")) {
                 return tmp.slice(0, tmp.length - 6);
             }
@@ -1272,16 +1315,16 @@
         }
 
         function addTab(array, query, display) {
-            var extraStyle = '';
+            var extraStyle = "";
             if (display === false) {
-                extraStyle = ' style="display: none;"';
+                extraStyle = " style=\"display: none;\"";
             }
 
-            var output = '';
+            var output = "";
             var duplicates = {};
             var length = 0;
             if (array.length > 0) {
-                output = '<table class="search-results"' + extraStyle + '>';
+                output = "<table class=\"search-results\"" + extraStyle + ">";
 
                 array.forEach(function(item) {
                     var name, type;
@@ -1297,50 +1340,50 @@
                     }
                     length += 1;
 
-                    output += '<tr class="' + type + ' result"><td>' +
-                              '<a href="' + item.href + '">' +
+                    output += "<tr class=\"" + type + " result\"><td>" +
+                              "<a href=\"" + item.href + "\">" +
                               (item.is_alias === true ?
-                               ('<span class="alias"><b>' + item.alias + ' </b></span><span ' +
-                                  'class="grey"><i>&nbsp;- see&nbsp;</i></span>') : '') +
-                              item.displayPath + '<span class="' + type + '">' +
-                              name + '</span></a></td><td>' +
-                              '<a href="' + item.href + '">' +
-                              '<span class="desc">' + escape(item.desc) +
-                              '&nbsp;</span></a></td></tr>';
+                               ("<span class=\"alias\"><b>" + item.alias + " </b></span><span " +
+                                  "class=\"grey\"><i>&nbsp;- see&nbsp;</i></span>") : "") +
+                              item.displayPath + "<span class=\"" + type + "\">" +
+                              name + "</span></a></td><td>" +
+                              "<a href=\"" + item.href + "\">" +
+                              "<span class=\"desc\">" + escape(item.desc) +
+                              "&nbsp;</span></a></td></tr>";
                 });
-                output += '</table>';
+                output += "</table>";
             } else {
-                output = '<div class="search-failed"' + extraStyle + '>No results :(<br/>' +
-                    'Try on <a href="https://duckduckgo.com/?q=' +
-                    encodeURIComponent('rust ' + query.query) +
-                    '">DuckDuckGo</a>?<br/><br/>' +
-                    'Or try looking in one of these:<ul><li>The <a ' +
-                    'href="https://doc.rust-lang.org/reference/index.html">Rust Reference</a> for' +
-                    ' technical details about the language.</li><li><a ' +
-                    'href="https://doc.rust-lang.org/rust-by-example/index.html">Rust By Example' +
-                    '</a> for expository code examples.</a></li><li>The <a ' +
-                    'href="https://doc.rust-lang.org/book/index.html">Rust Book</a> for ' +
-                    'introductions to language features and the language itself.</li><li><a ' +
-                    'href="https://docs.rs">Docs.rs</a> for documentation of crates released on ' +
-                    '<a href="https://crates.io/">crates.io</a>.</li></ul></div>';
+                output = "<div class=\"search-failed\"" + extraStyle + ">No results :(<br/>" +
+                    "Try on <a href=\"https://duckduckgo.com/?q=" +
+                    encodeURIComponent("rust " + query.query) +
+                    "\">DuckDuckGo</a>?<br/><br/>" +
+                    "Or try looking in one of these:<ul><li>The <a " +
+                    "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
+                    " for technical details about the language.</li><li><a " +
+                    "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " +
+                    "Example</a> for expository code examples.</a></li><li>The <a " +
+                    "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " +
+                    "introductions to language features and the language itself.</li><li><a " +
+                    "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" +
+                    " <a href=\"https://crates.io/\">crates.io</a>.</li></ul></div>";
             }
             return [output, length];
         }
 
         function makeTabHeader(tabNb, text, nbElems) {
             if (currentTab === tabNb) {
-                return '<div class="selected">' + text +
-                       ' <div class="count">(' + nbElems + ')</div></div>';
+                return "<div class=\"selected\">" + text +
+                       " <div class=\"count\">(" + nbElems + ")</div></div>";
             }
-            return '<div>' + text + ' <div class="count">(' + nbElems + ')</div></div>';
+            return "<div>" + text + " <div class=\"count\">(" + nbElems + ")</div></div>";
         }
 
-        function showResults(results, filterCrates) {
-            if (results['others'].length === 1 &&
-                getCurrentValue('rustdoc-go-to-only-result') === "true") {
-                var elem = document.createElement('a');
-                elem.href = results['others'][0].href;
-                elem.style.display = 'none';
+        function showResults(results) {
+            if (results.others.length === 1 &&
+                getCurrentValue("rustdoc-go-to-only-result") === "true") {
+                var elem = document.createElement("a");
+                elem.href = results.others[0].href;
+                elem.style.display = "none";
                 // For firefox, we need the element to be in the DOM so it can be clicked.
                 document.body.appendChild(elem);
                 elem.click();
@@ -1349,39 +1392,34 @@
 
             currentResults = query.id;
 
-            var ret_others = addTab(results['others'], query);
-            var ret_in_args = addTab(results['in_args'], query, false);
-            var ret_returned = addTab(results['returned'], query, false);
+            var ret_others = addTab(results.others, query);
+            var ret_in_args = addTab(results.in_args, query, false);
+            var ret_returned = addTab(results.returned, query, false);
 
-            var filter = "";
-            if (filterCrates !== undefined) {
-                filter = " (in <b>" + filterCrates + "</b> crate)";
-            }
-
-            var output = '<h1>Results for ' + escape(query.query) +
-                (query.type ? ' (type: ' + escape(query.type) + ')' : '') + filter + '</h1>' +
-                '<div id="titles">' +
+            var output = "<h1>Results for " + escape(query.query) +
+                (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
+                "<div id=\"titles\">" +
                 makeTabHeader(0, "In Names", ret_others[1]) +
                 makeTabHeader(1, "In Parameters", ret_in_args[1]) +
                 makeTabHeader(2, "In Return Types", ret_returned[1]) +
-                '</div><div id="results">' +
-                ret_others[0] + ret_in_args[0] + ret_returned[0] + '</div>';
+                "</div><div id=\"results\">" +
+                ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
 
-            addClass(document.getElementById('main'), 'hidden');
-            var search = document.getElementById('search');
-            removeClass(search, 'hidden');
+            addClass(main, "hidden");
+            var search = document.getElementById("search");
+            removeClass(search, "hidden");
             search.innerHTML = output;
-            var tds = search.getElementsByTagName('td');
+            var tds = search.getElementsByTagName("td");
             var td_width = 0;
             if (tds.length > 0) {
                 td_width = tds[0].offsetWidth;
             }
             var width = search.offsetWidth - 40 - td_width;
-            onEach(search.getElementsByClassName('desc'), function(e) {
-                e.style.width = width + 'px';
+            onEachLazy(search.getElementsByClassName("desc"), function(e) {
+                e.style.width = width + "px";
             });
             initSearchNav();
-            var elems = document.getElementById('titles').childNodes;
+            var elems = document.getElementById("titles").childNodes;
             elems[0].onclick = function() { printTab(0); };
             elems[1].onclick = function() { printTab(1); };
             elems[2].onclick = function() { printTab(2); };
@@ -1389,74 +1427,74 @@
         }
 
         function execSearch(query, searchWords, filterCrates) {
+            function getSmallest(arrays, positions, notDuplicates) {
+                var start = null;
+
+                for (var it = 0; it < positions.length; ++it) {
+                    if (arrays[it].length > positions[it] &&
+                        (start === null || start > arrays[it][positions[it]].lev) &&
+                        !notDuplicates[arrays[it][positions[it]].fullPath]) {
+                        start = arrays[it][positions[it]].lev;
+                    }
+                }
+                return start;
+            }
+
+            function mergeArrays(arrays) {
+                var ret = [];
+                var positions = [];
+                var notDuplicates = {};
+
+                for (var x = 0; x < arrays.length; ++x) {
+                    positions.push(0);
+                }
+                while (ret.length < MAX_RESULTS) {
+                    var smallest = getSmallest(arrays, positions, notDuplicates);
+
+                    if (smallest === null) {
+                        break;
+                    }
+                    for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) {
+                        if (arrays[x].length > positions[x] &&
+                                arrays[x][positions[x]].lev === smallest &&
+                                !notDuplicates[arrays[x][positions[x]].fullPath]) {
+                            ret.push(arrays[x][positions[x]]);
+                            notDuplicates[arrays[x][positions[x]].fullPath] = true;
+                            positions[x] += 1;
+                        }
+                    }
+                }
+                return ret;
+            }
+
             var queries = query.raw.split(",");
             var results = {
-                'in_args': [],
-                'returned': [],
-                'others': [],
+                "in_args": [],
+                "returned": [],
+                "others": [],
             };
 
             for (var i = 0; i < queries.length; ++i) {
-                var query = queries[i].trim();
+                query = queries[i].trim();
                 if (query.length !== 0) {
                     var tmp = execQuery(getQuery(query), searchWords, filterCrates);
 
-                    results['in_args'].push(tmp['in_args']);
-                    results['returned'].push(tmp['returned']);
-                    results['others'].push(tmp['others']);
+                    results.in_args.push(tmp.in_args);
+                    results.returned.push(tmp.returned);
+                    results.others.push(tmp.others);
                 }
             }
             if (queries.length > 1) {
-                function getSmallest(arrays, positions, notDuplicates) {
-                    var start = null;
-
-                    for (var it = 0; it < positions.length; ++it) {
-                        if (arrays[it].length > positions[it] &&
-                            (start === null || start > arrays[it][positions[it]].lev) &&
-                            !notDuplicates[arrays[it][positions[it]].fullPath]) {
-                            start = arrays[it][positions[it]].lev;
-                        }
-                    }
-                    return start;
-                }
-
-                function mergeArrays(arrays) {
-                    var ret = [];
-                    var positions = [];
-                    var notDuplicates = {};
-
-                    for (var x = 0; x < arrays.length; ++x) {
-                        positions.push(0);
-                    }
-                    while (ret.length < MAX_RESULTS) {
-                        var smallest = getSmallest(arrays, positions, notDuplicates);
-
-                        if (smallest === null) {
-                            break;
-                        }
-                        for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) {
-                            if (arrays[x].length > positions[x] &&
-                                    arrays[x][positions[x]].lev === smallest &&
-                                    !notDuplicates[arrays[x][positions[x]].fullPath]) {
-                                ret.push(arrays[x][positions[x]]);
-                                notDuplicates[arrays[x][positions[x]].fullPath] = true;
-                                positions[x] += 1;
-                            }
-                        }
-                    }
-                    return ret;
-                }
-
                 return {
-                    'in_args': mergeArrays(results['in_args']),
-                    'returned': mergeArrays(results['returned']),
-                    'others': mergeArrays(results['others']),
+                    "in_args": mergeArrays(results.in_args),
+                    "returned": mergeArrays(results.returned),
+                    "others": mergeArrays(results.others),
                 };
             } else {
                 return {
-                    'in_args': results['in_args'][0],
-                    'returned': results['returned'][0],
-                    'others': results['others'][0],
+                    "in_args": results.in_args[0],
+                    "returned": results.returned[0],
+                    "others": results.others[0],
                 };
             }
         }
@@ -1508,6 +1546,8 @@
         function buildIndex(rawSearchIndex) {
             searchIndex = [];
             var searchWords = [];
+            var i;
+
             for (var crate in rawSearchIndex) {
                 if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
 
@@ -1534,7 +1574,7 @@
 
                 // convert `paths` into an object form
                 var len = paths.length;
-                for (var i = 0; i < len; ++i) {
+                for (i = 0; i < len; ++i) {
                     paths[i] = {ty: paths[i][0], name: paths[i][1]};
                 }
 
@@ -1545,9 +1585,9 @@
                 // operation that is cached for the life of the page state so that
                 // all other search operations have access to this cached data for
                 // faster analysis operations
-                var len = items.length;
+                len = items.length;
                 var lastPath = "";
-                for (var i = 0; i < len; ++i) {
+                for (i = 0; i < len; ++i) {
                     var rawRow = items[i];
                     var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
                                path: rawRow[2] || lastPath, desc: rawRow[3],
@@ -1573,13 +1613,12 @@
                     if (browserSupportsHistoryApi()) {
                         history.replaceState("", "std - Rust", "?search=");
                     }
-                    var main = document.getElementById('main');
-                    if (hasClass(main, 'content')) {
-                        removeClass(main, 'hidden');
+                    if (hasClass(main, "content")) {
+                        removeClass(main, "hidden");
                     }
-                    var search_c = document.getElementById('search');
-                    if (hasClass(search_c, 'content')) {
-                        addClass(search_c, 'hidden');
+                    var search_c = document.getElementById("search");
+                    if (hasClass(search_c, "content")) {
+                        addClass(search_c, "hidden");
                     }
                 } else {
                     searchTimeout = setTimeout(search, 500);
@@ -1620,13 +1659,12 @@
                     // When browsing back from search results the main page
                     // visibility must be reset.
                     if (!params.search) {
-                        var main = document.getElementById('main');
-                        if (hasClass(main, 'content')) {
-                            removeClass(main, 'hidden');
+                        if (hasClass(main, "content")) {
+                            removeClass(main, "hidden");
                         }
-                        var search_c = document.getElementById('search');
-                        if (hasClass(search_c, 'content')) {
-                            addClass(search_c, 'hidden');
+                        var search_c = document.getElementById("search");
+                        if (hasClass(search_c, "content")) {
+                            addClass(search_c, "hidden");
                         }
                     }
                     // Revert to the previous title manually since the History
@@ -1643,9 +1681,9 @@
                     if (params.search) {
                         search_input.value = params.search;
                     } else {
-                        search_input.value = '';
+                        search_input.value = "";
                     }
-                    // Some browsers fire 'onpopstate' for every page load
+                    // Some browsers fire "onpopstate" for every page load
                     // (Chrome), while others fire the event only when actually
                     // popping a state (Firefox), which is why search() is
                     // called both here and at the end of the startSearch()
@@ -1660,13 +1698,13 @@
         startSearch();
 
         // Draw a convenient sidebar of known crates if we have a listing
-        if (rootPath === '../' || rootPath === "./") {
-            var sidebar = document.getElementsByClassName('sidebar-elems')[0];
+        if (rootPath === "../" || rootPath === "./") {
+            var sidebar = document.getElementsByClassName("sidebar-elems")[0];
             if (sidebar) {
-                var div = document.createElement('div');
-                div.className = 'block crate';
-                div.innerHTML = '<h3>Crates</h3>';
-                var ul = document.createElement('ul');
+                var div = document.createElement("div");
+                div.className = "block crate";
+                div.innerHTML = "<h3>Crates</h3>";
+                var ul = document.createElement("ul");
                 div.appendChild(ul);
 
                 var crates = [];
@@ -1678,17 +1716,17 @@
                 }
                 crates.sort();
                 for (var i = 0; i < crates.length; ++i) {
-                    var klass = 'crate';
+                    var klass = "crate";
                     if (rootPath !== "./" && crates[i] === window.currentCrate) {
-                        klass += ' current';
+                        klass += " current";
                     }
-                    var link = document.createElement('a');
-                    link.href = rootPath + crates[i] + '/index.html';
+                    var link = document.createElement("a");
+                    link.href = rootPath + crates[i] + "/index.html";
                     link.title = rawSearchIndex[crates[i]].doc;
                     link.className = klass;
                     link.textContent = crates[i];
 
-                    var li = document.createElement('li');
+                    var li = document.createElement("li");
                     li.appendChild(link);
                     ul.appendChild(li);
                 }
@@ -1701,41 +1739,44 @@
 
     // delayed sidebar rendering.
     function initSidebarItems(items) {
-        var sidebar = document.getElementsByClassName('sidebar-elems')[0];
+        var sidebar = document.getElementsByClassName("sidebar-elems")[0];
         var current = window.sidebarCurrent;
 
         function block(shortty, longty) {
             var filtered = items[shortty];
-            if (!filtered) { return; }
+            if (!filtered) {
+                return;
+            }
 
-            var div = document.createElement('div');
-            div.className = 'block ' + shortty;
-            var h3 = document.createElement('h3');
+            var div = document.createElement("div");
+            div.className = "block " + shortty;
+            var h3 = document.createElement("h3");
             h3.textContent = longty;
             div.appendChild(h3);
-            var ul = document.createElement('ul');
+            var ul = document.createElement("ul");
 
-            for (var i = 0; i < filtered.length; ++i) {
+            var length = filtered.length;
+            for (var i = 0; i < length; ++i) {
                 var item = filtered[i];
                 var name = item[0];
                 var desc = item[1]; // can be null
 
                 var klass = shortty;
                 if (name === current.name && shortty === current.ty) {
-                    klass += ' current';
+                    klass += " current";
                 }
                 var path;
-                if (shortty === 'mod') {
-                    path = name + '/index.html';
+                if (shortty === "mod") {
+                    path = name + "/index.html";
                 } else {
-                    path = shortty + '.' + name + '.html';
+                    path = shortty + "." + name + ".html";
                 }
-                var link = document.createElement('a');
+                var link = document.createElement("a");
                 link.href = current.relpath + path;
                 link.title = desc;
                 link.className = klass;
                 link.textContent = name;
-                var li = document.createElement('li');
+                var li = document.createElement("li");
                 li.appendChild(link);
                 ul.appendChild(li);
             }
@@ -1763,22 +1804,25 @@
     window.initSidebarItems = initSidebarItems;
 
     window.register_implementors = function(imp) {
-        var implementors = document.getElementById('implementors-list');
-        var synthetic_implementors = document.getElementById('synthetic-implementors-list');
+        var implementors = document.getElementById("implementors-list");
+        var synthetic_implementors = document.getElementById("synthetic-implementors-list");
 
         var libs = Object.getOwnPropertyNames(imp);
-        for (var i = 0; i < libs.length; ++i) {
+        var llength = libs.length;
+        for (var i = 0; i < llength; ++i) {
             if (libs[i] === currentCrate) { continue; }
             var structs = imp[libs[i]];
 
+            var slength = structs.length;
             struct_loop:
-            for (var j = 0; j < structs.length; ++j) {
+            for (var j = 0; j < slength; ++j) {
                 var struct = structs[j];
 
                 var list = struct.synthetic ? synthetic_implementors : implementors;
 
                 if (struct.synthetic) {
-                    for (var k = 0; k < struct.types.length; k++) {
+                    var stlength = struct.types.length;
+                    for (var k = 0; k < stlength; k++) {
                         if (window.inlined_types.has(struct.types[k])) {
                             continue struct_loop;
                         }
@@ -1786,21 +1830,22 @@
                     }
                 }
 
-                var code = document.createElement('code');
+                var code = document.createElement("code");
                 code.innerHTML = struct.text;
 
-                var x = code.getElementsByTagName('a');
-                for (var k = 0; k < x.length; k++) {
-                    var href = x[k].getAttribute('href');
-                    if (href && href.indexOf('http') !== 0) {
-                        x[k].setAttribute('href', rootPath + href);
+                var x = code.getElementsByTagName("a");
+                var xlength = x.length;
+                for (var it = 0; it < xlength; it++) {
+                    var href = x[it].getAttribute("href");
+                    if (href && href.indexOf("http") !== 0) {
+                        x[it].setAttribute("href", rootPath + href);
                     }
                 }
-                var display = document.createElement('h3');
+                var display = document.createElement("h3");
                 addClass(display, "impl");
-                display.innerHTML = '<span class="in-band"><table class="table-display"><tbody>\
-                    <tr><td><code>' + code.outerHTML + '</code></td><td></td></tr></tbody></table>\
-                    </span>';
+                display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
+                    "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
+                    "</tbody></table></span>";
                 list.appendChild(display);
             }
         }
@@ -1816,47 +1861,49 @@
         }
         // button will collapse the section
         // note that this text is also set in the HTML template in render.rs
-        return "\u2212"; // "\u2212" is '−' minus sign
+        return "\u2212"; // "\u2212" is "−" minus sign
     }
 
     function onEveryMatchingChild(elem, className, func) {
         if (elem && className && func) {
-            for (var i = 0; i < elem.childNodes.length; i++) {
-                if (hasClass(elem.childNodes[i], className)) {
-                    func(elem.childNodes[i]);
+            var length = elem.childNodes.length;
+            var nodes = elem.childNodes;
+            for (var i = 0; i < length; ++i) {
+                if (hasClass(nodes[i], className)) {
+                    func(nodes[i]);
                 } else {
-                    onEveryMatchingChild(elem.childNodes[i], className, func);
+                    onEveryMatchingChild(nodes[i], className, func);
                 }
             }
         }
     }
 
     function toggleAllDocs(pageId, fromAutoCollapse) {
-        var toggle = document.getElementById("toggle-all-docs");
-        if (!toggle) {
+        var innerToggle = document.getElementById("toggle-all-docs");
+        if (!innerToggle) {
             return;
         }
-        if (hasClass(toggle, "will-expand")) {
+        if (hasClass(innerToggle, "will-expand")) {
             updateLocalStorage("rustdoc-collapse", "false");
-            removeClass(toggle, "will-expand");
-            onEveryMatchingChild(toggle, "inner", function(e) {
+            removeClass(innerToggle, "will-expand");
+            onEveryMatchingChild(innerToggle, "inner", function(e) {
                 e.innerHTML = labelForToggleButton(false);
             });
-            toggle.title = "collapse all docs";
+            innerToggle.title = "collapse all docs";
             if (fromAutoCollapse !== true) {
-                onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
+                onEachLazy(document.getElementsByClassName("collapse-toggle"), function(e) {
                     collapseDocs(e, "show");
                 });
             }
         } else {
             updateLocalStorage("rustdoc-collapse", "true");
-            addClass(toggle, "will-expand");
-            onEveryMatchingChild(toggle, "inner", function(e) {
+            addClass(innerToggle, "will-expand");
+            onEveryMatchingChild(innerToggle, "inner", function(e) {
                 e.innerHTML = labelForToggleButton(true);
             });
-            toggle.title = "expand all docs";
+            innerToggle.title = "expand all docs";
             if (fromAutoCollapse !== true) {
-                onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
+                onEachLazy(document.getElementsByClassName("collapse-toggle"), function(e) {
                     collapseDocs(e, "hide", pageId);
                 });
             }
@@ -1870,27 +1917,58 @@
 
         function adjustToggle(arg) {
             return function(e) {
-                if (hasClass(e, 'toggle-label')) {
+                if (hasClass(e, "toggle-label")) {
                     if (arg) {
-                        e.style.display = 'inline-block';
+                        e.style.display = "inline-block";
                     } else {
-                        e.style.display = 'none';
+                        e.style.display = "none";
                     }
                 }
-                if (hasClass(e, 'inner')) {
+                if (hasClass(e, "inner")) {
                     e.innerHTML = labelForToggleButton(arg);
                 }
             };
-        };
+        }
 
-        if (!hasClass(toggle.parentNode, "impl")) {
-            var relatedDoc = toggle.parentNode.nextElementSibling;
+        function implHider(addOrRemove) {
+            return function(n) {
+                var is_method = hasClass(n, "method");
+                if (is_method || hasClass(n, "type")) {
+                    if (is_method === true) {
+                        if (addOrRemove) {
+                            addClass(n, "hidden-by-impl-hider");
+                        } else {
+                            removeClass(n, "hidden-by-impl-hider");
+                        }
+                    }
+                    var ns = n.nextElementSibling;
+                    while (true) {
+                        if (ns && (
+                                hasClass(ns, "docblock") ||
+                                hasClass(ns, "stability"))) {
+                            if (addOrRemove) {
+                                addClass(ns, "hidden-by-impl-hider");
+                            } else {
+                                removeClass(ns, "hidden-by-impl-hider");
+                            }
+                            ns = ns.nextElementSibling;
+                            continue;
+                        }
+                        break;
+                    }
+                }
+            };
+        }
+
+        var relatedDoc;
+        var action = mode;
+        if (hasClass(toggle.parentNode, "impl") === false) {
+            relatedDoc = toggle.parentNode.nextElementSibling;
             if (hasClass(relatedDoc, "stability")) {
                 relatedDoc = relatedDoc.nextElementSibling;
             }
             if (hasClass(relatedDoc, "docblock") || hasClass(relatedDoc, "sub-variant")) {
-                var action = mode;
-                if (action === "toggle") {
+                if (mode === "toggle") {
                     if (hasClass(relatedDoc, "hidden-by-usual-hider")) {
                         action = "show";
                     } else {
@@ -1899,67 +1977,35 @@
                 }
                 if (action === "hide") {
                     addClass(relatedDoc, "hidden-by-usual-hider");
-                    onEach(toggle.childNodes, adjustToggle(true));
-                    addClass(toggle.parentNode, 'collapsed');
+                    onEachLazy(toggle.childNodes, adjustToggle(true));
+                    addClass(toggle.parentNode, "collapsed");
                 } else if (action === "show") {
                     removeClass(relatedDoc, "hidden-by-usual-hider");
-                    removeClass(toggle.parentNode, 'collapsed');
-                    onEach(toggle.childNodes, adjustToggle(false));
+                    removeClass(toggle.parentNode, "collapsed");
+                    onEachLazy(toggle.childNodes, adjustToggle(false));
                 }
             }
         } else {
             // we are collapsing the impl block
-            function implHider(addOrRemove) {
-                return function(n) {
-                    var is_method = hasClass(n, "method");
-                    if (is_method || hasClass(n, "type")) {
-                        if (is_method === true) {
-                            if (addOrRemove) {
-                                addClass(n, "hidden-by-impl-hider");
-                            } else {
-                                removeClass(n, "hidden-by-impl-hider");
-                            }
-                        }
-                        var ns = n.nextElementSibling;
-                        while (true) {
-                            if (ns && (
-                                    hasClass(ns, "docblock") ||
-                                    hasClass(ns, "stability"))) {
-                                if (addOrRemove) {
-                                    addClass(ns, "hidden-by-impl-hider");
-                                } else {
-                                    removeClass(ns, "hidden-by-impl-hider");
-                                }
-                                ns = ns.nextElementSibling;
-                                continue;
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
 
             var parentElem = toggle.parentNode;
-            var relatedDoc = parentElem;
+            relatedDoc = parentElem;
             var docblock = relatedDoc.nextElementSibling;
 
-            while (!hasClass(relatedDoc, "impl-items")) {
+            while (hasClass(relatedDoc, "impl-items") === false) {
                 relatedDoc = relatedDoc.nextElementSibling;
             }
 
-            if ((!relatedDoc && !hasClass(docblock, "docblock")) ||
-                (pageId && onEach(relatedDoc.childNodes, function(e) {
-                    return e.id === pageId;
-                }) === true)) {
+            if ((!relatedDoc && hasClass(docblock, "docblock") === false) ||
+                (pageId && document.getElementById(pageId))) {
                 return;
             }
 
             // Hide all functions, but not associated types/consts
 
-            var action = mode;
-            if (action === "toggle") {
+            if (mode === "toggle") {
                 if (hasClass(relatedDoc, "fns-now-collapsed") ||
-                    hasClass(docblock,  "hidden-by-impl-hider")) {
+                    hasClass(docblock, "hidden-by-impl-hider")) {
                     action = "show";
                 } else {
                     action = "hide";
@@ -1969,13 +2015,25 @@
             if (action === "show") {
                 removeClass(relatedDoc, "fns-now-collapsed");
                 removeClass(docblock, "hidden-by-usual-hider");
-                onEach(toggle.childNodes, adjustToggle(false));
-                onEach(relatedDoc.childNodes, implHider(false));
+                onEachLazy(toggle.childNodes, adjustToggle(false));
+                onEachLazy(relatedDoc.childNodes, implHider(false));
             } else if (action === "hide") {
                 addClass(relatedDoc, "fns-now-collapsed");
                 addClass(docblock, "hidden-by-usual-hider");
-                onEach(toggle.childNodes, adjustToggle(true));
-                onEach(relatedDoc.childNodes, implHider(true));
+                onEachLazy(toggle.childNodes, adjustToggle(true));
+                onEachLazy(relatedDoc.childNodes, implHider(true));
+            }
+        }
+    }
+
+    function collapser(e, collapse) {
+        // inherent impl ids are like "impl" or impl-<number>'.
+        // they will never be hidden by default.
+        var n = e.parentElement;
+        if (n.id.match(/^impl(?:-\d+)?$/) === null) {
+            // Automatically minimize all non-inherent impls
+            if (collapse || hasClass(n, "impl")) {
+                collapseDocs(e, "hide", pageId);
             }
         }
     }
@@ -1983,88 +2041,112 @@
     function autoCollapse(pageId, collapse) {
         if (collapse) {
             toggleAllDocs(pageId, true);
-        }
-        var collapser = function(e) {
-                // inherent impl ids are like 'impl' or impl-<number>'.
-                // they will never be hidden by default.
-                var n = e.parentElement;
-                if (n.id.match(/^impl(?:-\d+)?$/) === null) {
-                    // Automatically minimize all non-inherent impls
-                    if (collapse || hasClass(n, 'impl')) {
-                        collapseDocs(e, "hide", pageId);
-                    }
-                }
-        };
-        if (getCurrentValue('rustdoc-trait-implementations') !== "false") {
-            var impl_list = document.getElementById('implementations-list');
+        } else if (getCurrentValue("rustdoc-trait-implementations") !== "false") {
+            var impl_list = document.getElementById("implementations-list");
 
             if (impl_list !== null) {
-                onEach(impl_list.getElementsByClassName("collapse-toggle"), collapser);
-            }
-        }
-        if (getCurrentValue('rustdoc-method-docs') !== "false") {
-            var implItems = document.getElementsByClassName('impl-items');
-
-            if (implItems && implItems.length > 0) {
-                onEach(implItems, function(elem) {
-                    onEach(elem.getElementsByClassName("collapse-toggle"), collapser);
+                onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) {
+                    collapser(e, collapse);
                 });
             }
         }
     }
 
-    var x = document.getElementById('toggle-all-docs');
-    if (x) {
-        x.onclick = toggleAllDocs;
+    var toggles = document.getElementById("toggle-all-docs");
+    if (toggles) {
+        toggles.onclick = toggleAllDocs;
     }
 
     function insertAfter(newNode, referenceNode) {
         referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
     }
 
-    function checkIfThereAreMethods(elems) {
-        var areThereMethods = false;
-
-        onEach(elems, function(e) {
-            if (hasClass(e, "method")) {
-                areThereMethods = true;
-                return true;
-            }
-        });
-        return areThereMethods;
+    function createSimpleToggle(sectionIsCollapsed) {
+        var toggle = document.createElement("a");
+        toggle.href = "javascript:void(0)";
+        toggle.className = "collapse-toggle";
+        toggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(sectionIsCollapsed) +
+                           "</span>]";
+        return toggle;
     }
 
-    var toggle = document.createElement('a');
-    toggle.href = 'javascript:void(0)';
-    toggle.className = 'collapse-toggle';
-    toggle.innerHTML = "[<span class='inner'>" + labelForToggleButton(false) + "</span>]";
+    var toggle = createSimpleToggle(false);
 
     var func = function(e) {
         var next = e.nextElementSibling;
-        if (hasClass(e, 'impl') && next && hasClass(next, 'docblock')) {
+        if (!next) {
+            return;
+        }
+        if (hasClass(next, "docblock") ||
+            (hasClass(next, "stability") &&
+             hasClass(next.nextElementSibling, "docblock"))) {
+            insertAfter(toggle.cloneNode(true), e.childNodes[e.childNodes.length - 1]);
+        }
+    };
+
+    var funcImpl = function(e) {
+        var next = e.nextElementSibling;
+        if (next && hasClass(next, "docblock")) {
             next = next.nextElementSibling;
         }
         if (!next) {
             return;
         }
-        if ((hasClass(e, 'method') || hasClass(e, 'associatedconstant') ||
-             checkIfThereAreMethods(next.childNodes)) &&
-            (hasClass(next, 'docblock') ||
-             hasClass(e, 'impl') ||
-             (hasClass(next, 'stability') &&
-              hasClass(next.nextElementSibling, 'docblock')))) {
+        if (next.getElementsByClassName("method").length > 0 && hasClass(e, "impl")) {
             insertAfter(toggle.cloneNode(true), e.childNodes[e.childNodes.length - 1]);
         }
     };
-    onEach(document.getElementsByClassName('method'), func);
-    onEach(document.getElementsByClassName('associatedconstant'), func);
-    onEach(document.getElementsByClassName('impl'), func);
-    onEach(document.getElementsByClassName('impl-items'), function(e) {
-        onEach(e.getElementsByClassName('associatedconstant'), func);
-        var hiddenElems = e.getElementsByClassName('hidden');
+
+    onEachLazy(document.getElementsByClassName("method"), func);
+    onEachLazy(document.getElementsByClassName("associatedconstant"), func);
+    onEachLazy(document.getElementsByClassName("impl"), funcImpl);
+    var impl_call = function() {};
+    if (getCurrentValue("rustdoc-method-docs") !== "false") {
+        impl_call = function(e, newToggle, pageId) {
+            if (e.id.match(/^impl(?:-\d+)?$/) === null) {
+                // Automatically minimize all non-inherent impls
+                if (hasClass(e, "impl")) {
+                    collapseDocs(newToggle, "hide", pageId);
+                }
+            }
+        };
+    }
+    var pageId = getPageId();
+    var newToggle = document.createElement("a");
+    newToggle.href = "javascript:void(0)";
+    newToggle.className = "collapse-toggle hidden-default collapsed";
+    newToggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) +
+                          "</span>] Show hidden undocumented items";
+    function toggleClicked() {
+        if (hasClass(this, "collapsed")) {
+            removeClass(this, "collapsed");
+            onEachLazy(this.parentNode.getElementsByClassName("hidden"), function(x) {
+                if (hasClass(x, "content") === false) {
+                    removeClass(x, "hidden");
+                    addClass(x, "x");
+                }
+            }, true);
+            this.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(false) +
+                             "</span>] Hide undocumented items";
+        } else {
+            addClass(this, "collapsed");
+            onEachLazy(this.parentNode.getElementsByClassName("x"), function(x) {
+                if (hasClass(x, "content") === false) {
+                    addClass(x, "hidden");
+                    removeClass(x, "x");
+                }
+            }, true);
+            this.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) +
+                             "</span>] Show hidden undocumented items";
+        }
+    }
+    onEachLazy(document.getElementsByClassName("impl-items"), function(e) {
+        onEachLazy(e.getElementsByClassName("associatedconstant"), func);
+        var hiddenElems = e.getElementsByClassName("hidden");
         var needToggle = false;
 
-        for (var i = 0; i < hiddenElems.length; ++i) {
+        var hlength = hiddenElems.length;
+        for (var i = 0; i < hlength; ++i) {
             if (hasClass(hiddenElems[i], "content") === false &&
                 hasClass(hiddenElems[i], "docblock") === false) {
                 needToggle = true;
@@ -2072,46 +2154,21 @@
             }
         }
         if (needToggle === true) {
-            var newToggle = document.createElement('a');
-            newToggle.href = 'javascript:void(0)';
-            newToggle.className = 'collapse-toggle hidden-default collapsed';
-            newToggle.innerHTML = "[<span class='inner'>" + labelForToggleButton(true) + "</span>" +
-                                  "] Show hidden undocumented items";
-            newToggle.onclick = function() {
-                if (hasClass(this, "collapsed")) {
-                    removeClass(this, "collapsed");
-                    onEach(this.parentNode.getElementsByClassName("hidden"), function(x) {
-                        if (hasClass(x, "content") === false) {
-                            removeClass(x, "hidden");
-                            addClass(x, "x");
-                        }
-                    }, true);
-                    this.innerHTML = "[<span class='inner'>" + labelForToggleButton(false) +
-                                     "</span>] Hide undocumented items"
-                } else {
-                    addClass(this, "collapsed");
-                    onEach(this.parentNode.getElementsByClassName("x"), function(x) {
-                        if (hasClass(x, "content") === false) {
-                            addClass(x, "hidden");
-                            removeClass(x, "x");
-                        }
-                    }, true);
-                    this.innerHTML = "[<span class='inner'>" + labelForToggleButton(true) +
-                                     "</span>] Show hidden undocumented items";
-                }
-            };
-            e.insertBefore(newToggle, e.firstChild);
+            var inner_toggle = newToggle.cloneNode(true);
+            inner_toggle.onclick = toggleClicked;
+            e.insertBefore(inner_toggle, e.firstChild);
+            impl_call(e, inner_toggle, pageId);
         }
     });
 
     function createToggle(otherMessage, fontSize, extraClass, show) {
-        var span = document.createElement('span');
-        span.className = 'toggle-label';
+        var span = document.createElement("span");
+        span.className = "toggle-label";
         if (show) {
-            span.style.display = 'none';
+            span.style.display = "none";
         }
         if (!otherMessage) {
-            span.innerHTML = '&nbsp;Expand&nbsp;description';
+            span.innerHTML = "&nbsp;Expand&nbsp;description";
         } else {
             span.innerHTML = otherMessage;
         }
@@ -2123,13 +2180,13 @@
         var mainToggle = toggle.cloneNode(true);
         mainToggle.appendChild(span);
 
-        var wrapper = document.createElement('div');
-        wrapper.className = 'toggle-wrapper';
+        var wrapper = document.createElement("div");
+        wrapper.className = "toggle-wrapper";
         if (!show) {
-            addClass(wrapper, 'collapsed');
-            var inner = mainToggle.getElementsByClassName('inner');
+            addClass(wrapper, "collapsed");
+            var inner = mainToggle.getElementsByClassName("inner");
             if (inner && inner.length > 0) {
-                inner[0].innerHTML = '+';
+                inner[0].innerHTML = "+";
             }
         }
         if (extraClass) {
@@ -2139,21 +2196,21 @@
         return wrapper;
     }
 
-    var showItemDeclarations = getCurrentValue('rustdoc-item-declarations') === "false";
+    var showItemDeclarations = getCurrentValue("rustdoc-item-declarations") === "false";
     function buildToggleWrapper(e) {
-        if (hasClass(e, 'autohide')) {
+        if (hasClass(e, "autohide")) {
             var wrap = e.previousElementSibling;
-            if (wrap && hasClass(wrap, 'toggle-wrapper')) {
-                var toggle = wrap.childNodes[0];
-                var extra = e.childNodes[0].tagName === 'H3';
+            if (wrap && hasClass(wrap, "toggle-wrapper")) {
+                var inner_toggle = wrap.childNodes[0];
+                var extra = e.childNodes[0].tagName === "H3";
 
-                e.style.display = 'none';
-                addClass(wrap, 'collapsed');
-                onEach(toggle.getElementsByClassName('inner'), function(e) {
+                e.style.display = "none";
+                addClass(wrap, "collapsed");
+                onEachLazy(inner_toggle.getElementsByClassName("inner"), function(e) {
                     e.innerHTML = labelForToggleButton(true);
                 });
-                onEach(toggle.getElementsByClassName('toggle-label'), function(e) {
-                    e.style.display = 'inline-block';
+                onEachLazy(inner_toggle.getElementsByClassName("toggle-label"), function(e) {
+                    e.style.display = "inline-block";
                     if (extra === true) {
                         i_e.innerHTML = " Show " + e.childNodes[0].innerHTML;
                     }
@@ -2161,28 +2218,28 @@
             }
         }
         if (e.parentNode.id === "main") {
-            var otherMessage = '';
+            var otherMessage = "";
             var fontSize;
             var extraClass;
 
             if (hasClass(e, "type-decl")) {
                 fontSize = "20px";
-                otherMessage = '&nbsp;Show&nbsp;declaration';
+                otherMessage = "&nbsp;Show&nbsp;declaration";
                 if (showItemDeclarations === false) {
-                    extraClass = 'collapsed';
+                    extraClass = "collapsed";
                 }
             } else if (hasClass(e, "sub-variant")) {
-                otherMessage = '&nbsp;Show&nbsp;fields';
+                otherMessage = "&nbsp;Show&nbsp;fields";
             } else if (hasClass(e, "non-exhaustive")) {
-                otherMessage = '&nbsp;This&nbsp;';
+                otherMessage = "&nbsp;This&nbsp;";
                 if (hasClass(e, "non-exhaustive-struct")) {
-                    otherMessage += 'struct';
+                    otherMessage += "struct";
                 } else if (hasClass(e, "non-exhaustive-enum")) {
-                    otherMessage += 'enum';
+                    otherMessage += "enum";
                 } else if (hasClass(e, "non-exhaustive-type")) {
-                    otherMessage += 'type';
+                    otherMessage += "type";
                 }
-                otherMessage += '&nbsp;is&nbsp;marked&nbsp;as&nbsp;non-exhaustive';
+                otherMessage += "&nbsp;is&nbsp;marked&nbsp;as&nbsp;non-exhaustive";
             } else if (hasClass(e.childNodes[0], "impl-items")) {
                 extraClass = "marg-left";
             }
@@ -2199,21 +2256,8 @@
         }
     }
 
-    onEach(document.getElementsByClassName('docblock'), buildToggleWrapper);
-    onEach(document.getElementsByClassName('sub-variant'), buildToggleWrapper);
-
-    function createToggleWrapper(tog) {
-        var span = document.createElement('span');
-        span.className = 'toggle-label';
-        span.style.display = 'none';
-        span.innerHTML = '&nbsp;Expand&nbsp;attributes';
-        tog.appendChild(span);
-
-        var wrapper = document.createElement('div');
-        wrapper.className = 'toggle-wrapper toggle-attributes';
-        wrapper.appendChild(tog);
-        return wrapper;
-    }
+    onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper);
+    onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper);
 
     // In the search display, allows to switch between tabs.
     function printTab(nb) {
@@ -2221,24 +2265,37 @@
             currentTab = nb;
         }
         var nb_copy = nb;
-        onEach(document.getElementById('titles').childNodes, function(elem) {
+        onEachLazy(document.getElementById("titles").childNodes, function(elem) {
             if (nb_copy === 0) {
-                addClass(elem, 'selected');
+                addClass(elem, "selected");
             } else {
-                removeClass(elem, 'selected');
+                removeClass(elem, "selected");
             }
             nb_copy -= 1;
         });
-        onEach(document.getElementById('results').childNodes, function(elem) {
+        onEachLazy(document.getElementById("results").childNodes, function(elem) {
             if (nb === 0) {
-                elem.style.display = '';
+                elem.style.display = "";
             } else {
-                elem.style.display = 'none';
+                elem.style.display = "none";
             }
             nb -= 1;
         });
     }
 
+    function createToggleWrapper(tog) {
+        var span = document.createElement("span");
+        span.className = "toggle-label";
+        span.style.display = "none";
+        span.innerHTML = "&nbsp;Expand&nbsp;attributes";
+        tog.appendChild(span);
+
+        var wrapper = document.createElement("div");
+        wrapper.className = "toggle-wrapper toggle-attributes";
+        wrapper.appendChild(tog);
+        return wrapper;
+    }
+
     // To avoid checking on "rustdoc-item-attributes" value on every loop...
     var itemAttributesFunc = function() {};
     if (getCurrentValue("rustdoc-item-attributes") !== "false") {
@@ -2246,8 +2303,9 @@
             collapseDocs(x.previousSibling.childNodes[0], "toggle");
         };
     }
-    onEach(document.getElementById('main').getElementsByClassName('attributes'), function(i_e) {
-        i_e.parentNode.insertBefore(createToggleWrapper(toggle.cloneNode(true)), i_e);
+    var attributesToggle = createToggleWrapper(createSimpleToggle(false));
+    onEachLazy(main.getElementsByClassName("attributes"), function(i_e) {
+        i_e.parentNode.insertBefore(attributesToggle.cloneNode(true), i_e);
         itemAttributesFunc(i_e);
     });
 
@@ -2255,45 +2313,45 @@
     var lineNumbersFunc = function() {};
     if (getCurrentValue("rustdoc-line-numbers") === "true") {
         lineNumbersFunc = function(x) {
-            var count = x.textContent.split('\n').length;
+            var count = x.textContent.split("\n").length;
             var elems = [];
             for (var i = 0; i < count; ++i) {
                 elems.push(i + 1);
             }
-            var node = document.createElement('pre');
-            addClass(node, 'line-number');
-            node.innerHTML = elems.join('\n');
+            var node = document.createElement("pre");
+            addClass(node, "line-number");
+            node.innerHTML = elems.join("\n");
             x.parentNode.insertBefore(node, x);
         };
     }
-    onEach(document.getElementsByClassName('rust-example-rendered'), function(e) {
-        if (hasClass(e, 'compile_fail')) {
+    onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
+        if (hasClass(e, "compile_fail")) {
             e.addEventListener("mouseover", function(event) {
-                this.parentElement.previousElementSibling.childNodes[0].style.color = '#f00';
+                this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
             });
             e.addEventListener("mouseout", function(event) {
-                this.parentElement.previousElementSibling.childNodes[0].style.color = '';
+                this.parentElement.previousElementSibling.childNodes[0].style.color = "";
             });
-        } else if (hasClass(e, 'ignore')) {
+        } else if (hasClass(e, "ignore")) {
             e.addEventListener("mouseover", function(event) {
-                this.parentElement.previousElementSibling.childNodes[0].style.color = '#ff9200';
+                this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
             });
             e.addEventListener("mouseout", function(event) {
-                this.parentElement.previousElementSibling.childNodes[0].style.color = '';
+                this.parentElement.previousElementSibling.childNodes[0].style.color = "";
             });
         }
         lineNumbersFunc(e);
     });
 
     function showModal(content) {
-        var modal = document.createElement('div');
+        var modal = document.createElement("div");
         modal.id = "important";
-        addClass(modal, 'modal');
-        modal.innerHTML = '<div class="modal-content"><div class="close" id="modal-close">✕</div>' +
-                          '<div class="whiter"></div><span class="docblock">' + content +
-                          '</span></div>';
-        document.getElementsByTagName('body')[0].appendChild(modal);
-        document.getElementById('modal-close').onclick = hideModal;
+        addClass(modal, "modal");
+        modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" +
+                          "</div><div class=\"whiter\"></div><span class=\"docblock\">" + content +
+                          "</span></div>";
+        document.getElementsByTagName("body")[0].appendChild(modal);
+        document.getElementById("modal-close").onclick = hideModal;
         modal.onclick = hideModal;
     }
 
@@ -2304,7 +2362,7 @@
         }
     }
 
-    onEach(document.getElementsByClassName('important-traits'), function(e) {
+    onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
         e.onclick = function() {
             showModal(e.lastElementChild.innerHTML);
         };
@@ -2312,7 +2370,7 @@
 
     function putBackSearch(search_input) {
         if (search_input.value !== "") {
-            addClass(document.getElementById("main"), "hidden");
+            addClass(main, "hidden");
             removeClass(document.getElementById("search"), "hidden");
             if (browserSupportsHistoryApi()) {
                 history.replaceState(search_input.value,
@@ -2330,16 +2388,16 @@
 
     var params = getQueryStringParams();
     if (params && params.search) {
-        addClass(document.getElementById("main"), "hidden");
+        addClass(main, "hidden");
         var search = document.getElementById("search");
         removeClass(search, "hidden");
-        search.innerHTML = '<h3 style="text-align: center;">Loading search results...</h3>';
+        search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>";
     }
 
     var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
     if (sidebar_menu) {
         sidebar_menu.onclick = function() {
-            var sidebar = document.getElementsByClassName('sidebar')[0];
+            var sidebar = document.getElementsByClassName("sidebar")[0];
             if (hasClass(sidebar, "mobile") === true) {
                 hideSidebar();
             } else {
@@ -2355,7 +2413,18 @@
     autoCollapse(getPageId(), getCurrentValue("rustdoc-collapse") === "true");
 
     if (window.location.hash && window.location.hash.length > 0) {
-        expandSection(window.location.hash.replace(/^#/, ''));
+        expandSection(window.location.hash.replace(/^#/, ""));
+    }
+
+    if (main) {
+        onEachLazy(main.getElementsByClassName("loading-content"), function(e) {
+            e.remove();
+        });
+        onEachLazy(main.childNodes, function(e) {
+            if (e.tagName === "H2" || e.tagName === "H3") {
+                e.nextElementSibling.style.display = "block";
+            }
+        });
     }
 
     function addSearchOptions(crates) {
@@ -2394,10 +2463,10 @@
 
 // Sets the focus on the search bar at the top of the page
 function focusSearchBar() {
-    document.getElementsByClassName('search-input')[0].focus();
+    document.getElementsByClassName("search-input")[0].focus();
 }
 
 // Removes the focus from the search bar
 function defocusSearchBar() {
-    document.getElementsByClassName('search-input')[0].blur();
+    document.getElementsByClassName("search-input")[0].blur();
 }
diff --git a/src/librustdoc/html/static/noscript.css b/src/librustdoc/html/static/noscript.css
new file mode 100644
index 0000000..f4de75f
--- /dev/null
+++ b/src/librustdoc/html/static/noscript.css
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+ * file at the top-level directory of this distribution and at
+ * http://rust-lang.org/COPYRIGHT.
+ *
+ * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+ * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+ * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+ * option. This file may not be copied, modified, or distributed
+ * except according to those terms.
+ */
+
+#main > h2 + div, #main > h2 + h3, #main > h3 + div {
+	display: block;
+}
+
+.loading-content {
+	display: none;
+}
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index cd5a8a7..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;
 }
 
@@ -368,6 +368,10 @@
 #main > .docblock h2 { font-size: 1.15em; }
 #main > .docblock h3, #main > .docblock h4, #main > .docblock h5 { font-size: 1em; }
 
+#main > h2 + div, #main > h2 + h3, #main > h3 + div {
+	display: none;
+}
+
 .docblock h1 { font-size: 1em; }
 .docblock h2 { font-size: 0.95em; }
 .docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; }
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
index e8f0c03..22ac52f 100644
--- a/src/librustdoc/html/static/storage.js
+++ b/src/librustdoc/html/static/storage.js
@@ -19,55 +19,38 @@
 var savedHref = [];
 
 function hasClass(elem, className) {
-    if (elem && className && elem.className) {
-        var elemClass = elem.className;
-        var start = elemClass.indexOf(className);
-        if (start === -1) {
-            return false;
-        } else if (elemClass.length === className.length) {
-            return true;
-        } else {
-            if (start > 0 && elemClass[start - 1] !== ' ') {
-                return false;
-            }
-            var end = start + className.length;
-            return !(end < elemClass.length && elemClass[end] !== ' ');
-        }
-    }
-    return false;
+    return elem && elem.classList && elem.classList.contains(className);
 }
 
 function addClass(elem, className) {
-    if (elem && className && !hasClass(elem, className)) {
-        if (elem.className && elem.className.length > 0) {
-            elem.className += ' ' + className;
-        } else {
-            elem.className = className;
-        }
+    if (!elem || !elem.classList) {
+        return;
     }
+    elem.classList.add(className);
 }
 
 function removeClass(elem, className) {
-    if (elem && className && elem.className) {
-        elem.className = (" " + elem.className + " ").replace(" " + className + " ", " ")
-                                                     .trim();
+    if (!elem || !elem.classList) {
+        return;
     }
+    elem.classList.remove(className);
 }
 
 function isHidden(elem) {
-    return (elem.offsetParent === null)
+    return elem.offsetParent === null;
 }
 
 function onEach(arr, func, reversed) {
     if (arr && arr.length > 0 && func) {
+        var length = arr.length;
         if (reversed !== true) {
-            for (var i = 0; i < arr.length; ++i) {
+            for (var i = 0; i < length; ++i) {
                 if (func(arr[i]) === true) {
                     return true;
                 }
             }
         } else {
-            for (var i = arr.length - 1; i >= 0; --i) {
+            for (var i = length - 1; i >= 0; --i) {
                 if (func(arr[i]) === true) {
                     return true;
                 }
@@ -77,6 +60,13 @@
     return false;
 }
 
+function onEachLazy(lazyArray, func, reversed) {
+    return onEach(
+        Array.prototype.slice.call(lazyArray),
+        func,
+        reversed);
+}
+
 function usableLocalStorage() {
     // Check if the browser supports localStorage at all:
     if (typeof(Storage) === "undefined") {
@@ -121,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);
         });
     }
@@ -133,8 +123,8 @@
     });
     if (found === true) {
         styleElem.href = newHref;
-        updateLocalStorage('rustdoc-theme', newTheme);
+        updateLocalStorage("rustdoc-theme", newTheme);
     }
 }
 
-switchTheme(currentTheme, mainTheme, getCurrentValue('rustdoc-theme') || 'light');
+switchTheme(currentTheme, mainTheme, getCurrentValue("rustdoc-theme") || "light");
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index a485fac..f71b2a8 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -23,6 +23,9 @@
 /// The file contents of `settings.css`, responsible for the items on the settings page.
 pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css");
 
+/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
+pub static NOSCRIPT_CSS: &'static str = include_str!("static/noscript.css");
+
 /// The file contents of `normalize.css`, included to even out standard elements between browser
 /// implementations.
 pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css");
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/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 004be1c..287984c 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -424,10 +424,11 @@
             hir::ItemKind::Use(ref path, kind) => {
                 let is_glob = kind == hir::UseKind::Glob;
 
-                // Struct and variant constructors always show up alongside their definitions, we've
-                // already processed them so just discard these.
+                // Struct and variant constructors and proc macro stubs always show up alongside
+                // their definitions, we've already processed them so just discard these.
                 match path.def {
-                    Def::StructCtor(..) | Def::VariantCtor(..) | Def::SelfCtor(..) => return,
+                    Def::StructCtor(..) | Def::VariantCtor(..) | Def::SelfCtor(..) |
+                    Def::Macro(_, MacroKind::ProcMacroStub) => return,
                     _ => {}
                 }
 
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/build.rs b/src/libstd/build.rs
index 2386f13..7143de5 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -68,7 +68,6 @@
         println!("cargo:rustc-link-lib=advapi32");
         println!("cargo:rustc-link-lib=ws2_32");
         println!("cargo:rustc-link-lib=userenv");
-        println!("cargo:rustc-link-lib=shell32");
     } else if target.contains("fuchsia") {
         println!("cargo:rustc-link-lib=zircon");
         println!("cargo:rustc-link-lib=fdio");
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/ffi/mod.rs b/src/libstd/ffi/mod.rs
index f46c4f2..7e15539 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -72,32 +72,32 @@
 //!
 //! * **From Rust to C:** [`CString`] represents an owned, C-friendly
 //! string: it is nul-terminated, and has no internal nul characters.
-//! Rust code can create a `CString` out of a normal string (provided
+//! Rust code can create a [`CString`] out of a normal string (provided
 //! that the string doesn't have nul characters in the middle), and
-//! then use a variety of methods to obtain a raw `*mut u8` that can
+//! then use a variety of methods to obtain a raw `*mut `[`u8`] that can
 //! then be passed as an argument to functions which use the C
 //! conventions for strings.
 //!
 //! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
-//! is what you would use to wrap a raw `*const u8` that you got from
-//! a C function. A `CStr` is guaranteed to be a nul-terminated array
-//! of bytes. Once you have a `CStr`, you can convert it to a Rust
-//! `&str` if it's valid UTF-8, or lossily convert it by adding
+//! is what you would use to wrap a raw `*const `[`u8`] that you got from
+//! a C function. A [`CStr`] is guaranteed to be a nul-terminated array
+//! of bytes. Once you have a [`CStr`], you can convert it to a Rust
+//! [`&str`][`str`] if it's valid UTF-8, or lossily convert it by adding
 //! replacement characters.
 //!
 //! [`OsString`] and [`OsStr`] are useful when you need to transfer
 //! strings to and from the operating system itself, or when capturing
-//! the output of external commands. Conversions between `OsString`,
-//! `OsStr` and Rust strings work similarly to those for [`CString`]
+//! the output of external commands. Conversions between [`OsString`],
+//! [`OsStr`] and Rust strings work similarly to those for [`CString`]
 //! and [`CStr`].
 //!
 //! * [`OsString`] represents an owned string in whatever
 //! representation the operating system prefers. In the Rust standard
 //! library, various APIs that transfer strings to/from the operating
-//! system use `OsString` instead of plain strings. For example,
+//! system use [`OsString`] instead of plain strings. For example,
 //! [`env::var_os()`] is used to query environment variables; it
-//! returns an `Option<OsString>`. If the environment variable exists
-//! you will get a `Some(os_string)`, which you can *then* try to
+//! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable
+//! exists you will get a [`Some`]`(os_string)`, which you can *then* try to
 //! convert to a Rust string. This yields a [`Result<>`], so that
 //! your code can detect errors in case the environment variable did
 //! not in fact contain valid Unicode data.
@@ -105,7 +105,7 @@
 //! * [`OsStr`] represents a borrowed reference to a string in a
 //! format that can be passed to the operating system. It can be
 //! converted into an UTF-8 Rust string slice in a similar way to
-//! `OsString`.
+//! [`OsString`].
 //!
 //! # Conversions
 //!
@@ -131,7 +131,7 @@
 //! Additionally, on Windows [`OsString`] implements the
 //! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
 //! trait, which provides a [`from_wide`] method. The result of this
-//! method is an `OsString` which can be round-tripped to a Windows
+//! method is an [`OsString`] which can be round-tripped to a Windows
 //! string losslessly.
 //!
 //! [`String`]: ../string/struct.String.html
@@ -160,6 +160,8 @@
 //! [`collect`]: ../iter/trait.Iterator.html#method.collect
 //! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
 //! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide
+//! [`Option`]: ../option/enum.Option.html
+//! [`Some`]: ../option/enum.Option.html#variant.Some
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index d581ba1..35ae493 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -195,9 +195,10 @@
 /// This module only currently provides one bit of information, [`readonly`],
 /// which is exposed on all currently supported platforms. Unix-specific
 /// functionality, such as mode bits, is available through the
-/// `os::unix::PermissionsExt` trait.
+/// [`PermissionsExt`] trait.
 ///
 /// [`readonly`]: struct.Permissions.html#method.readonly
+/// [`PermissionsExt`]: ../os/unix/fs/trait.PermissionsExt.html
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Permissions(fs_imp::FilePermissions);
@@ -1728,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/io/lazy.rs b/src/libstd/io/lazy.rs
index c2aaeb9..24965ff 100644
--- a/src/libstd/io/lazy.rs
+++ b/src/libstd/io/lazy.rs
@@ -26,7 +26,6 @@
 unsafe impl<T> Sync for Lazy<T> {}
 
 impl<T> Lazy<T> {
-    #[unstable(feature = "sys_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> Lazy<T> {
         Lazy {
             lock: Mutex::new(),
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 7c43ba5..ead38f2 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -271,6 +271,7 @@
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
+#![cfg_attr(not(stage0), feature(min_const_unsafe_fn))]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
 #![feature(nll)]
@@ -338,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/panicking.rs b/src/libstd/panicking.rs
index 6b47ba6..b6180fb 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -209,7 +209,8 @@
             if let Some(format) = log_backtrace {
                 let _ = backtrace::print(err, format);
             } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
-                let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` for a backtrace.");
+                let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` \
+                                       environment variable to display a backtrace.");
             }
         }
     };
diff --git a/src/libstd/sys/sgx/abi/mem.rs b/src/libstd/sys/sgx/abi/mem.rs
index 508f2ff..bf32c71 100644
--- a/src/libstd/sys/sgx/abi/mem.rs
+++ b/src/libstd/sys/sgx/abi/mem.rs
@@ -34,13 +34,6 @@
     base
 }
 
-pub fn is_enclave_range(p: *const u8, len: usize) -> bool {
-    let start=p as u64;
-    let end=start + (len as u64);
-    start >= image_base() &&
-        end <= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant
-}
-
 pub fn is_user_range(p: *const u8, len: usize) -> bool {
     let start=p as u64;
     let end=start + (len as u64);
diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs
index 2bc32c9..d1d180e 100644
--- a/src/libstd/sys/sgx/abi/usercalls/mod.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs
@@ -33,14 +33,6 @@
     }
 }
 
-pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
-    unsafe {
-        let mut userbuf = alloc::User::<ByteBuffer>::uninitialized();
-        raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
-        Ok(copy_user_buffer(&userbuf))
-    }
-}
-
 pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
     unsafe {
         let userbuf = alloc::User::new_from_enclave(buf);
diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs
index d3e8165..940f50f 100644
--- a/src/libstd/sys/sgx/condvar.rs
+++ b/src/libstd/sys/sgx/condvar.rs
@@ -18,7 +18,6 @@
 }
 
 impl Condvar {
-    #[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> Condvar {
         Condvar { inner: SpinMutex::new(WaitVariable::new(())) }
     }
diff --git a/src/libstd/sys/sgx/mutex.rs b/src/libstd/sys/sgx/mutex.rs
index 6633611..994cf91 100644
--- a/src/libstd/sys/sgx/mutex.rs
+++ b/src/libstd/sys/sgx/mutex.rs
@@ -20,7 +20,6 @@
 
 // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
 impl Mutex {
-    #[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> Mutex {
         Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
     }
@@ -79,7 +78,6 @@
 }
 
 impl ReentrantMutex {
-    #[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn uninitialized() -> ReentrantMutex {
         ReentrantMutex {
             inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 }))
diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs
index 7b6970b..a1551db 100644
--- a/src/libstd/sys/sgx/rwlock.rs
+++ b/src/libstd/sys/sgx/rwlock.rs
@@ -21,7 +21,6 @@
 //unsafe impl Sync for RWLock {} // FIXME
 
 impl RWLock {
-    #[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> RWLock {
         RWLock {
             readers: SpinMutex::new(WaitVariable::new(None)),
diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs
index ec1135b..ef0def1 100644
--- a/src/libstd/sys/sgx/waitqueue.rs
+++ b/src/libstd/sys/sgx/waitqueue.rs
@@ -50,7 +50,6 @@
 }
 
 impl<T> WaitVariable<T> {
-    #[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new(var: T) -> Self {
         WaitVariable {
             queue: WaitQueue::new(),
@@ -137,7 +136,6 @@
 }
 
 impl WaitQueue {
-    #[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> Self {
         WaitQueue {
             inner: UnsafeList::new()
@@ -255,7 +253,6 @@
     }
 
     impl<T> UnsafeList<T> {
-        #[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
         pub const fn new() -> Self {
             unsafe {
                 UnsafeList {
diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs
index 4784633..9e9198e 100644
--- a/src/libstd/sys/windows/args.rs
+++ b/src/libstd/sys/windows/args.rs
@@ -11,12 +11,14 @@
 #![allow(dead_code)] // runtime init functions not used during testing
 
 use os::windows::prelude::*;
+use sys::windows::os::current_exe;
 use sys::c;
-use slice;
-use ops::Range;
 use ffi::OsString;
-use libc::{c_int, c_void};
 use fmt;
+use vec;
+use core::iter;
+use slice;
+use path::PathBuf;
 
 pub unsafe fn init(_argc: isize, _argv: *const *const u8) { }
 
@@ -24,20 +26,146 @@
 
 pub fn args() -> Args {
     unsafe {
-        let mut nArgs: c_int = 0;
-        let lpCmdLine = c::GetCommandLineW();
-        let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
+        let lp_cmd_line = c::GetCommandLineW();
+        let parsed_args_list = parse_lp_cmd_line(
+            lp_cmd_line as *const u16,
+            || current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new()));
 
-        // szArcList can be NULL if CommandLinToArgvW failed,
-        // but in that case nArgs is 0 so we won't actually
-        // try to read a null pointer
-        Args { cur: szArgList, range: 0..(nArgs as isize) }
+        Args { parsed_args_list: parsed_args_list.into_iter() }
     }
 }
 
+/// Implements the Windows command-line argument parsing algorithm.
+///
+/// Microsoft's documentation for the Windows CLI argument format can be found at
+/// <https://docs.microsoft.com/en-us/previous-versions//17w5ykft(v=vs.85)>.
+///
+/// Windows includes a function to do this in shell32.dll,
+/// but linking with that DLL causes the process to be registered as a GUI application.
+/// GUI applications add a bunch of overhead, even if no windows are drawn. See
+/// <https://randomascii.wordpress.com/2018/12/03/a-not-called-function-can-cause-a-5x-slowdown/>.
+///
+/// This function was tested for equivalence to the shell32.dll implementation in
+/// Windows 10 Pro v1803, using an exhaustive test suite available at
+/// <https://gist.github.com/notriddle/dde431930c392e428055b2dc22e638f5> or
+/// <https://paste.gg/p/anonymous/47d6ed5f5bd549168b1c69c799825223>.
+unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_name: F)
+                                                 -> Vec<OsString> {
+    const BACKSLASH: u16 = '\\' as u16;
+    const QUOTE: u16 = '"' as u16;
+    const TAB: u16 = '\t' as u16;
+    const SPACE: u16 = ' ' as u16;
+    let mut ret_val = Vec::new();
+    if lp_cmd_line.is_null() || *lp_cmd_line == 0 {
+        ret_val.push(exe_name());
+        return ret_val;
+    }
+    let mut cmd_line = {
+        let mut end = 0;
+        while *lp_cmd_line.offset(end) != 0 {
+            end += 1;
+        }
+        slice::from_raw_parts(lp_cmd_line, end as usize)
+    };
+    // The executable name at the beginning is special.
+    cmd_line = match cmd_line[0] {
+        // The executable name ends at the next quote mark,
+        // no matter what.
+        QUOTE => {
+            let args = {
+                let mut cut = cmd_line[1..].splitn(2, |&c| c == QUOTE);
+                if let Some(exe) = cut.next() {
+                    ret_val.push(OsString::from_wide(exe));
+                }
+                cut.next()
+            };
+            if let Some(args) = args {
+                args
+            } else {
+                return ret_val;
+            }
+        }
+        // Implement quirk: when they say whitespace here,
+        // they include the entire ASCII control plane:
+        // "However, if lpCmdLine starts with any amount of whitespace, CommandLineToArgvW
+        // will consider the first argument to be an empty string. Excess whitespace at the
+        // end of lpCmdLine is ignored."
+        0...SPACE => {
+            ret_val.push(OsString::new());
+            &cmd_line[1..]
+        },
+        // The executable name ends at the next whitespace,
+        // no matter what.
+        _ => {
+            let args = {
+                let mut cut = cmd_line.splitn(2, |&c| c > 0 && c <= SPACE);
+                if let Some(exe) = cut.next() {
+                    ret_val.push(OsString::from_wide(exe));
+                }
+                cut.next()
+            };
+            if let Some(args) = args {
+                args
+            } else {
+                return ret_val;
+            }
+        }
+    };
+    let mut cur = Vec::new();
+    let mut in_quotes = false;
+    let mut was_in_quotes = false;
+    let mut backslash_count: usize = 0;
+    for &c in cmd_line {
+        match c {
+            // backslash
+            BACKSLASH => {
+                backslash_count += 1;
+                was_in_quotes = false;
+            },
+            QUOTE if backslash_count % 2 == 0 => {
+                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
+                backslash_count = 0;
+                if was_in_quotes {
+                    cur.push('"' as u16);
+                    was_in_quotes = false;
+                } else {
+                    was_in_quotes = in_quotes;
+                    in_quotes = !in_quotes;
+                }
+            }
+            QUOTE if backslash_count % 2 != 0 => {
+                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
+                backslash_count = 0;
+                was_in_quotes = false;
+                cur.push(b'"' as u16);
+            }
+            SPACE | TAB if !in_quotes => {
+                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
+                if !cur.is_empty() || was_in_quotes {
+                    ret_val.push(OsString::from_wide(&cur[..]));
+                    cur.truncate(0);
+                }
+                backslash_count = 0;
+                was_in_quotes = false;
+            }
+            _ => {
+                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
+                backslash_count = 0;
+                was_in_quotes = false;
+                cur.push(c);
+            }
+        }
+    }
+    cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
+    // include empty quoted strings at the end of the arguments list
+    if !cur.is_empty() || was_in_quotes || in_quotes {
+        ret_val.push(OsString::from_wide(&cur[..]));
+    }
+    ret_val
+}
+
 pub struct Args {
-    range: Range<isize>,
-    cur: *mut *mut u16,
+    parsed_args_list: vec::IntoIter<OsString>,
 }
 
 pub struct ArgsInnerDebug<'a> {
@@ -46,19 +174,7 @@
 
 impl<'a> fmt::Debug for ArgsInnerDebug<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.write_str("[")?;
-        let mut first = true;
-        for i in self.args.range.clone() {
-            if !first {
-                f.write_str(", ")?;
-            }
-            first = false;
-
-            // Here we do allocation which could be avoided.
-            fmt::Debug::fmt(&unsafe { os_string_from_ptr(*self.args.cur.offset(i)) }, f)?;
-        }
-        f.write_str("]")?;
-        Ok(())
+        self.args.parsed_args_list.as_slice().fmt(f)
     }
 }
 
@@ -70,38 +186,82 @@
     }
 }
 
-unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
-    let mut len = 0;
-    while *ptr.offset(len) != 0 { len += 1; }
-
-    // Push it onto the list.
-    let ptr = ptr as *const u16;
-    let buf = slice::from_raw_parts(ptr, len as usize);
-    OsStringExt::from_wide(buf)
-}
-
 impl Iterator for Args {
     type Item = OsString;
-    fn next(&mut self) -> Option<OsString> {
-        self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+    fn next(&mut self) -> Option<OsString> { self.parsed_args_list.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.parsed_args_list.size_hint() }
 }
 
 impl DoubleEndedIterator for Args {
-    fn next_back(&mut self) -> Option<OsString> {
-        self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
-    }
+    fn next_back(&mut self) -> Option<OsString> { self.parsed_args_list.next_back() }
 }
 
 impl ExactSizeIterator for Args {
-    fn len(&self) -> usize { self.range.len() }
+    fn len(&self) -> usize { self.parsed_args_list.len() }
 }
 
-impl Drop for Args {
-    fn drop(&mut self) {
-        // self.cur can be null if CommandLineToArgvW previously failed,
-        // but LocalFree ignores NULL pointers
-        unsafe { c::LocalFree(self.cur as *mut c_void); }
+#[cfg(test)]
+mod tests {
+    use sys::windows::args::*;
+    use ffi::OsString;
+
+    fn chk(string: &str, parts: &[&str]) {
+        let mut wide: Vec<u16> = OsString::from(string).encode_wide().collect();
+        wide.push(0);
+        let parsed = unsafe {
+            parse_lp_cmd_line(wide.as_ptr() as *const u16, || OsString::from("TEST.EXE"))
+        };
+        let expected: Vec<OsString> = parts.iter().map(|k| OsString::from(k)).collect();
+        assert_eq!(parsed.as_slice(), expected.as_slice());
+    }
+
+    #[test]
+    fn empty() {
+        chk("", &["TEST.EXE"]);
+        chk("\0", &["TEST.EXE"]);
+    }
+
+    #[test]
+    fn single_words() {
+        chk("EXE one_word", &["EXE", "one_word"]);
+        chk("EXE a", &["EXE", "a"]);
+        chk("EXE 😅", &["EXE", "😅"]);
+        chk("EXE 😅🤦", &["EXE", "😅🤦"]);
+    }
+
+    #[test]
+    fn official_examples() {
+        chk(r#"EXE "abc" d e"#, &["EXE", "abc", "d", "e"]);
+        chk(r#"EXE a\\\b d"e f"g h"#, &["EXE", r#"a\\\b"#, "de fg", "h"]);
+        chk(r#"EXE a\\\"b c d"#, &["EXE", r#"a\"b"#, "c", "d"]);
+        chk(r#"EXE a\\\\"b c" d e"#, &["EXE", r#"a\\b c"#, "d", "e"]);
+    }
+
+    #[test]
+    fn whitespace_behavior() {
+        chk(r#" test"#, &["", "test"]);
+        chk(r#"  test"#, &["", "test"]);
+        chk(r#" test test2"#, &["", "test", "test2"]);
+        chk(r#" test  test2"#, &["", "test", "test2"]);
+        chk(r#"test test2 "#, &["test", "test2"]);
+        chk(r#"test  test2 "#, &["test", "test2"]);
+        chk(r#"test "#, &["test"]);
+    }
+
+    #[test]
+    fn genius_quotes() {
+        chk(r#"EXE "" """#, &["EXE", "", ""]);
+        chk(r#"EXE "" """"#, &["EXE", "", "\""]);
+        chk(
+            r#"EXE "this is """all""" in the same argument""#,
+            &["EXE", "this is \"all\" in the same argument"]
+        );
+        chk(r#"EXE "a"""#, &["EXE", "a\""]);
+        chk(r#"EXE "a"" a"#, &["EXE", "a\"", "a"]);
+        // quotes cannot be escaped in command names
+        chk(r#""EXE" check"#, &["EXE", "check"]);
+        chk(r#""EXE check""#, &["EXE check"]);
+        chk(r#""EXE """for""" check"#, &["EXE ", r#"for""#, "check"]);
+        chk(r#""EXE \"for\" check"#, &[r#"EXE \"#, r#"for""#,  "check"]);
     }
 }
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index c84874a..fa21f45 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -1035,9 +1035,6 @@
 
     pub fn SetLastError(dwErrCode: DWORD);
     pub fn GetCommandLineW() -> *mut LPCWSTR;
-    pub fn LocalFree(ptr: *mut c_void);
-    pub fn CommandLineToArgvW(lpCmdLine: *mut LPCWSTR,
-                              pNumArgs: *mut c_int) -> *mut *mut u16;
     pub fn GetTempPathW(nBufferLength: DWORD,
                         lpBuffer: LPCWSTR) -> DWORD;
     pub fn OpenProcessToken(ProcessHandle: HANDLE,
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/libstd/sys_common/condvar.rs b/src/libstd/sys_common/condvar.rs
index 16bf080..b6f29dd 100644
--- a/src/libstd/sys_common/condvar.rs
+++ b/src/libstd/sys_common/condvar.rs
@@ -25,7 +25,6 @@
     ///
     /// Behavior is undefined if the condition variable is moved after it is
     /// first used with any of the functions below.
-    #[unstable(feature = "sys_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> Condvar { Condvar(imp::Condvar::new()) }
 
     /// Prepares the condition variable for use.
diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs
index 8768423..c6d531c 100644
--- a/src/libstd/sys_common/mutex.rs
+++ b/src/libstd/sys_common/mutex.rs
@@ -27,7 +27,6 @@
     /// Also, until `init` is called, behavior is undefined if this
     /// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock`
     /// are called by the thread currently holding the lock.
-    #[unstable(feature = "sys_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) }
 
     /// Prepare the mutex for use.
diff --git a/src/libstd/sys_common/rwlock.rs b/src/libstd/sys_common/rwlock.rs
index a430c25..71a4f01 100644
--- a/src/libstd/sys_common/rwlock.rs
+++ b/src/libstd/sys_common/rwlock.rs
@@ -22,7 +22,6 @@
     ///
     /// Behavior is undefined if the reader-writer lock is moved after it is
     /// first used with any of the functions below.
-    #[unstable(feature = "sys_internals", issue = "0")] // FIXME: min_const_fn
     pub const fn new() -> RWLock { RWLock(imp::RWLock::new()) }
 
     /// Acquires shared access to the underlying lock, blocking the current
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 eb71003..e3cccac 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -15,7 +15,7 @@
 use early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
 use source_map::{SourceMap, FilePathMapping};
 use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
-use errors::{Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
+use errors::{FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
 use feature_gate::UnstableFeatures;
 use parse::parser::Parser;
 use ptr::P;
@@ -192,6 +192,14 @@
     source_file_to_parser(sess, file_to_source_file(sess, path, None))
 }
 
+/// Create a new parser, returning buffered diagnostics if the file doesn't
+/// exist or from lexing the initial token stream.
+pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path)
+    -> Result<Parser<'a>, Vec<Diagnostic>> {
+    let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?;
+    maybe_source_file_to_parser(sess, file)
+}
+
 /// Given a session, a crate config, a path, and a span, add
 /// the file at the given path to the source_map, and return a parser.
 /// On an error, use the given span as the source of the problem.
@@ -237,17 +245,30 @@
 // base abstractions
 
 /// Given a session and a path and an optional span (for error reporting),
+/// add the path to the session's source_map and return the new source_file or
+/// error when a file can't be read.
+fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
+                   -> Result<Lrc<SourceFile>, Diagnostic> {
+    sess.source_map().load_file(path)
+    .map_err(|e| {
+        let msg = format!("couldn't read {}: {}", path.display(), e);
+        let mut diag = Diagnostic::new(Level::Fatal, &msg);
+        if let Some(sp) = spanopt {
+            diag.set_span(sp);
+        }
+        diag
+    })
+}
+
+/// Given a session and a path and an optional span (for error reporting),
 /// add the path to the session's source_map and return the new source_file.
 fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
                    -> Lrc<SourceFile> {
-    match sess.source_map().load_file(path) {
+    match try_file_to_source_file(sess, path, spanopt) {
         Ok(source_file) => source_file,
-        Err(e) => {
-            let msg = format!("couldn't read {}: {}", path.display(), e);
-            match spanopt {
-                Some(sp) => sess.span_diagnostic.span_fatal(sp, &msg).raise(),
-                None => sess.span_diagnostic.fatal(&msg).raise()
-            }
+        Err(d) => {
+            DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, d).emit();
+            FatalError.raise();
         }
     }
 }
@@ -842,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(),
@@ -859,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 ded6da9..a672a08 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1407,7 +1407,7 @@
                 // definition...
 
                 // We don't allow argument names to be left off in edition 2018.
-                p.parse_arg_general(p.span.rust_2018())
+                p.parse_arg_general(p.span.rust_2018(), true)
             })?;
             generics.where_clause = self.parse_where_clause()?;
 
@@ -1820,7 +1820,7 @@
 
     /// This version of parse arg doesn't necessarily require
     /// identifier names.
-    fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
+    fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool) -> PResult<'a, Arg> {
         maybe_whole!(self, NtArg, |x| x);
 
         if let Ok(Some(_)) = self.parse_self_arg() {
@@ -1852,6 +1852,17 @@
                         String::from("<identifier>: <type>"),
                         Applicability::HasPlaceholders,
                     );
+                } else if require_name && is_trait_item {
+                    if let PatKind::Ident(_, ident, _) = pat.node {
+                        err.span_suggestion_with_applicability(
+                            pat.span,
+                            "explicitly ignore parameter",
+                            format!("_: {}", ident),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+
+                    err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
                 }
 
                 return Err(err);
@@ -1917,7 +1928,7 @@
 
     /// Parse a single function argument
     crate fn parse_arg(&mut self) -> PResult<'a, Arg> {
-        self.parse_arg_general(true)
+        self.parse_arg_general(true, false)
     }
 
     /// Parse an argument in a lambda header e.g., |arg, arg|
@@ -2928,7 +2939,7 @@
                 _ => result.push(self.parse_token_tree().into()),
             }
         }
-        TokenStream::concat(result)
+        TokenStream::new(result)
     }
 
     /// Parse a prefix-unary-operator expr
@@ -4624,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(),
@@ -5473,7 +5484,7 @@
                             }
                         }
                     } else {
-                        match p.parse_arg_general(named_args) {
+                        match p.parse_arg_general(named_args, false) {
                             Ok(arg) => Ok(Some(arg)),
                             Err(mut e) => {
                                 e.emit();
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 8e4d3c0..ed74665 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -207,6 +207,10 @@
     Eof,
 }
 
+// `Token` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Token>() == 16);
+
 impl Token {
     pub fn interpolated(nt: Nonterminal) -> Token {
         Token::Interpolated(Lrc::new((nt, LazyTokenStream::new())))
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/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 8b7ffa4..9aafb9f 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -24,10 +24,13 @@
 #![feature(nll)]
 #![feature(non_exhaustive)]
 #![feature(optin_builtin_traits)]
+#![feature(rustc_attrs)]
 #![feature(specialization)]
+#![feature(step_trait)]
 #![cfg_attr(not(stage0), feature(stdsimd))]
 
 extern crate arena;
+#[macro_use]
 extern crate rustc_data_structures;
 
 #[macro_use]
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index f1adb9d..b720db8 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -14,6 +14,7 @@
 
 use arena::DroplessArena;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::indexed_vec::Idx;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 
 use std::fmt;
@@ -143,9 +144,18 @@
     }
 }
 
-/// A symbol is an interned or gensymed string.
+/// A symbol is an interned or gensymed string. The use of newtype_index! means
+/// that Option<Symbol> only takes up 4 bytes, because newtype_index! reserves
+/// the last 256 values for tagging purposes.
+///
+/// Note that Symbol cannot be a newtype_index! directly because it implements
+/// fmt::Debug, Encodable, and Decodable in special ways.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct Symbol(u32);
+pub struct Symbol(SymbolIndex);
+
+newtype_index! {
+    pub struct SymbolIndex { .. }
+}
 
 // The interner is pointed to by a thread local value which is only set on the main thread
 // with parallelization is disabled. So we don't allow `Symbol` to transfer between threads
@@ -156,6 +166,10 @@
 impl !Sync for Symbol { }
 
 impl Symbol {
+    const fn new(n: u32) -> Self {
+        Symbol(SymbolIndex::from_u32_const(n))
+    }
+
     /// Maps a string to its interned representation.
     pub fn intern(string: &str) -> Self {
         with_interner(|interner| interner.intern(string))
@@ -189,7 +203,7 @@
     }
 
     pub fn as_u32(self) -> u32 {
-        self.0
+        self.0.as_u32()
     }
 }
 
@@ -197,7 +211,7 @@
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
         if is_gensymed {
-            write!(f, "{}({})", self, self.0)
+            write!(f, "{}({:?})", self, self.0)
         } else {
             write!(f, "{}", self)
         }
@@ -229,6 +243,9 @@
 }
 
 // The `&'static str`s in this type actually point into the arena.
+//
+// Note that normal symbols are indexed upward from 0, and gensyms are indexed
+// downward from SymbolIndex::MAX_AS_U32.
 #[derive(Default)]
 pub struct Interner {
     arena: DroplessArena,
@@ -243,7 +260,7 @@
         for &string in init {
             if string == "" {
                 // We can't allocate empty strings in the arena, so handle this here.
-                let name = Symbol(this.strings.len() as u32);
+                let name = Symbol::new(this.strings.len() as u32);
                 this.names.insert("", name);
                 this.strings.push("");
             } else {
@@ -258,7 +275,7 @@
             return name;
         }
 
-        let name = Symbol(self.strings.len() as u32);
+        let name = Symbol::new(self.strings.len() as u32);
 
         // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
         // UTF-8.
@@ -276,10 +293,10 @@
     }
 
     pub fn interned(&self, symbol: Symbol) -> Symbol {
-        if (symbol.0 as usize) < self.strings.len() {
+        if (symbol.0.as_usize()) < self.strings.len() {
             symbol
         } else {
-            self.interned(self.gensyms[(!0 - symbol.0) as usize])
+            self.interned(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize])
         }
     }
 
@@ -290,17 +307,17 @@
 
     fn gensymed(&mut self, symbol: Symbol) -> Symbol {
         self.gensyms.push(symbol);
-        Symbol(!0 - self.gensyms.len() as u32 + 1)
+        Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1)
     }
 
     fn is_gensymed(&mut self, symbol: Symbol) -> bool {
-        symbol.0 as usize >= self.strings.len()
+        symbol.0.as_usize() >= self.strings.len()
     }
 
     pub fn get(&self, symbol: Symbol) -> &str {
-        match self.strings.get(symbol.0 as usize) {
+        match self.strings.get(symbol.0.as_usize()) {
             Some(string) => string,
-            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
+            None => self.get(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]),
         }
     }
 }
@@ -324,7 +341,7 @@
         $(
             #[allow(non_upper_case_globals)]
             pub const $konst: Keyword = Keyword {
-                ident: Ident::with_empty_ctxt(super::Symbol($index))
+                ident: Ident::with_empty_ctxt(super::Symbol::new($index))
             };
         )*
 
@@ -709,19 +726,19 @@
     fn interner_tests() {
         let mut i: Interner = Interner::default();
         // first one is zero:
-        assert_eq!(i.intern("dog"), Symbol(0));
+        assert_eq!(i.intern("dog"), Symbol::new(0));
         // re-use gets the same entry:
-        assert_eq!(i.intern("dog"), Symbol(0));
+        assert_eq!(i.intern("dog"), Symbol::new(0));
         // different string gets a different #:
-        assert_eq!(i.intern("cat"), Symbol(1));
-        assert_eq!(i.intern("cat"), Symbol(1));
+        assert_eq!(i.intern("cat"), Symbol::new(1));
+        assert_eq!(i.intern("cat"), Symbol::new(1));
         // dog is still at zero
-        assert_eq!(i.intern("dog"), Symbol(0));
-        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
-        // gensym of same string gets new number :
-        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
+        assert_eq!(i.intern("dog"), Symbol::new(0));
+        assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32));
+        // gensym of same string gets new number:
+        assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32 - 1));
         // gensym of *existing* string gets new number:
-        assert_eq!(i.gensym("dog"), Symbol(4294967293));
+        assert_eq!(i.gensym("dog"), Symbol::new(SymbolIndex::MAX_AS_U32 - 2));
     }
 
     #[test]
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/simd-intrinsic-generic-select.rs b/src/test/codegen/simd-intrinsic-generic-select.rs
index 8a64d74..24a4b2b 100644
--- a/src/test/codegen/simd-intrinsic-generic-select.rs
+++ b/src/test/codegen/simd-intrinsic-generic-select.rs
@@ -21,10 +21,15 @@
 
 #[repr(simd)]
 #[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub struct b8x4(pub i8, pub i8, pub i8, pub i8);
 
 extern "platform-intrinsic" {
     fn simd_select<T, U>(x: T, a: U, b: U) -> U;
+    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
 }
 
 // CHECK-LABEL: @select
@@ -33,3 +38,10 @@
     // CHECK: select <4 x i1>
     simd_select(m, a, b)
 }
+
+// CHECK-LABEL: @select_bitmask
+#[no_mangle]
+pub unsafe fn select_bitmask(m: i8, a: f32x8, b: f32x8) -> f32x8 {
+    // CHECK: select <8 x i1>
+    simd_select_bitmask(m, a, b)
+}
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/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/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs
index a51be37..350b30d 100644
--- a/src/test/debuginfo/pretty-std-collections.rs
+++ b/src/test/debuginfo/pretty-std-collections.rs
@@ -13,7 +13,11 @@
 // ignore-freebsd: gdb package too new
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// min-gdb-version 7.7
+
+// The pretty printers being tested here require the patch from
+// https://sourceware.org/bugzilla/show_bug.cgi?id=21763
+// min-gdb-version 8.1
+
 // min-lldb-version: 310
 
 // === GDB TESTS ===================================================================================
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-make-fulldeps/libtest-json/output.json b/src/test/run-make-fulldeps/libtest-json/output.json
index 80e75c8..2b831ea 100644
--- a/src/test/run-make-fulldeps/libtest-json/output.json
+++ b/src/test/run-make-fulldeps/libtest-json/output.json
@@ -2,7 +2,7 @@
 { "type": "test", "event": "started", "name": "a" }
 { "type": "test", "name": "a", "event": "ok" }
 { "type": "test", "event": "started", "name": "b" }
-{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:18:5\nnote: Run with `RUST_BACKTRACE=1` for a backtrace.\n" }
+{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:18:5\nnote: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" }
 { "type": "test", "event": "started", "name": "c" }
 { "type": "test", "name": "c", "event": "ok" }
 { "type": "test", "event": "started", "name": "d" }
diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk
index 3de358f..7939928 100644
--- a/src/test/run-make-fulldeps/tools.mk
+++ b/src/test/run-make-fulldeps/tools.mk
@@ -76,7 +76,7 @@
 # Extra flags needed to compile a working executable with the standard library
 ifdef IS_WINDOWS
 ifdef IS_MSVC
-	EXTRACFLAGS := ws2_32.lib userenv.lib shell32.lib advapi32.lib
+	EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib
 else
 	EXTRACFLAGS := -lws2_32 -luserenv
 endif
diff --git a/src/test/run-pass/ctfe/references.rs b/src/test/run-pass/ctfe/references.rs
index 946ed24..421f354 100644
--- a/src/test/run-pass/ctfe/references.rs
+++ b/src/test/run-pass/ctfe/references.rs
@@ -28,6 +28,7 @@
         _ => panic!("c"),
     }
 
+    #[allow(unreachable_patterns)]
     match &43 {
         &42 => panic!(),
         BOO => panic!(),
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/multi-panic.rs b/src/test/run-pass/multi-panic.rs
index 2e6e109..03e58fc 100644
--- a/src/test/run-pass/multi-panic.rs
+++ b/src/test/run-pass/multi-panic.rs
@@ -17,7 +17,8 @@
     let mut it = err.lines();
 
     assert_eq!(it.next().map(|l| l.starts_with("thread '<unnamed>' panicked at")), Some(true));
-    assert_eq!(it.next(), Some("note: Run with `RUST_BACKTRACE=1` for a backtrace."));
+    assert_eq!(it.next(), Some("note: Run with `RUST_BACKTRACE=1` \
+                                environment variable to display a backtrace."));
     assert_eq!(it.next().map(|l| l.starts_with("thread 'main' panicked at")), Some(true));
     assert_eq!(it.next(), None);
 }
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/simd/simd-intrinsic-generic-select.rs b/src/test/run-pass/simd/simd-intrinsic-generic-select.rs
index 590a299..74b99ca 100644
--- a/src/test/run-pass/simd/simd-intrinsic-generic-select.rs
+++ b/src/test/run-pass/simd/simd-intrinsic-generic-select.rs
@@ -28,6 +28,10 @@
 
 #[repr(simd)]
 #[derive(Copy, Clone, PartialEq, Debug)]
+struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 struct f32x4(pub f32, pub f32, pub f32, pub f32);
 
 #[repr(simd)]
@@ -36,6 +40,7 @@
 
 extern "platform-intrinsic" {
     fn simd_select<T, U>(x: T, a: U, b: U) -> U;
+    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
 }
 
 fn main() {
@@ -146,4 +151,29 @@
         let e = b8x4(t, f, t, t);
         assert_eq!(r, e);
     }
+
+    unsafe {
+        let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7);
+        let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15);
+
+        let r: u32x8 = simd_select_bitmask(0u8, a, b);
+        let e = b;
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0xffu8, a, b);
+        let e = a;
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b);
+        let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15);
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b);
+        let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7);
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b);
+        let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
+        assert_eq!(r, e);
+    }
 }
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-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout
index cd19099..bd6fa1f 100644
--- a/src/test/rustdoc-ui/failed-doctest-output.stdout
+++ b/src/test/rustdoc-ui/failed-doctest-output.stdout
@@ -13,13 +13,13 @@
   | ^^ not found in this scope
 
 thread '$DIR/failed-doctest-output.rs - OtherStruct (line 27)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:326:13
-note: Run with `RUST_BACKTRACE=1` for a backtrace.
+note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 ---- $DIR/failed-doctest-output.rs - SomeStruct (line 21) stdout ----
 thread '$DIR/failed-doctest-output.rs - SomeStruct (line 21)' panicked at 'test executable failed:
 
 thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
-note: Run with `RUST_BACKTRACE=1` for a backtrace.
+note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 ', src/librustdoc/test.rs:361:17
 
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/rustdoc/proc-macro.rs b/src/test/rustdoc/proc-macro.rs
index 23d0d00..05d64f8 100644
--- a/src/test/rustdoc/proc-macro.rs
+++ b/src/test/rustdoc/proc-macro.rs
@@ -61,3 +61,16 @@
 pub fn some_derive(_item: TokenStream) -> TokenStream {
     TokenStream::new()
 }
+
+// @has some_macros/foo/index.html
+pub mod foo {
+    // @has - '//code' 'pub use some_proc_macro;'
+    // @has - '//a/@href' '../../some_macros/macro.some_proc_macro.html'
+    pub use some_proc_macro;
+    // @has - '//code' 'pub use some_proc_attr;'
+    // @has - '//a/@href' '../../some_macros/attr.some_proc_attr.html'
+    pub use some_proc_attr;
+    // @has - '//code' 'pub use some_derive;'
+    // @has - '//a/@href' '../../some_macros/derive.SomeDerive.html'
+    pub use some_derive;
+}
diff --git a/src/test/ui/anon-params-denied-2018.stderr b/src/test/ui/anon-params-denied-2018.stderr
index 24a1e6e..dd9e933 100644
--- a/src/test/ui/anon-params-denied-2018.stderr
+++ b/src/test/ui/anon-params-denied-2018.stderr
@@ -2,13 +2,21 @@
   --> $DIR/anon-params-denied-2018.rs:6:15
    |
 LL |     fn foo(i32); //~ expected one of `:` or `@`, found `)`
-   |               ^ expected one of `:` or `@` here
+   |            ---^ expected one of `:` or `@` here
+   |            |
+   |            help: explicitly ignore parameter: `_: i32`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
 
 error: expected one of `:` or `@`, found `,`
   --> $DIR/anon-params-denied-2018.rs:8:36
    |
 LL |     fn bar_with_default_impl(String, String) {}
-   |                                    ^ expected one of `:` or `@` here
+   |                              ------^ expected one of `:` or `@` here
+   |                              |
+   |                              help: explicitly ignore parameter: `_: String`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
 
 error: aborting due to 2 previous errors
 
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/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/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/error-codes/E0424.rs b/src/test/ui/error-codes/E0424.rs
index 445d0c5..20d42da 100644
--- a/src/test/ui/error-codes/E0424.rs
+++ b/src/test/ui/error-codes/E0424.rs
@@ -19,4 +19,5 @@
 }
 
 fn main () {
+    let self = "self"; //~ ERROR E0424
 }
diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr
index a1b7a5f..5eccd7d 100644
--- a/src/test/ui/error-codes/E0424.stderr
+++ b/src/test/ui/error-codes/E0424.stderr
@@ -4,6 +4,12 @@
 LL |         self.bar(); //~ ERROR E0424
    |         ^^^^ `self` value is a keyword only available in methods with `self` parameter
 
-error: aborting due to previous error
+error[E0424]: expected unit struct/variant or constant, found module `self`
+  --> $DIR/E0424.rs:22:9
+   |
+LL |     let self = "self"; //~ ERROR E0424
+   |         ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0424`.
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-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-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index e2630b5..ed6b325 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -14,8 +14,8 @@
    |          ^^^^^^^
    |
    = note: the method `collect` exists but the following trait bounds were not satisfied:
-           `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:16:39: 19:6 found_e:_]>> : std::iter::Iterator`
            `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:16:39: 19:6 found_e:_]>> : std::iter::Iterator`
+           `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:16:39: 19:6 found_e:_]>> : std::iter::Iterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-35677.rs b/src/test/ui/issues/issue-35677.rs
new file mode 100644
index 0000000..46d3f7e
--- /dev/null
+++ b/src/test/ui/issues/issue-35677.rs
@@ -0,0 +1,5 @@
+use std::collections::HashMap;
+fn intersect_map<K, V>(this: &mut HashMap<K, V>, other: HashMap<K, V>) -> bool {
+    this.drain()
+    //~^ ERROR no method named
+}
diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr
new file mode 100644
index 0000000..dca096b
--- /dev/null
+++ b/src/test/ui/issues/issue-35677.stderr
@@ -0,0 +1,18 @@
+error[E0601]: `main` function not found in crate `issue_35677`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-35677.rs`
+
+error[E0599]: no method named `drain` found for type `&mut std::collections::HashMap<K, V>` in the current scope
+  --> $DIR/issue-35677.rs:3:10
+   |
+LL |     this.drain()
+   |          ^^^^^
+   |
+   = note: the method `drain` exists but the following trait bounds were not satisfied:
+           `K : std::cmp::Eq`
+           `K : std::hash::Hash`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0599, E0601.
+For more information about an error, try `rustc --explain E0599`.
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/lint/lint-unexported-no-mangle.stderr b/src/test/ui/lint/lint-unexported-no-mangle.stderr
index 063915d..1df2d7b 100644
--- a/src/test/ui/lint/lint-unexported-no-mangle.stderr
+++ b/src/test/ui/lint/lint-unexported-no-mangle.stderr
@@ -1,8 +1,8 @@
-warning: lint `private_no_mangle_fns` has been removed: `no longer an warning, #[no_mangle] functions always exported`
+warning: lint `private_no_mangle_fns` has been removed: `no longer a warning, #[no_mangle] functions always exported`
    |
    = note: requested on the command line with `-F private_no_mangle_fns`
 
-warning: lint `private_no_mangle_statics` has been removed: `no longer an warning, #[no_mangle] statics always exported`
+warning: lint `private_no_mangle_statics` has been removed: `no longer a warning, #[no_mangle] statics always exported`
    |
    = note: requested on the command line with `-F private_no_mangle_statics`
 
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/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index 86a92a7..1fbac9d 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -5,8 +5,8 @@
    |                                                       ^^^^^
    |
    = note: the method `count` exists but the following trait bounds were not satisfied:
-           `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
            `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
+           `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/issue-36053-2.rs:17:32
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/pattern/const-pat-ice.rs b/src/test/ui/pattern/const-pat-ice.rs
new file mode 100644
index 0000000..6496a2a
--- /dev/null
+++ b/src/test/ui/pattern/const-pat-ice.rs
@@ -0,0 +1,13 @@
+// failure-status: 101
+
+// This is a repro test for an ICE in our pattern handling of constants.
+
+const FOO: &&&u32 = &&&42;
+
+fn main() {
+    match unimplemented!() {
+        &&&42 => {},
+        FOO => {},
+        _ => {},
+    }
+}
diff --git a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
new file mode 100644
index 0000000..ff06588
--- /dev/null
+++ b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+fn main() {
+    let -2147483648..=2147483647 = 1;
+    let 0..=255 = 0u8;
+    let -128..=127 = 0i8;
+    let '\u{0000}'..='\u{10FFFF}' = 'v';
+}
diff --git a/src/test/ui/pattern/slice-pattern-const-2.rs b/src/test/ui/pattern/slice-pattern-const-2.rs
index 6f9501d..6cfef11 100644
--- a/src/test/ui/pattern/slice-pattern-const-2.rs
+++ b/src/test/ui/pattern/slice-pattern-const-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+#![deny(unreachable_patterns)]
 
 fn main() {
     let s = &[0x00; 4][..]; //Slice of any value
@@ -6,19 +6,26 @@
     match s {
         MAGIC_TEST => (),
         [0x00, 0x00, 0x00, 0x00] => (),
-        [4, 5, 6, 7] => (), // this should warn
+        [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         [0x00, 0x00, 0x00, 0x00] => (),
         MAGIC_TEST => (),
-        [4, 5, 6, 7] => (), // this should warn
+        [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         [0x00, 0x00, 0x00, 0x00] => (),
         [4, 5, 6, 7] => (),
-        MAGIC_TEST => (), // this should warn
+        MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+        _ => (),
+    }
+    const FOO: [u32; 1] = [4];
+    match [99] {
+        [0x00] => (),
+        [4] => (),
+        FOO => (), //~ ERROR unreachable pattern
         _ => (),
     }
 }
diff --git a/src/test/ui/pattern/slice-pattern-const-2.stderr b/src/test/ui/pattern/slice-pattern-const-2.stderr
new file mode 100644
index 0000000..95651cc
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const-2.stderr
@@ -0,0 +1,26 @@
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:9:9
+   |
+LL |         [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
+   |         ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/slice-pattern-const-2.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:15:9
+   |
+LL |         [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
+   |         ^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:28:9
+   |
+LL |         FOO => (), //~ ERROR unreachable pattern
+   |         ^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/pattern/slice-pattern-const-3.rs b/src/test/ui/pattern/slice-pattern-const-3.rs
index e7a30ce..8805c43 100644
--- a/src/test/ui/pattern/slice-pattern-const-3.rs
+++ b/src/test/ui/pattern/slice-pattern-const-3.rs
@@ -1,4 +1,4 @@
-// compile-pass
+#![deny(unreachable_patterns)]
 
 fn main() {
     let s = &["0x00"; 4][..]; //Slice of any value
@@ -6,19 +6,26 @@
     match s {
         MAGIC_TEST => (),
         ["0x00", "0x00", "0x00", "0x00"] => (),
-        ["4", "5", "6", "7"] => (), // this should warn
+        ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
         _ => (),
     }
     match s {
         ["0x00", "0x00", "0x00", "0x00"] => (),
         MAGIC_TEST => (),
-        ["4", "5", "6", "7"] => (), // this should warn
+        ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
         _ => (),
     }
     match s {
         ["0x00", "0x00", "0x00", "0x00"] => (),
         ["4", "5", "6", "7"] => (),
-        MAGIC_TEST => (), // this should warn
+        MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+        _ => (),
+    }
+    const FOO: [&str; 1] = ["boo"];
+    match ["baa"] {
+        ["0x00"] => (),
+        ["boo"] => (),
+        FOO => (), //~ ERROR unreachable pattern
         _ => (),
     }
 }
diff --git a/src/test/ui/pattern/slice-pattern-const-3.stderr b/src/test/ui/pattern/slice-pattern-const-3.stderr
new file mode 100644
index 0000000..531bbbc
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const-3.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-3.rs:28:9
+   |
+LL |         FOO => (), //~ ERROR unreachable pattern
+   |         ^^^
+   |
+note: lint level defined here
+  --> $DIR/slice-pattern-const-3.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/slice-pattern-const.rs b/src/test/ui/pattern/slice-pattern-const.rs
index d353f6c..f0a0451 100644
--- a/src/test/ui/pattern/slice-pattern-const.rs
+++ b/src/test/ui/pattern/slice-pattern-const.rs
@@ -1,4 +1,4 @@
-//compile-pass
+#![deny(unreachable_patterns)]
 
 fn main() {
     let s = &[0x00; 4][..]; //Slice of any value
@@ -6,19 +6,42 @@
     match s {
         MAGIC_TEST => (),
         [0x00, 0x00, 0x00, 0x00] => (),
-        [84, 69, 83, 84] => (), // this should warn
+        [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         [0x00, 0x00, 0x00, 0x00] => (),
         MAGIC_TEST => (),
-        [84, 69, 83, 84] => (), // this should warn
+        [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         [0x00, 0x00, 0x00, 0x00] => (),
         [84, 69, 83, 84] => (),
-        MAGIC_TEST => (), // this should warn
+        MAGIC_TEST => (), //~ ERROR unreachable pattern
         _ => (),
     }
+    const FOO: [u8; 1] = [4];
+    match [99] {
+        [0x00] => (),
+        [4] => (),
+        FOO => (), //~ ERROR unreachable pattern
+        _ => (),
+    }
+    const BAR: &[u8; 1] = &[4];
+    match &[99] {
+        [0x00] => (),
+        [4] => (),
+        BAR => (), //~ ERROR unreachable pattern
+        b"a" => (),
+        _ => (),
+    }
+
+    const BOO: &[u8; 0] = &[];
+    match &[] {
+        [] => (),
+        BOO => (), //~ ERROR unreachable pattern
+        b"" => (), //~ ERROR unreachable pattern
+        _ => (), //~ ERROR unreachable pattern
+    }
 }
diff --git a/src/test/ui/pattern/slice-pattern-const.stderr b/src/test/ui/pattern/slice-pattern-const.stderr
new file mode 100644
index 0000000..412e015
--- /dev/null
+++ b/src/test/ui/pattern/slice-pattern-const.stderr
@@ -0,0 +1,56 @@
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:9:9
+   |
+LL |         [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+   |         ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/slice-pattern-const.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:15:9
+   |
+LL |         [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+   |         ^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:21:9
+   |
+LL |         MAGIC_TEST => (), //~ ERROR unreachable pattern
+   |         ^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:28:9
+   |
+LL |         FOO => (), //~ ERROR unreachable pattern
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:35:9
+   |
+LL |         BAR => (), //~ ERROR unreachable pattern
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:43:9
+   |
+LL |         BOO => (), //~ ERROR unreachable pattern
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:44:9
+   |
+LL |         b"" => (), //~ ERROR unreachable pattern
+   |         ^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:45:9
+   |
+LL |         _ => (), //~ ERROR unreachable pattern
+   |         ^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
new file mode 100644
index 0000000..24676fe
--- /dev/null
+++ b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
@@ -0,0 +1,74 @@
+// This is a collection of examples where a function's formal
+// parameter has an explicit lifetime and a closure within that
+// function returns that formal parameter. The closure's return type,
+// to be correctly inferred, needs to include the lifetime introduced
+// by the function.
+//
+// This works today, which precludes changing things so that closures
+// follow the same lifetime-elision rules used elsehwere. See
+// rust-lang/rust#56537
+
+// compile-pass
+// We are already testing NLL explicitly via the revision system below.
+// ignore-compare-mode-nll
+
+// revisions: ll nll migrate
+//[ll] compile-flags:-Zborrowck=ast
+//[nll] compile-flags:-Zborrowck=mir -Z two-phase-borrows
+//[migrate] compile-flags:-Zborrowck=migrate -Z two-phase-borrows
+
+fn willy_no_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x| { p }; // no type annotation at all
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x| -> &str { p }; // type annotation on the return type
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x| -> &'w str { p }; // type+region annotation on return type
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_arg_type_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x: &str| -> &str { p }; // type annotation on arg and return types
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn willy_arg_type_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str {
+    let free_dumb = |_x: &str| -> &'w str { p }; // fully annotated
+    let hello = format!("Hello");
+    free_dumb(&hello)
+}
+
+fn main() {
+    let world = format!("World");
+    let w1: &str = {
+        let hello = format!("He11o");
+        willy_no_annot(&world, &hello)
+    };
+    let w2: &str = {
+        let hello = format!("He22o");
+        willy_ret_type_annot(&world, &hello)
+    };
+    let w3: &str = {
+        let hello = format!("He33o");
+        willy_ret_region_annot(&world, &hello)
+    };
+    let w4: &str = {
+        let hello = format!("He44o");
+        willy_arg_type_ret_type_annot(&world, &hello)
+    };
+    let w5: &str = {
+        let hello = format!("He55o");
+        willy_arg_type_ret_region_annot(&world, &hello)
+    };
+    assert_eq!((w1, w2, w3, w4, w5),
+               ("World","World","World","World","World"));
+}
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 d74d681..31ec8a7 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -33,6 +33,7 @@
 
 extern "platform-intrinsic" {
     fn simd_select<T, U>(x: T, a: U, b: U) -> U;
+    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
 }
 
 fn main() {
@@ -52,5 +53,20 @@
 
         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
+
+        simd_select_bitmask("x", x, x);
+        //~^ ERROR `&str` 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 61e4202..05317da 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
@@ -1,21 +1,51 @@
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
-  --> $DIR/simd-intrinsic-generic-select.rs:47:9
+  --> $DIR/simd-intrinsic-generic-select.rs:48:9
    |
 LL |         simd_select(m8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_`
-  --> $DIR/simd-intrinsic-generic-select.rs:50:9
+  --> $DIR/simd-intrinsic-generic-select.rs:51:9
    |
 LL |         simd_select(x, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_`
-  --> $DIR/simd-intrinsic-generic-select.rs:53:9
+  --> $DIR/simd-intrinsic-generic-select.rs:54:9
    |
 LL |         simd_select(z, z, z);
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+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: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:69:9
+   |
+LL |         simd_select_bitmask("x", x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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/suggestions/suggest-impl-trait-lifetime.fixed b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed
new file mode 100644
index 0000000..8592af1
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+use std::fmt::Debug;
+
+fn foo(d: impl Debug + 'static) {
+//~^ HELP consider adding an explicit lifetime bound  `'static` to `impl Debug`
+    bar(d);
+//~^ ERROR the parameter type `impl Debug` may not live long enough
+//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
+}
+
+fn bar(d: impl Debug + 'static) {
+    println!("{:?}", d)
+}
+
+fn main() {
+  foo("hi");
+}
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs
new file mode 100644
index 0000000..c67d78e
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+
+use std::fmt::Debug;
+
+fn foo(d: impl Debug) {
+//~^ HELP consider adding an explicit lifetime bound  `'static` to `impl Debug`
+    bar(d);
+//~^ ERROR the parameter type `impl Debug` may not live long enough
+//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
+}
+
+fn bar(d: impl Debug + 'static) {
+    println!("{:?}", d)
+}
+
+fn main() {
+  foo("hi");
+}
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
new file mode 100644
index 0000000..cba231d
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
@@ -0,0 +1,19 @@
+error[E0310]: the parameter type `impl Debug` may not live long enough
+  --> $DIR/suggest-impl-trait-lifetime.rs:7:5
+   |
+LL |     bar(d);
+   |     ^^^
+   |
+note: ...so that the type `impl Debug` will meet its required lifetime bounds
+  --> $DIR/suggest-impl-trait-lifetime.rs:7:5
+   |
+LL |     bar(d);
+   |     ^^^
+help: consider adding an explicit lifetime bound  `'static` to `impl Debug`...
+   |
+LL | fn foo(d: impl Debug + 'static) {
+   |           ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
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/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"),