Auto merge of #67850 - GuillaumeGomez:err-codes-checkup, r=Mark-Simulacrum

Error codes checkup and rustdoc test fix

This PR does a few things:

 * fix how rustdoc checks that an error code has been thrown (it only checked for "E0XXX" so if it appeared in the output because the file has it in its name or wherever, it passed the test, which was incorrect)
 * fix the failing code examples that weren't throwing the expected error code
diff --git a/Cargo.lock b/Cargo.lock
index a25f8db..4836e15 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -395,9 +395,9 @@
 
 [[package]]
 name = "cc"
-version = "1.0.47"
+version = "1.0.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8"
+checksum = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e"
 dependencies = [
  "jobserver",
  "num_cpus",
@@ -1995,9 +1995,9 @@
 
 [[package]]
 name = "measureme"
-version = "0.5.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8"
+checksum = "fef709d3257013bba7cff14fc504e07e80631d3fe0f6d38ce63b8f6510ccb932"
 dependencies = [
  "byteorder",
  "memmap",
@@ -3080,7 +3080,6 @@
  "jobserver",
  "log",
  "measureme",
- "num_cpus",
  "parking_lot",
  "polonius-engine",
  "rustc-rayon",
@@ -3090,7 +3089,6 @@
  "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
- "rustc_fs_util",
  "rustc_hir",
  "rustc_index",
  "rustc_macros",
@@ -3278,7 +3276,6 @@
  "jemalloc-sys",
  "rustc_codegen_ssa",
  "rustc_driver",
- "rustc_target",
 ]
 
 [[package]]
@@ -3349,17 +3346,6 @@
 ]
 
 [[package]]
-name = "rustc_asan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_ast_lowering"
 version = "0.0.0"
 dependencies = [
@@ -3368,6 +3354,7 @@
  "rustc_data_structures",
  "rustc_error_codes",
  "rustc_errors",
+ "rustc_hir",
  "rustc_index",
  "rustc_session",
  "rustc_span",
@@ -3377,6 +3364,21 @@
 ]
 
 [[package]]
+name = "rustc_ast_passes"
+version = "0.0.0"
+dependencies = [
+ "log",
+ "rustc_data_structures",
+ "rustc_error_codes",
+ "rustc_errors",
+ "rustc_feature",
+ "rustc_parse",
+ "rustc_session",
+ "rustc_span",
+ "syntax",
+]
+
+[[package]]
 name = "rustc_builtin_macros"
 version = "0.0.0"
 dependencies = [
@@ -3388,6 +3390,7 @@
  "rustc_expand",
  "rustc_feature",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "smallvec 1.0.0",
@@ -3408,9 +3411,9 @@
  "rustc_codegen_utils",
  "rustc_data_structures",
  "rustc_errors",
- "rustc_expand",
  "rustc_feature",
  "rustc_fs_util",
+ "rustc_hir",
  "rustc_incremental",
  "rustc_index",
  "rustc_llvm",
@@ -3439,6 +3442,7 @@
  "rustc_error_codes",
  "rustc_errors",
  "rustc_fs_util",
+ "rustc_hir",
  "rustc_incremental",
  "rustc_index",
  "rustc_session",
@@ -3458,6 +3462,7 @@
  "rustc",
  "rustc-demangle",
  "rustc_data_structures",
+ "rustc_hir",
  "rustc_metadata",
  "rustc_span",
  "rustc_target",
@@ -3493,7 +3498,6 @@
 version = "0.0.0"
 dependencies = [
  "env_logger 0.7.1",
- "graphviz",
  "lazy_static 1.3.0",
  "log",
  "rustc",
@@ -3502,13 +3506,13 @@
  "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
+ "rustc_hir",
  "rustc_interface",
  "rustc_lint",
  "rustc_metadata",
  "rustc_mir",
  "rustc_parse",
  "rustc_plugin_impl",
- "rustc_resolve",
  "rustc_save_analysis",
  "rustc_span",
  "rustc_target",
@@ -3540,11 +3544,13 @@
 version = "0.0.0"
 dependencies = [
  "log",
+ "rustc_ast_passes",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "serialize",
  "smallvec 1.0.0",
@@ -3590,6 +3596,7 @@
  "rustc",
  "rustc_data_structures",
  "rustc_fs_util",
+ "rustc_hir",
  "rustc_session",
  "rustc_span",
  "serialize",
@@ -3613,6 +3620,7 @@
  "rustc",
  "rustc-rayon",
  "rustc_ast_lowering",
+ "rustc_ast_passes",
  "rustc_builtin_macros",
  "rustc_codegen_llvm",
  "rustc_codegen_ssa",
@@ -3625,11 +3633,13 @@
  "rustc_lint",
  "rustc_metadata",
  "rustc_mir",
+ "rustc_mir_build",
  "rustc_parse",
  "rustc_passes",
  "rustc_plugin_impl",
  "rustc_privacy",
  "rustc_resolve",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "rustc_traits",
@@ -3655,7 +3665,9 @@
  "rustc",
  "rustc_data_structures",
  "rustc_error_codes",
+ "rustc_errors",
  "rustc_feature",
+ "rustc_hir",
  "rustc_index",
  "rustc_session",
  "rustc_span",
@@ -3674,17 +3686,6 @@
 ]
 
 [[package]]
-name = "rustc_lsan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_macros"
 version = "0.1.0"
 dependencies = [
@@ -3707,6 +3708,7 @@
  "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
+ "rustc_hir",
  "rustc_index",
  "rustc_parse",
  "rustc_span",
@@ -3721,7 +3723,6 @@
 name = "rustc_mir"
 version = "0.0.0"
 dependencies = [
- "arena",
  "either",
  "graphviz",
  "itertools 0.8.0",
@@ -3733,6 +3734,7 @@
  "rustc_data_structures",
  "rustc_error_codes",
  "rustc_errors",
+ "rustc_hir",
  "rustc_index",
  "rustc_lexer",
  "rustc_macros",
@@ -3744,14 +3746,25 @@
 ]
 
 [[package]]
-name = "rustc_msan"
+name = "rustc_mir_build"
 version = "0.0.0"
 dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
+ "arena",
+ "itertools 0.8.0",
+ "log",
+ "rustc",
+ "rustc_apfloat",
+ "rustc_data_structures",
+ "rustc_error_codes",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_macros",
+ "rustc_span",
+ "rustc_target",
+ "serialize",
+ "smallvec 1.0.0",
+ "syntax",
 ]
 
 [[package]]
@@ -3765,6 +3778,7 @@
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
+ "rustc_session",
  "rustc_span",
  "smallvec 1.0.0",
  "syntax",
@@ -3781,8 +3795,9 @@
  "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
+ "rustc_hir",
  "rustc_index",
- "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "syntax",
@@ -3794,6 +3809,9 @@
 dependencies = [
  "rustc",
  "rustc_error_codes",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_lint",
  "rustc_metadata",
  "rustc_span",
  "syntax",
@@ -3807,6 +3825,8 @@
  "rustc",
  "rustc_data_structures",
  "rustc_error_codes",
+ "rustc_errors",
+ "rustc_hir",
  "rustc_span",
  "rustc_typeck",
  "syntax",
@@ -3826,6 +3846,7 @@
  "rustc_errors",
  "rustc_expand",
  "rustc_feature",
+ "rustc_hir",
  "rustc_metadata",
  "rustc_session",
  "rustc_span",
@@ -3843,6 +3864,7 @@
  "rustc",
  "rustc_codegen_utils",
  "rustc_data_structures",
+ "rustc_hir",
  "rustc_parse",
  "rustc_span",
  "serde_json",
@@ -3856,6 +3878,7 @@
  "log",
  "num_cpus",
  "rustc_data_structures",
+ "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_fs_util",
@@ -3911,6 +3934,7 @@
  "log",
  "rustc",
  "rustc_data_structures",
+ "rustc_hir",
  "rustc_macros",
  "rustc_span",
  "rustc_target",
@@ -3919,17 +3943,6 @@
 ]
 
 [[package]]
-name = "rustc_tsan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_typeck"
 version = "0.0.0"
 dependencies = [
@@ -3939,6 +3952,7 @@
  "rustc_data_structures",
  "rustc_error_codes",
  "rustc_errors",
+ "rustc_hir",
  "rustc_index",
  "rustc_span",
  "rustc_target",
@@ -4289,10 +4303,6 @@
  "panic_unwind",
  "profiler_builtins",
  "rand 0.7.0",
- "rustc_asan",
- "rustc_lsan",
- "rustc_msan",
- "rustc_tsan",
  "unwind",
  "wasi 0.9.0+wasi-snapshot-preview1",
 ]
@@ -4446,8 +4456,6 @@
 name = "syntax"
 version = "0.0.0"
 dependencies = [
- "bitflags",
- "lazy_static 1.3.0",
  "log",
  "rustc_data_structures",
  "rustc_error_codes",
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index f7d8daa..00c8e72 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -343,6 +343,7 @@
                 tool::Rustdoc,
                 tool::Clippy,
                 native::Llvm,
+                native::Sanitizers,
                 tool::Rustfmt,
                 tool::Miri,
                 native::Lld
@@ -726,7 +727,7 @@
             self.clear_if_dirty(&my_out, &rustdoc);
         }
 
-        cargo.env("CARGO_TARGET_DIR", out_dir).arg(cmd).arg("-Zconfig-profile");
+        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd).arg("-Zconfig-profile");
 
         let profile_var = |name: &str| {
             let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
@@ -865,6 +866,18 @@
         let sysroot = if use_snapshot { self.rustc_snapshot_sysroot() } else { &maybe_sysroot };
         let libdir = self.rustc_libdir(compiler);
 
+        // Clear the output directory if the real rustc we're using has changed;
+        // Cargo cannot detect this as it thinks rustc is bootstrap/debug/rustc.
+        //
+        // Avoid doing this during dry run as that usually means the relevant
+        // compiler is not yet linked/copied properly.
+        //
+        // Only clear out the directory if we're compiling std; otherwise, we
+        // should let Cargo take care of things for us (via depdep info)
+        if !self.config.dry_run && mode == Mode::ToolStd && cmd == "build" {
+            self.clear_if_dirty(&out_dir, &self.rustc(compiler));
+        }
+
         // Customize the compiler we're running. Specify the compiler to cargo
         // as our shim and then pass it some various options used to configure
         // how the actual compiler itself is called.
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index d4016f1..b7651576 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -45,7 +45,7 @@
         let compiler = builder.compiler(0, builder.config.build);
 
         let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind));
-        std_cargo(builder, &compiler, target, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
 
         builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
         run_cargo(
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 2d60024..eced035 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -87,7 +87,7 @@
         target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter());
 
         let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
-        std_cargo(builder, &compiler, target, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
 
         builder.info(&format!(
             "Building stage{} std artifacts ({} -> {})",
@@ -153,17 +153,18 @@
         copy_and_stamp(Path::new(&src), "libunwind.a");
     }
 
+    if builder.config.sanitizers && compiler.stage != 0 {
+        // The sanitizers are only copied in stage1 or above,
+        // to avoid creating dependency on LLVM.
+        target_deps.extend(copy_sanitizers(builder, &compiler, target));
+    }
+
     target_deps
 }
 
 /// Configure cargo to compile the standard library, adding appropriate env vars
 /// and such.
-pub fn std_cargo(
-    builder: &Builder<'_>,
-    compiler: &Compiler,
-    target: Interned<String>,
-    cargo: &mut Cargo,
-) {
+pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, cargo: &mut Cargo) {
     if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
@@ -206,19 +207,6 @@
         let mut features = builder.std_features();
         features.push_str(&compiler_builtins_c_feature);
 
-        if compiler.stage != 0 && builder.config.sanitizers {
-            // This variable is used by the sanitizer runtime crates, e.g.
-            // rustc_lsan, to build the sanitizer runtime from C code
-            // When this variable is missing, those crates won't compile the C code,
-            // so we don't set this variable during stage0 where llvm-config is
-            // missing
-            // We also only build the runtimes when --enable-sanitizers (or its
-            // config.toml equivalent) is used
-            let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
-            cargo.env("LLVM_CONFIG", llvm_config);
-            cargo.env("RUSTC_BUILD_SANITIZERS", "1");
-        }
-
         cargo
             .arg("--features")
             .arg(features)
@@ -276,31 +264,43 @@
         let libdir = builder.sysroot_libdir(target_compiler, target);
         let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
         add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
-
-        if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
-            // The sanitizers are only built in stage1 or above, so the dylibs will
-            // be missing in stage0 and causes panic. See the `std()` function above
-            // for reason why the sanitizers are not built in stage0.
-            copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
-        }
     }
 }
 
-fn copy_apple_sanitizer_dylibs(
+/// Copies sanitizer runtime libraries into target libdir.
+fn copy_sanitizers(
     builder: &Builder<'_>,
-    native_dir: &Path,
-    platform: &str,
-    into: &Path,
-) {
-    for &sanitizer in &["asan", "tsan"] {
-        let filename = format!("lib__rustc__clang_rt.{}_{}_dynamic.dylib", sanitizer, platform);
-        let mut src_path = native_dir.join(sanitizer);
-        src_path.push("build");
-        src_path.push("lib");
-        src_path.push("darwin");
-        src_path.push(&filename);
-        builder.copy(&src_path, &into.join(filename));
+    compiler: &Compiler,
+    target: Interned<String>,
+) -> Vec<PathBuf> {
+    let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
+
+    if builder.config.dry_run {
+        return Vec::new();
     }
+
+    let mut target_deps = Vec::new();
+    let libdir = builder.sysroot_libdir(*compiler, target);
+
+    for runtime in &runtimes {
+        let dst = libdir.join(&runtime.name);
+        builder.copy(&runtime.path, &dst);
+
+        if target == "x86_64-apple-darwin" {
+            // Update the library install name reflect the fact it has been renamed.
+            let status = Command::new("install_name_tool")
+                .arg("-id")
+                .arg(format!("@rpath/{}", runtime.name))
+                .arg(&dst)
+                .status()
+                .expect("failed to execute `install_name_tool`");
+            assert!(status.success());
+        }
+
+        target_deps.push(dst);
+    }
+
+    target_deps
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -776,7 +776,6 @@
         let bindir = sysroot.join("bin");
         t!(fs::create_dir_all(&bindir));
         let compiler = builder.rustc(target_compiler);
-        let _ = fs::remove_file(&compiler);
         builder.copy(&rustc, &compiler);
 
         target_compiler
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 944df66..110c8b8 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -493,9 +493,13 @@
             config.mandir = install.mandir.clone().map(PathBuf::from);
         }
 
+        // We want the llvm-skip-rebuild flag to take precedence over the
+        // skip-rebuild config.toml option so we store it separately
+        // so that we can infer the right value
+        let mut llvm_skip_rebuild = flags.llvm_skip_rebuild;
+
         // Store off these values as options because if they're not provided
         // we'll infer default values for them later
-        let mut llvm_skip_rebuild = None;
         let mut llvm_assertions = None;
         let mut debug = None;
         let mut debug_assertions = None;
@@ -517,7 +521,7 @@
             }
             set(&mut config.ninja, llvm.ninja);
             llvm_assertions = llvm.assertions;
-            llvm_skip_rebuild = llvm.skip_rebuild;
+            llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild);
             set(&mut config.llvm_optimize, llvm.optimize);
             set(&mut config.llvm_thin_lto, llvm.thin_lto);
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index e64d4c8..8d13df3 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -984,10 +984,6 @@
             "src/libcore",
             "src/libpanic_abort",
             "src/libpanic_unwind",
-            "src/librustc_asan",
-            "src/librustc_lsan",
-            "src/librustc_msan",
-            "src/librustc_tsan",
             "src/libstd",
             "src/libunwind",
             "src/libtest",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 8cd7fc2..2040565 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -49,7 +49,7 @@
                 builder.ensure(RustbookSrc {
                     target: self.target,
                     name: INTERNER.intern_str($book_name),
-                    src: doc_src(builder),
+                    src: INTERNER.intern_path(builder.src.join($path)),
                 })
             }
         }
@@ -60,6 +60,7 @@
 // NOTE: When adding a book here, make sure to ALSO build the book by
 // adding a build step in `src/bootstrap/builder.rs`!
 book!(
+    CargoBook, "src/tools/cargo/src/doc", "cargo";
     EditionGuide, "src/doc/edition-guide", "edition-guide";
     EmbeddedBook, "src/doc/embedded-book", "embedded-book";
     Nomicon, "src/doc/nomicon", "nomicon";
@@ -69,10 +70,6 @@
     RustdocBook, "src/doc/rustdoc", "rustdoc";
 );
 
-fn doc_src(builder: &Builder<'_>) -> Interned<PathBuf> {
-    INTERNER.intern_path(builder.src.join("src/doc"))
-}
-
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct UnstableBook {
     target: Interned<String>,
@@ -96,49 +93,12 @@
         builder.ensure(RustbookSrc {
             target: self.target,
             name: INTERNER.intern_str("unstable-book"),
-            src: builder.md_doc_out(self.target),
+            src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")),
         })
     }
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub struct CargoBook {
-    target: Interned<String>,
-    name: Interned<String>,
-}
-
-impl Step for CargoBook {
-    type Output = ();
-    const DEFAULT: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let builder = run.builder;
-        run.path("src/tools/cargo/src/doc/book").default_condition(builder.config.docs)
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(CargoBook { target: run.target, name: INTERNER.intern_str("cargo") });
-    }
-
-    fn run(self, builder: &Builder<'_>) {
-        let target = self.target;
-        let name = self.name;
-        let src = builder.src.join("src/tools/cargo/src/doc");
-
-        let out = builder.doc_out(target);
-        t!(fs::create_dir_all(&out));
-
-        let out = out.join(name);
-
-        builder.info(&format!("Cargo Book ({}) - {}", target, name));
-
-        let _ = fs::remove_dir_all(&out);
-
-        builder.run(builder.tool_cmd(Tool::Rustbook).arg("build").arg(&src).arg("-d").arg(out));
-    }
-}
-
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 struct RustbookSrc {
     target: Interned<String>,
     name: Interned<String>,
@@ -164,7 +124,6 @@
         t!(fs::create_dir_all(&out));
 
         let out = out.join(name);
-        let src = src.join(name);
         let index = out.join("index.html");
         let rustbook = builder.tool_exe(Tool::Rustbook);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
@@ -182,7 +141,6 @@
 pub struct TheBook {
     compiler: Compiler,
     target: Interned<String>,
-    name: &'static str,
 }
 
 impl Step for TheBook {
@@ -198,7 +156,6 @@
         run.builder.ensure(TheBook {
             compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
-            name: "book",
         });
     }
 
@@ -206,45 +163,30 @@
     ///
     /// We need to build:
     ///
-    /// * Book (first edition)
-    /// * Book (second edition)
+    /// * Book
+    /// * Older edition redirects
     /// * Version info and CSS
     /// * Index page
     /// * Redirect pages
     fn run(self, builder: &Builder<'_>) {
         let compiler = self.compiler;
         let target = self.target;
-        let name = self.name;
 
         // build book
         builder.ensure(RustbookSrc {
             target,
-            name: INTERNER.intern_string(name.to_string()),
-            src: doc_src(builder),
+            name: INTERNER.intern_str("book"),
+            src: INTERNER.intern_path(builder.src.join("src/doc/book")),
         });
 
         // building older edition redirects
-
-        let source_name = format!("{}/first-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
-
-        let source_name = format!("{}/second-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
-
-        let source_name = format!("{}/2018-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
+        for edition in &["first-edition", "second-edition", "2018-edition"] {
+            builder.ensure(RustbookSrc {
+                target,
+                name: INTERNER.intern_string(format!("book/{}", edition)),
+                src: INTERNER.intern_path(builder.src.join("src/doc/book").join(edition)),
+            });
+        }
 
         // build the version info page and CSS
         builder.ensure(Standalone { compiler, target });
@@ -449,7 +391,7 @@
 
         let run_cargo_rustdoc_for = |package: &str| {
             let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc");
-            compile::std_cargo(builder, &compiler, target, &mut cargo);
+            compile::std_cargo(builder, target, &mut cargo);
 
             // Keep a whitelist so we do not build internal stdlib crates, these will be
             // build by the rustc step later if enabled.
@@ -531,7 +473,7 @@
 
         // Build cargo command.
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
-        cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden");
+        cargo.env("RUSTDOCFLAGS", "--document-private-items");
         compile::rustc_cargo(builder, &mut cargo, target);
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index ffc2436..1fbdd50 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -38,6 +38,8 @@
     //
     // true => deny, false => warn
     pub deny_warnings: Option<bool>,
+
+    pub llvm_skip_rebuild: Option<bool>,
 }
 
 pub enum Subcommand {
@@ -150,6 +152,14 @@
             "VALUE",
         );
         opts.optopt("", "error-format", "rustc error format", "FORMAT");
+        opts.optopt(
+            "",
+            "llvm-skip-rebuild",
+            "whether rebuilding llvm should be skipped \
+             a VALUE of TRUE indicates that llvm will not be rebuilt \
+             VALUE overrides the skip-rebuild option in config.toml.",
+            "VALUE",
+        );
 
         // fn usage()
         let usage =
@@ -487,6 +497,9 @@
                 .map(|p| p.into())
                 .collect::<Vec<_>>(),
             deny_warnings: parse_deny_warnings(&matches),
+            llvm_skip_rebuild: matches.opt_str("llvm-skip-rebuild").map(|s| s.to_lowercase()).map(
+                |s| s.parse::<bool>().expect("`llvm-skip-rebuild` should be either true or false"),
+            ),
         }
     }
 }
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 2a4e990..ce977f1 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -546,3 +546,118 @@
             .compile("rust_test_helpers");
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Sanitizers {
+    pub target: Interned<String>,
+}
+
+impl Step for Sanitizers {
+    type Output = Vec<SanitizerRuntime>;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/llvm-project/compiler-rt").path("src/sanitizers")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Sanitizers { target: run.target });
+    }
+
+    /// Builds sanitizer runtime libraries.
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let compiler_rt_dir = builder.src.join("src/llvm-project/compiler-rt");
+        if !compiler_rt_dir.exists() {
+            return Vec::new();
+        }
+
+        let out_dir = builder.native_dir(self.target).join("sanitizers");
+        let runtimes = supported_sanitizers(&out_dir, self.target);
+        if runtimes.is_empty() {
+            return runtimes;
+        }
+
+        let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+        if builder.config.dry_run {
+            return runtimes;
+        }
+
+        let done_stamp = out_dir.join("sanitizers-finished-building");
+        if done_stamp.exists() {
+            builder.info(&format!(
+                "Assuming that sanitizers rebuild is not necessary. \
+                To force a rebuild, remove the file `{}`",
+                done_stamp.display()
+            ));
+            return runtimes;
+        }
+
+        builder.info(&format!("Building sanitizers for {}", self.target));
+        let _time = util::timeit(&builder);
+
+        let mut cfg = cmake::Config::new(&compiler_rt_dir);
+        cfg.target(&self.target);
+        cfg.host(&builder.config.build);
+        cfg.profile("Release");
+
+        cfg.define("CMAKE_C_COMPILER_TARGET", self.target);
+        cfg.define("COMPILER_RT_BUILD_BUILTINS", "OFF");
+        cfg.define("COMPILER_RT_BUILD_CRT", "OFF");
+        cfg.define("COMPILER_RT_BUILD_LIBFUZZER", "OFF");
+        cfg.define("COMPILER_RT_BUILD_PROFILE", "OFF");
+        cfg.define("COMPILER_RT_BUILD_SANITIZERS", "ON");
+        cfg.define("COMPILER_RT_BUILD_XRAY", "OFF");
+        cfg.define("COMPILER_RT_DEFAULT_TARGET_ONLY", "ON");
+        cfg.define("COMPILER_RT_USE_LIBCXX", "OFF");
+        cfg.define("LLVM_CONFIG_PATH", &llvm_config);
+
+        t!(fs::create_dir_all(&out_dir));
+        cfg.out_dir(out_dir);
+
+        for runtime in &runtimes {
+            cfg.build_target(&runtime.cmake_target);
+            cfg.build();
+        }
+
+        t!(fs::write(&done_stamp, b""));
+
+        runtimes
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct SanitizerRuntime {
+    /// CMake target used to build the runtime.
+    pub cmake_target: String,
+    /// Path to the built runtime library.
+    pub path: PathBuf,
+    /// Library filename that will be used rustc.
+    pub name: String,
+}
+
+/// Returns sanitizers available on a given target.
+fn supported_sanitizers(out_dir: &Path, target: Interned<String>) -> Vec<SanitizerRuntime> {
+    let mut result = Vec::new();
+    match &*target {
+        "x86_64-apple-darwin" => {
+            for s in &["asan", "lsan", "tsan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}_osx_dynamic", s),
+                    path: out_dir
+                        .join(&format!("build/lib/darwin/libclang_rt.{}_osx_dynamic.dylib", s)),
+                    name: format!("librustc_rt.{}.dylib", s),
+                });
+            }
+        }
+        "x86_64-unknown-linux-gnu" => {
+            for s in &["asan", "lsan", "msan", "tsan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}-x86_64", s),
+                    path: out_dir.join(&format!("build/lib/linux/libclang_rt.{}-x86_64.a", s)),
+                    name: format!("librustc_rt.{}.a", s),
+                });
+            }
+        }
+        _ => {}
+    }
+    result
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index b5c8de0..10e0748 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1659,7 +1659,7 @@
         let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
         match mode {
             Mode::Std => {
-                compile::std_cargo(builder, &compiler, target, &mut cargo);
+                compile::std_cargo(builder, target, &mut cargo);
             }
             Mode::Rustc => {
                 builder.ensure(compile::Rustc { compiler, target });
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 9fd2038..7f24768 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -289,8 +289,8 @@
 macro_rules! bootstrap_tool {
     ($(
         $name:ident, $path:expr, $tool_name:expr
-        $(,llvm_tools = $llvm:expr)*
         $(,is_external_tool = $external:expr)*
+        $(,is_unstable_tool = $unstable:expr)*
         $(,features = $features:expr)*
         ;
     )+) => {
@@ -301,15 +301,6 @@
             )+
         }
 
-        impl Tool {
-            /// Whether this tool requires LLVM to run
-            pub fn uses_llvm_tools(&self) -> bool {
-                match self {
-                    $(Tool::$name => false $(|| $llvm)*,)+
-                }
-            }
-        }
-
         impl<'a> Builder<'a> {
             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                 match tool {
@@ -350,7 +341,12 @@
                     compiler: self.compiler,
                     target: self.target,
                     tool: $tool_name,
-                    mode: Mode::ToolBootstrap,
+                    mode: if false $(|| $unstable)* {
+                        // use in-tree libraries for unstable features
+                        Mode::ToolStd
+                    } else {
+                        Mode::ToolBootstrap
+                    },
                     path: $path,
                     is_optional_tool: false,
                     source_type: if false $(|| $external)* {
@@ -377,7 +373,7 @@
     Tidy, "src/tools/tidy", "tidy";
     Linkchecker, "src/tools/linkchecker", "linkchecker";
     CargoTest, "src/tools/cargotest", "cargotest";
-    Compiletest, "src/tools/compiletest", "compiletest", llvm_tools = true;
+    Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true;
     BuildManifest, "src/tools/build-manifest", "build-manifest";
     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
     RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true;
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 3f42533..43c3c57 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -1,7 +1,5 @@
-use std::fs::File;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
-use std::thread;
 use std::time::{SystemTime, UNIX_EPOCH};
 use std::{env, fs};
 
@@ -181,108 +179,6 @@
     }
 }
 
-#[must_use]
-pub struct NativeLibBoilerplate {
-    pub src_dir: PathBuf,
-    pub out_dir: PathBuf,
-}
-
-impl NativeLibBoilerplate {
-    /// On macOS we don't want to ship the exact filename that compiler-rt builds.
-    /// This conflicts with the system and ours is likely a wildly different
-    /// version, so they can't be substituted.
-    ///
-    /// As a result, we rename it here but we need to also use
-    /// `install_name_tool` on macOS to rename the commands listed inside of it to
-    /// ensure it's linked against correctly.
-    pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) {
-        if env::var("TARGET").unwrap() != "x86_64-apple-darwin" {
-            return;
-        }
-
-        let dir = self.out_dir.join("build/lib/darwin");
-        let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name);
-        let src = dir.join(&format!("lib{}.dylib", name));
-        let new_name = format!("lib__rustc__{}.dylib", name);
-        let dst = dir.join(&new_name);
-
-        println!("{} => {}", src.display(), dst.display());
-        fs::rename(&src, &dst).unwrap();
-        let status = Command::new("install_name_tool")
-            .arg("-id")
-            .arg(format!("@rpath/{}", new_name))
-            .arg(&dst)
-            .status()
-            .expect("failed to execute `install_name_tool`");
-        assert!(status.success());
-    }
-}
-
-impl Drop for NativeLibBoilerplate {
-    fn drop(&mut self) {
-        if !thread::panicking() {
-            t!(File::create(self.out_dir.join("rustbuild.timestamp")));
-        }
-    }
-}
-
-// Perform standard preparations for native libraries that are build only once for all stages.
-// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are
-// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler.
-// If Err is returned, then everything is up-to-date and further build actions can be skipped.
-// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out
-// of scope, so all the build actions should be completed until then.
-pub fn native_lib_boilerplate(
-    src_dir: &Path,
-    out_name: &str,
-    link_name: &str,
-    search_subdir: &str,
-) -> Result<NativeLibBoilerplate, ()> {
-    rerun_if_changed_anything_in_dir(src_dir);
-
-    let out_dir =
-        env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(|| env::var_os("OUT_DIR").unwrap());
-    let out_dir = PathBuf::from(out_dir).join(out_name);
-    t!(fs::create_dir_all(&out_dir));
-    if link_name.contains('=') {
-        println!("cargo:rustc-link-lib={}", link_name);
-    } else {
-        println!("cargo:rustc-link-lib=static={}", link_name);
-    }
-    println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display());
-
-    let timestamp = out_dir.join("rustbuild.timestamp");
-    if !up_to_date(Path::new("build.rs"), &timestamp) || !up_to_date(src_dir, &timestamp) {
-        Ok(NativeLibBoilerplate { src_dir: src_dir.to_path_buf(), out_dir })
-    } else {
-        Err(())
-    }
-}
-
-pub fn sanitizer_lib_boilerplate(
-    sanitizer_name: &str,
-) -> Result<(NativeLibBoilerplate, String), ()> {
-    let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() {
-        "x86_64-unknown-linux-gnu" => {
-            (format!("clang_rt.{}-x86_64", sanitizer_name), "build/lib/linux", false)
-        }
-        "x86_64-apple-darwin" => {
-            (format!("clang_rt.{}_osx_dynamic", sanitizer_name), "build/lib/darwin", true)
-        }
-        _ => return Err(()),
-    };
-    let to_link = if apple {
-        format!("dylib=__rustc__{}", link_name)
-    } else {
-        format!("static={}", link_name)
-    };
-    // This env var is provided by rustbuild to tell us where `compiler-rt`
-    // lives.
-    let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
-    let lib = native_lib_boilerplate(dir.as_ref(), sanitizer_name, &to_link, search_path)?;
-    Ok((lib, link_name))
-}
-
 fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
     t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
         let meta = t!(e.metadata());
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 5248e41..79a49fc 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -85,7 +85,7 @@
 
       dist-x86_64-apple:
         SCRIPT: ./x.py dist
-        RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
+        RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
         RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
         MACOSX_DEPLOYMENT_TARGET: 10.7
         NO_LLVM_ASSERTIONS: 1
@@ -100,25 +100,6 @@
         NO_LLVM_ASSERTIONS: 1
         NO_DEBUG_ASSERTIONS: 1
 
-      i686-apple:
-        SCRIPT: ./x.py test
-        RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc
-        RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-        MACOSX_DEPLOYMENT_TARGET: 10.8
-        MACOSX_STD_DEPLOYMENT_TARGET: 10.7
-        NO_LLVM_ASSERTIONS: 1
-        NO_DEBUG_ASSERTIONS: 1
-
-      dist-i686-apple:
-        SCRIPT: ./x.py dist
-        RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --set rust.jemalloc
-        RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-        MACOSX_DEPLOYMENT_TARGET: 10.7
-        NO_LLVM_ASSERTIONS: 1
-        NO_DEBUG_ASSERTIONS: 1
-        DIST_REQUIRE_ALL_TOOLS: 1
-
-
 
 - job: Windows
   timeoutInMinutes: 600
diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile
index b2748d9..890e132 100644
--- a/src/ci/docker/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:19.04
+FROM ubuntu:19.10
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile
index 4ec4364..b864c09 100644
--- a/src/ci/docker/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/x86_64-gnu/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:19.04
+FROM ubuntu:19.10
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh
index 4c04706..7c43d03 100755
--- a/src/ci/publish_toolstate.sh
+++ b/src/ci/publish_toolstate.sh
@@ -1,6 +1,9 @@
-#!/bin/sh
+#!/bin/bash
 
-set -eu
+set -euo pipefail
+IFS=$'\n\t'
+
+source "$(cd "$(dirname "$0")" && pwd)/shared.sh"
 
 # The following lines are also found in src/bootstrap/toolstate.rs,
 # so if updating here, please also update that file.
@@ -21,7 +24,7 @@
 FAILURE=1
 for RETRY_COUNT in 1 2 3 4 5; do
     #  The purpose is to publish the new "current" toolstate in the toolstate repo.
-    "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$GIT_COMMIT" \
+    "$(ciCheckoutPath)/src/tools/publish_toolstate.py" "$GIT_COMMIT" \
         "$GIT_COMMIT_MSG" \
         "$MESSAGE_FILE" \
         "$TOOLSTATE_REPO_ACCESS_TOKEN"
diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh
index f017999..e16a481 100755
--- a/src/ci/scripts/install-clang.sh
+++ b/src/ci/scripts/install-clang.sh
@@ -14,6 +14,15 @@
     ciCommandSetEnv CC "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang"
     ciCommandSetEnv CXX "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang++"
 
+    # macOS 10.15 onwards doesn't have libraries in /usr/include anymore: those
+    # are now located deep into the filesystem, under Xcode's own files. The
+    # native clang is configured to use the correct path, but our custom one
+    # doesn't. This sets the SDKROOT environment variable to the SDK so that
+    # our own clang can figure out the correct include path on its own.
+    if ! [[ -d "/usr/include" ]]; then
+        ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)"
+    fi
+
     # Configure `AR` specifically so rustbuild doesn't try to infer it as
     # `clang-ar` by accident.
     ciCommandSetEnv AR "ar"
diff --git a/src/ci/scripts/install-msys2-packages.sh b/src/ci/scripts/install-msys2-packages.sh
index 36d9202..843a2bf 100755
--- a/src/ci/scripts/install-msys2-packages.sh
+++ b/src/ci/scripts/install-msys2-packages.sh
@@ -6,7 +6,8 @@
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
 if isWindows; then
-    pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar
+    pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar \
+        binutils
 
     # Make sure we use the native python interpreter instead of some msys equivalent
     # one way or another. The msys interpreters seem to have weird path conversions
diff --git a/src/ci/shared.sh b/src/ci/shared.sh
index 98120f5..206065d 100644
--- a/src/ci/shared.sh
+++ b/src/ci/shared.sh
@@ -80,7 +80,7 @@
 
 function ciCheckoutPath {
     if isAzurePipelines; then
-        echo "${SYSTEM_WORKFOLDER}"
+        echo "${BUILD_SOURCESDIRECTORY}"
     elif isGitHubActions; then
         echo "${GITHUB_WORKSPACE}"
     else
@@ -99,7 +99,7 @@
     if isAzurePipelines; then
         echo "##vso[task.prependpath]${path}"
     elif isGitHubActions; then
-        echo "::add-path::${value}"
+        echo "::add-path::${path}"
     else
         echo "ciCommandAddPath only works inside CI!"
         exit 1
diff --git a/src/doc/book b/src/doc/book
index ef8bb56..5c5cfd2 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit ef8bb568035ded8ddfa30a9309026638cc3c8136
+Subproject commit 5c5cfd2e94cd42632798d9bd3d1116133e128ac9
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
index 6601cab..1a23902 160000
--- a/src/doc/edition-guide
+++ b/src/doc/edition-guide
@@ -1 +1 @@
-Subproject commit 6601cab4666596494a569f94aa63b7b3230e9769
+Subproject commit 1a2390247ad6d08160e0dd74f40a01a9578659c2
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index c262349..9493b7d 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit c26234930282210849256e4ecab925f0f2daf3be
+Subproject commit 9493b7d4dc97eda439bd8780f05ad7b234cd1cd7
diff --git a/src/doc/nomicon b/src/doc/nomicon
index 8be35b2..3e6e100 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit 8be35b201f9cf0a4c3fcc96c83ac21671dcf3112
+Subproject commit 3e6e1001dc6e095dbd5c88005e80969f60e384e1
diff --git a/src/doc/reference b/src/doc/reference
index d8dfe1b..e115753 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit d8dfe1b005c03584cd7adc4bfb72b005e7e84744
+Subproject commit e1157538e86d83df0cf95d5e33bd943f80d0248f
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index b7ac1bc..1d59403 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit b7ac1bc76b7d02a43c83b3a931d226f708aa1ff4
+Subproject commit 1d59403cb5269c190cc52a95584ecc280345495a
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
new file mode 100644
index 0000000..cbb90bd
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -0,0 +1,163 @@
+# `sanitizer`
+
+The tracking issue for this feature is: [#39699](https://github.com/rust-lang/rust/issues/39699).
+
+------------------------
+
+This feature allows for use of one of following sanitizers:
+
+* [AddressSanitizer][clang-asan] a faster memory error detector. Can
+  detect out-of-bounds access to heap, stack, and globals, use after free, use
+  after return, double free, invalid free, memory leaks.
+* [LeakSanitizer][clang-lsan] a run-time memory leak detector.
+* [MemorySanitizer][clang-msan] a detector of uninitialized reads.
+* [ThreadSanitizer][clang-tsan] a fast data race detector.
+
+To enable a sanitizer compile with `-Zsanitizer=...` option, where value is one
+of `address`, `leak`, `memory` or `thread`.
+
+# Examples
+
+This sections show various issues that can be detected with sanitizers.  For
+simplicity, the examples are prepared under assumption that optimization level
+used is zero.
+
+## AddressSanitizer
+
+Stack buffer overflow:
+
+```shell
+$ cat a.rs
+fn main() {
+    let xs = [0, 1, 2, 3];
+    let _y = unsafe { *xs.as_ptr().offset(4) };
+}
+$ rustc -Zsanitizer=address a.rs
+$ ./a
+=================================================================
+==10029==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcc15f43d0 at pc 0x55f77dc015c5 bp 0x7ffcc15f4390 sp 0x7ffcc15f4388
+READ of size 4 at 0x7ffcc15f43d0 thread T0
+    #0 0x55f77dc015c4 in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa5c4)
+    #1 0x55f77dc01cdb in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::haa8c76d1faa7b7ca (/tmp/a+0xacdb)
+    #2 0x55f77dc90f02 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::hfeb9a1aef9ac820d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:48:12
+    #3 0x55f77dc90f02 in std::panicking::try::do_call::h12f0919717b8e0a6 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:288:39
+    #4 0x55f77dc926c9 in __rust_maybe_catch_panic /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libpanic_unwind/lib.rs:80:7
+    #5 0x55f77dc9197c in std::panicking::try::h413b21cdcd6cfd86 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:267:12
+    #6 0x55f77dc9197c in std::panic::catch_unwind::hc5cc8ef2fd73424d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panic.rs:396:8
+    #7 0x55f77dc9197c in std::rt::lang_start_internal::h2039f418ab92218f /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:47:24
+    #8 0x55f77dc01c61 in std::rt::lang_start::ha905d28f6b61d691 (/tmp/a+0xac61)
+    #9 0x55f77dc0163a in main (/tmp/a+0xa63a)
+    #10 0x7f9b3cf5bbba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba)
+    #11 0x55f77dc01289 in _start (/tmp/a+0xa289)
+
+Address 0x7ffcc15f43d0 is located in stack of thread T0 at offset 48 in frame
+    #0 0x55f77dc0135f in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa35f)
+
+  This frame has 1 object(s):
+    [32, 48) 'xs' <== Memory access at offset 48 overflows this variable
+HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
+      (longjmp and C++ exceptions *are* supported)
+SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/a+0xa5c4) in a::main::hab3bd2a745c2d0ac
+Shadow bytes around the buggy address:
+  0x1000182b6820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6850: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6860: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+=>0x1000182b6870: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
+  0x1000182b6880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Shadow byte legend (one shadow byte represents 8 application bytes):
+  Addressable:           00
+  Partially addressable: 01 02 03 04 05 06 07 
+  Heap left redzone:       fa
+  Freed heap region:       fd
+  Stack left redzone:      f1
+  Stack mid redzone:       f2
+  Stack right redzone:     f3
+  Stack after return:      f5
+  Stack use after scope:   f8
+  Global redzone:          f9
+  Global init order:       f6
+  Poisoned by user:        f7
+  Container overflow:      fc
+  Array cookie:            ac
+  Intra object redzone:    bb
+  ASan internal:           fe
+  Left alloca redzone:     ca
+  Right alloca redzone:    cb
+  Shadow gap:              cc
+==10029==ABORTING
+```
+
+## MemorySanitizer
+
+Use of uninitialized memory. Note that we are using `-Zbuild-std` to instrument
+standard library, and passing `-msan-track-origins=2` to the LLVM to track
+origins of uninitialized memory:
+
+```shell
+$ cat src/main.rs
+use std::mem::MaybeUninit;
+
+fn main() {
+    unsafe {
+        let a = MaybeUninit::<[usize; 4]>::uninit();
+        let a = a.assume_init();
+        println!("{}", a[2]);
+    }
+}
+
+$ env RUSTFLAGS="-Zsanitizer=memory -Cllvm-args=-msan-track-origins=2" cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
+==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
+    #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
+...
+  Uninitialized value was stored to memory at
+    #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3
+    #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16
+
+  Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E'
+    #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
+```
+
+
+# Instrumentation of external dependencies and std
+
+The sanitizers to varying degrees work correctly with partially instrumented
+code. On the one extreme is LeakSanitizer that doesn't use any compile time
+instrumentation, on the other is MemorySanitizer that requires that all program
+code to be instrumented (failing to achieve that will inevitably result in
+false positives).
+
+It is strongly recommended to combine sanitizers with recompiled and
+instrumented standard library, for example using [cargo `-Zbuild-std`
+functionality][build-std].
+
+[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+
+# Build scripts and procedural macros
+
+Use of sanitizers together with build scripts and procedural macros is
+technically possible, but in almost all cases it would be best avoided.  This
+is especially true for procedural macros which would require an instrumented
+version of rustc.
+
+In more practical terms when using cargo always remember to pass `--target`
+flag, so that rustflags will not be applied to build scripts and procedural
+macros.
+
+# Additional Information
+
+* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
+* [AddressSanitizer in Clang][clang-asan]
+* [LeakSanitizer in Clang][clang-lsan]
+* [MemorySanitizer in Clang][clang-msan]
+* [ThreadSanitizer in Clang][clang-tsan]
+
+[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
+[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
+[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
+[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
diff --git a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md b/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
deleted file mode 100644
index 82ae67f..0000000
--- a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `sanitizer_runtime_lib`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index cc01de0..87a4924 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -1046,48 +1046,7 @@
 #[stable(feature = "box_slice_clone", since = "1.3.0")]
 impl<T: Clone> Clone for Box<[T]> {
     fn clone(&self) -> Self {
-        let mut new = BoxBuilder { data: RawVec::with_capacity(self.len()), len: 0 };
-
-        let mut target = new.data.ptr();
-
-        for item in self.iter() {
-            unsafe {
-                ptr::write(target, item.clone());
-                target = target.offset(1);
-            };
-
-            new.len += 1;
-        }
-
-        return unsafe { new.into_box() };
-
-        // Helper type for responding to panics correctly.
-        struct BoxBuilder<T> {
-            data: RawVec<T>,
-            len: usize,
-        }
-
-        impl<T> BoxBuilder<T> {
-            unsafe fn into_box(self) -> Box<[T]> {
-                let raw = ptr::read(&self.data);
-                mem::forget(self);
-                raw.into_box()
-            }
-        }
-
-        impl<T> Drop for BoxBuilder<T> {
-            fn drop(&mut self) {
-                let mut data = self.data.ptr();
-                let max = unsafe { data.add(self.len) };
-
-                while data != max {
-                    unsafe {
-                        ptr::read(data);
-                        data = data.offset(1);
-                    }
-                }
-            }
-        }
+        self.to_vec().into_boxed_slice()
     }
 }
 
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index 260e51d..f40e0b0 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -397,6 +397,7 @@
 
     /// Borrows a view into the values stored in the node.
     /// The caller must ensure that the node is not the shared root.
+    /// This function is not public, so doesn't have to support shared roots like `keys` does.
     fn vals(&self) -> &[V] {
         self.reborrow().into_val_slice()
     }
@@ -514,6 +515,7 @@
     }
 
     /// The caller must ensure that the node is not the shared root.
+    /// This function is not public, so doesn't have to support shared roots like `keys` does.
     fn keys_mut(&mut self) -> &mut [K] {
         unsafe { self.reborrow_mut().into_key_slice_mut() }
     }
@@ -589,20 +591,15 @@
         unsafe { &mut *(self.root as *mut Root<K, V>) }
     }
 
+    /// The caller must ensure that the node is not the shared root.
     fn into_key_slice_mut(mut self) -> &'a mut [K] {
-        // Same as for `into_key_slice` above, we try to avoid a run-time check.
-        if (mem::align_of::<NodeHeader<K, V, K>>() > mem::align_of::<NodeHeader<K, V>>()
-            || mem::size_of::<NodeHeader<K, V, K>>() != mem::size_of::<NodeHeader<K, V>>())
-            && self.is_shared_root()
-        {
-            &mut []
-        } else {
-            unsafe {
-                slice::from_raw_parts_mut(
-                    MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
-                    self.len(),
-                )
-            }
+        debug_assert!(!self.is_shared_root());
+        // We cannot be the shared root, so `as_leaf_mut` is okay.
+        unsafe {
+            slice::from_raw_parts_mut(
+                MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
+                self.len(),
+            )
         }
     }
 
diff --git a/src/liballoc/collections/btree/search.rs b/src/liballoc/collections/btree/search.rs
index 3f3c49a..48cbf67 100644
--- a/src/liballoc/collections/btree/search.rs
+++ b/src/liballoc/collections/btree/search.rs
@@ -46,6 +46,11 @@
     }
 }
 
+/// Returns the index in the node at which the key (or an equivalent) exists
+/// or could exist, and whether it exists in the node itself. If it doesn't
+/// exist in the node itself, it may exist in the subtree with that index
+/// (if the node has subtrees). If the key doesn't exist in node or subtree,
+/// the returned index is the position or subtree to insert at.
 pub fn search_linear<BorrowType, K, V, Type, Q: ?Sized>(
     node: &NodeRef<BorrowType, K, V, Type>,
     key: &Q,
@@ -54,6 +59,12 @@
     Q: Ord,
     K: Borrow<Q>,
 {
+    // This function is defined over all borrow types (immutable, mutable, owned),
+    // and may be called on the shared root in each case.
+    // Crucially, we use `keys()` here, i.e., we work with immutable data.
+    // `keys_mut()` does not support the shared root, so we cannot use it.
+    // Using `keys()` is fine here even if BorrowType is mutable, as all we return
+    // is an index -- not a reference.
     for (i, k) in node.keys().iter().enumerate() {
         match key.cmp(k.borrow()) {
             Ordering::Greater => {}
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index a27a138..e9cbf62 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1054,7 +1054,7 @@
     ///
     /// ```
     /// let mut vec = vec![1, 2, 3, 4];
-    /// vec.retain(|&x| x%2 == 0);
+    /// vec.retain(|&x| x % 2 == 0);
     /// assert_eq!(vec, [2, 4]);
     /// ```
     ///
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index b2d4b1b..4354e1c 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -17,7 +17,7 @@
 #[derive(Debug)]
 pub struct Excess(pub NonNull<u8>, pub usize);
 
-fn size_align<T>() -> (usize, usize) {
+const fn size_align<T>() -> (usize, usize) {
     (mem::size_of::<T>(), mem::align_of::<T>())
 }
 
@@ -64,8 +64,9 @@
     ///    must not overflow (i.e., the rounded value must be less than
     ///    `usize::MAX`).
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
+    pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
         if !align.is_power_of_two() {
             return Err(LayoutErr { private: () });
         }
@@ -106,28 +107,30 @@
 
     /// The minimum size in bytes for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn size(&self) -> usize {
+    pub const fn size(&self) -> usize {
         self.size_
     }
 
     /// The minimum byte alignment for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn align(&self) -> usize {
+    pub const fn align(&self) -> usize {
         self.align_.get()
     }
 
     /// Constructs a `Layout` suitable for holding a value of type `T`.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
     #[inline]
-    pub fn new<T>() -> Self {
+    pub const fn new<T>() -> Self {
         let (size, align) = size_align::<T>();
         // Note that the align is guaranteed by rustc to be a power of two and
         // the size+align combo is guaranteed to fit in our address space. As a
         // result use the unchecked constructor here to avoid inserting code
         // that panics if it isn't optimized well enough.
-        debug_assert!(Layout::from_size_align(size, align).is_ok());
         unsafe { Layout::from_size_align_unchecked(size, align) }
     }
 
@@ -181,8 +184,9 @@
     /// address for the whole allocated block of memory. One way to
     /// satisfy this constraint is to ensure `align <= self.align()`.
     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn padding_needed_for(&self, align: usize) -> usize {
+    pub const fn padding_needed_for(&self, align: usize) -> usize {
         let len = self.size();
 
         // Rounded up value is:
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 06e7e45..3ea4baa 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -821,10 +821,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lt(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Less) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Less))
     }
 
     /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
@@ -843,10 +840,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn le(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Less) | Some(Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Less) | Some(Equal))
     }
 
     /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
@@ -864,10 +858,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn gt(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Greater) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Greater))
     }
 
     /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
@@ -886,10 +877,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn ge(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Greater) | Some(Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Greater) | Some(Equal))
     }
 }
 
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index c958289..21a5698 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -2968,10 +2968,7 @@
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        match self.partial_cmp(other) {
-            Some(Ordering::Less) | Some(Ordering::Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Ordering::Less) | Some(Ordering::Equal))
     }
 
     /// Determines if the elements of this `Iterator` are lexicographically
@@ -3011,10 +3008,7 @@
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        match self.partial_cmp(other) {
-            Some(Ordering::Greater) | Some(Ordering::Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Ordering::Greater) | Some(Ordering::Equal))
     }
 
     /// Checks if the elements of this iterator are sorted.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 6f1d698..95ffe4f 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -70,7 +70,7 @@
 #![feature(bound_cloned)]
 #![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
-#![feature(const_fn)]
+#![feature(const_alloc_layout)]
 #![feature(const_if_match)]
 #![feature(const_panic)]
 #![feature(const_fn_union)]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index b6b4a46..072966a 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1416,6 +1416,7 @@
 ```"),
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow(unused_attributes)]
             #[allow_internal_unstable(const_if_match)]
             #[inline]
             pub const fn wrapping_abs(self) -> Self {
@@ -1709,6 +1710,7 @@
             #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow(unused_attributes)]
             #[allow_internal_unstable(const_if_match)]
             pub const fn overflowing_neg(self) -> (Self, bool) {
                 if self == Self::min_value() {
@@ -1997,6 +1999,7 @@
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow(unused_attributes)]
             #[allow_internal_unstable(const_if_match)]
             #[inline]
             #[rustc_inherit_overflow_checks]
@@ -4283,10 +4286,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_alphabetic(&self) -> bool {
-        match *self {
-            b'A'..=b'Z' | b'a'..=b'z' => true,
-            _ => false,
-        }
+        matches!(*self, b'A'..=b'Z' | b'a'..=b'z')
     }
 
     /// Checks if the value is an ASCII uppercase character:
@@ -4318,10 +4318,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_uppercase(&self) -> bool {
-        match *self {
-            b'A'..=b'Z' => true,
-            _ => false,
-        }
+        matches!(*self, b'A'..=b'Z')
     }
 
     /// Checks if the value is an ASCII lowercase character:
@@ -4353,10 +4350,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_lowercase(&self) -> bool {
-        match *self {
-            b'a'..=b'z' => true,
-            _ => false,
-        }
+        matches!(*self, b'a'..=b'z')
     }
 
     /// Checks if the value is an ASCII alphanumeric character:
@@ -4391,10 +4385,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_alphanumeric(&self) -> bool {
-        match *self {
-            b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' => true,
-            _ => false,
-        }
+        matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z')
     }
 
     /// Checks if the value is an ASCII decimal digit:
@@ -4426,10 +4417,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_digit(&self) -> bool {
-        match *self {
-            b'0'..=b'9' => true,
-            _ => false,
-        }
+        matches!(*self, b'0'..=b'9')
     }
 
     /// Checks if the value is an ASCII hexadecimal digit:
@@ -4464,10 +4452,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_hexdigit(&self) -> bool {
-        match *self {
-            b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f' => true,
-            _ => false,
-        }
+        matches!(*self, b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f')
     }
 
     /// Checks if the value is an ASCII punctuation character:
@@ -4503,10 +4488,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_punctuation(&self) -> bool {
-        match *self {
-            b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~' => true,
-            _ => false,
-        }
+        matches!(*self, b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~')
     }
 
     /// Checks if the value is an ASCII graphic character:
@@ -4538,10 +4520,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_graphic(&self) -> bool {
-        match *self {
-            b'!'..=b'~' => true,
-            _ => false,
-        }
+        matches!(*self, b'!'..=b'~')
     }
 
     /// Checks if the value is an ASCII whitespace character:
@@ -4590,10 +4569,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_whitespace(&self) -> bool {
-        match *self {
-            b'\t' | b'\n' | b'\x0C' | b'\r' | b' ' => true,
-            _ => false,
-        }
+        matches!(*self, b'\t' | b'\n' | b'\x0C' | b'\r' | b' ')
     }
 
     /// Checks if the value is an ASCII control character:
@@ -4627,10 +4603,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_control(&self) -> bool {
-        match *self {
-            b'\0'..=b'\x1F' | b'\x7F' => true,
-            _ => false,
-        }
+        matches!(*self, b'\0'..=b'\x1F' | b'\x7F')
     }
 }
 
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 2066a48..a471b17 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -187,10 +187,7 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_some(&self) -> bool {
-        match *self {
-            Some(_) => true,
-            None => false,
-        }
+        matches!(*self, Some(_))
     }
 
     /// Returns `true` if the option is a [`None`] value.
@@ -341,6 +338,7 @@
     /// x.expect("the world is ending"); // panics with `the world is ending`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn expect(self, msg: &str) -> T {
         match self {
@@ -374,6 +372,7 @@
     /// assert_eq!(x.unwrap(), "air"); // fails
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap(self) -> T {
         match self {
@@ -1015,6 +1014,7 @@
     /// }
     /// ```
     #[inline]
+    #[track_caller]
     #[unstable(feature = "option_expect_none", reason = "newly added", issue = "62633")]
     pub fn expect_none(self, msg: &str) {
         if let Some(val) = self {
@@ -1057,6 +1057,7 @@
     /// }
     /// ```
     #[inline]
+    #[track_caller]
     #[unstable(feature = "option_unwrap_none", reason = "newly added", issue = "62633")]
     pub fn unwrap_none(self) {
         if let Some(val) = self {
@@ -1184,6 +1185,7 @@
 // This is a separate function to reduce the code size of .expect() itself.
 #[inline(never)]
 #[cold]
+#[track_caller]
 fn expect_failed(msg: &str) -> ! {
     panic!("{}", msg)
 }
@@ -1191,6 +1193,7 @@
 // This is a separate function to reduce the code size of .expect_none() itself.
 #[inline(never)]
 #[cold]
+#[track_caller]
 fn expect_none_failed(msg: &str, value: &dyn fmt::Debug) -> ! {
     panic!("{}: {:?}", msg, value)
 }
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index aca6fb2..676d2c7 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -672,6 +672,7 @@
     #[stable(feature = "pin", since = "1.33.0")]
     pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U>
     where
+        U: ?Sized,
         F: FnOnce(&T) -> &U,
     {
         let pointer = &*self.pointer;
@@ -763,6 +764,7 @@
     #[stable(feature = "pin", since = "1.33.0")]
     pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U>
     where
+        U: ?Sized,
         F: FnOnce(&mut T) -> &mut U,
     {
         let pointer = Pin::get_unchecked_mut(self);
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
index b3bb2f1..4bc0a3e 100644
--- a/src/libcore/ptr/mut_ptr.rs
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -250,6 +250,20 @@
     /// *first_value = 4;
     /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
     /// ```
+    ///
+    /// # Null-unchecked version
+    ///
+    /// If you are sure the pointer can never be null and are looking for some kind of
+    /// `as_mut_unchecked` that returns the `&mut T` instead of `Option<&mut T>`, know that
+    /// you can dereference the pointer directly.
+    ///
+    /// ```
+    /// let mut s = [1, 2, 3];
+    /// let ptr: *mut u32 = s.as_mut_ptr();
+    /// let first_value = unsafe { &mut *ptr };
+    /// *first_value = 4;
+    /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
+    /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 5cfc810..c657ce3 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -282,10 +282,7 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn is_ok(&self) -> bool {
-        match *self {
-            Ok(_) => true,
-            Err(_) => false,
-        }
+        matches!(*self, Ok(_))
     }
 
     /// Returns `true` if the result is [`Err`].
@@ -957,6 +954,7 @@
     /// x.unwrap(); // panics with `emergency failure`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap(self) -> T {
         match self {
@@ -984,6 +982,7 @@
     /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "result_expect", since = "1.4.0")]
     pub fn expect(self, msg: &str) -> T {
         match self {
@@ -1017,6 +1016,7 @@
     /// assert_eq!(x.unwrap_err(), "emergency failure");
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_err(self) -> E {
         match self {
@@ -1044,6 +1044,7 @@
     /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "result_expect_err", since = "1.17.0")]
     pub fn expect_err(self, msg: &str) -> E {
         match self {
@@ -1091,13 +1092,51 @@
     }
 }
 
+#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
+impl<T, E: Into<!>> Result<T, E> {
+    /// Unwraps a result that can never be an [`Err`], yielding the content of the [`Ok`].
+    ///
+    /// Unlike [`unwrap`], this method is known to never panic on the
+    /// result types it is implemented for. Therefore, it can be used
+    /// instead of `unwrap` as a maintainability safeguard that will fail
+    /// to compile if the error type of the `Result` is later changed
+    /// to an error that can actually occur.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    /// [`unwrap`]: enum.Result.html#method.unwrap
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// # #![feature(never_type)]
+    /// # #![feature(unwrap_infallible)]
+    ///
+    /// fn only_good_news() -> Result<String, !> {
+    ///     Ok("this is fine".into())
+    /// }
+    ///
+    /// let s: String = only_good_news().into_ok();
+    /// println!("{}", s);
+    /// ```
+    #[inline]
+    pub fn into_ok(self) -> T {
+        match self {
+            Ok(x) => x,
+            Err(e) => e.into(),
+        }
+    }
+}
+
 #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
 impl<T: Deref, E> Result<T, E> {
     /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E>`.
     ///
     /// Leaves the original `Result` in-place, creating a new one containing a reference to the
     /// `Ok` type's `Deref::Target` type.
-    pub fn as_deref_ok(&self) -> Result<&T::Target, &E> {
+    pub fn as_deref(&self) -> Result<&T::Target, &E> {
         self.as_ref().map(|t| t.deref())
     }
 }
@@ -1114,23 +1153,12 @@
 }
 
 #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-impl<T: Deref, E: Deref> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E::Target>`.
-    ///
-    /// Leaves the original `Result` in-place, creating a new one containing a reference to both
-    /// the `Ok` and `Err` types' `Deref::Target` types.
-    pub fn as_deref(&self) -> Result<&T::Target, &E::Target> {
-        self.as_ref().map(|t| t.deref()).map_err(|e| e.deref())
-    }
-}
-
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
 impl<T: DerefMut, E> Result<T, E> {
     /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T::Target, &mut E>`.
     ///
     /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
     /// the `Ok` type's `Deref::Target` type.
-    pub fn as_deref_mut_ok(&mut self) -> Result<&mut T::Target, &mut E> {
+    pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {
         self.as_mut().map(|t| t.deref_mut())
     }
 }
@@ -1146,18 +1174,6 @@
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-impl<T: DerefMut, E: DerefMut> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to
-    /// `Result<&mut T::Target, &mut E::Target>`.
-    ///
-    /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
-    /// both the `Ok` and `Err` types' `Deref::Target` types.
-    pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target> {
-        self.as_mut().map(|t| t.deref_mut()).map_err(|e| e.deref_mut())
-    }
-}
-
 impl<T, E> Result<Option<T>, E> {
     /// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
     ///
@@ -1188,6 +1204,7 @@
 // This is a separate function to reduce the code size of the methods
 #[inline(never)]
 #[cold]
+#[track_caller]
 fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! {
     panic!("{}: {:?}", msg, error)
 }
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index 2cbdeb2..46d9499 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -46,10 +46,7 @@
     /// Checks whether the pattern matches at the front of the haystack
     #[inline]
     fn is_prefix_of(self, haystack: &'a str) -> bool {
-        match self.into_searcher(haystack).next() {
-            SearchStep::Match(0, _) => true,
-            _ => false,
-        }
+        matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _))
     }
 
     /// Checks whether the pattern matches at the back of the haystack
@@ -58,10 +55,7 @@
     where
         Self::Searcher: ReverseSearcher<'a>,
     {
-        match self.into_searcher(haystack).next_back() {
-            SearchStep::Match(_, j) if haystack.len() == j => true,
-            _ => false,
-        }
+        matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
     }
 }
 
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index a2352c0..fae95ca 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -134,16 +134,10 @@
 /// This function is different from [`std::thread::yield_now`] which directly yields to the
 /// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system.
 ///
-/// Spin locks can be very efficient for short lock durations because they do not involve context
-/// switches or interaction with the operating system. For long lock durations they become wasteful
-/// however because they use CPU cycles for the entire lock duration, and using a
-/// [`std::sync::Mutex`] is likely the better approach. If actively spinning for a long time is
-/// required, e.g. because code polls a non-blocking API, calling [`std::thread::yield_now`]
-/// or [`std::thread::sleep`] may be the best option.
-///
-/// **Note**: Spin locks are based on the underlying assumption that another thread will release
-/// the lock 'soon'. In order for this to work, that other thread must run on a different CPU or
-/// core (at least potentially). Spin locks do not work efficiently on single CPU / core platforms.
+/// A common use case for `spin_loop_hint` is implementing bounded optimistic spinning in a CAS
+/// loop in synchronization primitives. To avoid problems like priority inversion, it is strongly
+/// recommended that the spin loop is terminated after a finite amount of iterations and an
+/// appropriate blocking syscall is made.
 ///
 /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
 /// do anything at all.
diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs
index d567ae5..b3a4bd2 100644
--- a/src/libcore/task/poll.rs
+++ b/src/libcore/task/poll.rs
@@ -39,10 +39,7 @@
     #[inline]
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn is_ready(&self) -> bool {
-        match *self {
-            Poll::Ready(_) => true,
-            Poll::Pending => false,
-        }
+        matches!(*self, Poll::Ready(_))
     }
 
     /// Returns `true` if this is `Poll::Pending`
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 39f6133..86cf6fc 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -31,7 +31,6 @@
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
 #![feature(int_error_matching)]
-#![feature(const_fn)]
 #![feature(array_value_iter)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_is_partitioned)]
@@ -40,6 +39,8 @@
 #![feature(slice_from_raw_parts)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_raw_ptr_deref)]
+#![feature(never_type)]
+#![feature(unwrap_infallible)]
 
 extern crate test;
 
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index 499a561..c835313 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -184,6 +184,28 @@
 }
 
 #[test]
+pub fn test_into_ok() {
+    fn infallible_op() -> Result<isize, !> {
+        Ok(666)
+    }
+
+    assert_eq!(infallible_op().into_ok(), 666);
+
+    enum MyNeverToken {}
+    impl From<MyNeverToken> for ! {
+        fn from(never: MyNeverToken) -> ! {
+            match never {}
+        }
+    }
+
+    fn infallible_op2() -> Result<isize, MyNeverToken> {
+        Ok(667)
+    }
+
+    assert_eq!(infallible_op2().into_ok(), 667);
+}
+
+#[test]
 fn test_try() {
     fn try_result_some() -> Option<u8> {
         let val = Ok(1)?;
@@ -214,32 +236,18 @@
 
 #[test]
 fn test_result_as_deref() {
-    // &Result<T: Deref, E>::Ok(T).as_deref_ok() ->
+    // &Result<T: Deref, E>::Ok(T).as_deref() ->
     //      Result<&T::Deref::Target, &E>::Ok(&*T)
     let ref_ok = &Result::Ok::<&i32, u8>(&42);
     let expected_result = Result::Ok::<&i32, &u8>(&42);
-    assert_eq!(ref_ok.as_deref_ok(), expected_result);
+    assert_eq!(ref_ok.as_deref(), expected_result);
 
     let ref_ok = &Result::Ok::<String, u32>(String::from("a result"));
     let expected_result = Result::Ok::<&str, &u32>("a result");
-    assert_eq!(ref_ok.as_deref_ok(), expected_result);
+    assert_eq!(ref_ok.as_deref(), expected_result);
 
     let ref_ok = &Result::Ok::<Vec<i32>, u32>(vec![1, 2, 3, 4, 5]);
     let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
-    assert_eq!(ref_ok.as_deref_ok(), expected_result);
-
-    // &Result<T: Deref, E: Deref>::Ok(T).as_deref() ->
-    //      Result<&T::Deref::Target, &E::Deref::Target>::Ok(&*T)
-    let ref_ok = &Result::Ok::<&i32, &u8>(&42);
-    let expected_result = Result::Ok::<&i32, &u8>(&42);
-    assert_eq!(ref_ok.as_deref(), expected_result);
-
-    let ref_ok = &Result::Ok::<String, &u32>(String::from("a result"));
-    let expected_result = Result::Ok::<&str, &u32>("a result");
-    assert_eq!(ref_ok.as_deref(), expected_result);
-
-    let ref_ok = &Result::Ok::<Vec<i32>, &u32>(vec![1, 2, 3, 4, 5]);
-    let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
     assert_eq!(ref_ok.as_deref(), expected_result);
 
     // &Result<T, E: Deref>::Err(T).as_deref_err() ->
@@ -259,19 +267,21 @@
     // &Result<T: Deref, E: Deref>::Err(T).as_deref_err() ->
     //      Result<&T, &E::Deref::Target>::Err(&*E)
     let ref_err = &Result::Err::<&u8, &i32>(&41);
-    let expected_result = Result::Err::<&u8, &i32>(&41);
+    let expected_result = Result::Err::<&u8, &&i32>(&&41);
     assert_eq!(ref_err.as_deref(), expected_result);
 
-    let ref_err = &Result::Err::<&u32, String>(String::from("an error"));
-    let expected_result = Result::Err::<&u32, &str>("an error");
+    let s = String::from("an error");
+    let ref_err = &Result::Err::<&u32, String>(s.clone());
+    let expected_result = Result::Err::<&u32, &String>(&s);
     assert_eq!(ref_err.as_deref(), expected_result);
 
-    let ref_err = &Result::Err::<&u32, Vec<i32>>(vec![5, 4, 3, 2, 1]);
-    let expected_result = Result::Err::<&u32, &[i32]>([5, 4, 3, 2, 1].as_slice());
+    let v = vec![5, 4, 3, 2, 1];
+    let ref_err = &Result::Err::<&u32, Vec<i32>>(v.clone());
+    let expected_result = Result::Err::<&u32, &Vec<i32>>(&v);
     assert_eq!(ref_err.as_deref(), expected_result);
 
     // The following cases test calling `as_deref_*` with the wrong variant (i.e.
-    // `as_deref_ok()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`.
+    // `as_deref()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`.
     // While uncommon, these cases are supported to ensure that an `as_deref_*`
     // call can still be made even when one of the Result types does not implement
     // `Deref` (for example, std::io::Error).
@@ -290,57 +300,39 @@
     let expected_result = Result::Ok::<&[i32; 5], &u32>(&[1, 2, 3, 4, 5]);
     assert_eq!(ref_ok.as_deref_err(), expected_result);
 
-    // &Result<T: Deref, E>::Err(E).as_deref_ok() ->
+    // &Result<T: Deref, E>::Err(E).as_deref() ->
     //      Result<&T::Deref::Target, &E>::Err(&E)
     let ref_err = &Result::Err::<&u8, i32>(41);
     let expected_result = Result::Err::<&u8, &i32>(&41);
-    assert_eq!(ref_err.as_deref_ok(), expected_result);
+    assert_eq!(ref_err.as_deref(), expected_result);
 
     let ref_err = &Result::Err::<&u32, &str>("an error");
     let expected_result = Result::Err::<&u32, &&str>(&"an error");
-    assert_eq!(ref_err.as_deref_ok(), expected_result);
+    assert_eq!(ref_err.as_deref(), expected_result);
 
     let ref_err = &Result::Err::<&u32, [i32; 5]>([5, 4, 3, 2, 1]);
     let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]);
-    assert_eq!(ref_err.as_deref_ok(), expected_result);
+    assert_eq!(ref_err.as_deref(), expected_result);
 }
 
 #[test]
 fn test_result_as_deref_mut() {
-    // &mut Result<T: Deref, E>::Ok(T).as_deref_mut_ok() ->
+    // &mut Result<T: Deref, E>::Ok(T).as_deref_mut() ->
     //      Result<&mut T::Deref::Target, &mut E>::Ok(&mut *T)
     let mut val = 42;
     let mut expected_val = 42;
     let mut_ok = &mut Result::Ok::<&mut i32, u8>(&mut val);
     let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
-    assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_ok.as_deref_mut(), expected_result);
 
     let mut expected_string = String::from("a result");
     let mut_ok = &mut Result::Ok::<String, u32>(expected_string.clone());
     let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut());
-    assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_ok.as_deref_mut(), expected_result);
 
     let mut expected_vec = vec![1, 2, 3, 4, 5];
     let mut_ok = &mut Result::Ok::<Vec<i32>, u32>(expected_vec.clone());
     let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
-    assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
-
-    // &mut Result<T: Deref, E: Deref>::Ok(T).as_deref_mut() ->
-    //      Result<&mut T::Deref::Target, &mut E::Deref::Target>::Ok(&mut *T)
-    let mut val = 42;
-    let mut expected_val = 42;
-    let mut_ok = &mut Result::Ok::<&mut i32, &mut u8>(&mut val);
-    let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
-    assert_eq!(mut_ok.as_deref_mut(), expected_result);
-
-    let mut expected_string = String::from("a result");
-    let mut_ok = &mut Result::Ok::<String, &mut u32>(expected_string.clone());
-    let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut());
-    assert_eq!(mut_ok.as_deref_mut(), expected_result);
-
-    let mut expected_vec = vec![1, 2, 3, 4, 5];
-    let mut_ok = &mut Result::Ok::<Vec<i32>, &mut u32>(expected_vec.clone());
-    let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
     assert_eq!(mut_ok.as_deref_mut(), expected_result);
 
     // &mut Result<T, E: Deref>::Err(T).as_deref_mut_err() ->
@@ -364,23 +356,22 @@
     // &mut Result<T: Deref, E: Deref>::Err(T).as_deref_mut_err() ->
     //      Result<&mut T, &mut E::Deref::Target>::Err(&mut *E)
     let mut val = 41;
-    let mut expected_val = 41;
-    let mut_err = &mut Result::Err::<&mut u8, &mut i32>(&mut val);
-    let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
+    let mut_err = &mut Result::Err::<&mut u8, i32>(val);
+    let expected_result = Result::Err::<&mut u8, &mut i32>(&mut val);
     assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let mut expected_string = String::from("an error");
     let mut_err = &mut Result::Err::<&mut u32, String>(expected_string.clone());
-    let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.as_mut_str());
+    let expected_result = Result::Err::<&mut u32, &mut String>(&mut expected_string);
     assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let mut expected_vec = vec![5, 4, 3, 2, 1];
     let mut_err = &mut Result::Err::<&mut u32, Vec<i32>>(expected_vec.clone());
-    let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice());
+    let expected_result = Result::Err::<&mut u32, &mut Vec<i32>>(&mut expected_vec);
     assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     // The following cases test calling `as_deref_mut_*` with the wrong variant (i.e.
-    // `as_deref_mut_ok()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`.
+    // `as_deref_mut()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`.
     // While uncommon, these cases are supported to ensure that an `as_deref_mut_*`
     // call can still be made even when one of the Result types does not implement
     // `Deref` (for example, std::io::Error).
@@ -404,22 +395,22 @@
     let expected_result = Result::Ok::<&mut [i32; 5], &mut u32>(&mut expected_arr);
     assert_eq!(mut_ok.as_deref_mut_err(), expected_result);
 
-    // &mut Result<T: Deref, E>::Err(E).as_deref_mut_ok() ->
+    // &mut Result<T: Deref, E>::Err(E).as_deref_mut() ->
     //      Result<&mut T::Deref::Target, &mut E>::Err(&mut E)
     let mut expected_val = 41;
     let mut_err = &mut Result::Err::<&mut u8, i32>(expected_val.clone());
     let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
-    assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let string = String::from("an error");
     let expected_string = string.clone();
     let mut ref_str = expected_string.as_ref();
     let mut_err = &mut Result::Err::<&mut u32, &str>(string.as_str());
     let expected_result = Result::Err::<&mut u32, &mut &str>(&mut ref_str);
-    assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let mut expected_arr = [5, 4, 3, 2, 1];
     let mut_err = &mut Result::Err::<&mut u32, [i32; 5]>(expected_arr.clone());
     let expected_result = Result::Err::<&mut u32, &mut [i32; 5]>(&mut expected_arr);
-    assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_err.as_deref_mut(), expected_result);
 }
diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs
index 2098404..9d3fe52 100644
--- a/src/libpanic_unwind/emcc.rs
+++ b/src/libpanic_unwind/emcc.rs
@@ -63,7 +63,7 @@
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     let sz = mem::size_of_val(&data);
     let exception = __cxa_allocate_exception(sz);
-    if exception == ptr::null_mut() {
+    if exception.is_null() {
         return uw::_URC_FATAL_PHASE1_ERROR as u32;
     }
     ptr::write(exception as *mut _, data);
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index e612a63..6a48fa0 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -130,6 +130,9 @@
 #[cfg(target_arch = "hexagon")]
 const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
 
+#[cfg(target_arch = "riscv64")]
+const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
+
 // The following code is based on GCC's C and C++ personality routines.  For reference, see:
 // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 0b74a10..c51db69 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -21,7 +21,6 @@
 #![feature(nll)]
 #![feature(staged_api)]
 #![feature(allow_internal_unstable)]
-#![feature(const_fn)]
 #![feature(decl_macro)]
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs
index 04cd2ef..8adcff6 100644
--- a/src/libprofiler_builtins/build.rs
+++ b/src/libprofiler_builtins/build.rs
@@ -21,7 +21,6 @@
         "InstrProfilingPlatformLinux.c",
         "InstrProfilingPlatformOther.c",
         "InstrProfilingPlatformWindows.c",
-        "InstrProfilingRuntime.cc",
         "InstrProfilingUtil.c",
         "InstrProfilingValue.c",
         "InstrProfilingWriter.c",
@@ -68,10 +67,17 @@
     let root = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
     let root = Path::new(&root);
 
+    let src_root = root.join("lib").join("profile");
     for src in profile_sources {
-        cfg.file(root.join("lib").join("profile").join(src));
+        cfg.file(src_root.join(src));
     }
 
+    // The file was renamed in LLVM 10.
+    let old_runtime_path = src_root.join("InstrProfilingRuntime.cc");
+    let new_runtime_path = src_root.join("InstrProfilingRuntime.cpp");
+    cfg.file(if old_runtime_path.exists() { old_runtime_path } else { new_runtime_path });
+
+    cfg.include(root.join("include"));
     cfg.warnings(false);
     cfg.compile("profiler-rt");
 }
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 2e882cf..323ce3b6 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -15,7 +15,6 @@
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
-num_cpus = "1.0"
 scoped-tls = "1.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 rustc-rayon = "0.3.0"
@@ -27,8 +26,8 @@
 rustc_target = { path = "../librustc_target" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_index = { path = "../librustc_index" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
@@ -36,8 +35,7 @@
 parking_lot = "0.9"
 byteorder = { version = "1.3" }
 chalk-engine = { version = "0.9.0", default-features=false }
-rustc_fs_util = { path = "../librustc_fs_util" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-measureme = "0.5"
+measureme = "0.7.1"
 rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index 1c7d36b..cb3fdff 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -38,13 +38,13 @@
             [] tables: rustc::ty::TypeckTables<$tcx>,
             [] const_allocs: rustc::mir::interpret::Allocation,
             [] vtable_method: Option<(
-                rustc::hir::def_id::DefId,
+                rustc_hir::def_id::DefId,
                 rustc::ty::subst::SubstsRef<$tcx>
             )>,
-            [few, decode] mir_keys: rustc::hir::def_id::DefIdSet,
+            [few, decode] mir_keys: rustc_hir::def_id::DefIdSet,
             [decode] specialization_graph: rustc::traits::specialization_graph::Graph,
             [] region_scope_tree: rustc::middle::region::ScopeTree,
-            [] item_local_set: rustc::hir::ItemLocalSet,
+            [] item_local_set: rustc_hir::ItemLocalSet,
             [decode] mir_const_qualif: rustc_index::bit_set::BitSet<rustc::mir::Local>,
             [] trait_impls_of: rustc::ty::trait_def::TraitImpls,
             [] dropck_outlives:
@@ -87,75 +87,75 @@
                 >,
             [few] crate_inherent_impls: rustc::ty::CrateInherentImpls,
             [few] upstream_monomorphizations:
-                rustc::hir::def_id::DefIdMap<
+                rustc_hir::def_id::DefIdMap<
                     rustc_data_structures::fx::FxHashMap<
                         rustc::ty::subst::SubstsRef<'tcx>,
-                        rustc::hir::def_id::CrateNum
+                        rustc_hir::def_id::CrateNum
                     >
                 >,
             [few] diagnostic_items: rustc_data_structures::fx::FxHashMap<
                 rustc_span::symbol::Symbol,
-                rustc::hir::def_id::DefId,
+                rustc_hir::def_id::DefId,
             >,
             [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes,
             [few] lint_levels: rustc::lint::LintLevelMap,
             [few] stability_index: rustc::middle::stability::Index<'tcx>,
             [few] features: rustc_feature::Features,
-            [few] all_traits: Vec<rustc::hir::def_id::DefId>,
+            [few] all_traits: Vec<rustc_hir::def_id::DefId>,
             [few] privacy_access_levels: rustc::middle::privacy::AccessLevels,
             [few] target_features_whitelist: rustc_data_structures::fx::FxHashMap<
                 String,
                 Option<rustc_span::symbol::Symbol>
             >,
             [few] wasm_import_module_map: rustc_data_structures::fx::FxHashMap<
-                rustc::hir::def_id::DefId,
+                rustc_hir::def_id::DefId,
                 String
             >,
             [few] get_lib_features: rustc::middle::lib_features::LibFeatures,
             [few] defined_lib_features: rustc::middle::lang_items::LanguageItems,
-            [few] visible_parent_map: rustc::hir::def_id::DefIdMap<rustc::hir::def_id::DefId>,
+            [few] visible_parent_map: rustc_hir::def_id::DefIdMap<rustc_hir::def_id::DefId>,
             [few] foreign_module: rustc::middle::cstore::ForeignModule,
             [few] foreign_modules: Vec<rustc::middle::cstore::ForeignModule>,
-            [few] reachable_non_generics: rustc::hir::def_id::DefIdMap<
+            [few] reachable_non_generics: rustc_hir::def_id::DefIdMap<
                 rustc::middle::exported_symbols::SymbolExportLevel
             >,
             [few] crate_variances: rustc::ty::CrateVariancesMap<'tcx>,
             [few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
-            [] upvars: rustc_data_structures::fx::FxIndexMap<rustc::hir::HirId, rustc::hir::Upvar>,
+            [] upvars: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
 
             // HIR types
             [few] hir_forest: rustc::hir::map::Forest<$tcx>,
-            [] arm: rustc::hir::Arm<$tcx>,
+            [] arm: rustc_hir::Arm<$tcx>,
             [] attribute: syntax::ast::Attribute,
-            [] block: rustc::hir::Block<$tcx>,
-            [] bare_fn_ty: rustc::hir::BareFnTy<$tcx>,
-            [few] global_asm: rustc::hir::GlobalAsm,
-            [] generic_arg: rustc::hir::GenericArg<$tcx>,
-            [] generic_args: rustc::hir::GenericArgs<$tcx>,
-            [] generic_bound: rustc::hir::GenericBound<$tcx>,
-            [] generic_param: rustc::hir::GenericParam<$tcx>,
-            [] expr: rustc::hir::Expr<$tcx>,
-            [] field: rustc::hir::Field<$tcx>,
-            [] field_pat: rustc::hir::FieldPat<$tcx>,
-            [] fn_decl: rustc::hir::FnDecl<$tcx>,
-            [] foreign_item: rustc::hir::ForeignItem<$tcx>,
-            [] impl_item_ref: rustc::hir::ImplItemRef<$tcx>,
-            [] inline_asm: rustc::hir::InlineAsm<$tcx>,
-            [] local: rustc::hir::Local<$tcx>,
-            [few] macro_def: rustc::hir::MacroDef<$tcx>,
-            [] param: rustc::hir::Param<$tcx>,
-            [] pat: rustc::hir::Pat<$tcx>,
-            [] path: rustc::hir::Path<$tcx>,
-            [] path_segment: rustc::hir::PathSegment<$tcx>,
-            [] poly_trait_ref: rustc::hir::PolyTraitRef<$tcx>,
-            [] qpath: rustc::hir::QPath<$tcx>,
-            [] stmt: rustc::hir::Stmt<$tcx>,
-            [] struct_field: rustc::hir::StructField<$tcx>,
-            [] trait_item_ref: rustc::hir::TraitItemRef,
-            [] ty: rustc::hir::Ty<$tcx>,
-            [] type_binding: rustc::hir::TypeBinding<$tcx>,
-            [] variant: rustc::hir::Variant<$tcx>,
-            [] where_predicate: rustc::hir::WherePredicate<$tcx>,
+            [] block: rustc_hir::Block<$tcx>,
+            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
+            [few] global_asm: rustc_hir::GlobalAsm,
+            [] generic_arg: rustc_hir::GenericArg<$tcx>,
+            [] generic_args: rustc_hir::GenericArgs<$tcx>,
+            [] generic_bound: rustc_hir::GenericBound<$tcx>,
+            [] generic_param: rustc_hir::GenericParam<$tcx>,
+            [] expr: rustc_hir::Expr<$tcx>,
+            [] field: rustc_hir::Field<$tcx>,
+            [] field_pat: rustc_hir::FieldPat<$tcx>,
+            [] fn_decl: rustc_hir::FnDecl<$tcx>,
+            [] foreign_item: rustc_hir::ForeignItem<$tcx>,
+            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+            [] inline_asm: rustc_hir::InlineAsm<$tcx>,
+            [] local: rustc_hir::Local<$tcx>,
+            [few] macro_def: rustc_hir::MacroDef<$tcx>,
+            [] param: rustc_hir::Param<$tcx>,
+            [] pat: rustc_hir::Pat<$tcx>,
+            [] path: rustc_hir::Path<$tcx>,
+            [] path_segment: rustc_hir::PathSegment<$tcx>,
+            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
+            [] qpath: rustc_hir::QPath<$tcx>,
+            [] stmt: rustc_hir::Stmt<$tcx>,
+            [] struct_field: rustc_hir::StructField<$tcx>,
+            [] trait_item_ref: rustc_hir::TraitItemRef,
+            [] ty: rustc_hir::Ty<$tcx>,
+            [] type_binding: rustc_hir::TypeBinding<$tcx>,
+            [] variant: rustc_hir::Variant<$tcx>,
+            [] where_predicate: rustc_hir::WherePredicate<$tcx>,
         ], $tcx);
     )
 }
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 0dae5d0..858627a 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -49,13 +49,10 @@
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
-use crate::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use crate::hir::map::DefPathHash;
-use crate::hir::HirId;
+use crate::ich::{Fingerprint, StableHashingContext};
 use crate::mir;
 use crate::mir::interpret::GlobalId;
-
-use crate::ich::{Fingerprint, StableHashingContext};
 use crate::traits;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
@@ -64,7 +61,10 @@
 };
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
+
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::HirId;
 use rustc_span::symbol::Symbol;
 use std::fmt;
 use std::hash::Hash;
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 0d03c83..8d1efc7 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -1,17 +1,18 @@
 use crate::ty::{self, TyCtxt};
-use errors::Diagnostic;
 use parking_lot::{Condvar, Mutex};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::profiling::QueryInvocationId;
 use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
+use rustc_errors::Diagnostic;
 use rustc_index::vec::{Idx, IndexVec};
 use smallvec::SmallVec;
 use std::collections::hash_map::Entry;
 use std::env;
 use std::hash::Hash;
 use std::mem;
-use std::sync::atomic::Ordering::SeqCst;
+use std::sync::atomic::Ordering::Relaxed;
 
 use crate::ich::{Fingerprint, StableHashingContext, StableHashingContextProvider};
 
@@ -25,6 +26,12 @@
 #[derive(Clone)]
 pub struct DepGraph {
     data: Option<Lrc<DepGraphData>>,
+
+    /// This field is used for assigning DepNodeIndices when running in
+    /// non-incremental mode. Even in non-incremental mode we make sure that
+    /// each task has a `DepNodeIndex` that uniquely identifies it. This unique
+    /// ID is used for self-profiling.
+    virtual_dep_node_index: Lrc<AtomicU32>,
 }
 
 rustc_index::newtype_index! {
@@ -35,6 +42,13 @@
     pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
 }
 
+impl std::convert::From<DepNodeIndex> for QueryInvocationId {
+    #[inline]
+    fn from(dep_node_index: DepNodeIndex) -> Self {
+        QueryInvocationId(dep_node_index.as_u32())
+    }
+}
+
 #[derive(PartialEq)]
 pub enum DepNodeColor {
     Red,
@@ -105,11 +119,12 @@
                 previous: prev_graph,
                 colors: DepNodeColorMap::new(prev_graph_node_count),
             })),
+            virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
         }
     }
 
     pub fn new_disabled() -> DepGraph {
-        DepGraph { data: None }
+        DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) }
     }
 
     /// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
@@ -322,7 +337,7 @@
 
             (result, dep_node_index)
         } else {
-            (task(cx, arg), DepNodeIndex::INVALID)
+            (task(cx, arg), self.next_virtual_depnode_index())
         }
     }
 
@@ -352,7 +367,7 @@
             let dep_node_index = data.current.complete_anon_task(dep_kind, task_deps);
             (result, dep_node_index)
         } else {
-            (op(), DepNodeIndex::INVALID)
+            (op(), self.next_virtual_depnode_index())
         }
     }
 
@@ -478,8 +493,8 @@
             let current_dep_graph = &self.data.as_ref().unwrap().current;
 
             Some((
-                current_dep_graph.total_read_count.load(SeqCst),
-                current_dep_graph.total_duplicate_read_count.load(SeqCst),
+                current_dep_graph.total_read_count.load(Relaxed),
+                current_dep_graph.total_duplicate_read_count.load(Relaxed),
             ))
         } else {
             None
@@ -877,6 +892,11 @@
             }
         }
     }
+
+    fn next_virtual_depnode_index(&self) -> DepNodeIndex {
+        let index = self.virtual_dep_node_index.fetch_add(1, Relaxed);
+        DepNodeIndex::from_u32(index)
+    }
 }
 
 /// A "work product" is an intermediate result that we save into the
@@ -1087,7 +1107,7 @@
             if let Some(task_deps) = icx.task_deps {
                 let mut task_deps = task_deps.lock();
                 if cfg!(debug_assertions) {
-                    self.current.total_read_count.fetch_add(1, SeqCst);
+                    self.current.total_read_count.fetch_add(1, Relaxed);
                 }
                 if task_deps.read_set.insert(source) {
                     task_deps.reads.push(source);
@@ -1105,7 +1125,7 @@
                         }
                     }
                 } else if cfg!(debug_assertions) {
-                    self.current.total_duplicate_read_count.fetch_add(1, SeqCst);
+                    self.current.total_duplicate_read_count.fetch_add(1, Relaxed);
                 }
             }
         })
diff --git a/src/librustc/dep_graph/safe.rs b/src/librustc/dep_graph/safe.rs
index 5395117..23aef0c 100644
--- a/src/librustc/dep_graph/safe.rs
+++ b/src/librustc/dep_graph/safe.rs
@@ -1,8 +1,9 @@
 //! The `DepGraphSafe` trait
 
-use crate::hir::def_id::DefId;
-use crate::hir::BodyId;
 use crate::ty::TyCtxt;
+
+use rustc_hir::def_id::DefId;
+use rustc_hir::BodyId;
 use syntax::ast::NodeId;
 
 /// The `DepGraphSafe` trait is used to specify what kinds of values
diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs
index 640877d..45ef52d 100644
--- a/src/librustc/dep_graph/serialized.rs
+++ b/src/librustc/dep_graph/serialized.rs
@@ -2,7 +2,7 @@
 
 use crate::dep_graph::DepNode;
 use crate::ich::Fingerprint;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 
 rustc_index::newtype_index! {
     pub struct SerializedDepNodeIndex { .. }
diff --git a/src/librustc/hir.rs b/src/librustc/hir.rs
deleted file mode 100644
index 62160fe..0000000
--- a/src/librustc/hir.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! HIR datatypes. See the [rustc guide] for more info.
-//!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
-
-pub mod check_attr;
-pub use rustc_hir::def;
-pub mod exports;
-pub use rustc_hir::def_id;
-pub use rustc_hir::hir_id::*;
-pub mod intravisit;
-pub use rustc_hir::itemlikevisit;
-pub mod map;
-pub use rustc_hir::pat_util;
-pub use rustc_hir::print;
-pub mod upvars;
-
-pub use rustc_hir::BlockCheckMode::*;
-pub use rustc_hir::FunctionRetTy::*;
-pub use rustc_hir::PrimTy::*;
-pub use rustc_hir::UnOp::*;
-pub use rustc_hir::UnsafeSource::*;
-pub use rustc_hir::*;
-
-use crate::ty::query::Providers;
-
-pub fn provide(providers: &mut Providers<'_>) {
-    check_attr::provide(providers);
-    map::provide(providers);
-    upvars::provide(providers);
-}
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 08d4163..5a99e79 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -4,15 +4,18 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-use crate::hir::def_id::DefId;
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use crate::hir::DUMMY_HIR_ID;
-use crate::hir::{self, HirId, Item, ItemKind, TraitItem, TraitItemKind};
-use crate::lint::builtin::UNUSED_ATTRIBUTES;
+use crate::hir::map::Map;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
 
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::DUMMY_HIR_ID;
+use rustc_hir::{self, HirId, Item, ItemKind, TraitItem, TraitItemKind};
+use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast::Attribute;
@@ -430,21 +433,27 @@
         // Error on repr(transparent, <anything else>).
         if is_transparent && hints.len() > 1 {
             let hint_spans: Vec<_> = hint_spans.clone().collect();
-            span_err!(
+            struct_span_err!(
                 self.tcx.sess,
                 hint_spans,
                 E0692,
                 "transparent {} cannot have other repr hints",
                 target
-            );
+            )
+            .emit();
         }
         // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
         if (int_reprs > 1)
             || (is_simd && is_c)
             || (int_reprs == 1 && is_c && item.map_or(false, |item| is_c_like_enum(item)))
         {
-            let hint_spans: Vec<_> = hint_spans.collect();
-            span_warn!(self.tcx.sess, hint_spans, E0566, "conflicting representation hints");
+            struct_span_err!(
+                self.tcx.sess,
+                hint_spans.collect::<Vec<Span>>(),
+                E0566,
+                "conflicting representation hints",
+            )
+            .emit();
         }
     }
 
@@ -511,7 +520,9 @@
 }
 
 impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc/hir/exports.rs b/src/librustc/hir/exports.rs
index a2e885f..db020e3 100644
--- a/src/librustc/hir/exports.rs
+++ b/src/librustc/hir/exports.rs
@@ -1,7 +1,7 @@
-use crate::hir::def::Res;
-use crate::hir::def_id::DefIdMap;
 use crate::ty;
 
+use rustc_hir::def::Res;
+use rustc_hir::def_id::DefIdMap;
 use rustc_macros::HashStable;
 use rustc_span::Span;
 use syntax::ast;
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 9546c10..016fc93 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -11,10 +11,10 @@
 //! nested within a uniquely determined `FnLike`), and users can ask
 //! for the `Code` associated with a particular NodeId.
 
-use crate::hir as ast;
-use crate::hir::intravisit::FnKind;
-use crate::hir::map;
-use crate::hir::{Expr, FnDecl, Node};
+use crate::hir::map::Map;
+use rustc_hir as hir;
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Expr, FnDecl, Node};
 use rustc_span::Span;
 use syntax::ast::{Attribute, Ident};
 
@@ -39,37 +39,37 @@
     fn is_fn_like(&self) -> bool;
 }
 
-impl MaybeFnLike for ast::Item<'_> {
+impl MaybeFnLike for hir::Item<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::ItemKind::Fn(..) => true,
+            hir::ItemKind::Fn(..) => true,
             _ => false,
         }
     }
 }
 
-impl MaybeFnLike for ast::ImplItem<'_> {
+impl MaybeFnLike for hir::ImplItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::ImplItemKind::Method(..) => true,
+            hir::ImplItemKind::Method(..) => true,
             _ => false,
         }
     }
 }
 
-impl MaybeFnLike for ast::TraitItem<'_> {
+impl MaybeFnLike for hir::TraitItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true,
+            hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
             _ => false,
         }
     }
 }
 
-impl MaybeFnLike for ast::Expr<'_> {
+impl MaybeFnLike for hir::Expr<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::ExprKind::Closure(..) => true,
+            hir::ExprKind::Closure(..) => true,
             _ => false,
         }
     }
@@ -85,7 +85,7 @@
 }
 
 impl<'a> Code<'a> {
-    pub fn id(&self) -> ast::HirId {
+    pub fn id(&self) -> hir::HirId {
         match *self {
             Code::FnLike(node) => node.id(),
             Code::Expr(block) => block.hir_id,
@@ -93,13 +93,13 @@
     }
 
     /// Attempts to construct a Code from presumed FnLike or Expr node input.
-    pub fn from_node(map: &map::Map<'a>, id: ast::HirId) -> Option<Code<'a>> {
+    pub fn from_node(map: &Map<'a>, id: hir::HirId) -> Option<Code<'a>> {
         match map.get(id) {
-            map::Node::Block(_) => {
+            Node::Block(_) => {
                 //  Use the parent, hopefully an expression node.
                 Code::from_node(map, map.get_parent_node(id))
             }
-            map::Node::Expr(expr) => Some(Code::Expr(expr)),
+            Node::Expr(expr) => Some(Code::Expr(expr)),
             node => FnLikeNode::from_node(node).map(Code::FnLike),
         }
     }
@@ -109,12 +109,12 @@
 /// use when implementing FnLikeNode operations.
 struct ItemFnParts<'a> {
     ident: Ident,
-    decl: &'a ast::FnDecl<'a>,
-    header: ast::FnHeader,
-    vis: &'a ast::Visibility<'a>,
-    generics: &'a ast::Generics<'a>,
-    body: ast::BodyId,
-    id: ast::HirId,
+    decl: &'a hir::FnDecl<'a>,
+    header: hir::FnHeader,
+    vis: &'a hir::Visibility<'a>,
+    generics: &'a hir::Generics<'a>,
+    body: hir::BodyId,
+    id: hir::HirId,
     span: Span,
     attrs: &'a [Attribute],
 }
@@ -123,8 +123,8 @@
 /// for use when implementing FnLikeNode operations.
 struct ClosureParts<'a> {
     decl: &'a FnDecl<'a>,
-    body: ast::BodyId,
-    id: ast::HirId,
+    body: hir::BodyId,
+    id: hir::HirId,
     span: Span,
     attrs: &'a [Attribute],
 }
@@ -132,8 +132,8 @@
 impl<'a> ClosureParts<'a> {
     fn new(
         d: &'a FnDecl<'a>,
-        b: ast::BodyId,
-        id: ast::HirId,
+        b: hir::BodyId,
+        id: hir::HirId,
         s: Span,
         attrs: &'a [Attribute],
     ) -> Self {
@@ -145,19 +145,19 @@
     /// Attempts to construct a FnLikeNode from presumed FnLike node input.
     pub fn from_node(node: Node<'_>) -> Option<FnLikeNode<'_>> {
         let fn_like = match node {
-            map::Node::Item(item) => item.is_fn_like(),
-            map::Node::TraitItem(tm) => tm.is_fn_like(),
-            map::Node::ImplItem(it) => it.is_fn_like(),
-            map::Node::Expr(e) => e.is_fn_like(),
+            Node::Item(item) => item.is_fn_like(),
+            Node::TraitItem(tm) => tm.is_fn_like(),
+            Node::ImplItem(it) => it.is_fn_like(),
+            Node::Expr(e) => e.is_fn_like(),
             _ => false,
         };
         fn_like.then_some(FnLikeNode { node })
     }
 
-    pub fn body(self) -> ast::BodyId {
+    pub fn body(self) -> hir::BodyId {
         self.handle(
             |i: ItemFnParts<'a>| i.body,
-            |_, _, _: &'a ast::FnSig<'a>, _, body: ast::BodyId, _, _| body,
+            |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _, _| body,
             |c: ClosureParts<'a>| c.body,
         )
     }
@@ -165,7 +165,7 @@
     pub fn decl(self) -> &'a FnDecl<'a> {
         self.handle(
             |i: ItemFnParts<'a>| &*i.decl,
-            |_, _, sig: &'a ast::FnSig<'a>, _, _, _, _| &sig.decl,
+            |_, _, sig: &'a hir::FnSig<'a>, _, _, _, _| &sig.decl,
             |c: ClosureParts<'a>| c.decl,
         )
     }
@@ -173,29 +173,29 @@
     pub fn span(self) -> Span {
         self.handle(
             |i: ItemFnParts<'_>| i.span,
-            |_, _, _: &'a ast::FnSig<'a>, _, _, span, _| span,
+            |_, _, _: &'a hir::FnSig<'a>, _, _, span, _| span,
             |c: ClosureParts<'_>| c.span,
         )
     }
 
-    pub fn id(self) -> ast::HirId {
+    pub fn id(self) -> hir::HirId {
         self.handle(
             |i: ItemFnParts<'_>| i.id,
-            |id, _, _: &'a ast::FnSig<'a>, _, _, _, _| id,
+            |id, _, _: &'a hir::FnSig<'a>, _, _, _, _| id,
             |c: ClosureParts<'_>| c.id,
         )
     }
 
-    pub fn constness(self) -> ast::Constness {
-        self.kind().header().map_or(ast::Constness::NotConst, |header| header.constness)
+    pub fn constness(self) -> hir::Constness {
+        self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness)
     }
 
-    pub fn asyncness(self) -> ast::IsAsync {
-        self.kind().header().map_or(ast::IsAsync::NotAsync, |header| header.asyncness)
+    pub fn asyncness(self) -> hir::IsAsync {
+        self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness)
     }
 
-    pub fn unsafety(self) -> ast::Unsafety {
-        self.kind().header().map_or(ast::Unsafety::Normal, |header| header.unsafety)
+    pub fn unsafety(self) -> hir::Unsafety {
+        self.kind().header().map_or(hir::Unsafety::Normal, |header| header.unsafety)
     }
 
     pub fn kind(self) -> FnKind<'a> {
@@ -203,7 +203,7 @@
             FnKind::ItemFn(p.ident, p.generics, p.header, p.vis, p.attrs)
         };
         let closure = |c: ClosureParts<'a>| FnKind::Closure(c.attrs);
-        let method = |_, ident: Ident, sig: &'a ast::FnSig<'a>, vis, _, _, attrs| {
+        let method = |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _, attrs| {
             FnKind::Method(ident, sig, vis, attrs)
         };
         self.handle(item, method, closure)
@@ -213,19 +213,19 @@
     where
         I: FnOnce(ItemFnParts<'a>) -> A,
         M: FnOnce(
-            ast::HirId,
+            hir::HirId,
             Ident,
-            &'a ast::FnSig<'a>,
-            Option<&'a ast::Visibility<'a>>,
-            ast::BodyId,
+            &'a hir::FnSig<'a>,
+            Option<&'a hir::Visibility<'a>>,
+            hir::BodyId,
             Span,
             &'a [Attribute],
         ) -> A,
         C: FnOnce(ClosureParts<'a>) -> A,
     {
         match self.node {
-            map::Node::Item(i) => match i.kind {
-                ast::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts {
+            Node::Item(i) => match i.kind {
+                hir::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts {
                     id: i.hir_id,
                     ident: i.ident,
                     decl: &sig.decl,
@@ -238,20 +238,20 @@
                 }),
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
-            map::Node::TraitItem(ti) => match ti.kind {
-                ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => {
+            Node::TraitItem(ti) => match ti.kind {
+                hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
                     method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
             },
-            map::Node::ImplItem(ii) => match ii.kind {
-                ast::ImplItemKind::Method(ref sig, body) => {
+            Node::ImplItem(ii) => match ii.kind {
+                hir::ImplItemKind::Method(ref sig, body) => {
                     method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                 }
                 _ => bug!("impl method FnLikeNode that is not fn-like"),
             },
-            map::Node::Expr(e) => match e.kind {
-                ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
+            Node::Expr(e) => match e.kind {
+                hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
                     closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs))
                 }
                 _ => bug!("expr FnLikeNode that is not fn-like"),
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 2508328..b6be4bb 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -1,22 +1,24 @@
-use super::*;
-use crate::dep_graph::{DepGraph, DepKind, DepNodeIndex};
-use crate::hir;
-use crate::hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE};
-use crate::hir::intravisit::{NestedVisitorMap, Visitor};
-use crate::hir::map::HirEntryMap;
-use crate::ich::Fingerprint;
+use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
+use crate::hir::map::definitions::{self, DefPathHash};
+use crate::hir::map::{Entry, HirEntryMap, Map};
+use crate::ich::StableHashingContext;
 use crate::middle::cstore::CrateStore;
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
+use rustc_hir as hir;
+use rustc_hir::def_id::CRATE_DEF_INDEX;
+use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::*;
 use rustc_index::vec::IndexVec;
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::SourceMap;
-use rustc_span::Span;
-use std::iter::repeat;
+use rustc_span::{Span, Symbol, DUMMY_SP};
 use syntax::ast::NodeId;
 
-use crate::ich::StableHashingContext;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use std::iter::repeat;
 
 /// A visitor that walks over the HIR and collects `Node`s into a HIR map.
 pub(super) struct NodeCollector<'a, 'hir> {
@@ -49,15 +51,12 @@
     hir_body_nodes: Vec<(DefPathHash, Fingerprint)>,
 }
 
-fn input_dep_node_and_hash<I>(
+fn input_dep_node_and_hash(
     dep_graph: &DepGraph,
     hcx: &mut StableHashingContext<'_>,
     dep_node: DepNode,
-    input: I,
-) -> (DepNodeIndex, Fingerprint)
-where
-    I: for<'a> HashStable<StableHashingContext<'a>>,
-{
+    input: impl for<'a> HashStable<StableHashingContext<'a>>,
+) -> (DepNodeIndex, Fingerprint) {
     let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1;
 
     let hash = if dep_graph.is_fully_enabled() {
@@ -71,16 +70,13 @@
     (dep_node_index, hash)
 }
 
-fn alloc_hir_dep_nodes<I>(
+fn alloc_hir_dep_nodes(
     dep_graph: &DepGraph,
     hcx: &mut StableHashingContext<'_>,
     def_path_hash: DefPathHash,
-    item_like: I,
+    item_like: impl for<'a> HashStable<StableHashingContext<'a>>,
     hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>,
-) -> (DepNodeIndex, DepNodeIndex)
-where
-    I: for<'a> HashStable<StableHashingContext<'a>>,
-{
+) -> (DepNodeIndex, DepNodeIndex) {
     let sig = dep_graph
         .input_task(
             def_path_hash.to_dep_node(DepKind::Hir),
@@ -98,6 +94,21 @@
     (sig, full)
 }
 
+fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
+    let mut upstream_crates: Vec<_> = cstore
+        .crates_untracked()
+        .iter()
+        .map(|&cnum| {
+            let name = cstore.crate_name_untracked(cnum);
+            let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
+            let hash = cstore.crate_hash_untracked(cnum);
+            (name, disambiguator, hash)
+        })
+        .collect();
+    upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
+    upstream_crates
+}
+
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(
         sess: &'a Session,
@@ -190,18 +201,7 @@
             },
         );
 
-        let mut upstream_crates: Vec<_> = cstore
-            .crates_untracked()
-            .iter()
-            .map(|&cnum| {
-                let name = cstore.crate_name_untracked(cnum);
-                let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
-                let hash = cstore.crate_hash_untracked(cnum);
-                (name, disambiguator, hash)
-            })
-            .collect();
-
-        upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
+        let upstream_crates = upstream_crates(cstore);
 
         // We hash the final, remapped names of all local source files so we
         // don't have to include the path prefix remapping commandline args.
@@ -268,7 +268,7 @@
                     None => format!("{:?}", node),
                 };
 
-                let forgot_str = if hir_id == crate::hir::DUMMY_HIR_ID {
+                let forgot_str = if hir_id == hir::DUMMY_HIR_ID {
                     format!("\nMaybe you forgot to lower the node id {:?}?", node_id)
                 } else {
                     String::new()
@@ -336,11 +336,13 @@
 }
 
 impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
+    type Map = Map<'hir>;
+
     /// Because we want to track parent items and so forth, enable
     /// deep walking so that we walk nested items in the context of
     /// their outer items.
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         panic!("`visit_nested_xxx` must be manually implemented in this visitor");
     }
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index b04c352..ac2d7a9 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -4,22 +4,22 @@
 //! There are also some rather random cases (like const initializer
 //! expressions) that are mostly just leftovers.
 
-use crate::hir;
-use crate::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
-use crate::ich::Fingerprint;
-
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::IndexVec;
 use rustc_session::node_id::NodeMap;
 use rustc_session::CrateDisambiguator;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use syntax::ast;
+
 use std::borrow::Borrow;
 use std::fmt::Write;
 use std::hash::Hash;
-use syntax::ast;
 
 /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index a04fc8a..76e42b8 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -1,10 +1,13 @@
-use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
-use crate::hir::itemlikevisit::ItemLikeVisitor;
-use crate::hir::{self, intravisit, HirId, ItemLocalId};
+use crate::hir::map::Map;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::intravisit;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::{HirId, ItemLocalId};
 
-pub fn check_crate(hir_map: &hir::map::Map<'_>) {
+pub fn check_crate(hir_map: &Map<'_>) {
     hir_map.dep_graph.assert_ignored();
 
     let errors = Lock::new(Vec::new());
@@ -26,19 +29,19 @@
 }
 
 struct HirIdValidator<'a, 'hir> {
-    hir_map: &'a hir::map::Map<'hir>,
+    hir_map: &'a Map<'hir>,
     owner_def_index: Option<DefIndex>,
     hir_ids_seen: FxHashSet<ItemLocalId>,
     errors: &'a Lock<Vec<String>>,
 }
 
 struct OuterVisitor<'a, 'hir> {
-    hir_map: &'a hir::map::Map<'hir>,
+    hir_map: &'a Map<'hir>,
     errors: &'a Lock<Vec<String>>,
 }
 
 impl<'a, 'hir> OuterVisitor<'a, 'hir> {
-    fn new_inner_visitor(&self, hir_map: &'a hir::map::Map<'hir>) -> HirIdValidator<'a, 'hir> {
+    fn new_inner_visitor(&self, hir_map: &'a Map<'hir>) -> HirIdValidator<'a, 'hir> {
         HirIdValidator {
             hir_map,
             owner_def_index: None,
@@ -130,7 +133,9 @@
 }
 
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'hir> {
+    type Map = Map<'hir>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
         intravisit::NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index fc23482..46c5ee2 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -4,20 +4,21 @@
 };
 
 use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
-use crate::hir::def::{DefKind, Res};
-use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
-use crate::hir::itemlikevisit::ItemLikeVisitor;
-use crate::hir::print::Nested;
-use crate::hir::*;
 use crate::middle::cstore::CrateStoreDyn;
 use crate::ty::query::Providers;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::intravisit;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::print::Nested;
+use rustc_hir::*;
 use rustc_index::vec::IndexVec;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::kw;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, Name, NodeId};
 
@@ -185,12 +186,12 @@
 }
 
 impl<'map, 'hir> ParentHirIterator<'map, 'hir> {
-    fn new(current_id: HirId, map: &'map Map<'hir>) -> ParentHirIterator<'map, 'hir> {
-        ParentHirIterator { current_id, map }
+    fn new(current_id: HirId, map: &'map Map<'hir>) -> Self {
+        Self { current_id, map }
     }
 }
 
-impl<'map, 'hir> Iterator for ParentHirIterator<'map, 'hir> {
+impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
     type Item = (HirId, Node<'hir>);
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -404,6 +405,14 @@
         self.forest.krate()
     }
 
+    pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        self.read(id);
+
+        // N.B., intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.item(id)
+    }
+
     pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
         self.read(id.hir_id);
 
@@ -1084,6 +1093,24 @@
     }
 }
 
+impl<'hir> intravisit::Map<'hir> for Map<'hir> {
+    fn body(&self, id: BodyId) -> &'hir Body<'hir> {
+        self.body(id)
+    }
+
+    fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        self.item(id)
+    }
+
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
+        self.trait_item(id)
+    }
+
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        self.impl_item(id)
+    }
+}
+
 pub struct NodesMatchingSuffix<'a> {
     map: &'a Map<'a>,
     item_name: &'a String,
@@ -1243,7 +1270,7 @@
         definitions,
     };
 
-    sess.time("validate HIR map", || {
+    sess.time("validate_HIR_map", || {
         hir_id_validator::check_crate(&map);
     });
 
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
new file mode 100644
index 0000000..97c14dd
--- /dev/null
+++ b/src/librustc/hir/mod.rs
@@ -0,0 +1,16 @@
+//! HIR datatypes. See the [rustc guide] for more info.
+//!
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
+
+pub mod check_attr;
+pub mod exports;
+pub mod map;
+pub mod upvars;
+
+use crate::ty::query::Providers;
+
+pub fn provide(providers: &mut Providers<'_>) {
+    check_attr::provide(providers);
+    map::provide(providers);
+    upvars::provide(providers);
+}
diff --git a/src/librustc/hir/upvars.rs b/src/librustc/hir/upvars.rs
index ff6b054..4ca294f 100644
--- a/src/librustc/hir/upvars.rs
+++ b/src/librustc/hir/upvars.rs
@@ -1,11 +1,13 @@
 //! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s.
 
-use crate::hir::def::Res;
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use crate::hir::{self, HirId};
+use crate::hir::map::Map;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{self, HirId};
 use rustc_span::Span;
 
 pub fn provide(providers: &mut Providers<'_>) {
@@ -42,7 +44,9 @@
 }
 
 impl Visitor<'tcx> for LocalCollector {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -69,7 +73,9 @@
 }
 
 impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 86cad00..aade4c3 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -1,5 +1,3 @@
-use crate::hir;
-use crate::hir::def_id::{DefId, DefIndex};
 use crate::hir::map::definitions::Definitions;
 use crate::hir::map::DefPathHash;
 use crate::ich::{self, CachingSourceMapView};
@@ -7,17 +5,18 @@
 use crate::session::Session;
 use crate::ty::{fast_reject, TyCtxt};
 
-use std::cmp::Ord;
-
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, DefIndex};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, SourceFile};
 use syntax::ast;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
-use rustc_data_structures::sync::Lrc;
 use smallvec::SmallVec;
+use std::cmp::Ord;
 
 fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
     debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index f69051f..8961f7c 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -1,12 +1,11 @@
 //! This module contains `HashStable` implementations for various HIR data
 //! types in no particular order.
 
-use crate::hir;
-use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
 use crate::hir::map::DefPathHash;
 use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
-
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
 use smallvec::SmallVec;
 use std::mem;
 use syntax::attr;
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index e72a524..e173379 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -3,12 +3,11 @@
 
 use crate::ich::StableHashingContext;
 
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_span::SourceFile;
 use syntax::ast;
 
-use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use smallvec::SmallVec;
 
 impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {}
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 5e402dc..012900f 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -22,7 +22,7 @@
 use crate::ty::fold::TypeFoldable;
 use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, BoundVar, Ty, TyCtxt};
-use crate::util::captures::Captures;
+use rustc_data_structures::captures::Captures;
 use rustc_index::vec::Idx;
 use rustc_index::vec::IndexVec;
 use rustc_span::DUMMY_SP;
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index a9e56a9..5d765a2 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -32,7 +32,6 @@
 use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use super::{InferCtxt, MiscVariable, TypeTrace};
 
-use crate::hir::def_id::DefId;
 use crate::traits::{Obligation, PredicateObligations};
 use crate::ty::error::TypeError;
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -40,6 +39,7 @@
 use crate::ty::{self, InferConst, Ty, TyCtxt};
 use crate::ty::{IntType, UintType};
 
+use rustc_hir::def_id::DefId;
 use rustc_span::{Span, DUMMY_SP};
 use syntax::ast;
 
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 6a7707b..4a41cdb 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -1,13 +1,13 @@
 use super::combine::{CombineFields, RelationDir};
 use super::Subtype;
 
-use crate::hir::def_id::DefId;
-
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::subst::SubstsRef;
 use crate::ty::TyVar;
 use crate::ty::{self, Ty, TyCtxt};
 
+use rustc_hir::def_id::DefId;
+
 /// Ensures `a` is made equal to `b`. Returns `a` on success.
 pub struct Equate<'combine, 'infcx, 'tcx> {
     fields: &'combine mut CombineFields<'infcx, 'tcx>,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 69c5ea5..c52d433 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -49,12 +49,12 @@
 use super::region_constraints::GenericKind;
 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
 
-use crate::hir;
-use crate::hir::def_id::DefId;
-use crate::hir::Node;
+use crate::hir::map;
 use crate::infer::opaque_types;
 use crate::infer::{self, SuppressRegionErrors};
 use crate::middle::region;
+use crate::traits::error_reporting::report_object_safety_error;
+use crate::traits::object_safety_violations;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
 };
@@ -64,10 +64,14 @@
     subst::{Subst, SubstsRef},
     Region, Ty, TyCtxt, TypeFoldable,
 };
-
-use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_error_codes::*;
-use rustc_span::{Pos, Span};
+use rustc_errors::{pluralize, struct_span_err};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::Node;
+use rustc_span::{DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::{cmp, fmt};
 
@@ -78,212 +82,209 @@
 
 pub mod nice_region_error;
 
-impl<'tcx> TyCtxt<'tcx> {
-    pub fn note_and_explain_region(
-        self,
-        region_scope_tree: &region::ScopeTree,
-        err: &mut DiagnosticBuilder<'_>,
-        prefix: &str,
-        region: ty::Region<'tcx>,
-        suffix: &str,
-    ) {
-        let (description, span) = match *region {
-            ty::ReScope(scope) => {
-                let new_string;
-                let unknown_scope = || {
-                    format!("{}unknown scope: {:?}{}.  Please report a bug.", prefix, scope, suffix)
-                };
-                let span = scope.span(self, region_scope_tree);
-                let tag = match self.hir().find(scope.hir_id(region_scope_tree)) {
-                    Some(Node::Block(_)) => "block",
-                    Some(Node::Expr(expr)) => match expr.kind {
-                        hir::ExprKind::Call(..) => "call",
-                        hir::ExprKind::MethodCall(..) => "method call",
-                        hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
-                        hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let",
-                        hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for",
-                        hir::ExprKind::Match(..) => "match",
-                        _ => "expression",
-                    },
-                    Some(Node::Stmt(_)) => "statement",
-                    Some(Node::Item(it)) => Self::item_scope_tag(&it),
-                    Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it),
-                    Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it),
-                    Some(_) | None => {
-                        err.span_note(span, &unknown_scope());
-                        return;
-                    }
-                };
-                let scope_decorated_tag = match scope.data {
-                    region::ScopeData::Node => tag,
-                    region::ScopeData::CallSite => "scope of call-site for function",
-                    region::ScopeData::Arguments => "scope of function body",
-                    region::ScopeData::Destruction => {
-                        new_string = format!("destruction scope surrounding {}", tag);
-                        &new_string[..]
-                    }
-                    region::ScopeData::Remainder(first_statement_index) => {
-                        new_string = format!(
-                            "block suffix following statement {}",
-                            first_statement_index.index()
-                        );
-                        &new_string[..]
-                    }
-                };
-                self.explain_span(scope_decorated_tag, span)
-            }
-
-            ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
-                self.msg_span_from_free_region(region)
-            }
-
-            ty::ReEmpty => ("the empty lifetime".to_owned(), None),
-
-            ty::RePlaceholder(_) => (format!("any other region"), None),
-
-            // FIXME(#13998) RePlaceholder should probably print like
-            // ReFree rather than dumping Debug output on the user.
-            //
-            // We shouldn't really be having unification failures with ReVar
-            // and ReLateBound though.
-            ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
-                (format!("lifetime {:?}", region), None)
-            }
-
-            // We shouldn't encounter an error message with ReClosureBound.
-            ty::ReClosureBound(..) => {
-                bug!("encountered unexpected ReClosureBound: {:?}", region,);
-            }
-        };
-
-        TyCtxt::emit_msg_span(err, prefix, description, span, suffix);
-    }
-
-    pub fn note_and_explain_free_region(
-        self,
-        err: &mut DiagnosticBuilder<'_>,
-        prefix: &str,
-        region: ty::Region<'tcx>,
-        suffix: &str,
-    ) {
-        let (description, span) = self.msg_span_from_free_region(region);
-
-        TyCtxt::emit_msg_span(err, prefix, description, span, suffix);
-    }
-
-    fn msg_span_from_free_region(self, region: ty::Region<'tcx>) -> (String, Option<Span>) {
-        match *region {
-            ty::ReEarlyBound(_) | ty::ReFree(_) => {
-                self.msg_span_from_early_bound_and_free_regions(region)
-            }
-            ty::ReStatic => ("the static lifetime".to_owned(), None),
-            ty::ReEmpty => ("an empty lifetime".to_owned(), None),
-            _ => bug!("{:?}", region),
-        }
-    }
-
-    fn msg_span_from_early_bound_and_free_regions(
-        self,
-        region: ty::Region<'tcx>,
-    ) -> (String, Option<Span>) {
-        let cm = self.sess.source_map();
-
-        let scope = region.free_region_binding_scope(self);
-        let node = self.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID);
-        let tag = match self.hir().find(node) {
-            Some(Node::Block(_)) | Some(Node::Expr(_)) => "body",
-            Some(Node::Item(it)) => Self::item_scope_tag(&it),
-            Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it),
-            Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it),
-            _ => unreachable!(),
-        };
-        let (prefix, span) = match *region {
-            ty::ReEarlyBound(ref br) => {
-                let mut sp = cm.def_span(self.hir().span(node));
-                if let Some(param) =
-                    self.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
-                {
-                    sp = param.span;
+pub(super) fn note_and_explain_region(
+    tcx: TyCtxt<'tcx>,
+    region_scope_tree: &region::ScopeTree,
+    err: &mut DiagnosticBuilder<'_>,
+    prefix: &str,
+    region: ty::Region<'tcx>,
+    suffix: &str,
+) {
+    let (description, span) = match *region {
+        ty::ReScope(scope) => {
+            let new_string;
+            let unknown_scope =
+                || format!("{}unknown scope: {:?}{}.  Please report a bug.", prefix, scope, suffix);
+            let span = scope.span(tcx, region_scope_tree);
+            let tag = match tcx.hir().find(scope.hir_id(region_scope_tree)) {
+                Some(Node::Block(_)) => "block",
+                Some(Node::Expr(expr)) => match expr.kind {
+                    hir::ExprKind::Call(..) => "call",
+                    hir::ExprKind::MethodCall(..) => "method call",
+                    hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
+                    hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let",
+                    hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for",
+                    hir::ExprKind::Match(..) => "match",
+                    _ => "expression",
+                },
+                Some(Node::Stmt(_)) => "statement",
+                Some(Node::Item(it)) => item_scope_tag(&it),
+                Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
+                Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
+                Some(_) | None => {
+                    err.span_note(span, &unknown_scope());
+                    return;
                 }
-                (format!("the lifetime `{}` as defined on", br.name), sp)
-            }
-            ty::ReFree(ty::FreeRegion {
-                bound_region: ty::BoundRegion::BrNamed(_, name), ..
-            }) => {
-                let mut sp = cm.def_span(self.hir().span(node));
-                if let Some(param) =
-                    self.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
-                {
-                    sp = param.span;
+            };
+            let scope_decorated_tag = match scope.data {
+                region::ScopeData::Node => tag,
+                region::ScopeData::CallSite => "scope of call-site for function",
+                region::ScopeData::Arguments => "scope of function body",
+                region::ScopeData::Destruction => {
+                    new_string = format!("destruction scope surrounding {}", tag);
+                    &new_string[..]
                 }
-                (format!("the lifetime `{}` as defined on", name), sp)
+                region::ScopeData::Remainder(first_statement_index) => {
+                    new_string = format!(
+                        "block suffix following statement {}",
+                        first_statement_index.index()
+                    );
+                    &new_string[..]
+                }
+            };
+            explain_span(tcx, scope_decorated_tag, span)
+        }
+
+        ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
+            msg_span_from_free_region(tcx, region)
+        }
+
+        ty::ReEmpty => ("the empty lifetime".to_owned(), None),
+
+        ty::RePlaceholder(_) => (format!("any other region"), None),
+
+        // FIXME(#13998) RePlaceholder should probably print like
+        // ReFree rather than dumping Debug output on the user.
+        //
+        // We shouldn't really be having unification failures with ReVar
+        // and ReLateBound though.
+        ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
+            (format!("lifetime {:?}", region), None)
+        }
+
+        // We shouldn't encounter an error message with ReClosureBound.
+        ty::ReClosureBound(..) => {
+            bug!("encountered unexpected ReClosureBound: {:?}", region,);
+        }
+    };
+
+    emit_msg_span(err, prefix, description, span, suffix);
+}
+
+pub(super) fn note_and_explain_free_region(
+    tcx: TyCtxt<'tcx>,
+    err: &mut DiagnosticBuilder<'_>,
+    prefix: &str,
+    region: ty::Region<'tcx>,
+    suffix: &str,
+) {
+    let (description, span) = msg_span_from_free_region(tcx, region);
+
+    emit_msg_span(err, prefix, description, span, suffix);
+}
+
+fn msg_span_from_free_region(
+    tcx: TyCtxt<'tcx>,
+    region: ty::Region<'tcx>,
+) -> (String, Option<Span>) {
+    match *region {
+        ty::ReEarlyBound(_) | ty::ReFree(_) => {
+            msg_span_from_early_bound_and_free_regions(tcx, region)
+        }
+        ty::ReStatic => ("the static lifetime".to_owned(), None),
+        ty::ReEmpty => ("an empty lifetime".to_owned(), None),
+        _ => bug!("{:?}", region),
+    }
+}
+
+fn msg_span_from_early_bound_and_free_regions(
+    tcx: TyCtxt<'tcx>,
+    region: ty::Region<'tcx>,
+) -> (String, Option<Span>) {
+    let cm = tcx.sess.source_map();
+
+    let scope = region.free_region_binding_scope(tcx);
+    let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID);
+    let tag = match tcx.hir().find(node) {
+        Some(Node::Block(_)) | Some(Node::Expr(_)) => "body",
+        Some(Node::Item(it)) => item_scope_tag(&it),
+        Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
+        Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
+        _ => unreachable!(),
+    };
+    let (prefix, span) = match *region {
+        ty::ReEarlyBound(ref br) => {
+            let mut sp = cm.def_span(tcx.hir().span(node));
+            if let Some(param) =
+                tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
+            {
+                sp = param.span;
             }
-            ty::ReFree(ref fr) => match fr.bound_region {
-                ty::BrAnon(idx) => (
-                    format!("the anonymous lifetime #{} defined on", idx + 1),
-                    self.hir().span(node),
-                ),
-                _ => (
-                    format!("the lifetime `{}` as defined on", region),
-                    cm.def_span(self.hir().span(node)),
-                ),
-            },
-            _ => bug!(),
-        };
-        let (msg, opt_span) = self.explain_span(tag, span);
-        (format!("{} {}", prefix, msg), opt_span)
-    }
-
-    fn emit_msg_span(
-        err: &mut DiagnosticBuilder<'_>,
-        prefix: &str,
-        description: String,
-        span: Option<Span>,
-        suffix: &str,
-    ) {
-        let message = format!("{}{}{}", prefix, description, suffix);
-
-        if let Some(span) = span {
-            err.span_note(span, &message);
-        } else {
-            err.note(&message);
+            (format!("the lifetime `{}` as defined on", br.name), sp)
         }
-    }
-
-    fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
-        match item.kind {
-            hir::ItemKind::Impl(..) => "impl",
-            hir::ItemKind::Struct(..) => "struct",
-            hir::ItemKind::Union(..) => "union",
-            hir::ItemKind::Enum(..) => "enum",
-            hir::ItemKind::Trait(..) => "trait",
-            hir::ItemKind::Fn(..) => "function body",
-            _ => "item",
+        ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => {
+            let mut sp = cm.def_span(tcx.hir().span(node));
+            if let Some(param) =
+                tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
+            {
+                sp = param.span;
+            }
+            (format!("the lifetime `{}` as defined on", name), sp)
         }
-    }
+        ty::ReFree(ref fr) => match fr.bound_region {
+            ty::BrAnon(idx) => {
+                (format!("the anonymous lifetime #{} defined on", idx + 1), tcx.hir().span(node))
+            }
+            _ => (
+                format!("the lifetime `{}` as defined on", region),
+                cm.def_span(tcx.hir().span(node)),
+            ),
+        },
+        _ => bug!(),
+    };
+    let (msg, opt_span) = explain_span(tcx, tag, span);
+    (format!("{} {}", prefix, msg), opt_span)
+}
 
-    fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
-        match item.kind {
-            hir::TraitItemKind::Method(..) => "method body",
-            hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
-        }
-    }
+fn emit_msg_span(
+    err: &mut DiagnosticBuilder<'_>,
+    prefix: &str,
+    description: String,
+    span: Option<Span>,
+    suffix: &str,
+) {
+    let message = format!("{}{}{}", prefix, description, suffix);
 
-    fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
-        match item.kind {
-            hir::ImplItemKind::Method(..) => "method body",
-            hir::ImplItemKind::Const(..)
-            | hir::ImplItemKind::OpaqueTy(..)
-            | hir::ImplItemKind::TyAlias(..) => "associated item",
-        }
+    if let Some(span) = span {
+        err.span_note(span, &message);
+    } else {
+        err.note(&message);
     }
+}
 
-    fn explain_span(self, heading: &str, span: Span) -> (String, Option<Span>) {
-        let lo = self.sess.source_map().lookup_char_pos(span.lo());
-        (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
+fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
+    match item.kind {
+        hir::ItemKind::Impl(..) => "impl",
+        hir::ItemKind::Struct(..) => "struct",
+        hir::ItemKind::Union(..) => "union",
+        hir::ItemKind::Enum(..) => "enum",
+        hir::ItemKind::Trait(..) => "trait",
+        hir::ItemKind::Fn(..) => "function body",
+        _ => "item",
     }
 }
 
+fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
+    match item.kind {
+        hir::TraitItemKind::Method(..) => "method body",
+        hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
+    }
+}
+
+fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
+    match item.kind {
+        hir::ImplItemKind::Method(..) => "method body",
+        hir::ImplItemKind::Const(..)
+        | hir::ImplItemKind::OpaqueTy(..)
+        | hir::ImplItemKind::TyAlias(..) => "associated item",
+    }
+}
+
+fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option<Span>) {
+    let lo = tcx.sess.source_map().lookup_char_pos(span.lo());
+    (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
+}
+
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn report_region_errors(
         &self,
@@ -455,7 +456,7 @@
         terr: &TypeError<'tcx>,
     ) {
         use hir::def_id::CrateNum;
-        use hir::map::DisambiguatedDefPathData;
+        use map::DisambiguatedDefPathData;
         use ty::print::Printer;
         use ty::subst::GenericArg;
 
@@ -851,7 +852,7 @@
         sig2: &ty::PolyFnSig<'tcx>,
     ) -> (DiagnosticStyledString, DiagnosticStyledString) {
         let get_lifetimes = |sig| {
-            use crate::hir::def::Namespace;
+            use rustc_hir::def::Namespace;
             let mut s = String::new();
             let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
                 .name_all_regions(sig)
@@ -1289,6 +1290,8 @@
         mut values: Option<ValuePairs<'tcx>>,
         terr: &TypeError<'tcx>,
     ) {
+        let span = cause.span(self.tcx);
+
         // For some types of errors, expected-found does not make
         // sense, so just ignore the values we were given.
         match terr {
@@ -1298,6 +1301,100 @@
             _ => {}
         }
 
+        struct OpaqueTypesVisitor<'tcx> {
+            types: FxHashMap<TyCategory, FxHashSet<Span>>,
+            expected: FxHashMap<TyCategory, FxHashSet<Span>>,
+            found: FxHashMap<TyCategory, FxHashSet<Span>>,
+            ignore_span: Span,
+            tcx: TyCtxt<'tcx>,
+        }
+
+        impl<'tcx> OpaqueTypesVisitor<'tcx> {
+            fn visit_expected_found(
+                tcx: TyCtxt<'tcx>,
+                expected: Ty<'tcx>,
+                found: Ty<'tcx>,
+                ignore_span: Span,
+            ) -> Self {
+                let mut types_visitor = OpaqueTypesVisitor {
+                    types: Default::default(),
+                    expected: Default::default(),
+                    found: Default::default(),
+                    ignore_span,
+                    tcx,
+                };
+                // The visitor puts all the relevant encountered types in `self.types`, but in
+                // here we want to visit two separate types with no relation to each other, so we
+                // move the results from `types` to `expected` or `found` as appropriate.
+                expected.visit_with(&mut types_visitor);
+                std::mem::swap(&mut types_visitor.expected, &mut types_visitor.types);
+                found.visit_with(&mut types_visitor);
+                std::mem::swap(&mut types_visitor.found, &mut types_visitor.types);
+                types_visitor
+            }
+
+            fn report(&self, err: &mut DiagnosticBuilder<'_>) {
+                self.add_labels_for_types(err, "expected", &self.expected);
+                self.add_labels_for_types(err, "found", &self.found);
+            }
+
+            fn add_labels_for_types(
+                &self,
+                err: &mut DiagnosticBuilder<'_>,
+                target: &str,
+                types: &FxHashMap<TyCategory, FxHashSet<Span>>,
+            ) {
+                for (key, values) in types.iter() {
+                    let count = values.len();
+                    let kind = key.descr();
+                    for sp in values {
+                        err.span_label(
+                            *sp,
+                            format!(
+                                "{}{}{} {}{}",
+                                if sp.is_desugaring(DesugaringKind::Async) {
+                                    "the `Output` of this `async fn`'s "
+                                } else if count == 1 {
+                                    "the "
+                                } else {
+                                    ""
+                                },
+                                if count > 1 { "one of the " } else { "" },
+                                target,
+                                kind,
+                                pluralize!(count),
+                            ),
+                        );
+                    }
+                }
+            }
+        }
+
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                if let Some((kind, def_id)) = TyCategory::from_ty(t) {
+                    let span = self.tcx.def_span(def_id);
+                    // Avoid cluttering the output when the "found" and error span overlap:
+                    //
+                    // error[E0308]: mismatched types
+                    //   --> $DIR/issue-20862.rs:2:5
+                    //    |
+                    // LL |     |y| x + y
+                    //    |     ^^^^^^^^^
+                    //    |     |
+                    //    |     the found closure
+                    //    |     expected `()`, found closure
+                    //    |
+                    //    = note: expected unit type `()`
+                    //                 found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
+                    if !self.ignore_span.overlaps(span) {
+                        self.types.entry(kind).or_default().insert(span);
+                    }
+                }
+                t.super_visit_with(self)
+            }
+        }
+
         debug!("note_type_err(diag={:?})", diag);
         let (expected_found, exp_found, is_simple_error) = match values {
             None => (None, None, false),
@@ -1306,6 +1403,13 @@
                     ValuePairs::Types(exp_found) => {
                         let is_simple_err =
                             exp_found.expected.is_simple_text() && exp_found.found.is_simple_text();
+                        OpaqueTypesVisitor::visit_expected_found(
+                            self.tcx,
+                            exp_found.expected,
+                            exp_found.found,
+                            span,
+                        )
+                        .report(diag);
 
                         (is_simple_err, Some(exp_found))
                     }
@@ -1323,8 +1427,6 @@
             }
         };
 
-        let span = cause.span(self.tcx);
-
         // Ignore msg for object safe coercion
         // since E0038 message will be printed
         match terr {
@@ -1336,7 +1438,6 @@
                 }
             }
         };
-
         if let Some((expected, found)) = expected_found {
             let expected_label = exp_found.map_or("type".into(), |ef| ef.expected.prefix_string());
             let found_label = exp_found.map_or("type".into(), |ef| ef.found.prefix_string());
@@ -1488,8 +1589,8 @@
         let failure_code = trace.cause.as_failure_code(terr);
         let mut diag = match failure_code {
             FailureCode::Error0038(did) => {
-                let violations = self.tcx.object_safety_violations(did);
-                self.tcx.report_object_safety_error(span, did, violations)
+                let violations = object_safety_violations(self.tcx, did);
+                report_object_safety_error(self.tcx, span, did, violations)
             }
             FailureCode::Error0317(failure_str) => {
                 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
@@ -1718,7 +1819,8 @@
                     "consider adding an explicit lifetime bound for `{}`",
                     bound_kind
                 ));
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     &format!("{} must be valid for ", labeled_user_string),
@@ -1746,7 +1848,8 @@
     ) {
         let mut err = self.report_inference_failure(var_origin);
 
-        self.tcx.note_and_explain_region(
+        note_and_explain_region(
+            self.tcx,
             region_scope_tree,
             &mut err,
             "first, the lifetime cannot outlive ",
@@ -1770,7 +1873,8 @@
                     (self.values_str(&sup_trace.values), self.values_str(&sub_trace.values))
                 {
                     if sub_expected == sup_expected && sub_found == sup_found {
-                        self.tcx.note_and_explain_region(
+                        note_and_explain_region(
+                            self.tcx,
                             region_scope_tree,
                             &mut err,
                             "...but the lifetime must also be valid for ",
@@ -1793,7 +1897,8 @@
 
         self.note_region_origin(&mut err, &sup_origin);
 
-        self.tcx.note_and_explain_region(
+        note_and_explain_region(
+            self.tcx,
             region_scope_tree,
             &mut err,
             "but, the lifetime must be valid for ",
@@ -1929,3 +2034,34 @@
         }
     }
 }
+
+/// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
+/// extra information about each type, but we only care about the category.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+crate enum TyCategory {
+    Closure,
+    Opaque,
+    Generator,
+    Foreign,
+}
+
+impl TyCategory {
+    fn descr(&self) -> &'static str {
+        match self {
+            Self::Closure => "closure",
+            Self::Opaque => "opaque type",
+            Self::Generator => "generator",
+            Self::Foreign => "foreign type",
+        }
+    }
+
+    pub fn from_ty(ty: Ty<'_>) -> Option<(Self, DefId)> {
+        match ty.kind {
+            ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
+            ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
+            ty::Generator(def_id, ..) => Some((Self::Generator, def_id)),
+            ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
+            _ => None,
+        }
+    }
+}
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 889b7b4..70f7987 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -1,11 +1,13 @@
-use crate::hir::def::{DefKind, Namespace};
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use crate::hir::{self, Body, Expr, ExprKind, FunctionRetTy, HirId, Local, Pat};
+use crate::hir::map::Map;
 use crate::infer::type_variable::TypeVariableOriginKind;
 use crate::infer::InferCtxt;
 use crate::ty::print::Print;
 use crate::ty::{self, DefIdTree, Infer, Ty, TyVar};
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Namespace};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Body, Expr, ExprKind, FunctionRetTy, HirId, Local, Pat};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -16,7 +18,7 @@
 struct FindLocalByTypeVisitor<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     target_ty: Ty<'tcx>,
-    hir_map: &'a hir::map::Map<'tcx>,
+    hir_map: &'a Map<'tcx>,
     found_local_pattern: Option<&'tcx Pat<'tcx>>,
     found_arg_pattern: Option<&'tcx Pat<'tcx>>,
     found_ty: Option<Ty<'tcx>>,
@@ -25,11 +27,7 @@
 }
 
 impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
-    fn new(
-        infcx: &'a InferCtxt<'a, 'tcx>,
-        target_ty: Ty<'tcx>,
-        hir_map: &'a hir::map::Map<'tcx>,
-    ) -> Self {
+    fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: &'a Map<'tcx>) -> Self {
         Self {
             infcx,
             target_ty,
@@ -68,7 +66,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.hir_map)
     }
 
@@ -151,16 +151,13 @@
     E0284,
 }
 
-impl Into<errors::DiagnosticId> for TypeAnnotationNeeded {
-    fn into(self) -> errors::DiagnosticId {
-        syntax::diagnostic_used!(E0282);
-        syntax::diagnostic_used!(E0283);
-        syntax::diagnostic_used!(E0284);
-        errors::DiagnosticId::Error(match self {
-            Self::E0282 => "E0282".to_string(),
-            Self::E0283 => "E0283".to_string(),
-            Self::E0284 => "E0284".to_string(),
-        })
+impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
+    fn into(self) -> rustc_errors::DiagnosticId {
+        match self {
+            Self::E0282 => rustc_errors::error_code!(E0282),
+            Self::E0283 => rustc_errors::error_code!(E0283),
+            Self::E0284 => rustc_errors::error_code!(E0284),
+        }
     }
 }
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
index cfb6d5b..d6e5020 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -6,6 +6,7 @@
 use crate::util::common::ErrorReported;
 
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when both the concerned regions are anonymous.
diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
index 0b22633..8e2592b 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -1,9 +1,10 @@
-use crate::hir;
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use crate::hir::Node;
+use crate::hir::map::Map;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::middle::resolve_lifetime as rl;
 use crate::ty::{self, Region, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::Node;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// This function calls the `visit_ty` method for the parameters
@@ -90,7 +91,9 @@
 }
 
 impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -207,7 +210,9 @@
 }
 
 impl Visitor<'tcx> for TyPathVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'tcx>> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
index 5da65a3..8749d6c 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
@@ -3,7 +3,7 @@
 use crate::infer::InferCtxt;
 use crate::ty::{self, TyCtxt};
 use crate::util::common::ErrorReported;
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_span::source_map::Span;
 
 mod different_lifetimes;
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 94b8d16..2344d40 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -1,9 +1,9 @@
 //! Error Reporting for Anonymous Region Lifetime Errors
 //! where one region is named and the other is anonymous.
-use crate::hir::{FunctionRetTy, TyKind};
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::ty;
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir::{FunctionRetTy, TyKind};
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
index 8914ff8..af0e5ef 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
@@ -1,13 +1,12 @@
 //! Error Reporting for Anonymous Region Lifetime Errors
 //! where both the regions are anonymous.
 
-use crate::hir::Node;
-use crate::hir::{Expr, ExprKind::Closure};
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
 use crate::infer::SubregionOrigin;
 use crate::ty::RegionKind;
 use crate::util::common::ErrorReported;
+use rustc_hir::{Expr, ExprKind::Closure, Node};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when binding escapes a closure.
diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
index e6758f6..7b31fe7 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -1,5 +1,3 @@
-use crate::hir::def::Namespace;
-use crate::hir::def_id::DefId;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::ValuePairs;
@@ -9,7 +7,9 @@
 use crate::ty::print::{FmtPrinter, Print, RegionHighlightMode};
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, TyCtxt};
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
+use rustc_hir::def::Namespace;
+use rustc_hir::def_id::DefId;
 
 use std::fmt::{self, Write};
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 69ebbe1..c6fc4cd 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -1,10 +1,11 @@
 //! Error Reporting for static impl Traits.
 
+use crate::infer::error_reporting::msg_span_from_free_region;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::ty::{BoundRegion, FreeRegion, RegionKind};
 use crate::util::common::ErrorReported;
-use errors::Applicability;
+use rustc_errors::Applicability;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
@@ -32,7 +33,7 @@
                     );
                     err.span_label(sup_origin.span(), "...but this borrow...");
 
-                    let (lifetime, lt_sp_opt) = self.tcx().msg_span_from_free_region(sup_r);
+                    let (lifetime, lt_sp_opt) = msg_span_from_free_region(self.tcx(), sup_r);
                     if let Some(lifetime_sp) = lt_sp_opt {
                         err.span_note(lifetime_sp, &format!("...can't outlive {}", lifetime));
                     }
diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs
index ece55c4..52ccb14 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/util.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs
@@ -1,10 +1,10 @@
 //! Helper functions corresponding to lifetime errors due to
 //! anonymous regions.
 
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::ty::{self, DefIdTree, Region, Ty};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 
 // The struct contains the information about the anonymous region
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index 979bcca..6303104 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -1,8 +1,9 @@
+use crate::infer::error_reporting::note_and_explain_region;
 use crate::infer::{self, InferCtxt, SubregionOrigin};
 use crate::middle::region;
 use crate::ty::error::TypeError;
 use crate::ty::{self, Region};
-use errors::DiagnosticBuilder;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 
 use rustc_error_codes::*;
 
@@ -167,8 +168,9 @@
             infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
                 let mut err = self.report_and_explain_type_error(trace, &terr);
-                self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "...");
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(self.tcx, region_scope_tree, &mut err, "", sup, "...");
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "...does not necessarily outlive ",
@@ -185,14 +187,16 @@
                     "lifetime of reference outlives lifetime of \
                                                 borrowed content..."
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "...the reference is valid for ",
                     sub,
                     "...",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "...but the borrowed content is only valid for ",
@@ -211,14 +215,16 @@
                                                 of captured variable `{}`...",
                     var_name
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "...the borrowed pointer is valid for ",
                     sub,
                     "...",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     &format!("...but `{}` is only valid for ", var_name),
@@ -230,14 +236,16 @@
             infer::InfStackClosure(span) => {
                 let mut err =
                     struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame");
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "...the closure must be valid for ",
                     sub,
                     "...",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "...but the closure's stack frame is only valid \
@@ -254,7 +262,8 @@
                     E0315,
                     "cannot invoke closure outside of its lifetime"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the closure is only valid for ",
@@ -270,7 +279,8 @@
                     E0473,
                     "dereference of reference outside its lifetime"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the reference is only valid for ",
@@ -288,14 +298,16 @@
                                                 enclosing closure",
                     self.tcx.hir().name(id)
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "captured variable is valid for ",
                     sup,
                     "",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "closure is valid for ",
@@ -311,7 +323,8 @@
                     E0475,
                     "index of slice outside its lifetime"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the slice is only valid for ",
@@ -328,14 +341,16 @@
                     "lifetime of the source pointer does not outlive \
                                                 lifetime bound of the object type"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "object type is valid for ",
                     sub,
                     "",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "source pointer is only valid for ",
@@ -354,14 +369,16 @@
                     self.ty_to_string(ty)
                 );
                 match *sub {
-                    ty::ReStatic => self.tcx.note_and_explain_region(
+                    ty::ReStatic => note_and_explain_region(
+                        self.tcx,
                         region_scope_tree,
                         &mut err,
                         "type must satisfy ",
                         sub,
                         "",
                     ),
-                    _ => self.tcx.note_and_explain_region(
+                    _ => note_and_explain_region(
+                        self.tcx,
                         region_scope_tree,
                         &mut err,
                         "type must outlive ",
@@ -374,14 +391,16 @@
             infer::RelateRegionParamBound(span) => {
                 let mut err =
                     struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "lifetime parameter instantiated with ",
                     sup,
                     "",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "but lifetime parameter must outlive ",
@@ -399,7 +418,8 @@
                                                 parameter) is not valid at this point",
                     self.ty_to_string(ty)
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "type must outlive ",
@@ -416,7 +436,8 @@
                     "lifetime of method receiver does not outlive the \
                                                 method call"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the receiver is only valid for ",
@@ -433,7 +454,8 @@
                     "lifetime of function argument does not outlive \
                                                 the function call"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the function argument is only valid for ",
@@ -450,7 +472,8 @@
                     "lifetime of return value does not outlive the \
                                                 function call"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the return value is only valid for ",
@@ -467,7 +490,8 @@
                     "lifetime of operand does not outlive the \
                                                 operation"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the operand is only valid for ",
@@ -483,7 +507,8 @@
                     E0484,
                     "reference is not valid at the time of borrow"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the borrow is only valid for ",
@@ -500,7 +525,8 @@
                     "automatically reference is not valid at the time \
                                                 of borrow"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the automatic borrow is only valid for ",
@@ -518,7 +544,8 @@
                                                 not valid during the expression: `{}`",
                     self.ty_to_string(t)
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "type is only valid for ",
@@ -536,14 +563,16 @@
                                                 called while references are dead"
                 );
                 // FIXME (22171): terms "super/subregion" are suboptimal
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "superregion: ",
                     sup,
                     "",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "subregion: ",
@@ -560,7 +589,8 @@
                     "lifetime of variable does not enclose its \
                                                 declaration"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the variable is only valid for ",
@@ -576,7 +606,8 @@
                     E0489,
                     "type/lifetime parameter not in scope here"
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the parameter is only valid for ",
@@ -593,14 +624,16 @@
                     "a value of type `{}` is borrowed for too long",
                     self.ty_to_string(ty)
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the type is valid for ",
                     sub,
                     "",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "but the borrow lasts for ",
@@ -618,14 +651,16 @@
                                                 than the data it references",
                     self.ty_to_string(ty)
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "the pointer is valid for ",
                     sub,
                     "",
                 );
-                self.tcx.note_and_explain_region(
+                note_and_explain_region(
+                    self.tcx,
                     region_scope_tree,
                     &mut err,
                     "but the referenced data is only valid for ",
diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs
index b7a3ff6..a930e70 100644
--- a/src/librustc/infer/lexical_region_resolve/graphviz.rs
+++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs
@@ -9,13 +9,13 @@
 use graphviz as dot;
 
 use super::Constraint;
-use crate::hir::def_id::DefIndex;
 use crate::infer::region_constraints::RegionConstraintData;
 use crate::infer::SubregionOrigin;
 use crate::middle::free_region::RegionRelations;
 use crate::middle::region;
 use crate::ty;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::DefIndex;
 
 use std::borrow::Cow;
 use std::collections::btree_map::BTreeMap;
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 3fd5d3b..0bc49a2 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -1,6 +1,5 @@
 //! Lexical region resolution.
 
-use crate::hir::def_id::DefId;
 use crate::infer::region_constraints::Constraint;
 use crate::infer::region_constraints::GenericKind;
 use crate::infer::region_constraints::MemberConstraint;
@@ -19,6 +18,7 @@
 use rustc_data_structures::graph::implementation::{
     Direction, Graph, NodeIndex, INCOMING, OUTGOING,
 };
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::Span;
@@ -204,9 +204,7 @@
         // want to stop at the first constraint that makes a change.
         let mut any_changed = false;
         for member_constraint in &self.data.member_constraints {
-            if self.enforce_member_constraint(graph, member_constraint, var_values) {
-                any_changed = true;
-            }
+            any_changed |= self.enforce_member_constraint(graph, member_constraint, var_values);
         }
         any_changed
     }
@@ -337,9 +335,7 @@
             for index in live_indices.iter() {
                 let constraint = constraints[index];
                 let (edge_changed, retain) = process_constraint(constraint);
-                if edge_changed {
-                    changed = true;
-                }
+                changed |= edge_changed;
                 if !retain {
                     let changed = killed_indices.insert(index);
                     debug_assert!(changed);
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 5c11659..f67669e 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -7,8 +7,6 @@
 pub use self::ValuePairs::*;
 pub use crate::ty::IntVarValue;
 
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::infer::canonical::{Canonical, CanonicalVarValues};
 use crate::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use crate::middle::free_region::RegionRelations;
@@ -23,10 +21,12 @@
 use crate::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
 use crate::ty::{ConstVid, FloatVid, IntVid, TyVid};
 
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unify as ut;
+use rustc_errors::DiagnosticBuilder;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use std::cell::{Cell, Ref, RefCell, RefMut};
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 638ab01..a1afb1a 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -1,17 +1,18 @@
-use crate::hir;
-use crate::hir::def_id::{DefId, DefIdMap};
-use crate::hir::Node;
-use crate::infer::outlives::free_region_map::FreeRegionRelations;
+use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region};
 use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
 use crate::middle::region;
 use crate::traits::{self, PredicateObligation};
 use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::free_region_map::FreeRegionRelations;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
 use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use errors::DiagnosticBuilder;
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, DefIdMap};
+use rustc_hir::Node;
 use rustc_span::Span;
 
 use rustc_error_codes::*;
@@ -349,7 +350,8 @@
             debug!("constrain_opaque_type: bounds={:#?}", bounds);
             let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
 
-            let required_region_bounds = tcx.required_region_bounds(opaque_type, bounds.predicates);
+            let required_region_bounds =
+                required_region_bounds(tcx, opaque_type, bounds.predicates);
             debug_assert!(!required_region_bounds.is_empty());
 
             for required_region in required_region_bounds {
@@ -522,11 +524,7 @@
         err.span_label(span, label);
 
         if nightly_options::is_nightly_build() {
-            help!(
-                err,
-                "add #![feature(member_constraints)] to the crate attributes \
-                   to enable"
-            );
+            err.help("add #![feature(member_constraints)] to the crate attributes to enable");
         }
 
         err.emit();
@@ -624,7 +622,8 @@
         //
         // (*) if not, the `tainted_by_errors` flag would be set to
         // true in any case, so we wouldn't be here at all.
-        tcx.note_and_explain_free_region(
+        note_and_explain_free_region(
+            tcx,
             &mut err,
             &format!("hidden type `{}` captures ", hidden_ty),
             hidden_region,
@@ -649,7 +648,8 @@
             // If the `region_scope_tree` is available, this is being
             // invoked from the "region inferencer error". We can at
             // least report a really cryptic error for now.
-            tcx.note_and_explain_region(
+            note_and_explain_region(
+                tcx,
                 region_scope_tree,
                 &mut err,
                 &format!("hidden type `{}` captures ", hidden_ty),
@@ -1130,7 +1130,7 @@
 
         debug!("instantiate_opaque_types: bounds={:?}", bounds);
 
-        let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone());
+        let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone());
         debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
 
         // Make sure that we are in fact defining the *entire* type
@@ -1225,3 +1225,67 @@
     );
     res
 }
+
+/// Given a set of predicates that apply to an object type, returns
+/// the region bounds that the (erased) `Self` type must
+/// outlive. Precisely *because* the `Self` type is erased, the
+/// parameter `erased_self_ty` must be supplied to indicate what type
+/// has been used to represent `Self` in the predicates
+/// themselves. This should really be a unique type; `FreshTy(0)` is a
+/// popular choice.
+///
+/// N.B., in some cases, particularly around higher-ranked bounds,
+/// this function returns a kind of conservative approximation.
+/// That is, all regions returned by this function are definitely
+/// required, but there may be other region bounds that are not
+/// returned, as well as requirements like `for<'a> T: 'a`.
+///
+/// Requires that trait definitions have been processed so that we can
+/// elaborate predicates and walk supertraits.
+//
+// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's
+// what this code should accept.
+crate fn required_region_bounds(
+    tcx: TyCtxt<'tcx>,
+    erased_self_ty: Ty<'tcx>,
+    predicates: Vec<ty::Predicate<'tcx>>,
+) -> Vec<ty::Region<'tcx>> {
+    debug!(
+        "required_region_bounds(erased_self_ty={:?}, predicates={:?})",
+        erased_self_ty, predicates
+    );
+
+    assert!(!erased_self_ty.has_escaping_bound_vars());
+
+    traits::elaborate_predicates(tcx, predicates)
+        .filter_map(|predicate| {
+            match predicate {
+                ty::Predicate::Projection(..)
+                | ty::Predicate::Trait(..)
+                | ty::Predicate::Subtype(..)
+                | ty::Predicate::WellFormed(..)
+                | ty::Predicate::ObjectSafe(..)
+                | ty::Predicate::ClosureKind(..)
+                | ty::Predicate::RegionOutlives(..)
+                | ty::Predicate::ConstEvaluatable(..) => None,
+                ty::Predicate::TypeOutlives(predicate) => {
+                    // Search for a bound of the form `erased_self_ty
+                    // : 'a`, but be wary of something like `for<'a>
+                    // erased_self_ty : 'a` (we interpret a
+                    // higher-ranked bound like that as 'static,
+                    // though at present the code in `fulfill.rs`
+                    // considers such bounds to be unsatisfiable, so
+                    // it's kind of a moot point since you could never
+                    // construct such an object, but this seems
+                    // correct even if that code changes).
+                    let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
+                    if t == &erased_self_ty && !r.has_escaping_bound_vars() {
+                        Some(*r)
+                    } else {
+                        None
+                    }
+                }
+            }
+        })
+        .collect()
+}
diff --git a/src/librustc/infer/outlives/env.rs b/src/librustc/infer/outlives/env.rs
index e27f1a8..ee2e629 100644
--- a/src/librustc/infer/outlives/env.rs
+++ b/src/librustc/infer/outlives/env.rs
@@ -1,9 +1,9 @@
-use crate::hir;
-use crate::infer::outlives::free_region_map::FreeRegionMap;
 use crate::infer::{GenericKind, InferCtxt};
 use crate::traits::query::outlives_bounds::{self, OutlivesBound};
+use crate::ty::free_region_map::FreeRegionMap;
 use crate::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
 use rustc_span::Span;
 
 /// The `OutlivesEnvironment` collects information about what outlives
diff --git a/src/librustc/infer/outlives/mod.rs b/src/librustc/infer/outlives/mod.rs
index e421d6f..6fc7247 100644
--- a/src/librustc/infer/outlives/mod.rs
+++ b/src/librustc/infer/outlives/mod.rs
@@ -1,6 +1,5 @@
 //! Various code related to computing outlives relations.
 
 pub mod env;
-pub mod free_region_map;
 pub mod obligations;
 pub mod verify;
diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs
index 4bafd2e..45e4a84 100644
--- a/src/librustc/infer/outlives/obligations.rs
+++ b/src/librustc/infer/outlives/obligations.rs
@@ -59,7 +59,6 @@
 //! might later infer `?U` to something like `&'b u32`, which would
 //! imply that `'b: 'a`.
 
-use crate::hir;
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::outlives::verify::VerifyBoundCx;
 use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
@@ -68,6 +67,7 @@
 use crate::ty::subst::GenericArgKind;
 use crate::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// Registers that the given region obligation must be resolved
diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs
index 828d4c2..8ee8482 100644
--- a/src/librustc/infer/outlives/verify.rs
+++ b/src/librustc/infer/outlives/verify.rs
@@ -1,10 +1,10 @@
-use crate::hir::def_id::DefId;
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::{GenericKind, VerifyBound};
 use crate::traits;
 use crate::ty::subst::{InternalSubsts, Subst};
 use crate::ty::{self, Ty, TyCtxt};
-use crate::util::captures::Captures;
+use rustc_data_structures::captures::Captures;
+use rustc_hir::def_id::DefId;
 
 /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
 /// obligation into a series of `'a: 'b` constraints and "verifys", as
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 323aa1f..f218bf1 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -6,7 +6,6 @@
 use super::unify_key;
 use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
 
-use crate::hir::def_id::DefId;
 use crate::ty::ReStatic;
 use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::{ReLateBound, ReVar};
@@ -14,6 +13,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unify as ut;
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_span::Span;
 
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index 27bcb63..089c6dd 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -1,5 +1,5 @@
-use crate::hir::def_id::DefId;
 use crate::ty::{self, Ty, TyVid};
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index ce8263f..2164a0b 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -31,7 +31,6 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(const_transmute)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
@@ -73,8 +72,6 @@
 #[macro_use]
 extern crate log;
 #[macro_use]
-extern crate syntax;
-#[macro_use]
 extern crate smallvec;
 
 #[cfg(test)]
@@ -101,7 +98,6 @@
 
 pub mod util {
     pub mod bug;
-    pub mod captures;
     pub mod common;
 }
 
diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs
new file mode 100644
index 0000000..2ed6cd5
--- /dev/null
+++ b/src/librustc/lint.rs
@@ -0,0 +1,369 @@
+use std::cmp;
+
+use crate::ich::StableHashingContext;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_hir::HirId;
+pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass};
+use rustc_session::{DiagnosticMessageId, Session};
+use rustc_span::hygiene::MacroKind;
+use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
+use rustc_span::{Span, Symbol};
+
+/// How a lint level was set.
+#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
+pub enum LintSource {
+    /// Lint is at the default level as declared
+    /// in rustc or a plugin.
+    Default,
+
+    /// Lint level was set by an attribute.
+    Node(Symbol, Span, Option<Symbol> /* RFC 2383 reason */),
+
+    /// Lint level was set by a command-line flag.
+    CommandLine(Symbol),
+}
+
+pub type LevelSource = (Level, LintSource);
+
+pub struct LintLevelSets {
+    pub list: Vec<LintSet>,
+    pub lint_cap: Level,
+}
+
+pub enum LintSet {
+    CommandLine {
+        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
+        // flag.
+        specs: FxHashMap<LintId, LevelSource>,
+    },
+
+    Node {
+        specs: FxHashMap<LintId, LevelSource>,
+        parent: u32,
+    },
+}
+
+impl LintLevelSets {
+    pub fn new() -> Self {
+        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
+    }
+
+    pub fn get_lint_level(
+        &self,
+        lint: &'static Lint,
+        idx: u32,
+        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        sess: &Session,
+    ) -> LevelSource {
+        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
+
+        // If `level` is none then we actually assume the default level for this
+        // lint.
+        let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));
+
+        // If we're about to issue a warning, check at the last minute for any
+        // directives against the warnings "lint". If, for example, there's an
+        // `allow(warnings)` in scope then we want to respect that instead.
+        if level == Level::Warn {
+            let (warnings_level, warnings_src) =
+                self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux);
+            if let Some(configured_warning_level) = warnings_level {
+                if configured_warning_level != Level::Warn {
+                    level = configured_warning_level;
+                    src = warnings_src;
+                }
+            }
+        }
+
+        // Ensure that we never exceed the `--cap-lints` argument.
+        level = cmp::min(level, self.lint_cap);
+
+        if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
+            // Ensure that we never exceed driver level.
+            level = cmp::min(*driver_level, level);
+        }
+
+        return (level, src);
+    }
+
+    pub fn get_lint_id_level(
+        &self,
+        id: LintId,
+        mut idx: u32,
+        aux: Option<&FxHashMap<LintId, LevelSource>>,
+    ) -> (Option<Level>, LintSource) {
+        if let Some(specs) = aux {
+            if let Some(&(level, src)) = specs.get(&id) {
+                return (Some(level), src);
+            }
+        }
+        loop {
+            match self.list[idx as usize] {
+                LintSet::CommandLine { ref specs } => {
+                    if let Some(&(level, src)) = specs.get(&id) {
+                        return (Some(level), src);
+                    }
+                    return (None, LintSource::Default);
+                }
+                LintSet::Node { ref specs, parent } => {
+                    if let Some(&(level, src)) = specs.get(&id) {
+                        return (Some(level), src);
+                    }
+                    idx = parent;
+                }
+            }
+        }
+    }
+}
+
+pub struct LintLevelMap {
+    pub sets: LintLevelSets,
+    pub id_to_set: FxHashMap<HirId, u32>,
+}
+
+impl LintLevelMap {
+    /// If the `id` was previously registered with `register_id` when building
+    /// this `LintLevelMap` this returns the corresponding lint level and source
+    /// of the lint level for the lint provided.
+    ///
+    /// If the `id` was not previously registered, returns `None`. If `None` is
+    /// returned then the parent of `id` should be acquired and this function
+    /// should be called again.
+    pub fn level_and_source(
+        &self,
+        lint: &'static Lint,
+        id: HirId,
+        session: &Session,
+    ) -> Option<LevelSource> {
+        self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
+    }
+}
+
+impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        let LintLevelMap { ref sets, ref id_to_set } = *self;
+
+        id_to_set.hash_stable(hcx, hasher);
+
+        let LintLevelSets { ref list, lint_cap } = *sets;
+
+        lint_cap.hash_stable(hcx, hasher);
+
+        hcx.while_hashing_spans(true, |hcx| {
+            list.len().hash_stable(hcx, hasher);
+
+            // We are working under the assumption here that the list of
+            // lint-sets is built in a deterministic order.
+            for lint_set in list {
+                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);
+
+                match *lint_set {
+                    LintSet::CommandLine { ref specs } => {
+                        specs.hash_stable(hcx, hasher);
+                    }
+                    LintSet::Node { ref specs, parent } => {
+                        specs.hash_stable(hcx, hasher);
+                        parent.hash_stable(hcx, hasher);
+                    }
+                }
+            }
+        })
+    }
+}
+
+pub fn struct_lint_level<'a>(
+    sess: &'a Session,
+    lint: &'static Lint,
+    level: Level,
+    src: LintSource,
+    span: Option<MultiSpan>,
+    msg: &str,
+) -> DiagnosticBuilder<'a> {
+    let mut err = match (level, span) {
+        (Level::Allow, _) => return sess.diagnostic().struct_dummy(),
+        (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg),
+        (Level::Warn, None) => sess.struct_warn(msg),
+        (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg),
+        (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg),
+    };
+
+    // Check for future incompatibility lints and issue a stronger warning.
+    let lint_id = LintId::of(lint);
+    let future_incompatible = lint.future_incompatible;
+
+    // If this code originates in a foreign macro, aka something that this crate
+    // did not itself author, then it's likely that there's nothing this crate
+    // can do about it. We probably want to skip the lint entirely.
+    if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
+        // Any suggestions made here are likely to be incorrect, so anything we
+        // emit shouldn't be automatically fixed by rustfix.
+        err.allow_suggestions(false);
+
+        // If this is a future incompatible lint it'll become a hard error, so
+        // we have to emit *something*. Also allow lints to whitelist themselves
+        // on a case-by-case basis for emission in a foreign macro.
+        if future_incompatible.is_none() && !lint.report_in_external_macro {
+            err.cancel();
+            // Don't continue further, since we don't want to have
+            // `diag_span_note_once` called for a diagnostic that isn't emitted.
+            return err;
+        }
+    }
+
+    let name = lint.name_lower();
+    match src {
+        LintSource::Default => {
+            sess.diag_note_once(
+                &mut err,
+                DiagnosticMessageId::from(lint),
+                &format!("`#[{}({})]` on by default", level.as_str(), name),
+            );
+        }
+        LintSource::CommandLine(lint_flag_val) => {
+            let flag = match level {
+                Level::Warn => "-W",
+                Level::Deny => "-D",
+                Level::Forbid => "-F",
+                Level::Allow => panic!(),
+            };
+            let hyphen_case_lint_name = name.replace("_", "-");
+            if lint_flag_val.as_str() == name {
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    &format!(
+                        "requested on the command line with `{} {}`",
+                        flag, hyphen_case_lint_name
+                    ),
+                );
+            } else {
+                let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    &format!(
+                        "`{} {}` implied by `{} {}`",
+                        flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
+                    ),
+                );
+            }
+        }
+        LintSource::Node(lint_attr_name, src, reason) => {
+            if let Some(rationale) = reason {
+                err.note(&rationale.as_str());
+            }
+            sess.diag_span_note_once(
+                &mut err,
+                DiagnosticMessageId::from(lint),
+                src,
+                "lint level defined here",
+            );
+            if lint_attr_name.as_str() != name {
+                let level_str = level.as_str();
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    &format!(
+                        "`#[{}({})]` implied by `#[{}({})]`",
+                        level_str, name, level_str, lint_attr_name
+                    ),
+                );
+            }
+        }
+    }
+
+    err.code(DiagnosticId::Lint(name));
+
+    if let Some(future_incompatible) = future_incompatible {
+        const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \
+             it will become a hard error";
+
+        let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
+            "once this method is added to the standard library, \
+             the ambiguity may cause an error or change in behavior!"
+                .to_owned()
+        } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
+            "this borrowing pattern was not meant to be accepted, \
+             and may become a hard error in the future"
+                .to_owned()
+        } else if let Some(edition) = future_incompatible.edition {
+            format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
+        } else {
+            format!("{} in a future release!", STANDARD_MESSAGE)
+        };
+        let citation = format!("for more information, see {}", future_incompatible.reference);
+        err.warn(&explanation);
+        err.note(&citation);
+    }
+
+    return err;
+}
+
+/// Returns whether `span` originates in a foreign crate's external macro.
+///
+/// This is used to test whether a lint should not even begin to figure out whether it should
+/// be reported on the current node.
+pub fn in_external_macro(sess: &Session, span: Span) -> bool {
+    let expn_data = span.ctxt().outer_expn_data();
+    match expn_data.kind {
+        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
+        ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
+        ExpnKind::Macro(MacroKind::Bang, _) => {
+            if expn_data.def_site.is_dummy() {
+                // Dummy span for the `def_site` means it's an external macro.
+                return true;
+            }
+            match sess.source_map().span_to_snippet(expn_data.def_site) {
+                Ok(code) => !code.starts_with("macro_rules"),
+                // No snippet means external macro or compiler-builtin expansion.
+                Err(_) => true,
+            }
+        }
+        ExpnKind::Macro(..) => true, // definitely a plugin
+    }
+}
+
+pub fn add_elided_lifetime_in_path_suggestion(
+    sess: &Session,
+    db: &mut DiagnosticBuilder<'_>,
+    n: usize,
+    path_span: Span,
+    incl_angl_brckt: bool,
+    insertion_span: Span,
+    anon_lts: String,
+) {
+    let (replace_span, suggestion) = if incl_angl_brckt {
+        (insertion_span, anon_lts)
+    } else {
+        // When possible, prefer a suggestion that replaces the whole
+        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
+        // at a point (which makes for an ugly/confusing label)
+        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
+            // But our spans can get out of whack due to macros; if the place we think
+            // we want to insert `'_` isn't even within the path expression's span, we
+            // should bail out of making any suggestion rather than panicking on a
+            // subtract-with-overflow or string-slice-out-out-bounds (!)
+            // FIXME: can we do better?
+            if insertion_span.lo().0 < path_span.lo().0 {
+                return;
+            }
+            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
+            if insertion_index > snippet.len() {
+                return;
+            }
+            let (before, after) = snippet.split_at(insertion_index);
+            (path_span, format!("{}{}{}", before, anon_lts, after))
+        } else {
+            (insertion_span, anon_lts)
+        }
+    };
+    db.span_suggestion(
+        replace_span,
+        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
+        suggestion,
+        Applicability::MachineApplicable,
+    );
+}
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
deleted file mode 100644
index 40e6f22..0000000
--- a/src/librustc/lint/levels.rs
+++ /dev/null
@@ -1,549 +0,0 @@
-use std::cmp;
-
-use crate::hir::HirId;
-use crate::ich::StableHashingContext;
-use crate::lint::builtin;
-use crate::lint::context::{CheckLintNameResult, LintStore};
-use crate::lint::{self, Level, Lint, LintId, LintSource};
-use crate::session::Session;
-use errors::{Applicability, DiagnosticBuilder};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_span::source_map::MultiSpan;
-use rustc_span::symbol::{sym, Symbol};
-use syntax::ast;
-use syntax::attr;
-use syntax::feature_gate;
-use syntax::print::pprust;
-
-use rustc_error_codes::*;
-
-pub struct LintLevelSets {
-    list: Vec<LintSet>,
-    lint_cap: Level,
-}
-
-enum LintSet {
-    CommandLine {
-        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
-        // flag.
-        specs: FxHashMap<LintId, (Level, LintSource)>,
-    },
-
-    Node {
-        specs: FxHashMap<LintId, (Level, LintSource)>,
-        parent: u32,
-    },
-}
-
-impl LintLevelSets {
-    pub fn new(sess: &Session, lint_store: &LintStore) -> LintLevelSets {
-        let mut me = LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid };
-        me.process_command_line(sess, lint_store);
-        return me;
-    }
-
-    pub fn builder<'a>(
-        sess: &'a Session,
-        warn_about_weird_lints: bool,
-        store: &LintStore,
-    ) -> LintLevelsBuilder<'a> {
-        LintLevelsBuilder::new(sess, warn_about_weird_lints, LintLevelSets::new(sess, store))
-    }
-
-    fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
-        let mut specs = FxHashMap::default();
-        self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
-
-        for &(ref lint_name, level) in &sess.opts.lint_opts {
-            store.check_lint_name_cmdline(sess, &lint_name, level);
-
-            // If the cap is less than this specified level, e.g., if we've got
-            // `--cap-lints allow` but we've also got `-D foo` then we ignore
-            // this specification as the lint cap will set it to allow anyway.
-            let level = cmp::min(level, self.lint_cap);
-
-            let lint_flag_val = Symbol::intern(lint_name);
-            let ids = match store.find_lints(&lint_name) {
-                Ok(ids) => ids,
-                Err(_) => continue, // errors handled in check_lint_name_cmdline above
-            };
-            for id in ids {
-                let src = LintSource::CommandLine(lint_flag_val);
-                specs.insert(id, (level, src));
-            }
-        }
-
-        self.list.push(LintSet::CommandLine { specs: specs });
-    }
-
-    fn get_lint_level(
-        &self,
-        lint: &'static Lint,
-        idx: u32,
-        aux: Option<&FxHashMap<LintId, (Level, LintSource)>>,
-        sess: &Session,
-    ) -> (Level, LintSource) {
-        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
-
-        // If `level` is none then we actually assume the default level for this
-        // lint.
-        let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));
-
-        // If we're about to issue a warning, check at the last minute for any
-        // directives against the warnings "lint". If, for example, there's an
-        // `allow(warnings)` in scope then we want to respect that instead.
-        if level == Level::Warn {
-            let (warnings_level, warnings_src) =
-                self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS), idx, aux);
-            if let Some(configured_warning_level) = warnings_level {
-                if configured_warning_level != Level::Warn {
-                    level = configured_warning_level;
-                    src = warnings_src;
-                }
-            }
-        }
-
-        // Ensure that we never exceed the `--cap-lints` argument.
-        level = cmp::min(level, self.lint_cap);
-
-        if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
-            // Ensure that we never exceed driver level.
-            level = cmp::min(*driver_level, level);
-        }
-
-        return (level, src);
-    }
-
-    fn get_lint_id_level(
-        &self,
-        id: LintId,
-        mut idx: u32,
-        aux: Option<&FxHashMap<LintId, (Level, LintSource)>>,
-    ) -> (Option<Level>, LintSource) {
-        if let Some(specs) = aux {
-            if let Some(&(level, src)) = specs.get(&id) {
-                return (Some(level), src);
-            }
-        }
-        loop {
-            match self.list[idx as usize] {
-                LintSet::CommandLine { ref specs } => {
-                    if let Some(&(level, src)) = specs.get(&id) {
-                        return (Some(level), src);
-                    }
-                    return (None, LintSource::Default);
-                }
-                LintSet::Node { ref specs, parent } => {
-                    if let Some(&(level, src)) = specs.get(&id) {
-                        return (Some(level), src);
-                    }
-                    idx = parent;
-                }
-            }
-        }
-    }
-}
-
-pub struct LintLevelsBuilder<'a> {
-    sess: &'a Session,
-    sets: LintLevelSets,
-    id_to_set: FxHashMap<HirId, u32>,
-    cur: u32,
-    warn_about_weird_lints: bool,
-}
-
-pub struct BuilderPush {
-    prev: u32,
-    pub changed: bool,
-}
-
-impl<'a> LintLevelsBuilder<'a> {
-    pub fn new(
-        sess: &'a Session,
-        warn_about_weird_lints: bool,
-        sets: LintLevelSets,
-    ) -> LintLevelsBuilder<'a> {
-        assert_eq!(sets.list.len(), 1);
-        LintLevelsBuilder {
-            sess,
-            sets,
-            cur: 0,
-            id_to_set: Default::default(),
-            warn_about_weird_lints,
-        }
-    }
-
-    /// Pushes a list of AST lint attributes onto this context.
-    ///
-    /// This function will return a `BuilderPush` object which should be passed
-    /// to `pop` when this scope for the attributes provided is exited.
-    ///
-    /// This function will perform a number of tasks:
-    ///
-    /// * It'll validate all lint-related attributes in `attrs`
-    /// * It'll mark all lint-related attributes as used
-    /// * Lint levels will be updated based on the attributes provided
-    /// * Lint attributes are validated, e.g., a #[forbid] can't be switched to
-    ///   #[allow]
-    ///
-    /// Don't forget to call `pop`!
-    pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush {
-        let mut specs = FxHashMap::default();
-        let sess = self.sess;
-        let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
-        for attr in attrs {
-            let level = match Level::from_symbol(attr.name_or_empty()) {
-                None => continue,
-                Some(lvl) => lvl,
-            };
-
-            let meta = unwrap_or!(attr.meta(), continue);
-            attr::mark_used(attr);
-
-            let mut metas = unwrap_or!(meta.meta_item_list(), continue);
-
-            if metas.is_empty() {
-                // FIXME (#55112): issue unused-attributes lint for `#[level()]`
-                continue;
-            }
-
-            // Before processing the lint names, look for a reason (RFC 2383)
-            // at the end.
-            let mut reason = None;
-            let tail_li = &metas[metas.len() - 1];
-            if let Some(item) = tail_li.meta_item() {
-                match item.kind {
-                    ast::MetaItemKind::Word => {} // actual lint names handled later
-                    ast::MetaItemKind::NameValue(ref name_value) => {
-                        if item.path == sym::reason {
-                            // found reason, reslice meta list to exclude it
-                            metas = &metas[0..metas.len() - 1];
-                            // FIXME (#55112): issue unused-attributes lint if we thereby
-                            // don't have any lint names (`#[level(reason = "foo")]`)
-                            if let ast::LitKind::Str(rationale, _) = name_value.kind {
-                                if !self.sess.features_untracked().lint_reasons {
-                                    feature_gate::feature_err(
-                                        &self.sess.parse_sess,
-                                        sym::lint_reasons,
-                                        item.span,
-                                        "lint reasons are experimental",
-                                    )
-                                    .emit();
-                                }
-                                reason = Some(rationale);
-                            } else {
-                                bad_attr(name_value.span)
-                                    .span_label(name_value.span, "reason must be a string literal")
-                                    .emit();
-                            }
-                        } else {
-                            bad_attr(item.span)
-                                .span_label(item.span, "bad attribute argument")
-                                .emit();
-                        }
-                    }
-                    ast::MetaItemKind::List(_) => {
-                        bad_attr(item.span).span_label(item.span, "bad attribute argument").emit();
-                    }
-                }
-            }
-
-            for li in metas {
-                let meta_item = match li.meta_item() {
-                    Some(meta_item) if meta_item.is_word() => meta_item,
-                    _ => {
-                        let sp = li.span();
-                        let mut err = bad_attr(sp);
-                        let mut add_label = true;
-                        if let Some(item) = li.meta_item() {
-                            if let ast::MetaItemKind::NameValue(_) = item.kind {
-                                if item.path == sym::reason {
-                                    err.span_label(sp, "reason in lint attribute must come last");
-                                    add_label = false;
-                                }
-                            }
-                        }
-                        if add_label {
-                            err.span_label(sp, "bad attribute argument");
-                        }
-                        err.emit();
-                        continue;
-                    }
-                };
-                let tool_name = if meta_item.path.segments.len() > 1 {
-                    let tool_ident = meta_item.path.segments[0].ident;
-                    if !attr::is_known_lint_tool(tool_ident) {
-                        span_err!(
-                            sess,
-                            tool_ident.span,
-                            E0710,
-                            "an unknown tool name found in scoped lint: `{}`",
-                            pprust::path_to_string(&meta_item.path),
-                        );
-                        continue;
-                    }
-
-                    Some(tool_ident.name)
-                } else {
-                    None
-                };
-                let name = meta_item.path.segments.last().expect("empty lint name").ident.name;
-                match store.check_lint_name(&name.as_str(), tool_name) {
-                    CheckLintNameResult::Ok(ids) => {
-                        let src = LintSource::Node(name, li.span(), reason);
-                        for id in ids {
-                            specs.insert(*id, (level, src));
-                        }
-                    }
-
-                    CheckLintNameResult::Tool(result) => {
-                        match result {
-                            Ok(ids) => {
-                                let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
-                                let src = LintSource::Node(
-                                    Symbol::intern(complete_name),
-                                    li.span(),
-                                    reason,
-                                );
-                                for id in ids {
-                                    specs.insert(*id, (level, src));
-                                }
-                            }
-                            Err((Some(ids), new_lint_name)) => {
-                                let lint = builtin::RENAMED_AND_REMOVED_LINTS;
-                                let (lvl, src) =
-                                    self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
-                                let msg = format!(
-                                    "lint name `{}` is deprecated \
-                                     and may not have an effect in the future. \
-                                     Also `cfg_attr(cargo-clippy)` won't be necessary anymore",
-                                    name
-                                );
-                                lint::struct_lint_level(
-                                    self.sess,
-                                    lint,
-                                    lvl,
-                                    src,
-                                    Some(li.span().into()),
-                                    &msg,
-                                )
-                                .span_suggestion(
-                                    li.span(),
-                                    "change it to",
-                                    new_lint_name.to_string(),
-                                    Applicability::MachineApplicable,
-                                )
-                                .emit();
-
-                                let src = LintSource::Node(
-                                    Symbol::intern(&new_lint_name),
-                                    li.span(),
-                                    reason,
-                                );
-                                for id in ids {
-                                    specs.insert(*id, (level, src));
-                                }
-                            }
-                            Err((None, _)) => {
-                                // If Tool(Err(None, _)) is returned, then either the lint does not
-                                // exist in the tool or the code was not compiled with the tool and
-                                // therefore the lint was never added to the `LintStore`. To detect
-                                // this is the responsibility of the lint tool.
-                            }
-                        }
-                    }
-
-                    _ if !self.warn_about_weird_lints => {}
-
-                    CheckLintNameResult::Warning(msg, renamed) => {
-                        let lint = builtin::RENAMED_AND_REMOVED_LINTS;
-                        let (level, src) =
-                            self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
-                        let mut err = lint::struct_lint_level(
-                            self.sess,
-                            lint,
-                            level,
-                            src,
-                            Some(li.span().into()),
-                            &msg,
-                        );
-                        if let Some(new_name) = renamed {
-                            err.span_suggestion(
-                                li.span(),
-                                "use the new name",
-                                new_name,
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                        err.emit();
-                    }
-                    CheckLintNameResult::NoLint(suggestion) => {
-                        let lint = builtin::UNKNOWN_LINTS;
-                        let (level, src) =
-                            self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
-                        let msg = format!("unknown lint: `{}`", name);
-                        let mut db = lint::struct_lint_level(
-                            self.sess,
-                            lint,
-                            level,
-                            src,
-                            Some(li.span().into()),
-                            &msg,
-                        );
-
-                        if let Some(suggestion) = suggestion {
-                            db.span_suggestion(
-                                li.span(),
-                                "did you mean",
-                                suggestion.to_string(),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-
-                        db.emit();
-                    }
-                }
-            }
-        }
-
-        for (id, &(level, ref src)) in specs.iter() {
-            if level == Level::Forbid {
-                continue;
-            }
-            let forbid_src = match self.sets.get_lint_id_level(*id, self.cur, None) {
-                (Some(Level::Forbid), src) => src,
-                _ => continue,
-            };
-            let forbidden_lint_name = match forbid_src {
-                LintSource::Default => id.to_string(),
-                LintSource::Node(name, _, _) => name.to_string(),
-                LintSource::CommandLine(name) => name.to_string(),
-            };
-            let (lint_attr_name, lint_attr_span) = match *src {
-                LintSource::Node(name, span, _) => (name, span),
-                _ => continue,
-            };
-            let mut diag_builder = struct_span_err!(
-                self.sess,
-                lint_attr_span,
-                E0453,
-                "{}({}) overruled by outer forbid({})",
-                level.as_str(),
-                lint_attr_name,
-                forbidden_lint_name
-            );
-            diag_builder.span_label(lint_attr_span, "overruled by previous forbid");
-            match forbid_src {
-                LintSource::Default => {}
-                LintSource::Node(_, forbid_source_span, reason) => {
-                    diag_builder.span_label(forbid_source_span, "`forbid` level set here");
-                    if let Some(rationale) = reason {
-                        diag_builder.note(&rationale.as_str());
-                    }
-                }
-                LintSource::CommandLine(_) => {
-                    diag_builder.note("`forbid` lint level was set on command line");
-                }
-            }
-            diag_builder.emit();
-            // don't set a separate error for every lint in the group
-            break;
-        }
-
-        let prev = self.cur;
-        if specs.len() > 0 {
-            self.cur = self.sets.list.len() as u32;
-            self.sets.list.push(LintSet::Node { specs: specs, parent: prev });
-        }
-
-        BuilderPush { prev: prev, changed: prev != self.cur }
-    }
-
-    /// Called after `push` when the scope of a set of attributes are exited.
-    pub fn pop(&mut self, push: BuilderPush) {
-        self.cur = push.prev;
-    }
-
-    /// Used to emit a lint-related diagnostic based on the current state of
-    /// this lint context.
-    pub fn struct_lint(
-        &self,
-        lint: &'static Lint,
-        span: Option<MultiSpan>,
-        msg: &str,
-    ) -> DiagnosticBuilder<'a> {
-        let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess);
-        lint::struct_lint_level(self.sess, lint, level, src, span, msg)
-    }
-
-    /// Registers the ID provided with the current set of lints stored in
-    /// this context.
-    pub fn register_id(&mut self, id: HirId) {
-        self.id_to_set.insert(id, self.cur);
-    }
-
-    pub fn build(self) -> LintLevelSets {
-        self.sets
-    }
-
-    pub fn build_map(self) -> LintLevelMap {
-        LintLevelMap { sets: self.sets, id_to_set: self.id_to_set }
-    }
-}
-
-pub struct LintLevelMap {
-    sets: LintLevelSets,
-    id_to_set: FxHashMap<HirId, u32>,
-}
-
-impl LintLevelMap {
-    /// If the `id` was previously registered with `register_id` when building
-    /// this `LintLevelMap` this returns the corresponding lint level and source
-    /// of the lint level for the lint provided.
-    ///
-    /// If the `id` was not previously registered, returns `None`. If `None` is
-    /// returned then the parent of `id` should be acquired and this function
-    /// should be called again.
-    pub fn level_and_source(
-        &self,
-        lint: &'static Lint,
-        id: HirId,
-        session: &Session,
-    ) -> Option<(Level, LintSource)> {
-        self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let LintLevelMap { ref sets, ref id_to_set } = *self;
-
-        id_to_set.hash_stable(hcx, hasher);
-
-        let LintLevelSets { ref list, lint_cap } = *sets;
-
-        lint_cap.hash_stable(hcx, hasher);
-
-        hcx.while_hashing_spans(true, |hcx| {
-            list.len().hash_stable(hcx, hasher);
-
-            // We are working under the assumption here that the list of
-            // lint-sets is built in a deterministic order.
-            for lint_set in list {
-                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);
-
-                match *lint_set {
-                    LintSet::CommandLine { ref specs } => {
-                        specs.hash_stable(hcx, hasher);
-                    }
-                    LintSet::Node { ref specs, parent } => {
-                        specs.hash_stable(hcx, hasher);
-                        parent.hash_stable(hcx, hasher);
-                    }
-                }
-            }
-        })
-    }
-}
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
deleted file mode 100644
index 3c55669..0000000
--- a/src/librustc/lint/mod.rs
+++ /dev/null
@@ -1,593 +0,0 @@
-//! Lints, aka compiler warnings.
-//!
-//! A 'lint' check is a kind of miscellaneous constraint that a user _might_
-//! want to enforce, but might reasonably want to permit as well, on a
-//! module-by-module basis. They contrast with static constraints enforced by
-//! other phases of the compiler, which are generally required to hold in order
-//! to compile the program at all.
-//!
-//! Most lints can be written as `LintPass` instances. These run after
-//! all other analyses. The `LintPass`es built into rustc are defined
-//! within `builtin.rs`, which has further comments on how to add such a lint.
-//! rustc can also load user-defined lint plugins via the plugin mechanism.
-//!
-//! Some of rustc's lints are defined elsewhere in the compiler and work by
-//! calling `add_lint()` on the overall `Session` object. This works when
-//! it happens before the main lint pass, which emits the lints stored by
-//! `add_lint()`. To emit lints after the main lint pass (from codegen, for
-//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
-//! in `context.rs`.
-
-pub use self::Level::*;
-pub use self::LintSource::*;
-
-use rustc_data_structures::sync;
-
-use crate::hir;
-use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::ty::TyCtxt;
-use errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_session::node_id::NodeMap;
-use rustc_session::{DiagnosticMessageId, Session};
-use rustc_span::hygiene::MacroKind;
-use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-use syntax::ast;
-
-pub use crate::lint::context::{
-    BufferedEarlyLint, CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore,
-};
-
-pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
-
-/// Declares a static `LintArray` and return it as an expression.
-#[macro_export]
-macro_rules! lint_array {
-    ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
-    ($( $lint:expr ),*) => {{
-        vec![$($lint),*]
-    }}
-}
-
-pub type LintArray = Vec<&'static Lint>;
-
-pub trait LintPass {
-    fn name(&self) -> &'static str;
-}
-
-/// Implements `LintPass for $name` with the given list of `Lint` statics.
-#[macro_export]
-macro_rules! impl_lint_pass {
-    ($name:ident => [$($lint:expr),* $(,)?]) => {
-        impl LintPass for $name {
-            fn name(&self) -> &'static str { stringify!($name) }
-        }
-        impl $name {
-            pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) }
-        }
-    };
-}
-
-/// Declares a type named `$name` which implements `LintPass`.
-/// To the right of `=>` a comma separated list of `Lint` statics is given.
-#[macro_export]
-macro_rules! declare_lint_pass {
-    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
-        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
-        $crate::impl_lint_pass!($name => [$($lint),*]);
-    };
-}
-
-#[macro_export]
-macro_rules! late_lint_methods {
-    ($macro:path, $args:tt, [$hir:tt]) => (
-        $macro!($args, [$hir], [
-            fn check_param(a: &$hir hir::Param<$hir>);
-            fn check_body(a: &$hir hir::Body<$hir>);
-            fn check_body_post(a: &$hir hir::Body<$hir>);
-            fn check_name(a: Span, b: ast::Name);
-            fn check_crate(a: &$hir hir::Crate<$hir>);
-            fn check_crate_post(a: &$hir hir::Crate<$hir>);
-            fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
-            fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
-            fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
-            fn check_foreign_item_post(a: &$hir hir::ForeignItem<$hir>);
-            fn check_item(a: &$hir hir::Item<$hir>);
-            fn check_item_post(a: &$hir hir::Item<$hir>);
-            fn check_local(a: &$hir hir::Local<$hir>);
-            fn check_block(a: &$hir hir::Block<$hir>);
-            fn check_block_post(a: &$hir hir::Block<$hir>);
-            fn check_stmt(a: &$hir hir::Stmt<$hir>);
-            fn check_arm(a: &$hir hir::Arm<$hir>);
-            fn check_pat(a: &$hir hir::Pat<$hir>);
-            fn check_expr(a: &$hir hir::Expr<$hir>);
-            fn check_expr_post(a: &$hir hir::Expr<$hir>);
-            fn check_ty(a: &$hir hir::Ty<$hir>);
-            fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
-            fn check_generics(a: &$hir hir::Generics<$hir>);
-            fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>);
-            fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>, b: hir::TraitBoundModifier);
-            fn check_fn(
-                a: hir::intravisit::FnKind<$hir>,
-                b: &$hir hir::FnDecl<$hir>,
-                c: &$hir hir::Body<$hir>,
-                d: Span,
-                e: hir::HirId);
-            fn check_fn_post(
-                a: hir::intravisit::FnKind<$hir>,
-                b: &$hir hir::FnDecl<$hir>,
-                c: &$hir hir::Body<$hir>,
-                d: Span,
-                e: hir::HirId
-            );
-            fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
-            fn check_trait_item_post(a: &$hir hir::TraitItem<$hir>);
-            fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
-            fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
-            fn check_struct_def(a: &$hir hir::VariantData<$hir>);
-            fn check_struct_def_post(a: &$hir hir::VariantData<$hir>);
-            fn check_struct_field(a: &$hir hir::StructField<$hir>);
-            fn check_variant(a: &$hir hir::Variant<$hir>);
-            fn check_variant_post(a: &$hir hir::Variant<$hir>);
-            fn check_lifetime(a: &$hir hir::Lifetime);
-            fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
-            fn check_attribute(a: &$hir ast::Attribute);
-
-            /// Called when entering a syntax node that can have lint attributes such
-            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
-            fn enter_lint_attrs(a: &$hir [ast::Attribute]);
-
-            /// Counterpart to `enter_lint_attrs`.
-            fn exit_lint_attrs(a: &$hir [ast::Attribute]);
-        ]);
-    )
-}
-
-/// Trait for types providing lint checks.
-///
-/// Each `check` method checks a single syntax node, and should not
-/// invoke methods recursively (unlike `Visitor`). By default they
-/// do nothing.
-//
-// FIXME: eliminate the duplication with `Visitor`. But this also
-// contains a few lint-specific methods with no equivalent in `Visitor`.
-
-macro_rules! expand_lint_pass_methods {
-    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
-    )
-}
-
-macro_rules! declare_late_lint_pass {
-    ([], [$hir:tt], [$($methods:tt)*]) => (
-        pub trait LateLintPass<'a, $hir>: LintPass {
-            expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]);
-        }
-    )
-}
-
-late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
-
-#[macro_export]
-macro_rules! expand_combined_late_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
-    })
-}
-
-#[macro_export]
-macro_rules! expand_combined_late_lint_pass_methods {
-    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(fn $name(&mut self, context: &LateContext<'a, 'tcx>, $($param: $arg),*) {
-            expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
-        })*
-    )
-}
-
-#[macro_export]
-macro_rules! declare_combined_late_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
-        #[allow(non_snake_case)]
-        $v struct $name {
-            $($passes: $passes,)*
-        }
-
-        impl $name {
-            $v fn new() -> Self {
-                Self {
-                    $($passes: $constructor,)*
-                }
-            }
-
-            $v fn get_lints() -> LintArray {
-                let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
-                lints
-            }
-        }
-
-        impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name {
-            expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
-        }
-
-        impl LintPass for $name {
-            fn name(&self) -> &'static str {
-                panic!()
-            }
-        }
-    )
-}
-
-#[macro_export]
-macro_rules! early_lint_methods {
-    ($macro:path, $args:tt) => (
-        $macro!($args, [
-            fn check_param(a: &ast::Param);
-            fn check_ident(a: ast::Ident);
-            fn check_crate(a: &ast::Crate);
-            fn check_crate_post(a: &ast::Crate);
-            fn check_mod(a: &ast::Mod, b: Span, c: ast::NodeId);
-            fn check_mod_post(a: &ast::Mod, b: Span, c: ast::NodeId);
-            fn check_foreign_item(a: &ast::ForeignItem);
-            fn check_foreign_item_post(a: &ast::ForeignItem);
-            fn check_item(a: &ast::Item);
-            fn check_item_post(a: &ast::Item);
-            fn check_local(a: &ast::Local);
-            fn check_block(a: &ast::Block);
-            fn check_block_post(a: &ast::Block);
-            fn check_stmt(a: &ast::Stmt);
-            fn check_arm(a: &ast::Arm);
-            fn check_pat(a: &ast::Pat);
-            fn check_pat_post(a: &ast::Pat);
-            fn check_expr(a: &ast::Expr);
-            fn check_expr_post(a: &ast::Expr);
-            fn check_ty(a: &ast::Ty);
-            fn check_generic_param(a: &ast::GenericParam);
-            fn check_generics(a: &ast::Generics);
-            fn check_where_predicate(a: &ast::WherePredicate);
-            fn check_poly_trait_ref(a: &ast::PolyTraitRef,
-                                    b: &ast::TraitBoundModifier);
-            fn check_fn(a: syntax::visit::FnKind<'_>, b: &ast::FnDecl, c: Span, d_: ast::NodeId);
-            fn check_fn_post(
-                a: syntax::visit::FnKind<'_>,
-                b: &ast::FnDecl,
-                c: Span,
-                d: ast::NodeId
-            );
-            fn check_trait_item(a: &ast::AssocItem);
-            fn check_trait_item_post(a: &ast::AssocItem);
-            fn check_impl_item(a: &ast::AssocItem);
-            fn check_impl_item_post(a: &ast::AssocItem);
-            fn check_struct_def(a: &ast::VariantData);
-            fn check_struct_def_post(a: &ast::VariantData);
-            fn check_struct_field(a: &ast::StructField);
-            fn check_variant(a: &ast::Variant);
-            fn check_variant_post(a: &ast::Variant);
-            fn check_lifetime(a: &ast::Lifetime);
-            fn check_path(a: &ast::Path, b: ast::NodeId);
-            fn check_attribute(a: &ast::Attribute);
-            fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
-            fn check_mac(a: &ast::Mac);
-
-            /// Called when entering a syntax node that can have lint attributes such
-            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
-            fn enter_lint_attrs(a: &[ast::Attribute]);
-
-            /// Counterpart to `enter_lint_attrs`.
-            fn exit_lint_attrs(a: &[ast::Attribute]);
-        ]);
-    )
-}
-
-macro_rules! expand_early_lint_pass_methods {
-    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
-    )
-}
-
-macro_rules! declare_early_lint_pass {
-    ([], [$($methods:tt)*]) => (
-        pub trait EarlyLintPass: LintPass {
-            expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
-        }
-    )
-}
-
-early_lint_methods!(declare_early_lint_pass, []);
-
-#[macro_export]
-macro_rules! expand_combined_early_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
-    })
-}
-
-#[macro_export]
-macro_rules! expand_combined_early_lint_pass_methods {
-    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
-            expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
-        })*
-    )
-}
-
-#[macro_export]
-macro_rules! declare_combined_early_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
-        #[allow(non_snake_case)]
-        $v struct $name {
-            $($passes: $passes,)*
-        }
-
-        impl $name {
-            $v fn new() -> Self {
-                Self {
-                    $($passes: $constructor,)*
-                }
-            }
-
-            $v fn get_lints() -> LintArray {
-                let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
-                lints
-            }
-        }
-
-        impl EarlyLintPass for $name {
-            expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
-        }
-
-        impl LintPass for $name {
-            fn name(&self) -> &'static str {
-                panic!()
-            }
-        }
-    )
-}
-
-/// A lint pass boxed up as a trait object.
-pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
-pub type LateLintPassObject =
-    Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send + sync::Sync + 'static>;
-
-/// How a lint level was set.
-#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
-pub enum LintSource {
-    /// Lint is at the default level as declared
-    /// in rustc or a plugin.
-    Default,
-
-    /// Lint level was set by an attribute.
-    Node(ast::Name, Span, Option<Symbol> /* RFC 2383 reason */),
-
-    /// Lint level was set by a command-line flag.
-    CommandLine(Symbol),
-}
-
-pub type LevelSource = (Level, LintSource);
-
-pub mod builtin;
-mod context;
-pub mod internal;
-mod levels;
-
-pub use self::levels::{LintLevelMap, LintLevelSets, LintLevelsBuilder};
-
-#[derive(Default)]
-pub struct LintBuffer {
-    pub map: NodeMap<Vec<BufferedEarlyLint>>,
-}
-
-impl LintBuffer {
-    pub fn add_lint(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: MultiSpan,
-        msg: &str,
-        diagnostic: BuiltinLintDiagnostics,
-    ) {
-        let early_lint = BufferedEarlyLint {
-            lint_id: LintId::of(lint),
-            ast_id: id,
-            span: sp,
-            msg: msg.to_string(),
-            diagnostic,
-        };
-        let arr = self.map.entry(id).or_default();
-        if !arr.contains(&early_lint) {
-            arr.push(early_lint);
-        }
-    }
-
-    pub fn take(&mut self, id: ast::NodeId) -> Vec<BufferedEarlyLint> {
-        self.map.remove(&id).unwrap_or_default()
-    }
-
-    pub fn buffer_lint<S: Into<MultiSpan>>(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: S,
-        msg: &str,
-    ) {
-        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
-    }
-
-    pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: S,
-        msg: &str,
-        diagnostic: BuiltinLintDiagnostics,
-    ) {
-        self.add_lint(lint, id, sp.into(), msg, diagnostic)
-    }
-}
-
-pub fn struct_lint_level<'a>(
-    sess: &'a Session,
-    lint: &'static Lint,
-    level: Level,
-    src: LintSource,
-    span: Option<MultiSpan>,
-    msg: &str,
-) -> DiagnosticBuilder<'a> {
-    let mut err = match (level, span) {
-        (Level::Allow, _) => return sess.diagnostic().struct_dummy(),
-        (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg),
-        (Level::Warn, None) => sess.struct_warn(msg),
-        (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg),
-        (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg),
-    };
-
-    // Check for future incompatibility lints and issue a stronger warning.
-    let lint_id = LintId::of(lint);
-    let future_incompatible = lint.future_incompatible;
-
-    // If this code originates in a foreign macro, aka something that this crate
-    // did not itself author, then it's likely that there's nothing this crate
-    // can do about it. We probably want to skip the lint entirely.
-    if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
-        // Any suggestions made here are likely to be incorrect, so anything we
-        // emit shouldn't be automatically fixed by rustfix.
-        err.allow_suggestions(false);
-
-        // If this is a future incompatible lint it'll become a hard error, so
-        // we have to emit *something*. Also allow lints to whitelist themselves
-        // on a case-by-case basis for emission in a foreign macro.
-        if future_incompatible.is_none() && !lint.report_in_external_macro {
-            err.cancel();
-            // Don't continue further, since we don't want to have
-            // `diag_span_note_once` called for a diagnostic that isn't emitted.
-            return err;
-        }
-    }
-
-    let name = lint.name_lower();
-    match src {
-        LintSource::Default => {
-            sess.diag_note_once(
-                &mut err,
-                DiagnosticMessageId::from(lint),
-                &format!("`#[{}({})]` on by default", level.as_str(), name),
-            );
-        }
-        LintSource::CommandLine(lint_flag_val) => {
-            let flag = match level {
-                Level::Warn => "-W",
-                Level::Deny => "-D",
-                Level::Forbid => "-F",
-                Level::Allow => panic!(),
-            };
-            let hyphen_case_lint_name = name.replace("_", "-");
-            if lint_flag_val.as_str() == name {
-                sess.diag_note_once(
-                    &mut err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "requested on the command line with `{} {}`",
-                        flag, hyphen_case_lint_name
-                    ),
-                );
-            } else {
-                let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
-                sess.diag_note_once(
-                    &mut err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`{} {}` implied by `{} {}`",
-                        flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
-                    ),
-                );
-            }
-        }
-        LintSource::Node(lint_attr_name, src, reason) => {
-            if let Some(rationale) = reason {
-                err.note(&rationale.as_str());
-            }
-            sess.diag_span_note_once(
-                &mut err,
-                DiagnosticMessageId::from(lint),
-                src,
-                "lint level defined here",
-            );
-            if lint_attr_name.as_str() != name {
-                let level_str = level.as_str();
-                sess.diag_note_once(
-                    &mut err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`#[{}({})]` implied by `#[{}({})]`",
-                        level_str, name, level_str, lint_attr_name
-                    ),
-                );
-            }
-        }
-    }
-
-    err.code(DiagnosticId::Lint(name));
-
-    if let Some(future_incompatible) = future_incompatible {
-        const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \
-             it will become a hard error";
-
-        let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
-            "once this method is added to the standard library, \
-             the ambiguity may cause an error or change in behavior!"
-                .to_owned()
-        } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
-            "this borrowing pattern was not meant to be accepted, \
-             and may become a hard error in the future"
-                .to_owned()
-        } else if let Some(edition) = future_incompatible.edition {
-            format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
-        } else {
-            format!("{} in a future release!", STANDARD_MESSAGE)
-        };
-        let citation = format!("for more information, see {}", future_incompatible.reference);
-        err.warn(&explanation);
-        err.note(&citation);
-    }
-
-    return err;
-}
-
-pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
-    let attrs = tcx.hir().attrs(id);
-    attrs.iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some())
-}
-
-/// Returns whether `span` originates in a foreign crate's external macro.
-///
-/// This is used to test whether a lint should not even begin to figure out whether it should
-/// be reported on the current node.
-pub fn in_external_macro(sess: &Session, span: Span) -> bool {
-    let expn_data = span.ctxt().outer_expn_data();
-    match expn_data.kind {
-        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
-        ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
-        ExpnKind::Macro(MacroKind::Bang, _) => {
-            if expn_data.def_site.is_dummy() {
-                // Dummy span for the `def_site` means it's an external macro.
-                return true;
-            }
-            match sess.source_map().span_to_snippet(expn_data.def_site) {
-                Ok(code) => !code.starts_with("macro_rules"),
-                // No snippet means external macro or compiler-builtin expansion.
-                Err(_) => true,
-            }
-        }
-        ExpnKind::Macro(..) => true, // definitely a plugin
-    }
-}
-
-/// Returns `true` if `span` originates in a derive-macro's expansion.
-pub fn in_derive_expansion(span: Span) -> bool {
-    if let ExpnKind::Macro(MacroKind::Derive, _) = span.ctxt().outer_expn_data().kind {
-        return true;
-    }
-    false
-}
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index be7603f..5b1e767 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -2,15 +2,15 @@
 //! are *mostly* used as a part of that interface, but these should
 //! probably get a better home if someone can find one.
 
-use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use crate::hir::map as hir_map;
 use crate::hir::map::definitions::{DefKey, DefPathTable};
 use crate::session::search_paths::PathKind;
-use crate::session::{CrateDisambiguator, Session};
-use crate::ty::{self, TyCtxt};
-use rustc_data_structures::svh::Svh;
+use crate::session::CrateDisambiguator;
+use crate::ty::TyCtxt;
 
+use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, MetadataRef};
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_macros::HashStable;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -208,7 +208,6 @@
     fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
     fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
-    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
 
     // This is basically a 1-based range of ints, which is a little
     // silly - I may fix that.
diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs
index 756af9b..e4af54f 100644
--- a/src/librustc/middle/exported_symbols.rs
+++ b/src/librustc/middle/exported_symbols.rs
@@ -1,8 +1,8 @@
-use crate::hir::def_id::{DefId, LOCAL_CRATE};
 use crate::ich::StableHashingContext;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, TyCtxt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use std::cmp;
 use std::mem;
 
diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs
index e6c51cc..355f949 100644
--- a/src/librustc/middle/free_region.rs
+++ b/src/librustc/middle/free_region.rs
@@ -3,10 +3,10 @@
 //! or explicit bounds. In that case, we track the bounds using the `TransitiveRelation` type,
 //! and use that to decide when one free region outlives another, and so forth.
 
-use crate::hir::def_id::DefId;
-use crate::infer::outlives::free_region_map::{FreeRegionMap, FreeRegionRelations};
 use crate::middle::region;
+use crate::ty::free_region_map::{FreeRegionMap, FreeRegionRelations};
 use crate::ty::{self, Region, TyCtxt};
+use rustc_hir::def_id::DefId;
 
 /// Combines a `region::ScopeTree` (which governs relationships between
 /// scopes) and a `FreeRegionMap` (which governs relationships between
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 0e9a2a3..42fc3e0 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -9,15 +9,16 @@
 
 pub use self::LangItem::*;
 
-use crate::hir;
 use crate::hir::check_attr::Target;
-use crate::hir::def_id::DefId;
-use crate::hir::itemlikevisit::ItemLikeVisitor;
 use crate::middle::cstore::ExternCrate;
 use crate::middle::weak_lang_items;
 use crate::ty::{self, TyCtxt};
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
@@ -184,7 +185,8 @@
                         span,
                         E0152,
                         "duplicate lang item found: `{}`.",
-                        name),
+                        name
+                    ),
                     None => {
                         match self.tcx.extern_crate(item_def_id) {
                             Some(ExternCrate {dependency_of, ..}) => {
@@ -204,7 +206,7 @@
                     },
                 };
                 if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
-                    span_note!(&mut err, span, "first defined here.");
+                    err.span_note(span, "first defined here.");
                 } else {
                     match self.tcx.extern_crate(original_def_id) {
                         Some(ExternCrate {dependency_of, ..}) => {
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index c4da4d7..4756e83 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -2,10 +2,9 @@
 //! outside their scopes. This pass will also generate a set of exported items
 //! which are available for use externally when compiled as a library.
 
-use crate::hir::def_id::DefIdSet;
-use crate::hir::HirId;
-
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::DefIdSet;
+use rustc_hir::HirId;
 use rustc_macros::HashStable;
 use std::fmt;
 use std::hash::Hash;
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index ee96b59..9e9c8bd 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -6,15 +6,14 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
-use crate::hir;
-use crate::hir::def_id::DefId;
-use crate::hir::Node;
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::ty::{self, DefIdTree, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::Node;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
 use rustc_span::{Span, DUMMY_SP};
 
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 951181c..c21ba1b 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -1,11 +1,11 @@
 //! Name resolution for lifetimes: type declarations.
 
-use crate::hir::def_id::{DefId, LocalDefId};
-use crate::hir::{GenericParam, ItemLocalId};
-use crate::hir::{GenericParamKind, LifetimeParamKind};
 use crate::ty;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{GenericParam, ItemLocalId};
+use rustc_hir::{GenericParamKind, LifetimeParamKind};
 use rustc_macros::HashStable;
 
 /// The origin of a named lifetime definition.
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 0c756c7..1176ffc 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -3,23 +3,21 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::hir::def::DefKind;
-use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
-use crate::hir::{self, HirId};
-use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::lint::{self, in_derive_expansion, Lint};
 use crate::session::{DiagnosticMessageId, Session};
 use crate::ty::{self, TyCtxt};
-
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::GateIssue;
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
+use rustc_hir::{self, HirId};
+use rustc_session::lint::{self, BuiltinLintDiagnostics, Lint, LintBuffer};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::CRATE_NODE_ID;
 use syntax::attr::{self, ConstStability, Deprecation, RustcDeprecation, Stability};
-use syntax::errors::Applicability;
-use syntax::feature_gate::feature_err_issue;
+use syntax::sess::feature_err_issue;
 
 use std::num::NonZeroU32;
 
@@ -196,13 +194,13 @@
 }
 
 pub fn early_report_deprecation(
-    lint_buffer: &'a mut lint::LintBuffer,
+    lint_buffer: &'a mut LintBuffer,
     message: &str,
     suggestion: Option<Symbol>,
     lint: &'static Lint,
     span: Span,
 ) {
-    if in_derive_expansion(span) {
+    if span.in_derive_expansion() {
         return;
     }
 
@@ -219,7 +217,7 @@
     def_id: DefId,
     hir_id: HirId,
 ) {
-    if in_derive_expansion(span) {
+    if span.in_derive_expansion() {
         return;
     }
 
@@ -245,35 +243,35 @@
     Unmarked,
 }
 
-impl<'tcx> TyCtxt<'tcx> {
-    // See issue #38412.
-    fn skip_stability_check_due_to_privacy(self, mut def_id: DefId) -> bool {
-        // Check if `def_id` is a trait method.
-        match self.def_kind(def_id) {
-            Some(DefKind::Method) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => {
-                if let ty::TraitContainer(trait_def_id) = self.associated_item(def_id).container {
-                    // Trait methods do not declare visibility (even
-                    // for visibility info in cstore). Use containing
-                    // trait instead, so methods of `pub` traits are
-                    // themselves considered `pub`.
-                    def_id = trait_def_id;
-                }
+// See issue #38412.
+fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool {
+    // Check if `def_id` is a trait method.
+    match tcx.def_kind(def_id) {
+        Some(DefKind::Method) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => {
+            if let ty::TraitContainer(trait_def_id) = tcx.associated_item(def_id).container {
+                // Trait methods do not declare visibility (even
+                // for visibility info in cstore). Use containing
+                // trait instead, so methods of `pub` traits are
+                // themselves considered `pub`.
+                def_id = trait_def_id;
             }
-            _ => {}
         }
-
-        let visibility = self.visibility(def_id);
-
-        match visibility {
-            // Must check stability for `pub` items.
-            ty::Visibility::Public => false,
-
-            // These are not visible outside crate; therefore
-            // stability markers are irrelevant, if even present.
-            ty::Visibility::Restricted(..) | ty::Visibility::Invisible => true,
-        }
+        _ => {}
     }
 
+    let visibility = tcx.visibility(def_id);
+
+    match visibility {
+        // Must check stability for `pub` items.
+        ty::Visibility::Public => false,
+
+        // These are not visible outside crate; therefore
+        // stability markers are irrelevant, if even present.
+        ty::Visibility::Restricted(..) | ty::Visibility::Invisible => true,
+    }
+}
+
+impl<'tcx> TyCtxt<'tcx> {
     /// Evaluates the stability of an item.
     ///
     /// Returns `EvalResult::Allow` if the item is stable, or unstable but the corresponding
@@ -338,7 +336,7 @@
         }
 
         // Issue #38412: private items lack stability markers.
-        if self.skip_stability_check_due_to_privacy(def_id) {
+        if skip_stability_check_due_to_privacy(self, def_id) {
             return EvalResult::Allow;
         }
 
@@ -402,9 +400,7 @@
             }
         }
     }
-}
 
-impl<'tcx> TyCtxt<'tcx> {
     pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {
         self.lookup_deprecation_entry(id).map(|depr| depr.attr)
     }
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index bdf34e8..fdffd12 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -3,12 +3,13 @@
 use crate::middle::lang_items;
 use crate::session::config;
 
-use crate::hir;
-use crate::hir::def_id::DefId;
-use crate::hir::intravisit;
-use crate::hir::intravisit::{NestedVisitorMap, Visitor};
+use crate::hir::map::Map;
 use crate::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::PanicStrategy;
@@ -124,15 +125,20 @@
                 self.items.missing.push(lang_items::$item);
             }
         } else)* {
-            span_err!(self.tcx.sess, span, E0264,
-                      "unknown external lang item: `{}`",
-                      name);
+            struct_span_err!(
+                self.tcx.sess, span, E0264,
+                "unknown external lang item: `{}`",
+                name
+            )
+            .emit();
         }
     }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index dddc3cf..8643bd6 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -1,6 +1,5 @@
 use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
 
-use crate::hir;
 use crate::hir::map::definitions::DefPathData;
 use crate::mir;
 use crate::ty::layout::{Align, LayoutError, Size};
@@ -8,8 +7,9 @@
 use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
-use errors::DiagnosticBuilder;
 use hir::GeneratorKind;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_hir as hir;
 use rustc_macros::HashStable;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Pos, Span};
@@ -154,7 +154,7 @@
                 .next()
                 .unwrap_or(lint_root);
             tcx.struct_span_lint_hir(
-                crate::rustc::lint::builtin::CONST_ERR,
+                rustc_session::lint::builtin::CONST_ERR,
                 hir_id,
                 tcx.span,
                 message,
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 185fa4c..99113d6 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -115,7 +115,6 @@
 
 pub use self::pointer::{CheckInAllocMsg, Pointer, PointerArithmetic};
 
-use crate::hir::def_id::DefId;
 use crate::mir;
 use crate::ty::codec::TyDecoder;
 use crate::ty::layout::{self, Size};
@@ -125,6 +124,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock};
 use rustc_data_structures::tiny_list::TinyList;
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable, Encoder};
 use std::fmt;
diff --git a/src/librustc/mir/interpret/queries.rs b/src/librustc/mir/interpret/queries.rs
index b560363..ed57f81 100644
--- a/src/librustc/mir/interpret/queries.rs
+++ b/src/librustc/mir/interpret/queries.rs
@@ -1,9 +1,9 @@
 use super::{ConstEvalResult, ErrorHandled, GlobalId};
 
-use crate::hir::def_id::DefId;
 use crate::mir;
 use crate::ty::subst::{InternalSubsts, SubstsRef};
 use crate::ty::{self, TyCtxt};
+use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -36,11 +36,16 @@
         param_env: ty::ParamEnv<'tcx>,
         def_id: DefId,
         substs: SubstsRef<'tcx>,
+        promoted: Option<mir::Promoted>,
         span: Option<Span>,
     ) -> ConstEvalResult<'tcx> {
         let instance = ty::Instance::resolve(self, param_env, def_id, substs);
         if let Some(instance) = instance {
-            self.const_eval_instance(param_env, instance, span)
+            if let Some(promoted) = promoted {
+                self.const_eval_promoted(param_env, instance, promoted)
+            } else {
+                self.const_eval_instance(param_env, instance, span)
+            }
         } else {
             Err(ErrorHandled::TooGeneric)
         }
@@ -63,11 +68,11 @@
     /// Evaluate a promoted constant.
     pub fn const_eval_promoted(
         self,
+        param_env: ty::ParamEnv<'tcx>,
         instance: ty::Instance<'tcx>,
         promoted: mir::Promoted,
     ) -> ConstEvalResult<'tcx> {
         let cid = GlobalId { instance, promoted: Some(promoted) };
-        let param_env = ty::ParamEnv::reveal_all();
         self.const_eval_validated(param_env.and(cid))
     }
 }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index a293fd1..ccd2a96 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1,12 +1,7 @@
-// ignore-tidy-filelength
-
 //! MIR datatypes and passes. See the [rustc guide] for more info.
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
 
-use crate::hir::def::{CtorKind, Namespace};
-use crate::hir::def_id::DefId;
-use crate::hir::{self, GeneratorKind};
 use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
@@ -17,19 +12,21 @@
 use crate::ty::{
     self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex,
 };
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, Namespace};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{self, GeneratorKind};
 
 use polonius_engine::Atom;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::graph::{self, GraphSuccessors};
-use rustc_data_structures::sync::Lrc;
 use rustc_index::bit_set::BitMatrix;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
-use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::fmt::{self, Debug, Display, Formatter, Write};
 use std::ops::Index;
@@ -38,13 +35,15 @@
 pub use syntax::ast::Mutability;
 use syntax::ast::Name;
 
-pub use crate::mir::cache::{BodyAndCache, ReadOnlyBodyAndCache};
-pub use crate::mir::interpret::AssertMessage;
+pub use self::cache::{BodyAndCache, ReadOnlyBodyAndCache};
+pub use self::interpret::AssertMessage;
+pub use self::query::*;
 pub use crate::read_only;
 
 mod cache;
 pub mod interpret;
 pub mod mono;
+mod query;
 pub mod tcx;
 pub mod traversal;
 pub mod visit;
@@ -165,6 +164,16 @@
 
     /// A span representing this MIR, for error reporting.
     pub span: Span,
+
+    /// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because
+    /// we'd statically know that no thing with interior mutability will ever be available to the
+    /// user without some serious unsafe code.  Now this means that our promoted is actually
+    /// &[(SOME_CELL, 42)] and the MIR using it will do the &promoted[i].1 projection because the
+    /// index may be a runtime value. Such a promoted value is illegal because it has reachable
+    /// interior mutability. This flag just makes this situation very obvious where the previous
+    /// implementation without the flag hid this situation silently.
+    /// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
+    pub ignore_interior_mut_in_const_validation: bool,
 }
 
 impl<'tcx> Body<'tcx> {
@@ -201,6 +210,7 @@
             spread_arg: None,
             var_debug_info,
             span,
+            ignore_interior_mut_in_const_validation: false,
             control_flow_destroyed,
         }
     }
@@ -1641,9 +1651,9 @@
 
 /// A path to a value; something that can be evaluated without
 /// changing or disturbing program state.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable)]
 pub struct Place<'tcx> {
-    pub base: PlaceBase<'tcx>,
+    pub local: Local,
 
     /// projection out of a place (access a field, deref a pointer, etc)
     pub projection: &'tcx List<PlaceElem<'tcx>>,
@@ -1651,58 +1661,6 @@
 
 impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub enum PlaceBase<'tcx> {
-    /// local variable
-    Local(Local),
-
-    /// static or static mut variable
-    Static(Box<Static<'tcx>>),
-}
-
-/// We store the normalized type to avoid requiring normalization when reading MIR
-#[derive(
-    Clone,
-    Debug,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
-pub struct Static<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub kind: StaticKind<'tcx>,
-    /// The `DefId` of the item this static was declared in. For promoted values, usually, this is
-    /// the same as the `DefId` of the `mir::Body` containing the `Place` this promoted appears in.
-    /// However, after inlining, that might no longer be the case as inlined `Place`s are copied
-    /// into the calling frame.
-    pub def_id: DefId,
-}
-
-#[derive(
-    Clone,
-    Debug,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    HashStable,
-    RustcEncodable,
-    RustcDecodable
-)]
-pub enum StaticKind<'tcx> {
-    /// Promoted references consist of an id (`Promoted`) and the substs necessary to monomorphize
-    /// it. Usually, these substs are just the identity substs for the item. However, the inliner
-    /// will adjust these substs when it inlines a function based on the substs at the callsite.
-    Promoted(Promoted, SubstsRef<'tcx>),
-    Static,
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub enum ProjectionElem<V, T> {
@@ -1790,14 +1748,14 @@
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct PlaceRef<'a, 'tcx> {
-    pub base: &'a PlaceBase<'tcx>,
+    pub local: &'a Local,
     pub projection: &'a [PlaceElem<'tcx>],
 }
 
 impl<'tcx> Place<'tcx> {
     // FIXME change this to a const fn by also making List::empty a const fn.
     pub fn return_place() -> Place<'tcx> {
-        Place { base: PlaceBase::Local(RETURN_PLACE), projection: List::empty() }
+        Place { local: RETURN_PLACE, projection: List::empty() }
     }
 
     /// Returns `true` if this `Place` contains a `Deref` projection.
@@ -1814,10 +1772,8 @@
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local_or_deref_local(&self) -> Option<Local> {
         match self.as_ref() {
-            PlaceRef { base: &PlaceBase::Local(local), projection: &[] }
-            | PlaceRef { base: &PlaceBase::Local(local), projection: &[ProjectionElem::Deref] } => {
-                Some(local)
-            }
+            PlaceRef { local, projection: &[] }
+            | PlaceRef { local, projection: &[ProjectionElem::Deref] } => Some(*local),
             _ => None,
         }
     }
@@ -1829,19 +1785,13 @@
     }
 
     pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
-        PlaceRef { base: &self.base, projection: &self.projection }
+        PlaceRef { local: &self.local, projection: &self.projection }
     }
 }
 
 impl From<Local> for Place<'_> {
     fn from(local: Local) -> Self {
-        Place { base: local.into(), projection: List::empty() }
-    }
-}
-
-impl From<Local> for PlaceBase<'_> {
-    fn from(local: Local) -> Self {
-        PlaceBase::Local(local)
+        Place { local, projection: List::empty() }
     }
 }
 
@@ -1852,10 +1802,8 @@
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local_or_deref_local(&self) -> Option<Local> {
         match self {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] }
-            | PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] } => {
-                Some(*local)
-            }
+            PlaceRef { local, projection: [] }
+            | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(**local),
             _ => None,
         }
     }
@@ -1864,7 +1812,7 @@
     /// projections, return `Some(_X)`.
     pub fn as_local(&self) -> Option<Local> {
         match self {
-            PlaceRef { base: PlaceBase::Local(l), projection: [] } => Some(*l),
+            PlaceRef { local, projection: [] } => Some(**local),
             _ => None,
         }
     }
@@ -1886,7 +1834,7 @@
             }
         }
 
-        write!(fmt, "{:?}", self.base)?;
+        write!(fmt, "{:?}", self.local)?;
 
         for elem in self.projection.iter() {
             match elem {
@@ -1930,22 +1878,6 @@
     }
 }
 
-impl Debug for PlaceBase<'_> {
-    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        match *self {
-            PlaceBase::Local(id) => write!(fmt, "{:?}", id),
-            PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static, def_id }) => {
-                write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty)
-            }
-            PlaceBase::Static(box self::Static {
-                ty,
-                kind: StaticKind::Promoted(promoted, _),
-                def_id: _,
-            }) => write!(fmt, "({:?}: {:?})", promoted, ty),
-        }
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Scopes
 
@@ -2647,221 +2579,6 @@
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
-pub enum UnsafetyViolationKind {
-    General,
-    /// Permitted both in `const fn`s and regular `fn`s.
-    GeneralAndConstFn,
-    BorrowPacked(hir::HirId),
-}
-
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UnsafetyViolation {
-    pub source_info: SourceInfo,
-    pub description: Symbol,
-    pub details: Symbol,
-    pub kind: UnsafetyViolationKind,
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UnsafetyCheckResult {
-    /// Violations that are propagated *upwards* from this function.
-    pub violations: Lrc<[UnsafetyViolation]>,
-    /// `unsafe` blocks in this function, along with whether they are used. This is
-    /// used for the "unused_unsafe" lint.
-    pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
-}
-
-rustc_index::newtype_index! {
-    pub struct GeneratorSavedLocal {
-        derive [HashStable]
-        DEBUG_FORMAT = "_{}",
-    }
-}
-
-/// The layout of generator state.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct GeneratorLayout<'tcx> {
-    /// The type of every local stored inside the generator.
-    pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
-
-    /// Which of the above fields are in each variant. Note that one field may
-    /// be stored in multiple variants.
-    pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
-
-    /// Which saved locals are storage-live at the same time. Locals that do not
-    /// have conflicts with each other are allowed to overlap in the computed
-    /// layout.
-    pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct BorrowCheckResult<'tcx> {
-    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
-    pub used_mut_upvars: SmallVec<[Field; 8]>,
-}
-
-/// The result of the `mir_const_qualif` query.
-///
-/// Each field corresponds to an implementer of the `Qualif` trait in
-/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
-/// `Qualif`.
-#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ConstQualifs {
-    pub has_mut_interior: bool,
-    pub needs_drop: bool,
-}
-
-/// After we borrow check a closure, we are left with various
-/// requirements that we have inferred between the free regions that
-/// appear in the closure's signature or on its field types. These
-/// requirements are then verified and proved by the closure's
-/// creating function. This struct encodes those requirements.
-///
-/// The requirements are listed as being between various
-/// `RegionVid`. The 0th region refers to `'static`; subsequent region
-/// vids refer to the free regions that appear in the closure (or
-/// generator's) type, in order of appearance. (This numbering is
-/// actually defined by the `UniversalRegions` struct in the NLL
-/// region checker. See for example
-/// `UniversalRegions::closure_mapping`.) Note that we treat the free
-/// regions in the closure's type "as if" they were erased, so their
-/// precise identity is not important, only their position.
-///
-/// Example: If type check produces a closure with the closure substs:
-///
-/// ```text
-/// ClosureSubsts = [
-///     i8,                                  // the "closure kind"
-///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
-///     &'a String,                          // some upvar
-/// ]
-/// ```
-///
-/// here, there is one unique free region (`'a`) but it appears
-/// twice. We would "renumber" each occurrence to a unique vid, as follows:
-///
-/// ```text
-/// ClosureSubsts = [
-///     i8,                                  // the "closure kind"
-///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
-///     &'2 String,                          // some upvar
-/// ]
-/// ```
-///
-/// Now the code might impose a requirement like `'1: '2`. When an
-/// instance of the closure is created, the corresponding free regions
-/// can be extracted from its type and constrained to have the given
-/// outlives relationship.
-///
-/// In some cases, we have to record outlives requirements between
-/// types and regions as well. In that case, if those types include
-/// any regions, those regions are recorded as `ReClosureBound`
-/// instances assigned one of these same indices. Those regions will
-/// be substituted away by the creator. We use `ReClosureBound` in
-/// that case because the regions must be allocated in the global
-/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use
-/// internally within the rest of the NLL code).
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ClosureRegionRequirements<'tcx> {
-    /// The number of external regions defined on the closure. In our
-    /// example above, it would be 3 -- one for `'static`, then `'1`
-    /// and `'2`. This is just used for a sanity check later on, to
-    /// make sure that the number of regions we see at the callsite
-    /// matches.
-    pub num_external_vids: usize,
-
-    /// Requirements between the various free regions defined in
-    /// indices.
-    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
-}
-
-/// Indicates an outlives-constraint between a type or between two
-/// free regions declared on the closure.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ClosureOutlivesRequirement<'tcx> {
-    // This region or type ...
-    pub subject: ClosureOutlivesSubject<'tcx>,
-
-    // ... must outlive this one.
-    pub outlived_free_region: ty::RegionVid,
-
-    // If not, report an error here ...
-    pub blame_span: Span,
-
-    // ... due to this reason.
-    pub category: ConstraintCategory,
-}
-
-/// Outlives-constraints can be categorized to determine whether and why they
-/// are interesting (for error reporting). Order of variants indicates sort
-/// order of the category, thereby influencing diagnostic output.
-///
-/// See also [rustc_mir::borrow_check::nll::constraints].
-#[derive(
-    Copy,
-    Clone,
-    Debug,
-    Eq,
-    PartialEq,
-    PartialOrd,
-    Ord,
-    Hash,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
-pub enum ConstraintCategory {
-    Return,
-    Yield,
-    UseAsConst,
-    UseAsStatic,
-    TypeAnnotation,
-    Cast,
-
-    /// A constraint that came from checking the body of a closure.
-    ///
-    /// We try to get the category that the closure used when reporting this.
-    ClosureBounds,
-    CallArgument,
-    CopyBound,
-    SizedBound,
-    Assignment,
-    OpaqueType,
-
-    /// A "boring" constraint (caused by the given location) is one that
-    /// the user probably doesn't want to see described in diagnostics,
-    /// because it is kind of an artifact of the type system setup.
-    /// Example: `x = Foo { field: y }` technically creates
-    /// intermediate regions representing the "type of `Foo { field: y
-    /// }`", and data flows from `y` into those variables, but they
-    /// are not very interesting. The assignment into `x` on the other
-    /// hand might be.
-    Boring,
-    // Boring and applicable everywhere.
-    BoringNoLocation,
-
-    /// A constraint that doesn't correspond to anything the user sees.
-    Internal,
-}
-
-/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
-/// that must outlive some region.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub enum ClosureOutlivesSubject<'tcx> {
-    /// Subject is a type, typically a type parameter, but could also
-    /// be a projection. Indicates a requirement like `T: 'a` being
-    /// passed to the caller, where the type here is `T`.
-    ///
-    /// The type here is guaranteed not to contain any free regions at
-    /// present.
-    Ty(Ty<'tcx>),
-
-    /// Subject is a free region from the closure. Indicates a requirement
-    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
-    Region(ty::RegionVid),
-}
-
 /*
  * `TypeFoldable` implementations for MIR types
 */
@@ -3006,27 +2723,11 @@
 
 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        Place { base: self.base.fold_with(folder), projection: self.projection.fold_with(folder) }
+        Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.base.visit_with(visitor) || self.projection.visit_with(visitor)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        match self {
-            PlaceBase::Local(local) => PlaceBase::Local(local.fold_with(folder)),
-            PlaceBase::Static(static_) => PlaceBase::Static(static_.fold_with(folder)),
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        match self {
-            PlaceBase::Local(local) => local.visit_with(visitor),
-            PlaceBase::Static(static_) => (**static_).visit_with(visitor),
-        }
+        self.local.visit_with(visitor) || self.projection.visit_with(visitor)
     }
 }
 
@@ -3041,42 +2742,6 @@
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        Static {
-            ty: self.ty.fold_with(folder),
-            kind: self.kind.fold_with(folder),
-            def_id: self.def_id,
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        let Static { ty, kind, def_id: _ } = self;
-
-        ty.visit_with(visitor) || kind.visit_with(visitor)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for StaticKind<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        match self {
-            StaticKind::Promoted(promoted, substs) => {
-                StaticKind::Promoted(promoted.fold_with(folder), substs.fold_with(folder))
-            }
-            StaticKind::Static => StaticKind::Static,
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        match self {
-            StaticKind::Promoted(promoted, substs) => {
-                promoted.visit_with(visitor) || substs.visit_with(visitor)
-            }
-            StaticKind::Static => false,
-        }
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         use crate::mir::Rvalue::*;
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 2dbe1d4..51ce575 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -1,6 +1,4 @@
 use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
-use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use crate::hir::HirId;
 use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
 use crate::session::config::OptLevel;
 use crate::ty::print::obsolete::DefPathBasedNames;
@@ -8,6 +6,8 @@
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::HirId;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
 use std::fmt;
diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs
new file mode 100644
index 0000000..34f58ab
--- /dev/null
+++ b/src/librustc/mir/query.rs
@@ -0,0 +1,223 @@
+//! Values computed by queries that use MIR.
+
+use crate::ty::{self, Ty};
+use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_index::bit_set::BitMatrix;
+use rustc_index::vec::IndexVec;
+use rustc_span::{Span, Symbol};
+use rustc_target::abi::VariantIdx;
+use smallvec::SmallVec;
+
+use super::{Field, SourceInfo};
+
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+pub enum UnsafetyViolationKind {
+    General,
+    /// Permitted both in `const fn`s and regular `fn`s.
+    GeneralAndConstFn,
+    BorrowPacked(hir::HirId),
+}
+
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+pub struct UnsafetyViolation {
+    pub source_info: SourceInfo,
+    pub description: Symbol,
+    pub details: Symbol,
+    pub kind: UnsafetyViolationKind,
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub struct UnsafetyCheckResult {
+    /// Violations that are propagated *upwards* from this function.
+    pub violations: Lrc<[UnsafetyViolation]>,
+    /// `unsafe` blocks in this function, along with whether they are used. This is
+    /// used for the "unused_unsafe" lint.
+    pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
+}
+
+rustc_index::newtype_index! {
+    pub struct GeneratorSavedLocal {
+        derive [HashStable]
+        DEBUG_FORMAT = "_{}",
+    }
+}
+
+/// The layout of generator state.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct GeneratorLayout<'tcx> {
+    /// The type of every local stored inside the generator.
+    pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
+
+    /// Which of the above fields are in each variant. Note that one field may
+    /// be stored in multiple variants.
+    pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
+
+    /// Which saved locals are storage-live at the same time. Locals that do not
+    /// have conflicts with each other are allowed to overlap in the computed
+    /// layout.
+    pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct BorrowCheckResult<'tcx> {
+    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
+    pub used_mut_upvars: SmallVec<[Field; 8]>,
+}
+
+/// The result of the `mir_const_qualif` query.
+///
+/// Each field corresponds to an implementer of the `Qualif` trait in
+/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
+/// `Qualif`.
+#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ConstQualifs {
+    pub has_mut_interior: bool,
+    pub needs_drop: bool,
+}
+
+/// After we borrow check a closure, we are left with various
+/// requirements that we have inferred between the free regions that
+/// appear in the closure's signature or on its field types. These
+/// requirements are then verified and proved by the closure's
+/// creating function. This struct encodes those requirements.
+///
+/// The requirements are listed as being between various
+/// `RegionVid`. The 0th region refers to `'static`; subsequent region
+/// vids refer to the free regions that appear in the closure (or
+/// generator's) type, in order of appearance. (This numbering is
+/// actually defined by the `UniversalRegions` struct in the NLL
+/// region checker. See for example
+/// `UniversalRegions::closure_mapping`.) Note that we treat the free
+/// regions in the closure's type "as if" they were erased, so their
+/// precise identity is not important, only their position.
+///
+/// Example: If type check produces a closure with the closure substs:
+///
+/// ```text
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
+///     &'a String,                          // some upvar
+/// ]
+/// ```
+///
+/// here, there is one unique free region (`'a`) but it appears
+/// twice. We would "renumber" each occurrence to a unique vid, as follows:
+///
+/// ```text
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
+///     &'2 String,                          // some upvar
+/// ]
+/// ```
+///
+/// Now the code might impose a requirement like `'1: '2`. When an
+/// instance of the closure is created, the corresponding free regions
+/// can be extracted from its type and constrained to have the given
+/// outlives relationship.
+///
+/// In some cases, we have to record outlives requirements between
+/// types and regions as well. In that case, if those types include
+/// any regions, those regions are recorded as `ReClosureBound`
+/// instances assigned one of these same indices. Those regions will
+/// be substituted away by the creator. We use `ReClosureBound` in
+/// that case because the regions must be allocated in the global
+/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use
+/// internally within the rest of the NLL code).
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ClosureRegionRequirements<'tcx> {
+    /// The number of external regions defined on the closure. In our
+    /// example above, it would be 3 -- one for `'static`, then `'1`
+    /// and `'2`. This is just used for a sanity check later on, to
+    /// make sure that the number of regions we see at the callsite
+    /// matches.
+    pub num_external_vids: usize,
+
+    /// Requirements between the various free regions defined in
+    /// indices.
+    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
+}
+
+/// Indicates an outlives-constraint between a type or between two
+/// free regions declared on the closure.
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ClosureOutlivesRequirement<'tcx> {
+    // This region or type ...
+    pub subject: ClosureOutlivesSubject<'tcx>,
+
+    // ... must outlive this one.
+    pub outlived_free_region: ty::RegionVid,
+
+    // If not, report an error here ...
+    pub blame_span: Span,
+
+    // ... due to this reason.
+    pub category: ConstraintCategory,
+}
+
+/// Outlives-constraints can be categorized to determine whether and why they
+/// are interesting (for error reporting). Order of variants indicates sort
+/// order of the category, thereby influencing diagnostic output.
+///
+/// See also [rustc_mir::borrow_check::nll::constraints].
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
+pub enum ConstraintCategory {
+    Return,
+    Yield,
+    UseAsConst,
+    UseAsStatic,
+    TypeAnnotation,
+    Cast,
+
+    /// A constraint that came from checking the body of a closure.
+    ///
+    /// We try to get the category that the closure used when reporting this.
+    ClosureBounds,
+    CallArgument,
+    CopyBound,
+    SizedBound,
+    Assignment,
+    OpaqueType,
+
+    /// A "boring" constraint (caused by the given location) is one that
+    /// the user probably doesn't want to see described in diagnostics,
+    /// because it is kind of an artifact of the type system setup.
+    /// Example: `x = Foo { field: y }` technically creates
+    /// intermediate regions representing the "type of `Foo { field: y
+    /// }`", and data flows from `y` into those variables, but they
+    /// are not very interesting. The assignment into `x` on the other
+    /// hand might be.
+    Boring,
+    // Boring and applicable everywhere.
+    BoringNoLocation,
+
+    /// A constraint that doesn't correspond to anything the user sees.
+    Internal,
+}
+
+/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
+/// that must outlive some region.
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub enum ClosureOutlivesSubject<'tcx> {
+    /// Subject is a type, typically a type parameter, but could also
+    /// be a projection. Indicates a requirement like `T: 'a` being
+    /// passed to the caller, where the type here is `T`.
+    ///
+    /// The type here is guaranteed not to contain any free regions at
+    /// present.
+    Ty(Ty<'tcx>),
+
+    /// Subject is a free region from the closure. Indicates a requirement
+    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
+    Region(ty::RegionVid),
+}
+
+/// The constituent parts of an ADT or array.
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct DestructuredConst<'tcx> {
+    pub variant: VariantIdx,
+    pub fields: &'tcx [&'tcx ty::Const<'tcx>],
+}
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 2342211..e2aac56 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -3,12 +3,12 @@
  * building is complete.
  */
 
-use crate::hir;
 use crate::mir::*;
 use crate::ty::layout::VariantIdx;
 use crate::ty::subst::Subst;
 use crate::ty::util::IntTypeExt;
 use crate::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
 
 #[derive(Copy, Clone, Debug, TypeFoldable)]
 pub struct PlaceTy<'tcx> {
@@ -114,7 +114,7 @@
 
 impl<'tcx> Place<'tcx> {
     pub fn ty_from<D>(
-        base: &PlaceBase<'tcx>,
+        local: &Local,
         projection: &[PlaceElem<'tcx>],
         local_decls: &D,
         tcx: TyCtxt<'tcx>,
@@ -124,26 +124,16 @@
     {
         projection
             .iter()
-            .fold(base.ty(local_decls), |place_ty, elem| place_ty.projection_ty(tcx, elem))
+            .fold(PlaceTy::from_ty(local_decls.local_decls()[*local].ty), |place_ty, elem| {
+                place_ty.projection_ty(tcx, elem)
+            })
     }
 
     pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
     where
         D: HasLocalDecls<'tcx>,
     {
-        Place::ty_from(&self.base, &self.projection, local_decls, tcx)
-    }
-}
-
-impl<'tcx> PlaceBase<'tcx> {
-    pub fn ty<D>(&self, local_decls: &D) -> PlaceTy<'tcx>
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        match self {
-            PlaceBase::Local(index) => PlaceTy::from_ty(local_decls.local_decls()[*index].ty),
-            PlaceBase::Static(data) => PlaceTy::from_ty(data.ty),
-        }
+        Place::ty_from(&self.local, &self.projection, local_decls, tcx)
     }
 }
 
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 9173c32..4c5db1b 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -164,10 +164,10 @@
             }
 
             fn visit_place_base(&mut self,
-                                base: & $($mutability)? PlaceBase<'tcx>,
+                                local: & $($mutability)? Local,
                                 context: PlaceContext,
                                 location: Location) {
-                self.super_place_base(base, context, location);
+                self.super_place_base(local, context, location);
             }
 
             visit_place_fns!($($mutability)?);
@@ -705,17 +705,10 @@
             }
 
             fn super_place_base(&mut self,
-                                place_base: & $($mutability)? PlaceBase<'tcx>,
+                                local: & $($mutability)? Local,
                                 context: PlaceContext,
                                 location: Location) {
-                match place_base {
-                    PlaceBase::Local(local) => {
-                        self.visit_local(local, context, location);
-                    }
-                    PlaceBase::Static(box Static { kind: _, ty, def_id: _ }) => {
-                        self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
-                    }
-                }
+                self.visit_local(local, context, location);
             }
 
             fn super_local_decl(&mut self,
@@ -848,7 +841,7 @@
             context: PlaceContext,
             location: Location,
         ) {
-            self.visit_place_base(&mut place.base, context, location);
+            self.visit_place_base(&mut place.local, context, location);
 
             if let Some(new_projection) = self.process_projection(&place.projection) {
                 place.projection = self.tcx().intern_place_elems(&new_projection);
@@ -889,23 +882,23 @@
     () => (
         fn visit_projection(
             &mut self,
-            base: &PlaceBase<'tcx>,
+            local: &Local,
             projection: &[PlaceElem<'tcx>],
             context: PlaceContext,
             location: Location,
         ) {
-            self.super_projection(base, projection, context, location);
+            self.super_projection(local, projection, context, location);
         }
 
         fn visit_projection_elem(
             &mut self,
-            base: &PlaceBase<'tcx>,
+            local: &Local,
             proj_base: &[PlaceElem<'tcx>],
             elem: &PlaceElem<'tcx>,
             context: PlaceContext,
             location: Location,
         ) {
-            self.super_projection_elem(base, proj_base, elem, context, location);
+            self.super_projection_elem(local, proj_base, elem, context, location);
         }
 
         fn super_place(
@@ -924,9 +917,9 @@
                 };
             }
 
-            self.visit_place_base(&place.base, context, location);
+            self.visit_place_base(&place.local, context, location);
 
-            self.visit_projection(&place.base,
+            self.visit_projection(&place.local,
                                   &place.projection,
                                   context,
                                   location);
@@ -934,7 +927,7 @@
 
         fn super_projection(
             &mut self,
-            base: &PlaceBase<'tcx>,
+            local: &Local,
             projection: &[PlaceElem<'tcx>],
             context: PlaceContext,
             location: Location,
@@ -942,13 +935,13 @@
             let mut cursor = projection;
             while let [proj_base @ .., elem] = cursor {
                 cursor = proj_base;
-                self.visit_projection_elem(base, cursor, elem, context, location);
+                self.visit_projection_elem(local, cursor, elem, context, location);
             }
         }
 
         fn super_projection_elem(
             &mut self,
-            _base: &PlaceBase<'tcx>,
+            _local: &Local,
             _proj_base: &[PlaceElem<'tcx>],
             elem: &PlaceElem<'tcx>,
             _context: PlaceContext,
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index e814973..50ef115 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -1,5 +1,4 @@
 use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex};
-use crate::hir::def_id::{CrateNum, DefId, DefIndex};
 use crate::mir;
 use crate::mir::interpret::GlobalId;
 use crate::traits;
@@ -12,6 +11,7 @@
 use crate::ty::query::QueryDescription;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
 
 use rustc_span::symbol::Symbol;
 use std::borrow::Cow;
@@ -82,7 +82,7 @@
             desc { "looking up the native libraries of a linked crate" }
         }
 
-        query lint_levels(_: CrateNum) -> &'tcx lint::LintLevelMap {
+        query lint_levels(_: CrateNum) -> &'tcx LintLevelMap {
             eval_always
             desc { "computing the lint levels for items in this crate" }
         }
@@ -505,6 +505,15 @@
             desc { "extract field of const" }
         }
 
+        /// Destructure a constant ADT or array into its variant indent and its
+        /// field values.
+        query destructure_const(
+            key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
+        ) -> mir::DestructuredConst<'tcx> {
+            no_force
+            desc { "destructure constant" }
+        }
+
         query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
             no_force
             desc { "get a &core::panic::Location referring to a span" }
@@ -686,10 +695,6 @@
             fatal_cycle
             desc { "checking if the crate has_panic_handler" }
         }
-        query is_sanitizer_runtime(_: CrateNum) -> bool {
-            fatal_cycle
-            desc { "query a crate is `#![sanitizer_runtime]`" }
-        }
         query is_profiler_runtime(_: CrateNum) -> bool {
             fatal_cycle
             desc { "query a crate is `#![profiler_runtime]`" }
diff --git a/src/librustc/traits/codegen/mod.rs b/src/librustc/traits/codegen/mod.rs
index 8bd3f31..8a264a7 100644
--- a/src/librustc/traits/codegen/mod.rs
+++ b/src/librustc/traits/codegen/mod.rs
@@ -8,7 +8,6 @@
     FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable,
 };
 use crate::ty::fold::TypeFoldable;
-use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{self, TyCtxt};
 
 /// Attempts to resolve an obligation to a vtable. The result is
@@ -76,31 +75,6 @@
     })
 }
 
-impl<'tcx> TyCtxt<'tcx> {
-    /// Monomorphizes a type from the AST by first applying the
-    /// in-scope substitutions and then normalizing any associated
-    /// types.
-    pub fn subst_and_normalize_erasing_regions<T>(
-        self,
-        param_substs: SubstsRef<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        value: &T,
-    ) -> T
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!(
-            "subst_and_normalize_erasing_regions(\
-             param_substs={:?}, \
-             value={:?}, \
-             param_env={:?})",
-            param_substs, value, param_env,
-        );
-        let substituted = value.subst(self, param_substs);
-        self.normalize_erasing_regions(param_env, substituted)
-    }
-}
-
 // # Global Cache
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 16bf69f..29ea478 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -4,7 +4,6 @@
 //! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
 //! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
 
-use crate::hir::def_id::{DefId, LOCAL_CRATE};
 use crate::infer::{CombinedSnapshot, InferOk};
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::IntercrateMode;
@@ -12,6 +11,7 @@
 use crate::ty::fold::TypeFoldable;
 use crate::ty::subst::Subst;
 use crate::ty::{self, Ty, TyCtxt};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
 
@@ -38,7 +38,7 @@
     pub involves_placeholder: bool,
 }
 
-pub fn add_placeholder_note(err: &mut errors::DiagnosticBuilder<'_>) {
+pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
     err.note(&format!(
         "this behavior recently changed as a result of a bug fix; \
          see rust-lang/rust#56105 for details"
diff --git a/src/librustc/traits/engine.rs b/src/librustc/traits/engine.rs
index b664540..5b80448 100644
--- a/src/librustc/traits/engine.rs
+++ b/src/librustc/traits/engine.rs
@@ -1,7 +1,7 @@
-use crate::hir::def_id::DefId;
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
 use crate::ty::{self, ToPredicate, Ty, TyCtxt};
+use rustc_hir::def_id::DefId;
 
 use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
 use super::{ObligationCause, PredicateObligation};
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 009e52e..0c9a73d 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -6,14 +6,12 @@
     TraitNotObjectSafe,
 };
 
-use crate::hir;
-use crate::hir::def_id::DefId;
-use crate::hir::Node;
-use crate::infer::error_reporting::TypeAnnotationNeeded as ErrorCode;
+use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{self, InferCtxt};
 use crate::mir::interpret::ErrorHandled;
 use crate::session::DiagnosticMessageId;
+use crate::traits::object_safety_violations;
 use crate::ty::error::ExpectedFound;
 use crate::ty::fast_reject;
 use crate::ty::fold::TypeFolder;
@@ -23,9 +21,11 @@
 use crate::ty::TypeckTables;
 use crate::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
 
-use errors::{pluralize, Applicability, DiagnosticBuilder, Style};
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::Node;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
@@ -446,7 +446,7 @@
                 flags.push((sym::from_method, Some(method.to_string())));
             }
         }
-        if let Some(t) = self.get_parent_trait_ref(&obligation.cause.code) {
+        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
             flags.push((sym::parent_trait, Some(t)));
         }
 
@@ -665,13 +665,21 @@
     }
 
     /// Gets the parent trait chain start
-    fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> {
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
         match code {
             &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
                 match self.get_parent_trait_ref(&data.parent_code) {
                     Some(t) => Some(t),
-                    None => Some(parent_trait_ref.skip_binder().self_ty().to_string()),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span =
+                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
+                        Some((ty.to_string(), span))
+                    }
                 }
             }
             _ => None,
@@ -719,9 +727,15 @@
                             return;
                         }
                         let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message) = self
+                        let (post_message, pre_message, type_def) = self
                             .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{}`", t),
+                                    format!("within `{}`, ", t),
+                                    s.map(|s| (format!("within this `{}`", t), s)),
+                                )
+                            })
                             .unwrap_or_default();
 
                         let OnUnimplementedNote { message, label, note, enclosing_scope } =
@@ -795,6 +809,9 @@
                         } else {
                             err.span_label(span, explanation);
                         }
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, &msg);
+                        }
                         if let Some(ref s) = note {
                             // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
                             err.note(s.as_str());
@@ -917,8 +934,8 @@
                     }
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = self.tcx.object_safety_violations(trait_def_id);
-                        self.tcx.report_object_safety_error(span, trait_def_id, violations)
+                        let violations = object_safety_violations(self.tcx, trait_def_id);
+                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
                     }
 
                     ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
@@ -1081,8 +1098,8 @@
             }
 
             TraitNotObjectSafe(did) => {
-                let violations = self.tcx.object_safety_violations(did);
-                self.tcx.report_object_safety_error(span, did, violations)
+                let violations = object_safety_violations(self.tcx, did);
+                report_object_safety_error(self.tcx, span, did, violations)
             }
 
             // already reported in the query
@@ -1947,64 +1964,62 @@
     }
 }
 
-impl<'tcx> TyCtxt<'tcx> {
-    pub fn recursive_type_with_infinite_size_error(
-        self,
-        type_def_id: DefId,
-    ) -> DiagnosticBuilder<'tcx> {
-        assert!(type_def_id.is_local());
-        let span = self.hir().span_if_local(type_def_id).unwrap();
-        let span = self.sess.source_map().def_span(span);
-        let mut err = struct_span_err!(
-            self.sess,
-            span,
-            E0072,
-            "recursive type `{}` has infinite size",
-            self.def_path_str(type_def_id)
-        );
-        err.span_label(span, "recursive type has infinite size");
-        err.help(&format!(
-            "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
+pub fn recursive_type_with_infinite_size_error(
+    tcx: TyCtxt<'tcx>,
+    type_def_id: DefId,
+) -> DiagnosticBuilder<'tcx> {
+    assert!(type_def_id.is_local());
+    let span = tcx.hir().span_if_local(type_def_id).unwrap();
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0072,
+        "recursive type `{}` has infinite size",
+        tcx.def_path_str(type_def_id)
+    );
+    err.span_label(span, "recursive type has infinite size");
+    err.help(&format!(
+        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
                            at some point to make `{}` representable",
-            self.def_path_str(type_def_id)
-        ));
-        err
+        tcx.def_path_str(type_def_id)
+    ));
+    err
+}
+
+pub fn report_object_safety_error(
+    tcx: TyCtxt<'tcx>,
+    span: Span,
+    trait_def_id: DefId,
+    violations: Vec<ObjectSafetyViolation>,
+) -> DiagnosticBuilder<'tcx> {
+    let trait_str = tcx.def_path_str(trait_def_id);
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0038,
+        "the trait `{}` cannot be made into an object",
+        trait_str
+    );
+    err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
+
+    let mut reported_violations = FxHashSet::default();
+    for violation in violations {
+        if reported_violations.insert(violation.clone()) {
+            match violation.span() {
+                Some(span) => err.span_label(span, violation.error_msg()),
+                None => err.note(&violation.error_msg()),
+            };
+        }
     }
 
-    pub fn report_object_safety_error(
-        self,
-        span: Span,
-        trait_def_id: DefId,
-        violations: Vec<ObjectSafetyViolation>,
-    ) -> DiagnosticBuilder<'tcx> {
-        let trait_str = self.def_path_str(trait_def_id);
-        let span = self.sess.source_map().def_span(span);
-        let mut err = struct_span_err!(
-            self.sess,
-            span,
-            E0038,
-            "the trait `{}` cannot be made into an object",
-            trait_str
-        );
-        err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
-
-        let mut reported_violations = FxHashSet::default();
-        for violation in violations {
-            if reported_violations.insert(violation.clone()) {
-                match violation.span() {
-                    Some(span) => err.span_label(span, violation.error_msg()),
-                    None => err.note(&violation.error_msg()),
-                };
-            }
-        }
-
-        if self.sess.trait_methods_not_found.borrow().contains(&span) {
-            // Avoid emitting error caused by non-existing method (#58734)
-            err.cancel();
-        }
-
-        err
+    if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
+        // Avoid emitting error caused by non-existing method (#58734)
+        err.cancel();
     }
+
+    err
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
@@ -2077,7 +2092,12 @@
                 }
                 let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
                 err.note(&format!("cannot resolve `{}`", predicate));
-                if let (Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _)) =
+                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
+                } else if let (
+                    Ok(ref snippet),
+                    ObligationCauseCode::BindingObligation(ref def_id, _),
+                ) =
                     (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
                 {
                     let generics = self.tcx.generics_of(*def_id);
@@ -2175,6 +2195,30 @@
         err.emit();
     }
 
+    fn suggest_fully_qualified_path(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def_id: DefId,
+        span: Span,
+        trait_ref: DefId,
+    ) {
+        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
+                err.note(&format!(
+                    "{}s cannot be accessed directly on a `trait`, they can only be \
+                        accessed through a specific `impl`",
+                    assoc_item.kind.suggestion_descr(),
+                ));
+                err.span_suggestion(
+                    span,
+                    "use the fully qualified path to an implementation",
+                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
+                    Applicability::HasPlaceholders,
+                );
+            }
+        }
+    }
+
     /// Returns `true` if the trait predicate may apply for *some* assignment
     /// to the type parameters.
     fn predicate_can_apply(
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 6143752..46ece6f 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -9,6 +9,7 @@
 use super::engine::{TraitEngine, TraitEngineExt};
 use super::project;
 use super::select::SelectionContext;
+use super::wf;
 use super::CodeAmbiguity;
 use super::CodeProjectionError;
 use super::CodeSelectionError;
@@ -461,7 +462,7 @@
             }
 
             ty::Predicate::WellFormed(ty) => {
-                match ty::wf::obligations(
+                match wf::obligations(
                     self.selcx.infcx(),
                     obligation.param_env,
                     obligation.cause.body_id,
@@ -514,6 +515,7 @@
                             obligation.param_env,
                             def_id,
                             substs,
+                            None,
                             Some(obligation.cause.span),
                         ) {
                             Ok(_) => ProcessResult::Changed(vec![]),
diff --git a/src/librustc/traits/misc.rs b/src/librustc/traits/misc.rs
new file mode 100644
index 0000000..08c3a77
--- /dev/null
+++ b/src/librustc/traits/misc.rs
@@ -0,0 +1,202 @@
+//! Miscellaneous type-system utilities that are too small to deserve their own modules.
+
+use crate::middle::lang_items;
+use crate::traits::{self, ObligationCause};
+use crate::ty::util::NeedsDrop;
+use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
+
+use rustc_hir as hir;
+use rustc_span::DUMMY_SP;
+
+#[derive(Clone)]
+pub enum CopyImplementationError<'tcx> {
+    InfrigingFields(Vec<&'tcx ty::FieldDef>),
+    NotAnAdt,
+    HasDestructor,
+}
+
+pub fn can_type_implement_copy(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    self_type: Ty<'tcx>,
+) -> Result<(), CopyImplementationError<'tcx>> {
+    // FIXME: (@jroesch) float this code up
+    tcx.infer_ctxt().enter(|infcx| {
+        let (adt, substs) = match self_type.kind {
+            // These types used to have a builtin impl.
+            // Now libcore provides that impl.
+            ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::Char
+            | ty::RawPtr(..)
+            | ty::Never
+            | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
+
+            ty::Adt(adt, substs) => (adt, substs),
+
+            _ => return Err(CopyImplementationError::NotAnAdt),
+        };
+
+        let mut infringing = Vec::new();
+        for variant in &adt.variants {
+            for field in &variant.fields {
+                let ty = field.ty(tcx, substs);
+                if ty.references_error() {
+                    continue;
+                }
+                let span = tcx.def_span(field.did);
+                let cause = ObligationCause { span, ..ObligationCause::dummy() };
+                let ctx = traits::FulfillmentContext::new();
+                match traits::fully_normalize(&infcx, ctx, cause, param_env, &ty) {
+                    Ok(ty) => {
+                        if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
+                            infringing.push(field);
+                        }
+                    }
+                    Err(errors) => {
+                        infcx.report_fulfillment_errors(&errors, None, false);
+                    }
+                };
+            }
+        }
+        if !infringing.is_empty() {
+            return Err(CopyImplementationError::InfrigingFields(infringing));
+        }
+        if adt.has_dtor(tcx) {
+            return Err(CopyImplementationError::HasDestructor);
+        }
+
+        Ok(())
+    })
+}
+
+fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    is_item_raw(tcx, query, lang_items::CopyTraitLangItem)
+}
+
+fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    is_item_raw(tcx, query, lang_items::SizedTraitLangItem)
+}
+
+fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    is_item_raw(tcx, query, lang_items::FreezeTraitLangItem)
+}
+
+fn is_item_raw<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+    item: lang_items::LangItem,
+) -> bool {
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(item, None);
+    tcx.infer_ctxt().enter(|infcx| {
+        traits::type_known_to_meet_bound_modulo_regions(
+            &infcx,
+            param_env,
+            ty,
+            trait_def_id,
+            DUMMY_SP,
+        )
+    })
+}
+
+fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> NeedsDrop {
+    let (param_env, ty) = query.into_parts();
+
+    let needs_drop = |ty: Ty<'tcx>| -> bool { tcx.needs_drop_raw(param_env.and(ty)).0 };
+
+    assert!(!ty.needs_infer());
+
+    NeedsDrop(match ty.kind {
+        // Fast-path for primitive types
+        ty::Infer(ty::FreshIntTy(_))
+        | ty::Infer(ty::FreshFloatTy(_))
+        | ty::Bool
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Never
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::Char
+        | ty::GeneratorWitness(..)
+        | ty::RawPtr(_)
+        | ty::Ref(..)
+        | ty::Str => false,
+
+        // Foreign types can never have destructors
+        ty::Foreign(..) => false,
+
+        // `ManuallyDrop` doesn't have a destructor regardless of field types.
+        ty::Adt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false,
+
+        // Issue #22536: We first query `is_copy_modulo_regions`.  It sees a
+        // normalized version of the type, and therefore will definitely
+        // know whether the type implements Copy (and thus needs no
+        // cleanup/drop/zeroing) ...
+        _ if ty.is_copy_modulo_regions(tcx, param_env, DUMMY_SP) => false,
+
+        // ... (issue #22536 continued) but as an optimization, still use
+        // prior logic of asking for the structural "may drop".
+
+        // FIXME(#22815): Note that this is a conservative heuristic;
+        // it may report that the type "may drop" when actual type does
+        // not actually have a destructor associated with it. But since
+        // the type absolutely did not have the `Copy` bound attached
+        // (see above), it is sound to treat it as having a destructor.
+
+        // User destructors are the only way to have concrete drop types.
+        ty::Adt(def, _) if def.has_dtor(tcx) => true,
+
+        // Can refer to a type which may drop.
+        // FIXME(eddyb) check this against a ParamEnv.
+        ty::Dynamic(..)
+        | ty::Projection(..)
+        | ty::Param(_)
+        | ty::Bound(..)
+        | ty::Placeholder(..)
+        | ty::Opaque(..)
+        | ty::Infer(_)
+        | ty::Error => true,
+
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
+        // Zero-length arrays never contain anything to drop.
+        ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false,
+
+        // Structural recursion.
+        ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
+
+        ty::Closure(def_id, ref substs) => {
+            substs.as_closure().upvar_tys(def_id, tcx).any(needs_drop)
+        }
+
+        // Pessimistically assume that all generators will require destructors
+        // as we don't know if a destructor is a noop or not until after the MIR
+        // state transformation pass
+        ty::Generator(..) => true,
+
+        ty::Tuple(..) => ty.tuple_fields().any(needs_drop),
+
+        // unions don't have destructors because of the child types,
+        // only if they manually implement `Drop` (handled above).
+        ty::Adt(def, _) if def.is_union() => false,
+
+        ty::Adt(def, substs) => def
+            .variants
+            .iter()
+            .any(|variant| variant.fields.iter().any(|field| needs_drop(field.ty(tcx, substs)))),
+    })
+}
+
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    *providers = ty::query::Providers {
+        is_copy_raw,
+        is_sized_raw,
+        is_freeze_raw,
+        needs_drop_raw,
+        ..*providers
+    };
+}
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 5c44d5b..2d3160d 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -10,6 +10,7 @@
 mod engine;
 pub mod error_reporting;
 mod fulfill;
+pub mod misc;
 mod object_safety;
 mod on_unimplemented;
 mod project;
@@ -17,10 +18,10 @@
 mod select;
 mod specialize;
 mod structural_impls;
+mod structural_match;
 mod util;
+pub mod wf;
 
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::infer::{InferCtxt, SuppressRegionErrors};
 use crate::middle::region;
@@ -31,6 +32,8 @@
 use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt};
 use crate::util::common::ErrorReported;
 use chalk_engine;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_span::{Span, DUMMY_SP};
 use syntax::ast;
@@ -47,6 +50,9 @@
 pub use self::coherence::{OrphanCheckErr, OverlapResult};
 pub use self::engine::{TraitEngine, TraitEngineExt};
 pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
+pub use self::object_safety::astconv_object_safety_violations;
+pub use self::object_safety::is_vtable_safe_method;
+pub use self::object_safety::object_safety_violations;
 pub use self::object_safety::MethodViolationCode;
 pub use self::object_safety::ObjectSafetyViolation;
 pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
@@ -59,9 +65,16 @@
 pub use self::specialize::specialization_graph::FutureCompatOverlapError;
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
+pub use self::structural_match::search_for_structural_match_violation;
+pub use self::structural_match::type_marked_structural;
+pub use self::structural_match::NonStructuralMatchTy;
 pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{
+    get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
+    predicate_for_trait_def, upcast_choices,
+};
+pub use self::util::{
     supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
 };
 
@@ -1062,7 +1075,7 @@
             let def_id = trait_method.def_id;
 
             // Some methods cannot be called on an object; skip those.
-            if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) {
+            if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
                 debug!("vtable_methods: not vtable safe");
                 return None;
             }
@@ -1231,6 +1244,7 @@
 }
 
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    misc::provide(providers);
     *providers = ty::query::Providers {
         is_object_safe: object_safety::is_object_safe_provider,
         specialization_graph_of: specialize::specialization_graph_provider,
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 30ffdc2..ce57fb8 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -10,17 +10,18 @@
 
 use super::elaborate_predicates;
 
-use crate::hir;
-use crate::hir::def_id::DefId;
-use crate::lint;
 use crate::traits::{self, Obligation, ObligationCause};
 use crate::ty::subst::{InternalSubsts, Subst};
 use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
+use syntax::ast;
+
 use std::borrow::Cow;
 use std::iter::{self};
-use syntax::ast::{self};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum ObjectSafetyViolation {
@@ -108,614 +109,620 @@
     UndispatchableReceiver,
 }
 
-impl<'tcx> TyCtxt<'tcx> {
-    /// Returns the object safety violations that affect
-    /// astconv -- currently, `Self` in supertraits. This is needed
-    /// because `object_safety_violations` can't be used during
-    /// type collection.
-    pub fn astconv_object_safety_violations(
-        self,
-        trait_def_id: DefId,
-    ) -> Vec<ObjectSafetyViolation> {
-        debug_assert!(self.generics_of(trait_def_id).has_self);
-        let violations = traits::supertrait_def_ids(self, trait_def_id)
-            .filter(|&def_id| self.predicates_reference_self(def_id, true))
-            .map(|_| ObjectSafetyViolation::SupertraitSelf)
-            .collect();
+/// Returns the object safety violations that affect
+/// astconv -- currently, `Self` in supertraits. This is needed
+/// because `object_safety_violations` can't be used during
+/// type collection.
+pub fn astconv_object_safety_violations(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+) -> Vec<ObjectSafetyViolation> {
+    debug_assert!(tcx.generics_of(trait_def_id).has_self);
+    let violations = traits::supertrait_def_ids(tcx, trait_def_id)
+        .filter(|&def_id| predicates_reference_self(tcx, def_id, true))
+        .map(|_| ObjectSafetyViolation::SupertraitSelf)
+        .collect();
 
-        debug!(
-            "astconv_object_safety_violations(trait_def_id={:?}) = {:?}",
-            trait_def_id, violations
-        );
+    debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations);
 
-        violations
+    violations
+}
+
+pub fn object_safety_violations(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+) -> Vec<ObjectSafetyViolation> {
+    debug_assert!(tcx.generics_of(trait_def_id).has_self);
+    debug!("object_safety_violations: {:?}", trait_def_id);
+
+    traits::supertrait_def_ids(tcx, trait_def_id)
+        .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id))
+        .collect()
+}
+
+/// We say a method is *vtable safe* if it can be invoked on a trait
+/// object. Note that object-safe traits can have some
+/// non-vtable-safe methods, so long as they require `Self: Sized` or
+/// otherwise ensure that they cannot be used when `Self = Trait`.
+pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
+    debug_assert!(tcx.generics_of(trait_def_id).has_self);
+    debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
+    // Any method that has a `Self: Sized` bound cannot be called.
+    if generics_require_sized_self(tcx, method.def_id) {
+        return false;
     }
 
-    pub fn object_safety_violations(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
-        debug_assert!(self.generics_of(trait_def_id).has_self);
-        debug!("object_safety_violations: {:?}", trait_def_id);
-
-        traits::supertrait_def_ids(self, trait_def_id)
-            .flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
-            .collect()
-    }
-
-    /// We say a method is *vtable safe* if it can be invoked on a trait
-    /// object. Note that object-safe traits can have some
-    /// non-vtable-safe methods, so long as they require `Self: Sized` or
-    /// otherwise ensure that they cannot be used when `Self = Trait`.
-    pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
-        debug_assert!(self.generics_of(trait_def_id).has_self);
-        debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
-        // Any method that has a `Self: Sized` bound cannot be called.
-        if self.generics_require_sized_self(method.def_id) {
-            return false;
-        }
-
-        match self.virtual_call_violation_for_method(trait_def_id, method) {
-            None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
-            Some(_) => false,
-        }
-    }
-
-    fn object_safety_violations_for_trait(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
-        // Check methods for violations.
-        let mut violations: Vec<_> = self
-            .associated_items(trait_def_id)
-            .filter(|item| item.kind == ty::AssocKind::Method)
-            .filter_map(|item| {
-                self.object_safety_violation_for_method(trait_def_id, &item).map(|code| {
-                    ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span)
-                })
-            })
-            .filter(|violation| {
-                if let ObjectSafetyViolation::Method(
-                    _,
-                    MethodViolationCode::WhereClauseReferencesSelf,
-                    span,
-                ) = violation
-                {
-                    // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
-                    // It's also hard to get a use site span, so we use the method definition span.
-                    self.lint_node_note(
-                        lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
-                        hir::CRATE_HIR_ID,
-                        *span,
-                        &format!(
-                            "the trait `{}` cannot be made into an object",
-                            self.def_path_str(trait_def_id)
-                        ),
-                        &violation.error_msg(),
-                    );
-                    false
-                } else {
-                    true
-                }
-            })
-            .collect();
-
-        // Check the trait itself.
-        if self.trait_has_sized_self(trait_def_id) {
-            violations.push(ObjectSafetyViolation::SizedSelf);
-        }
-        if self.predicates_reference_self(trait_def_id, false) {
-            violations.push(ObjectSafetyViolation::SupertraitSelf);
-        }
-
-        violations.extend(
-            self.associated_items(trait_def_id)
-                .filter(|item| item.kind == ty::AssocKind::Const)
-                .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
-        );
-
-        debug!(
-            "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
-            trait_def_id, violations
-        );
-
-        violations
-    }
-
-    fn predicates_reference_self(self, trait_def_id: DefId, supertraits_only: bool) -> bool {
-        let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
-        let predicates = if supertraits_only {
-            self.super_predicates_of(trait_def_id)
-        } else {
-            self.predicates_of(trait_def_id)
-        };
-        let self_ty = self.types.self_param;
-        let has_self_ty = |t: Ty<'tcx>| t.walk().any(|t| t == self_ty);
-        predicates
-            .predicates
-            .iter()
-            .map(|(predicate, _)| predicate.subst_supertrait(self, &trait_ref))
-            .any(|predicate| {
-                match predicate {
-                    ty::Predicate::Trait(ref data) => {
-                        // In the case of a trait predicate, we can skip the "self" type.
-                        data.skip_binder().input_types().skip(1).any(has_self_ty)
-                    }
-                    ty::Predicate::Projection(ref data) => {
-                        // And similarly for projections. This should be redundant with
-                        // the previous check because any projection should have a
-                        // matching `Trait` predicate with the same inputs, but we do
-                        // the check to be safe.
-                        //
-                        // Note that we *do* allow projection *outputs* to contain
-                        // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
-                        // we just require the user to specify *both* outputs
-                        // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
-                        //
-                        // This is ALT2 in issue #56288, see that for discussion of the
-                        // possible alternatives.
-                        data.skip_binder()
-                            .projection_ty
-                            .trait_ref(self)
-                            .input_types()
-                            .skip(1)
-                            .any(has_self_ty)
-                    }
-                    ty::Predicate::WellFormed(..)
-                    | ty::Predicate::ObjectSafe(..)
-                    | ty::Predicate::TypeOutlives(..)
-                    | ty::Predicate::RegionOutlives(..)
-                    | ty::Predicate::ClosureKind(..)
-                    | ty::Predicate::Subtype(..)
-                    | ty::Predicate::ConstEvaluatable(..) => false,
-                }
-            })
-    }
-
-    fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
-        self.generics_require_sized_self(trait_def_id)
-    }
-
-    fn generics_require_sized_self(self, def_id: DefId) -> bool {
-        let sized_def_id = match self.lang_items().sized_trait() {
-            Some(def_id) => def_id,
-            None => {
-                return false; /* No Sized trait, can't require it! */
-            }
-        };
-
-        // Search for a predicate like `Self : Sized` amongst the trait bounds.
-        let predicates = self.predicates_of(def_id);
-        let predicates = predicates.instantiate_identity(self).predicates;
-        elaborate_predicates(self, predicates).any(|predicate| match predicate {
-            ty::Predicate::Trait(ref trait_pred) => {
-                trait_pred.def_id() == sized_def_id
-                    && trait_pred.skip_binder().self_ty().is_param(0)
-            }
-            ty::Predicate::Projection(..)
-            | ty::Predicate::Subtype(..)
-            | ty::Predicate::RegionOutlives(..)
-            | ty::Predicate::WellFormed(..)
-            | ty::Predicate::ObjectSafe(..)
-            | ty::Predicate::ClosureKind(..)
-            | ty::Predicate::TypeOutlives(..)
-            | ty::Predicate::ConstEvaluatable(..) => false,
-        })
-    }
-
-    /// Returns `Some(_)` if this method makes the containing trait not object safe.
-    fn object_safety_violation_for_method(
-        self,
-        trait_def_id: DefId,
-        method: &ty::AssocItem,
-    ) -> Option<MethodViolationCode> {
-        debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
-        // Any method that has a `Self : Sized` requisite is otherwise
-        // exempt from the regulations.
-        if self.generics_require_sized_self(method.def_id) {
-            return None;
-        }
-
-        self.virtual_call_violation_for_method(trait_def_id, method)
-    }
-
-    /// Returns `Some(_)` if this method cannot be called on a trait
-    /// object; this does not necessarily imply that the enclosing trait
-    /// is not object safe, because the method might have a where clause
-    /// `Self:Sized`.
-    fn virtual_call_violation_for_method(
-        self,
-        trait_def_id: DefId,
-        method: &ty::AssocItem,
-    ) -> Option<MethodViolationCode> {
-        // The method's first parameter must be named `self`
-        if !method.method_has_self_argument {
-            return Some(MethodViolationCode::StaticMethod);
-        }
-
-        let sig = self.fn_sig(method.def_id);
-
-        for input_ty in &sig.skip_binder().inputs()[1..] {
-            if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
-                return Some(MethodViolationCode::ReferencesSelf);
-            }
-        }
-        if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
-            return Some(MethodViolationCode::ReferencesSelf);
-        }
-
-        // We can't monomorphize things like `fn foo<A>(...)`.
-        let own_counts = self.generics_of(method.def_id).own_counts();
-        if own_counts.types + own_counts.consts != 0 {
-            return Some(MethodViolationCode::Generic);
-        }
-
-        if self
-            .predicates_of(method.def_id)
-            .predicates
-            .iter()
-            // A trait object can't claim to live more than the concrete type,
-            // so outlives predicates will always hold.
-            .cloned()
-            .filter(|(p, _)| p.to_opt_type_outlives().is_none())
-            .collect::<Vec<_>>()
-            // Do a shallow visit so that `contains_illegal_self_type_reference`
-            // may apply it's custom visiting.
-            .visit_tys_shallow(|t| self.contains_illegal_self_type_reference(trait_def_id, t))
-        {
-            return Some(MethodViolationCode::WhereClauseReferencesSelf);
-        }
-
-        let receiver_ty =
-            self.liberate_late_bound_regions(method.def_id, &sig.map_bound(|sig| sig.inputs()[0]));
-
-        // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
-        // However, this is already considered object-safe. We allow it as a special case here.
-        // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
-        // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
-        if receiver_ty != self.types.self_param {
-            if !self.receiver_is_dispatchable(method, receiver_ty) {
-                return Some(MethodViolationCode::UndispatchableReceiver);
-            } else {
-                // Do sanity check to make sure the receiver actually has the layout of a pointer.
-
-                use crate::ty::layout::Abi;
-
-                let param_env = self.param_env(method.def_id);
-
-                let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
-                    match self.layout_of(param_env.and(ty)) {
-                        Ok(layout) => &layout.abi,
-                        Err(err) => {
-                            bug!("error: {}\n while computing layout for type {:?}", err, ty)
-                        }
-                    }
-                };
-
-                // e.g., `Rc<()>`
-                let unit_receiver_ty =
-                    self.receiver_for_self_ty(receiver_ty, self.mk_unit(), method.def_id);
-
-                match abi_of_ty(unit_receiver_ty) {
-                    &Abi::Scalar(..) => (),
-                    abi => {
-                        self.sess.delay_span_bug(
-                            self.def_span(method.def_id),
-                            &format!(
-                                "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
-                                abi
-                            ),
-                        );
-                    }
-                }
-
-                let trait_object_ty =
-                    self.object_ty_for_trait(trait_def_id, self.mk_region(ty::ReStatic));
-
-                // e.g., `Rc<dyn Trait>`
-                let trait_object_receiver =
-                    self.receiver_for_self_ty(receiver_ty, trait_object_ty, method.def_id);
-
-                match abi_of_ty(trait_object_receiver) {
-                    &Abi::ScalarPair(..) => (),
-                    abi => {
-                        self.sess.delay_span_bug(
-                            self.def_span(method.def_id),
-                            &format!(
-                                "receiver when `Self = {}` should have a ScalarPair ABI; \
-                                 found {:?}",
-                                trait_object_ty, abi
-                            ),
-                        );
-                    }
-                }
-            }
-        }
-
-        None
-    }
-
-    /// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
-    /// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
-    fn receiver_for_self_ty(
-        self,
-        receiver_ty: Ty<'tcx>,
-        self_ty: Ty<'tcx>,
-        method_def_id: DefId,
-    ) -> Ty<'tcx> {
-        debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
-        let substs = InternalSubsts::for_item(self, method_def_id, |param, _| {
-            if param.index == 0 { self_ty.into() } else { self.mk_param_from_def(param) }
-        });
-
-        let result = receiver_ty.subst(self, substs);
-        debug!(
-            "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
-            receiver_ty, self_ty, method_def_id, result
-        );
-        result
-    }
-
-    /// Creates the object type for the current trait. For example,
-    /// if the current trait is `Deref`, then this will be
-    /// `dyn Deref<Target = Self::Target> + 'static`.
-    fn object_ty_for_trait(self, trait_def_id: DefId, lifetime: ty::Region<'tcx>) -> Ty<'tcx> {
-        debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
-
-        let trait_ref = ty::TraitRef::identity(self, trait_def_id);
-
-        let trait_predicate = ty::ExistentialPredicate::Trait(
-            ty::ExistentialTraitRef::erase_self_ty(self, trait_ref),
-        );
-
-        let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
-            .flat_map(|super_trait_ref| {
-                self.associated_items(super_trait_ref.def_id())
-                    .map(move |item| (super_trait_ref, item))
-            })
-            .filter(|(_, item)| item.kind == ty::AssocKind::Type)
-            .collect::<Vec<_>>();
-
-        // existential predicates need to be in a specific order
-        associated_types.sort_by_cached_key(|(_, item)| self.def_path_hash(item.def_id));
-
-        let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
-            // We *can* get bound lifetimes here in cases like
-            // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
-            //
-            // binder moved to (*)...
-            let super_trait_ref = super_trait_ref.skip_binder();
-            ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
-                ty: self.mk_projection(item.def_id, super_trait_ref.substs),
-                item_def_id: item.def_id,
-                substs: super_trait_ref.substs,
-            })
-        });
-
-        let existential_predicates = self
-            .mk_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
-
-        let object_ty = self.mk_dynamic(
-            // (*) ... binder re-introduced here
-            ty::Binder::bind(existential_predicates),
-            lifetime,
-        );
-
-        debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
-
-        object_ty
-    }
-
-    /// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
-    /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
-    /// in the following way:
-    /// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
-    /// - require the following bound:
-    ///
-    ///   ```
-    ///   Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
-    ///   ```
-    ///
-    ///   where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
-    ///   (substitution notation).
-    ///
-    /// Some examples of receiver types and their required obligation:
-    /// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
-    /// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
-    /// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
-    ///
-    /// The only case where the receiver is not dispatchable, but is still a valid receiver
-    /// type (just not object-safe), is when there is more than one level of pointer indirection.
-    /// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
-    /// is no way, or at least no inexpensive way, to coerce the receiver from the version where
-    /// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
-    /// contained by the trait object, because the object that needs to be coerced is behind
-    /// a pointer.
-    ///
-    /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
-    /// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
-    /// is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561).
-    /// Instead, we fudge a little by introducing a new type parameter `U` such that
-    /// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
-    /// Written as a chalk-style query:
-    ///
-    ///     forall (U: Trait + ?Sized) {
-    ///         if (Self: Unsize<U>) {
-    ///             Receiver: DispatchFromDyn<Receiver[Self => U]>
-    ///         }
-    ///     }
-    ///
-    /// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
-    /// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
-    /// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
-    //
-    // FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
-    // fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
-    // `self: Wrapper<Self>`.
-    #[allow(dead_code)]
-    fn receiver_is_dispatchable(self, method: &ty::AssocItem, receiver_ty: Ty<'tcx>) -> bool {
-        debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
-
-        let traits =
-            (self.lang_items().unsize_trait(), self.lang_items().dispatch_from_dyn_trait());
-        let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
-            (u, cu)
-        } else {
-            debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
-            return false;
-        };
-
-        // the type `U` in the query
-        // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
-        // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
-        // replace this with `dyn Trait`
-        let unsized_self_ty: Ty<'tcx> =
-            self.mk_ty_param(::std::u32::MAX, Symbol::intern("RustaceansAreAwesome"));
-
-        // `Receiver[Self => U]`
-        let unsized_receiver_ty =
-            self.receiver_for_self_ty(receiver_ty, unsized_self_ty, method.def_id);
-
-        // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
-        // `U: ?Sized` is already implied here
-        let param_env = {
-            let mut param_env = self.param_env(method.def_id);
-
-            // Self: Unsize<U>
-            let unsize_predicate = ty::TraitRef {
-                def_id: unsize_did,
-                substs: self.mk_substs_trait(self.types.self_param, &[unsized_self_ty.into()]),
-            }
-            .to_predicate();
-
-            // U: Trait<Arg1, ..., ArgN>
-            let trait_predicate = {
-                let substs =
-                    InternalSubsts::for_item(self, method.container.assert_trait(), |param, _| {
-                        if param.index == 0 {
-                            unsized_self_ty.into()
-                        } else {
-                            self.mk_param_from_def(param)
-                        }
-                    });
-
-                ty::TraitRef { def_id: unsize_did, substs }.to_predicate()
-            };
-
-            let caller_bounds: Vec<Predicate<'tcx>> = param_env
-                .caller_bounds
-                .iter()
-                .cloned()
-                .chain(iter::once(unsize_predicate))
-                .chain(iter::once(trait_predicate))
-                .collect();
-
-            param_env.caller_bounds = self.intern_predicates(&caller_bounds);
-
-            param_env
-        };
-
-        // Receiver: DispatchFromDyn<Receiver[Self => U]>
-        let obligation = {
-            let predicate = ty::TraitRef {
-                def_id: dispatch_from_dyn_did,
-                substs: self.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
-            }
-            .to_predicate();
-
-            Obligation::new(ObligationCause::dummy(), param_env, predicate)
-        };
-
-        self.infer_ctxt().enter(|ref infcx| {
-            // the receiver is dispatchable iff the obligation holds
-            infcx.predicate_must_hold_modulo_regions(&obligation)
-        })
-    }
-
-    fn contains_illegal_self_type_reference(self, trait_def_id: DefId, ty: Ty<'tcx>) -> bool {
-        // This is somewhat subtle. In general, we want to forbid
-        // references to `Self` in the argument and return types,
-        // since the value of `Self` is erased. However, there is one
-        // exception: it is ok to reference `Self` in order to access
-        // an associated type of the current trait, since we retain
-        // the value of those associated types in the object type
-        // itself.
-        //
-        // ```rust
-        // trait SuperTrait {
-        //     type X;
-        // }
-        //
-        // trait Trait : SuperTrait {
-        //     type Y;
-        //     fn foo(&self, x: Self) // bad
-        //     fn foo(&self) -> Self // bad
-        //     fn foo(&self) -> Option<Self> // bad
-        //     fn foo(&self) -> Self::Y // OK, desugars to next example
-        //     fn foo(&self) -> <Self as Trait>::Y // OK
-        //     fn foo(&self) -> Self::X // OK, desugars to next example
-        //     fn foo(&self) -> <Self as SuperTrait>::X // OK
-        // }
-        // ```
-        //
-        // However, it is not as simple as allowing `Self` in a projected
-        // type, because there are illegal ways to use `Self` as well:
-        //
-        // ```rust
-        // trait Trait : SuperTrait {
-        //     ...
-        //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
-        // }
-        // ```
-        //
-        // Here we will not have the type of `X` recorded in the
-        // object type, and we cannot resolve `Self as SomeOtherTrait`
-        // without knowing what `Self` is.
-
-        let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
-        let mut error = false;
-        let self_ty = self.types.self_param;
-        ty.maybe_walk(|ty| {
-            match ty.kind {
-                ty::Param(_) => {
-                    if ty == self_ty {
-                        error = true;
-                    }
-
-                    false // no contained types to walk
-                }
-
-                ty::Projection(ref data) => {
-                    // This is a projected type `<Foo as SomeTrait>::X`.
-
-                    // Compute supertraits of current trait lazily.
-                    if supertraits.is_none() {
-                        let trait_ref =
-                            ty::Binder::bind(ty::TraitRef::identity(self, trait_def_id));
-                        supertraits = Some(traits::supertraits(self, trait_ref).collect());
-                    }
-
-                    // Determine whether the trait reference `Foo as
-                    // SomeTrait` is in fact a supertrait of the
-                    // current trait. In that case, this type is
-                    // legal, because the type `X` will be specified
-                    // in the object type.  Note that we can just use
-                    // direct equality here because all of these types
-                    // are part of the formal parameter listing, and
-                    // hence there should be no inference variables.
-                    let projection_trait_ref = ty::Binder::bind(data.trait_ref(self));
-                    let is_supertrait_of_current_trait =
-                        supertraits.as_ref().unwrap().contains(&projection_trait_ref);
-
-                    if is_supertrait_of_current_trait {
-                        false // do not walk contained types, do not report error, do collect $200
-                    } else {
-                        true // DO walk contained types, POSSIBLY reporting an error
-                    }
-                }
-
-                _ => true, // walk contained types, if any
-            }
-        });
-
-        error
+    match virtual_call_violation_for_method(tcx, trait_def_id, method) {
+        None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
+        Some(_) => false,
     }
 }
 
+fn object_safety_violations_for_trait(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+) -> Vec<ObjectSafetyViolation> {
+    // Check methods for violations.
+    let mut violations: Vec<_> = tcx
+        .associated_items(trait_def_id)
+        .filter(|item| item.kind == ty::AssocKind::Method)
+        .filter_map(|item| {
+            object_safety_violation_for_method(tcx, trait_def_id, &item)
+                .map(|code| ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span))
+        })
+        .filter(|violation| {
+            if let ObjectSafetyViolation::Method(
+                _,
+                MethodViolationCode::WhereClauseReferencesSelf,
+                span,
+            ) = violation
+            {
+                // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
+                // It's also hard to get a use site span, so we use the method definition span.
+                tcx.struct_span_lint_hir(
+                    WHERE_CLAUSES_OBJECT_SAFETY,
+                    hir::CRATE_HIR_ID,
+                    *span,
+                    &format!(
+                        "the trait `{}` cannot be made into an object",
+                        tcx.def_path_str(trait_def_id)
+                    ),
+                )
+                .note(&violation.error_msg())
+                .emit();
+                false
+            } else {
+                true
+            }
+        })
+        .collect();
+
+    // Check the trait itself.
+    if trait_has_sized_self(tcx, trait_def_id) {
+        violations.push(ObjectSafetyViolation::SizedSelf);
+    }
+    if predicates_reference_self(tcx, trait_def_id, false) {
+        violations.push(ObjectSafetyViolation::SupertraitSelf);
+    }
+
+    violations.extend(
+        tcx.associated_items(trait_def_id)
+            .filter(|item| item.kind == ty::AssocKind::Const)
+            .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
+    );
+
+    debug!(
+        "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
+        trait_def_id, violations
+    );
+
+    violations
+}
+
+fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_only: bool) -> bool {
+    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
+    let predicates = if supertraits_only {
+        tcx.super_predicates_of(trait_def_id)
+    } else {
+        tcx.predicates_of(trait_def_id)
+    };
+    let self_ty = tcx.types.self_param;
+    let has_self_ty = |t: Ty<'_>| t.walk().any(|t| t == self_ty);
+    predicates
+        .predicates
+        .iter()
+        .map(|(predicate, _)| predicate.subst_supertrait(tcx, &trait_ref))
+        .any(|predicate| {
+            match predicate {
+                ty::Predicate::Trait(ref data) => {
+                    // In the case of a trait predicate, we can skip the "self" type.
+                    data.skip_binder().input_types().skip(1).any(has_self_ty)
+                }
+                ty::Predicate::Projection(ref data) => {
+                    // And similarly for projections. This should be redundant with
+                    // the previous check because any projection should have a
+                    // matching `Trait` predicate with the same inputs, but we do
+                    // the check to be safe.
+                    //
+                    // Note that we *do* allow projection *outputs* to contain
+                    // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
+                    // we just require the user to specify *both* outputs
+                    // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
+                    //
+                    // This is ALT2 in issue #56288, see that for discussion of the
+                    // possible alternatives.
+                    data.skip_binder()
+                        .projection_ty
+                        .trait_ref(tcx)
+                        .input_types()
+                        .skip(1)
+                        .any(has_self_ty)
+                }
+                ty::Predicate::WellFormed(..)
+                | ty::Predicate::ObjectSafe(..)
+                | ty::Predicate::TypeOutlives(..)
+                | ty::Predicate::RegionOutlives(..)
+                | ty::Predicate::ClosureKind(..)
+                | ty::Predicate::Subtype(..)
+                | ty::Predicate::ConstEvaluatable(..) => false,
+            }
+        })
+}
+
+fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
+    generics_require_sized_self(tcx, trait_def_id)
+}
+
+fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    let sized_def_id = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => {
+            return false; /* No Sized trait, can't require it! */
+        }
+    };
+
+    // Search for a predicate like `Self : Sized` amongst the trait bounds.
+    let predicates = tcx.predicates_of(def_id);
+    let predicates = predicates.instantiate_identity(tcx).predicates;
+    elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
+        ty::Predicate::Trait(ref trait_pred) => {
+            trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
+        }
+        ty::Predicate::Projection(..)
+        | ty::Predicate::Subtype(..)
+        | ty::Predicate::RegionOutlives(..)
+        | ty::Predicate::WellFormed(..)
+        | ty::Predicate::ObjectSafe(..)
+        | ty::Predicate::ClosureKind(..)
+        | ty::Predicate::TypeOutlives(..)
+        | ty::Predicate::ConstEvaluatable(..) => false,
+    })
+}
+
+/// Returns `Some(_)` if this method makes the containing trait not object safe.
+fn object_safety_violation_for_method(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+    method: &ty::AssocItem,
+) -> Option<MethodViolationCode> {
+    debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
+    // Any method that has a `Self : Sized` requisite is otherwise
+    // exempt from the regulations.
+    if generics_require_sized_self(tcx, method.def_id) {
+        return None;
+    }
+
+    virtual_call_violation_for_method(tcx, trait_def_id, method)
+}
+
+/// Returns `Some(_)` if this method cannot be called on a trait
+/// object; this does not necessarily imply that the enclosing trait
+/// is not object safe, because the method might have a where clause
+/// `Self:Sized`.
+fn virtual_call_violation_for_method<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_def_id: DefId,
+    method: &ty::AssocItem,
+) -> Option<MethodViolationCode> {
+    // The method's first parameter must be named `self`
+    if !method.method_has_self_argument {
+        return Some(MethodViolationCode::StaticMethod);
+    }
+
+    let sig = tcx.fn_sig(method.def_id);
+
+    for input_ty in &sig.skip_binder().inputs()[1..] {
+        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
+            return Some(MethodViolationCode::ReferencesSelf);
+        }
+    }
+    if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
+        return Some(MethodViolationCode::ReferencesSelf);
+    }
+
+    // We can't monomorphize things like `fn foo<A>(...)`.
+    let own_counts = tcx.generics_of(method.def_id).own_counts();
+    if own_counts.types + own_counts.consts != 0 {
+        return Some(MethodViolationCode::Generic);
+    }
+
+    if tcx
+        .predicates_of(method.def_id)
+        .predicates
+        .iter()
+        // A trait object can't claim to live more than the concrete type,
+        // so outlives predicates will always hold.
+        .cloned()
+        .filter(|(p, _)| p.to_opt_type_outlives().is_none())
+        .collect::<Vec<_>>()
+        // Do a shallow visit so that `contains_illegal_self_type_reference`
+        // may apply it's custom visiting.
+        .visit_tys_shallow(|t| contains_illegal_self_type_reference(tcx, trait_def_id, t))
+    {
+        return Some(MethodViolationCode::WhereClauseReferencesSelf);
+    }
+
+    let receiver_ty =
+        tcx.liberate_late_bound_regions(method.def_id, &sig.map_bound(|sig| sig.inputs()[0]));
+
+    // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
+    // However, this is already considered object-safe. We allow it as a special case here.
+    // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
+    // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
+    if receiver_ty != tcx.types.self_param {
+        if !receiver_is_dispatchable(tcx, method, receiver_ty) {
+            return Some(MethodViolationCode::UndispatchableReceiver);
+        } else {
+            // Do sanity check to make sure the receiver actually has the layout of a pointer.
+
+            use crate::ty::layout::Abi;
+
+            let param_env = tcx.param_env(method.def_id);
+
+            let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
+                match tcx.layout_of(param_env.and(ty)) {
+                    Ok(layout) => &layout.abi,
+                    Err(err) => bug!("error: {}\n while computing layout for type {:?}", err, ty),
+                }
+            };
+
+            // e.g., `Rc<()>`
+            let unit_receiver_ty =
+                receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);
+
+            match abi_of_ty(unit_receiver_ty) {
+                &Abi::Scalar(..) => (),
+                abi => {
+                    tcx.sess.delay_span_bug(
+                        tcx.def_span(method.def_id),
+                        &format!(
+                            "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
+                            abi
+                        ),
+                    );
+                }
+            }
+
+            let trait_object_ty =
+                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
+
+            // e.g., `Rc<dyn Trait>`
+            let trait_object_receiver =
+                receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
+
+            match abi_of_ty(trait_object_receiver) {
+                &Abi::ScalarPair(..) => (),
+                abi => {
+                    tcx.sess.delay_span_bug(
+                        tcx.def_span(method.def_id),
+                        &format!(
+                            "receiver when `Self = {}` should have a ScalarPair ABI; \
+                                 found {:?}",
+                            trait_object_ty, abi
+                        ),
+                    );
+                }
+            }
+        }
+    }
+
+    None
+}
+
+/// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
+/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
+fn receiver_for_self_ty<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    receiver_ty: Ty<'tcx>,
+    self_ty: Ty<'tcx>,
+    method_def_id: DefId,
+) -> Ty<'tcx> {
+    debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
+    let substs = InternalSubsts::for_item(tcx, method_def_id, |param, _| {
+        if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
+    });
+
+    let result = receiver_ty.subst(tcx, substs);
+    debug!(
+        "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
+        receiver_ty, self_ty, method_def_id, result
+    );
+    result
+}
+
+/// Creates the object type for the current trait. For example,
+/// if the current trait is `Deref`, then this will be
+/// `dyn Deref<Target = Self::Target> + 'static`.
+fn object_ty_for_trait<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_def_id: DefId,
+    lifetime: ty::Region<'tcx>,
+) -> Ty<'tcx> {
+    debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
+
+    let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
+
+    let trait_predicate =
+        ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+    let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
+        .flat_map(|super_trait_ref| {
+            tcx.associated_items(super_trait_ref.def_id()).map(move |item| (super_trait_ref, item))
+        })
+        .filter(|(_, item)| item.kind == ty::AssocKind::Type)
+        .collect::<Vec<_>>();
+
+    // existential predicates need to be in a specific order
+    associated_types.sort_by_cached_key(|(_, item)| tcx.def_path_hash(item.def_id));
+
+    let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
+        // We *can* get bound lifetimes here in cases like
+        // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
+        //
+        // binder moved to (*)...
+        let super_trait_ref = super_trait_ref.skip_binder();
+        ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
+            ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
+            item_def_id: item.def_id,
+            substs: super_trait_ref.substs,
+        })
+    });
+
+    let existential_predicates =
+        tcx.mk_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
+
+    let object_ty = tcx.mk_dynamic(
+        // (*) ... binder re-introduced here
+        ty::Binder::bind(existential_predicates),
+        lifetime,
+    );
+
+    debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
+
+    object_ty
+}
+
+/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
+/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
+/// in the following way:
+/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
+/// - require the following bound:
+///
+///   ```
+///   Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
+///   ```
+///
+///   where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
+///   (substitution notation).
+///
+/// Some examples of receiver types and their required obligation:
+/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
+/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
+/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
+///
+/// The only case where the receiver is not dispatchable, but is still a valid receiver
+/// type (just not object-safe), is when there is more than one level of pointer indirection.
+/// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
+/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
+/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
+/// contained by the trait object, because the object that needs to be coerced is behind
+/// a pointer.
+///
+/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
+/// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
+/// is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561).
+/// Instead, we fudge a little by introducing a new type parameter `U` such that
+/// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
+/// Written as a chalk-style query:
+///
+///     forall (U: Trait + ?Sized) {
+///         if (Self: Unsize<U>) {
+///             Receiver: DispatchFromDyn<Receiver[Self => U]>
+///         }
+///     }
+///
+/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
+/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
+/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
+//
+// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
+// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
+// `self: Wrapper<Self>`.
+#[allow(dead_code)]
+fn receiver_is_dispatchable<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    method: &ty::AssocItem,
+    receiver_ty: Ty<'tcx>,
+) -> bool {
+    debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
+
+    let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
+    let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
+        (u, cu)
+    } else {
+        debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
+        return false;
+    };
+
+    // the type `U` in the query
+    // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
+    // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
+    // replace this with `dyn Trait`
+    let unsized_self_ty: Ty<'tcx> =
+        tcx.mk_ty_param(::std::u32::MAX, Symbol::intern("RustaceansAreAwesome"));
+
+    // `Receiver[Self => U]`
+    let unsized_receiver_ty =
+        receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
+
+    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
+    // `U: ?Sized` is already implied here
+    let param_env = {
+        let mut param_env = tcx.param_env(method.def_id);
+
+        // Self: Unsize<U>
+        let unsize_predicate = ty::TraitRef {
+            def_id: unsize_did,
+            substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
+        }
+        .to_predicate();
+
+        // U: Trait<Arg1, ..., ArgN>
+        let trait_predicate = {
+            let substs =
+                InternalSubsts::for_item(tcx, method.container.assert_trait(), |param, _| {
+                    if param.index == 0 {
+                        unsized_self_ty.into()
+                    } else {
+                        tcx.mk_param_from_def(param)
+                    }
+                });
+
+            ty::TraitRef { def_id: unsize_did, substs }.to_predicate()
+        };
+
+        let caller_bounds: Vec<Predicate<'tcx>> = param_env
+            .caller_bounds
+            .iter()
+            .cloned()
+            .chain(iter::once(unsize_predicate))
+            .chain(iter::once(trait_predicate))
+            .collect();
+
+        param_env.caller_bounds = tcx.intern_predicates(&caller_bounds);
+
+        param_env
+    };
+
+    // Receiver: DispatchFromDyn<Receiver[Self => U]>
+    let obligation = {
+        let predicate = ty::TraitRef {
+            def_id: dispatch_from_dyn_did,
+            substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
+        }
+        .to_predicate();
+
+        Obligation::new(ObligationCause::dummy(), param_env, predicate)
+    };
+
+    tcx.infer_ctxt().enter(|ref infcx| {
+        // the receiver is dispatchable iff the obligation holds
+        infcx.predicate_must_hold_modulo_regions(&obligation)
+    })
+}
+
+fn contains_illegal_self_type_reference<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_def_id: DefId,
+    ty: Ty<'tcx>,
+) -> bool {
+    // This is somewhat subtle. In general, we want to forbid
+    // references to `Self` in the argument and return types,
+    // since the value of `Self` is erased. However, there is one
+    // exception: it is ok to reference `Self` in order to access
+    // an associated type of the current trait, since we retain
+    // the value of those associated types in the object type
+    // itself.
+    //
+    // ```rust
+    // trait SuperTrait {
+    //     type X;
+    // }
+    //
+    // trait Trait : SuperTrait {
+    //     type Y;
+    //     fn foo(&self, x: Self) // bad
+    //     fn foo(&self) -> Self // bad
+    //     fn foo(&self) -> Option<Self> // bad
+    //     fn foo(&self) -> Self::Y // OK, desugars to next example
+    //     fn foo(&self) -> <Self as Trait>::Y // OK
+    //     fn foo(&self) -> Self::X // OK, desugars to next example
+    //     fn foo(&self) -> <Self as SuperTrait>::X // OK
+    // }
+    // ```
+    //
+    // However, it is not as simple as allowing `Self` in a projected
+    // type, because there are illegal ways to use `Self` as well:
+    //
+    // ```rust
+    // trait Trait : SuperTrait {
+    //     ...
+    //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
+    // }
+    // ```
+    //
+    // Here we will not have the type of `X` recorded in the
+    // object type, and we cannot resolve `Self as SomeOtherTrait`
+    // without knowing what `Self` is.
+
+    let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
+    let mut error = false;
+    let self_ty = tcx.types.self_param;
+    ty.maybe_walk(|ty| {
+        match ty.kind {
+            ty::Param(_) => {
+                if ty == self_ty {
+                    error = true;
+                }
+
+                false // no contained types to walk
+            }
+
+            ty::Projection(ref data) => {
+                // This is a projected type `<Foo as SomeTrait>::X`.
+
+                // Compute supertraits of current trait lazily.
+                if supertraits.is_none() {
+                    let trait_ref = ty::Binder::bind(ty::TraitRef::identity(tcx, trait_def_id));
+                    supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
+                }
+
+                // Determine whether the trait reference `Foo as
+                // SomeTrait` is in fact a supertrait of the
+                // current trait. In that case, this type is
+                // legal, because the type `X` will be specified
+                // in the object type.  Note that we can just use
+                // direct equality here because all of these types
+                // are part of the formal parameter listing, and
+                // hence there should be no inference variables.
+                let projection_trait_ref = ty::Binder::bind(data.trait_ref(tcx));
+                let is_supertrait_of_current_trait =
+                    supertraits.as_ref().unwrap().contains(&projection_trait_ref);
+
+                if is_supertrait_of_current_trait {
+                    false // do not walk contained types, do not report error, do collect $200
+                } else {
+                    true // DO walk contained types, POSSIBLY reporting an error
+                }
+            }
+
+            _ => true, // walk contained types, if any
+        }
+    });
+
+    error
+}
+
 pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
-    tcx.object_safety_violations(trait_def_id).is_empty()
+    object_safety_violations(tcx, trait_def_id).is_empty()
 }
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index f1a04da..1afe153 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -1,10 +1,11 @@
 use fmt_macros::{Parser, Piece, Position};
 
-use crate::hir::def_id::DefId;
 use crate::ty::{self, GenericParamDefKind, TyCtxt};
 use crate::util::common::ErrorReported;
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 use syntax::ast::{MetaItem, NestedMetaItem};
@@ -293,26 +294,28 @@
                         match generics.params.iter().find(|param| param.name == s) {
                             Some(_) => (),
                             None => {
-                                span_err!(
+                                struct_span_err!(
                                     tcx.sess,
                                     span,
                                     E0230,
                                     "there is no parameter `{}` on trait `{}`",
                                     s,
                                     name
-                                );
+                                )
+                                .emit();
                                 result = Err(ErrorReported);
                             }
                         }
                     }
                     // `{:1}` and `{}` are not to be used
                     Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             span,
                             E0231,
                             "only named substitution parameters are allowed"
-                        );
+                        )
+                        .emit();
                         result = Err(ErrorReported);
                     }
                 },
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index c29011c..5bc211a 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -12,14 +12,13 @@
 use super::SelectionError;
 use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData};
 
-use crate::hir::def_id::DefId;
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
 use crate::ty::fold::{TypeFoldable, TypeFolder};
 use crate::ty::subst::{InternalSubsts, Subst};
 use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
-use crate::util::common::FN_OUTPUT_NAME;
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
@@ -1057,7 +1056,7 @@
                     node_item.item.defaultness.has_value()
                 } else {
                     node_item.item.defaultness.is_default()
-                        || selcx.tcx().impl_is_default(node_item.node.def_id())
+                        || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
                 };
 
                 // Only reveal a specializable default if we're past type-checking
@@ -1263,26 +1262,30 @@
 
     let gen_def_id = tcx.lang_items().gen_trait().unwrap();
 
-    let predicate = tcx
-        .generator_trait_ref_and_outputs(gen_def_id, obligation.predicate.self_ty(), gen_sig)
-        .map_bound(|(trait_ref, yield_ty, return_ty)| {
-            let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
-            let ty = if name == sym::Return {
-                return_ty
-            } else if name == sym::Yield {
-                yield_ty
-            } else {
-                bug!()
-            };
+    let predicate = super::util::generator_trait_ref_and_outputs(
+        tcx,
+        gen_def_id,
+        obligation.predicate.self_ty(),
+        gen_sig,
+    )
+    .map_bound(|(trait_ref, yield_ty, return_ty)| {
+        let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
+        let ty = if name == sym::Return {
+            return_ty
+        } else if name == sym::Yield {
+            yield_ty
+        } else {
+            bug!()
+        };
 
-            ty::ProjectionPredicate {
-                projection_ty: ty::ProjectionTy {
-                    substs: trait_ref.substs,
-                    item_def_id: obligation.predicate.item_def_id,
-                },
-                ty: ty,
-            }
-        });
+        ty::ProjectionPredicate {
+            projection_ty: ty::ProjectionTy {
+                substs: trait_ref.substs,
+                item_def_id: obligation.predicate.item_def_id,
+            },
+            ty: ty,
+        }
+    });
 
     confirm_param_env_candidate(selcx, obligation, predicate)
         .with_addl_obligations(vtable.nested)
@@ -1349,21 +1352,21 @@
     // the `Output` associated type is declared on `FnOnce`
     let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
 
-    let predicate = tcx
-        .closure_trait_ref_and_return_type(
-            fn_once_def_id,
-            obligation.predicate.self_ty(),
-            fn_sig,
-            flag,
-        )
-        .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy::from_ref_and_name(
-                tcx,
-                trait_ref,
-                Ident::with_dummy_span(FN_OUTPUT_NAME),
-            ),
-            ty: ret_type,
-        });
+    let predicate = super::util::closure_trait_ref_and_return_type(
+        tcx,
+        fn_once_def_id,
+        obligation.predicate.self_ty(),
+        fn_sig,
+        flag,
+    )
+    .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
+        projection_ty: ty::ProjectionTy::from_ref_and_name(
+            tcx,
+            trait_ref,
+            Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME),
+        ),
+        ty: ret_type,
+    });
 
     confirm_param_env_candidate(selcx, obligation, predicate)
 }
@@ -1464,7 +1467,7 @@
     // cycle error if the specialization graph is currently being built.
     let impl_node = specialization_graph::Node::Impl(impl_def_id);
     for item in impl_node.items(tcx) {
-        if item.kind == ty::AssocKind::Type
+        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
             && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
         {
             return specialization_graph::NodeItem {
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 87f7f67..34866b6 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -76,15 +76,15 @@
 impl<'tcx> DropckOutlivesResult<'tcx> {
     pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
         if let Some(overflow_ty) = self.overflows.iter().next() {
-            let mut err = struct_span_err!(
+            rustc_errors::struct_span_err!(
                 tcx.sess,
                 span,
                 E0320,
                 "overflow while adding drop-check rules for {}",
                 ty,
-            );
-            err.note(&format!("overflowed on {}", overflow_ty));
-            err.emit();
+            )
+            .note(&format!("overflowed on {}", overflow_ty))
+            .emit();
         }
     }
 
diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs
index fb9f460..440268a 100644
--- a/src/librustc/traits/query/mod.rs
+++ b/src/librustc/traits/query/mod.rs
@@ -13,7 +13,6 @@
 pub mod evaluate_obligation;
 pub mod method_autoderef;
 pub mod normalize;
-pub mod normalize_erasing_regions;
 pub mod outlives_bounds;
 pub mod type_op;
 
diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs
index 6a0bc16..07e57e8 100644
--- a/src/librustc/traits/query/outlives_bounds.rs
+++ b/src/librustc/traits/query/outlives_bounds.rs
@@ -1,9 +1,9 @@
-use crate::hir;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferCtxt;
 use crate::traits::query::NoSolution;
 use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
 use crate::ty::{self, Ty};
+use rustc_hir as hir;
 use rustc_span::source_map::Span;
 
 use crate::ich::StableHashingContext;
diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs
index e183a5a..46b656e 100644
--- a/src/librustc/traits/query/type_op/ascribe_user_type.rs
+++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs
@@ -1,8 +1,8 @@
-use crate::hir::def_id::DefId;
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
 use crate::ty::subst::UserSubsts;
 use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
+use rustc_hir::def_id::DefId;
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
 pub struct AscribeUserType<'tcx> {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 0d35ad2..e96697c 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -11,6 +11,8 @@
 use super::project;
 use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey};
 use super::util;
+use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
+use super::wf;
 use super::DerivedObligationCause;
 use super::Selection;
 use super::SelectionResult;
@@ -30,17 +32,17 @@
 };
 
 use crate::dep_graph::{DepKind, DepNodeIndex};
-use crate::hir::def_id::DefId;
 use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
 use crate::middle::lang_items;
 use crate::ty::fast_reject;
 use crate::ty::relate::TypeRelation;
 use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc_hir::def_id::DefId;
 
-use crate::hir;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lock;
+use rustc_hir as hir;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
@@ -100,7 +102,7 @@
 impl IntercrateAmbiguityCause {
     /// Emits notes when the overlap is caused by complex intercrate ambiguities.
     /// See #23980 for details.
-    pub fn add_intercrate_ambiguity_hint(&self, err: &mut errors::DiagnosticBuilder<'_>) {
+    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
         err.note(&self.intercrate_ambiguity_hint());
     }
 
@@ -737,7 +739,7 @@
                 }
             }
 
-            ty::Predicate::WellFormed(ty) => match ty::wf::obligations(
+            ty::Predicate::WellFormed(ty) => match wf::obligations(
                 self.infcx,
                 obligation.param_env,
                 obligation.cause.body_id,
@@ -800,8 +802,13 @@
 
             ty::Predicate::ConstEvaluatable(def_id, substs) => {
                 if !(obligation.param_env, substs).has_local_value() {
-                    match self.tcx().const_eval_resolve(obligation.param_env, def_id, substs, None)
-                    {
+                    match self.tcx().const_eval_resolve(
+                        obligation.param_env,
+                        def_id,
+                        substs,
+                        None,
+                        None,
+                    ) {
                         Ok(_) => Ok(EvaluatedToOk),
                         Err(_) => Ok(EvaluatedToErr),
                     }
@@ -1153,7 +1160,7 @@
     /// to have a *lower* recursion_depth than the obligation used to create it.
     /// Projection sub-obligations may be returned from the projection cache,
     /// which results in obligations with an 'old' `recursion_depth`.
-    /// Additionally, methods like `ty::wf::obligations` and
+    /// Additionally, methods like `wf::obligations` and
     /// `InferCtxt.subtype_predicate` produce subobligations without
     /// taking in a 'parent' depth, causing the generated subobligations
     /// to have a `recursion_depth` of `0`.
@@ -2651,7 +2658,8 @@
                             recursion_depth,
                             &skol_ty,
                         );
-                    let skol_obligation = self.tcx().predicate_for_trait_def(
+                    let skol_obligation = predicate_for_trait_def(
+                        self.tcx(),
                         param_env,
                         cause.clone(),
                         trait_def_id,
@@ -2988,7 +2996,7 @@
             // we pass over, we sum up the set of number of vtable
             // entries, so that we can compute the offset for the selected
             // trait.
-            vtable_base = nonmatching.map(|t| tcx.count_own_vtable_entries(t)).sum();
+            vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum();
         }
 
         VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested }
@@ -3003,15 +3011,14 @@
         // Okay to skip binder; it is reintroduced below.
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let sig = self_ty.fn_sig(self.tcx());
-        let trait_ref = self
-            .tcx()
-            .closure_trait_ref_and_return_type(
-                obligation.predicate.def_id(),
-                self_ty,
-                sig,
-                util::TupleArgumentsFlag::Yes,
-            )
-            .map_bound(|(trait_ref, _)| trait_ref);
+        let trait_ref = closure_trait_ref_and_return_type(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            self_ty,
+            sig,
+            util::TupleArgumentsFlag::Yes,
+        )
+        .map_bound(|(trait_ref, _)| trait_ref);
 
         let Normalized { value: trait_ref, obligations } = project::normalize_with_depth(
             self,
@@ -3381,7 +3388,8 @@
                 nested.extend(obligations);
 
                 // Construct the nested `Field<T>: Unsize<Field<U>>` predicate.
-                nested.push(tcx.predicate_for_trait_def(
+                nested.push(predicate_for_trait_def(
+                    tcx,
                     obligation.param_env,
                     obligation.cause.clone(),
                     obligation.predicate.def_id(),
@@ -3416,7 +3424,8 @@
                 nested.extend(obligations);
 
                 // Construct the nested `T: Unsize<U>` predicate.
-                nested.push(tcx.predicate_for_trait_def(
+                nested.push(predicate_for_trait_def(
+                    tcx,
                     obligation.param_env,
                     obligation.cause.clone(),
                     obligation.predicate.def_id(),
@@ -3627,14 +3636,14 @@
         // in fact unparameterized (or at least does not reference any
         // regions bound in the obligation). Still probably some
         // refactoring could make this nicer.
-        self.tcx()
-            .closure_trait_ref_and_return_type(
-                obligation.predicate.def_id(),
-                obligation.predicate.skip_binder().self_ty(), // (1)
-                closure_type,
-                util::TupleArgumentsFlag::No,
-            )
-            .map_bound(|(trait_ref, _)| trait_ref)
+        closure_trait_ref_and_return_type(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            obligation.predicate.skip_binder().self_ty(), // (1)
+            closure_type,
+            util::TupleArgumentsFlag::No,
+        )
+        .map_bound(|(trait_ref, _)| trait_ref)
     }
 
     fn generator_trait_ref_unnormalized(
@@ -3651,13 +3660,13 @@
         // regions bound in the obligation). Still probably some
         // refactoring could make this nicer.
 
-        self.tcx()
-            .generator_trait_ref_and_outputs(
-                obligation.predicate.def_id(),
-                obligation.predicate.skip_binder().self_ty(), // (1)
-                gen_sig,
-            )
-            .map_bound(|(trait_ref, ..)| trait_ref)
+        super::util::generator_trait_ref_and_outputs(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            obligation.predicate.skip_binder().self_ty(), // (1)
+            gen_sig,
+        )
+        .map_bound(|(trait_ref, ..)| trait_ref)
     }
 
     /// Returns the obligations that are implied by instantiating an
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 9d3e9e3..f5199db 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -11,14 +11,15 @@
 
 pub mod specialization_graph;
 
-use crate::hir::def_id::DefId;
 use crate::infer::{InferCtxt, InferOk};
-use crate::lint;
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use crate::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
 use rustc_span::DUMMY_SP;
 
 use super::util::impl_trait_ref_and_oblig;
@@ -341,7 +342,7 @@
                                 unreachable!("converted to hard error above")
                             }
                             FutureCompatOverlapErrorKind::Issue33140 => {
-                                lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS
+                                ORDER_DEPENDENT_TRAIT_OBJECTS
                             }
                         };
                         tcx.struct_span_lint_hir(
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 200c218..c176f13 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -1,12 +1,12 @@
 use super::OverlapError;
 
-use crate::hir::def_id::{DefId, DefIdMap};
 use crate::ich::{self, StableHashingContext};
 use crate::traits;
 use crate::ty::fast_reject::{self, SimplifiedType};
 use crate::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{DefId, DefIdMap};
 use syntax::ast::Ident;
 
 /// A per-trait graph of impls in specialization order. At the moment, this
diff --git a/src/librustc/ty/structural_match.rs b/src/librustc/traits/structural_match.rs
similarity index 99%
rename from src/librustc/ty/structural_match.rs
rename to src/librustc/traits/structural_match.rs
index 13cb5fd..b2c3c23 100644
--- a/src/librustc/ty/structural_match.rs
+++ b/src/librustc/traits/structural_match.rs
@@ -1,15 +1,13 @@
-use crate::hir;
+use crate::ty::fold::{TypeFoldable, TypeVisitor};
+use crate::ty::{self, AdtDef, Ty, TyCtxt};
+
 use rustc::infer::InferCtxt;
 use rustc::traits::ObligationCause;
 use rustc::traits::{self, ConstPatternStructural, TraitEngine};
-
 use rustc_data_structures::fx::FxHashSet;
-
+use rustc_hir as hir;
 use rustc_span::Span;
 
-use crate::ty::fold::{TypeFoldable, TypeVisitor};
-use crate::ty::{self, AdtDef, Ty, TyCtxt};
-
 #[derive(Debug)]
 pub enum NonStructuralMatchTy<'tcx> {
     Adt(&'tcx AdtDef),
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 9951311..65fd809 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -1,13 +1,13 @@
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_span::Span;
 use smallvec::SmallVec;
 
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::ty::outlives::Component;
 use crate::ty::subst::{GenericArg, Subst, SubstsRef};
 use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 
 use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
 
@@ -548,125 +548,123 @@
     Obligation { cause, param_env, recursion_depth, predicate: trait_ref.to_predicate() }
 }
 
-impl<'tcx> TyCtxt<'tcx> {
-    pub fn predicate_for_trait_def(
-        self,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: ObligationCause<'tcx>,
-        trait_def_id: DefId,
-        recursion_depth: usize,
-        self_ty: Ty<'tcx>,
-        params: &[GenericArg<'tcx>],
-    ) -> PredicateObligation<'tcx> {
-        let trait_ref =
-            ty::TraitRef { def_id: trait_def_id, substs: self.mk_substs_trait(self_ty, params) };
-        predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
+pub fn predicate_for_trait_def(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    trait_def_id: DefId,
+    recursion_depth: usize,
+    self_ty: Ty<'tcx>,
+    params: &[GenericArg<'tcx>],
+) -> PredicateObligation<'tcx> {
+    let trait_ref =
+        ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
+    predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
+}
+
+/// Casts a trait reference into a reference to one of its super
+/// traits; returns `None` if `target_trait_def_id` is not a
+/// supertrait.
+pub fn upcast_choices(
+    tcx: TyCtxt<'tcx>,
+    source_trait_ref: ty::PolyTraitRef<'tcx>,
+    target_trait_def_id: DefId,
+) -> Vec<ty::PolyTraitRef<'tcx>> {
+    if source_trait_ref.def_id() == target_trait_def_id {
+        return vec![source_trait_ref]; // Shortcut the most common case.
     }
 
-    /// Casts a trait reference into a reference to one of its super
-    /// traits; returns `None` if `target_trait_def_id` is not a
-    /// supertrait.
-    pub fn upcast_choices(
-        self,
-        source_trait_ref: ty::PolyTraitRef<'tcx>,
-        target_trait_def_id: DefId,
-    ) -> Vec<ty::PolyTraitRef<'tcx>> {
-        if source_trait_ref.def_id() == target_trait_def_id {
-            return vec![source_trait_ref]; // Shortcut the most common case.
+    supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
+}
+
+/// Given a trait `trait_ref`, returns the number of vtable entries
+/// that come from `trait_ref`, excluding its supertraits. Used in
+/// computing the vtable base for an upcast trait of a trait object.
+pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
+    let mut entries = 0;
+    // Count number of methods and add them to the total offset.
+    // Skip over associated types and constants.
+    for trait_item in tcx.associated_items(trait_ref.def_id()) {
+        if trait_item.kind == ty::AssocKind::Method {
+            entries += 1;
         }
-
-        supertraits(self, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
     }
+    entries
+}
 
-    /// Given a trait `trait_ref`, returns the number of vtable entries
-    /// that come from `trait_ref`, excluding its supertraits. Used in
-    /// computing the vtable base for an upcast trait of a trait object.
-    pub fn count_own_vtable_entries(self, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
-        let mut entries = 0;
-        // Count number of methods and add them to the total offset.
-        // Skip over associated types and constants.
-        for trait_item in self.associated_items(trait_ref.def_id()) {
-            if trait_item.kind == ty::AssocKind::Method {
-                entries += 1;
-            }
+/// Given an upcast trait object described by `object`, returns the
+/// index of the method `method_def_id` (which should be part of
+/// `object.upcast_trait_ref`) within the vtable for `object`.
+pub fn get_vtable_index_of_object_method<N>(
+    tcx: TyCtxt<'tcx>,
+    object: &super::VtableObjectData<'tcx, N>,
+    method_def_id: DefId,
+) -> usize {
+    // Count number of methods preceding the one we are selecting and
+    // add them to the total offset.
+    // Skip over associated types and constants.
+    let mut entries = object.vtable_base;
+    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()) {
+        if trait_item.def_id == method_def_id {
+            // The item with the ID we were given really ought to be a method.
+            assert_eq!(trait_item.kind, ty::AssocKind::Method);
+            return entries;
         }
-        entries
-    }
-
-    /// Given an upcast trait object described by `object`, returns the
-    /// index of the method `method_def_id` (which should be part of
-    /// `object.upcast_trait_ref`) within the vtable for `object`.
-    pub fn get_vtable_index_of_object_method<N>(
-        self,
-        object: &super::VtableObjectData<'tcx, N>,
-        method_def_id: DefId,
-    ) -> usize {
-        // Count number of methods preceding the one we are selecting and
-        // add them to the total offset.
-        // Skip over associated types and constants.
-        let mut entries = object.vtable_base;
-        for trait_item in self.associated_items(object.upcast_trait_ref.def_id()) {
-            if trait_item.def_id == method_def_id {
-                // The item with the ID we were given really ought to be a method.
-                assert_eq!(trait_item.kind, ty::AssocKind::Method);
-                return entries;
-            }
-            if trait_item.kind == ty::AssocKind::Method {
-                entries += 1;
-            }
-        }
-
-        bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
-    }
-
-    pub fn closure_trait_ref_and_return_type(
-        self,
-        fn_trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        sig: ty::PolyFnSig<'tcx>,
-        tuple_arguments: TupleArgumentsFlag,
-    ) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> {
-        let arguments_tuple = match tuple_arguments {
-            TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
-            TupleArgumentsFlag::Yes => self.intern_tup(sig.skip_binder().inputs()),
-        };
-        let trait_ref = ty::TraitRef {
-            def_id: fn_trait_def_id,
-            substs: self.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
-        };
-        ty::Binder::bind((trait_ref, sig.skip_binder().output()))
-    }
-
-    pub fn generator_trait_ref_and_outputs(
-        self,
-        fn_trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        sig: ty::PolyGenSig<'tcx>,
-    ) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
-        let trait_ref =
-            ty::TraitRef { def_id: fn_trait_def_id, substs: self.mk_substs_trait(self_ty, &[]) };
-        ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
-    }
-
-    pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
-        match self.hir().as_local_hir_id(node_item_def_id) {
-            Some(hir_id) => {
-                let item = self.hir().expect_item(hir_id);
-                if let hir::ItemKind::Impl(_, _, defaultness, ..) = item.kind {
-                    defaultness.is_default()
-                } else {
-                    false
-                }
-            }
-            None => self.impl_defaultness(node_item_def_id).is_default(),
+        if trait_item.kind == ty::AssocKind::Method {
+            entries += 1;
         }
     }
 
-    pub fn impl_item_is_final(self, assoc_item: &ty::AssocItem) -> bool {
-        assoc_item.defaultness.is_final() && !self.impl_is_default(assoc_item.container.id())
+    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+}
+
+pub fn closure_trait_ref_and_return_type(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyFnSig<'tcx>,
+    tuple_arguments: TupleArgumentsFlag,
+) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> {
+    let arguments_tuple = match tuple_arguments {
+        TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
+        TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
+    };
+    let trait_ref = ty::TraitRef {
+        def_id: fn_trait_def_id,
+        substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
+    };
+    ty::Binder::bind((trait_ref, sig.skip_binder().output()))
+}
+
+pub fn generator_trait_ref_and_outputs(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyGenSig<'tcx>,
+) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
+    let trait_ref =
+        ty::TraitRef { def_id: fn_trait_def_id, substs: tcx.mk_substs_trait(self_ty, &[]) };
+    ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
+}
+
+pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
+    match tcx.hir().as_local_hir_id(node_item_def_id) {
+        Some(hir_id) => {
+            let item = tcx.hir().expect_item(hir_id);
+            if let hir::ItemKind::Impl(_, _, defaultness, ..) = item.kind {
+                defaultness.is_default()
+            } else {
+                false
+            }
+        }
+        None => tcx.impl_defaultness(node_item_def_id).is_default(),
     }
 }
 
+pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
+    assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
+}
+
 pub enum TupleArgumentsFlag {
     Yes,
     No,
diff --git a/src/librustc/ty/wf.rs b/src/librustc/traits/wf.rs
similarity index 98%
rename from src/librustc/ty/wf.rs
rename to src/librustc/traits/wf.rs
index 4969e72..2301395 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/traits/wf.rs
@@ -1,10 +1,11 @@
-use crate::hir;
-use crate::hir::def_id::DefId;
+use crate::infer::opaque_types::required_region_bounds;
 use crate::infer::InferCtxt;
 use crate::middle::lang_items;
 use crate::traits::{self, AssocTypeBoundData};
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::Span;
 use std::iter::once;
@@ -358,7 +359,9 @@
     /// Pushes the obligations required for an array length to be WF
     /// into `self.out`.
     fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
-        if let ty::ConstKind::Unevaluated(def_id, substs) = constant.val {
+        if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val {
+            assert!(promoted.is_none());
+
             let obligations = self.nominal_obligations(def_id, substs);
             self.out.extend(obligations);
 
@@ -514,7 +517,7 @@
                     // of whatever returned this exact `impl Trait`.
 
                     // for named opaque `impl Trait` types we still need to check them
-                    if super::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
+                    if ty::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
                         let obligations = self.nominal_obligations(did, substs);
                         self.out.extend(obligations);
                     }
@@ -668,7 +671,7 @@
 /// from the declarations of `SomeTrait`, `Send`, and friends -- if
 /// they declare `trait SomeTrait : 'static`, for example, then
 /// `'static` would appear in the list. The hard work is done by
-/// `ty::required_region_bounds`, see that for more information.
+/// `infer::required_region_bounds`, see that for more information.
 pub fn object_region_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
@@ -689,7 +692,7 @@
         })
         .collect();
 
-    tcx.required_region_bounds(open_ty, predicates)
+    required_region_bounds(tcx, open_ty, predicates)
 }
 
 /// Find the span of a generic bound affecting an associated type.
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index e1b63a6..ebefb03 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -1,7 +1,7 @@
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
diff --git a/src/librustc/ty/binding.rs b/src/librustc/ty/binding.rs
index 2229507..5ee8811 100644
--- a/src/librustc/ty/binding.rs
+++ b/src/librustc/ty/binding.rs
@@ -1,6 +1,6 @@
-use crate::hir::BindingAnnotation;
-use crate::hir::BindingAnnotation::*;
-use crate::hir::Mutability;
+use rustc_hir::BindingAnnotation;
+use rustc_hir::BindingAnnotation::*;
+use rustc_hir::Mutability;
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
 pub enum BindingMode {
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index 3ccbc09..df1602b 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -7,12 +7,12 @@
 // persisting to incr. comp. caches.
 
 use crate::arena::ArenaAllocatable;
-use crate::hir::def_id::{CrateNum, DefId};
 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use crate::mir::{self, interpret::Allocation};
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, List, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
 use rustc_span::Span;
 use std::hash::Hash;
@@ -226,11 +226,11 @@
 where
     D: TyDecoder<'tcx>,
 {
-    let base: mir::PlaceBase<'tcx> = Decodable::decode(decoder)?;
+    let local: mir::Local = Decodable::decode(decoder)?;
     let len = decoder.read_usize()?;
     let projection: &'tcx List<mir::PlaceElem<'tcx>> =
         decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
-    Ok(mir::Place { base, projection })
+    Ok(mir::Place { local, projection })
 }
 
 #[inline]
@@ -353,7 +353,7 @@
             use $crate::ty;
             use $crate::ty::codec::*;
             use $crate::ty::subst::SubstsRef;
-            use $crate::hir::def_id::{CrateNum};
+            use rustc_hir::def_id::{CrateNum};
 
             use rustc_span::Span;
 
diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs
deleted file mode 100644
index 518ad63..0000000
--- a/src/librustc/ty/constness.rs
+++ /dev/null
@@ -1,156 +0,0 @@
-use crate::hir;
-use crate::hir::def_id::DefId;
-use crate::hir::map::blocks::FnLikeNode;
-use crate::ty::query::Providers;
-use crate::ty::TyCtxt;
-use rustc_span::symbol::Symbol;
-use rustc_target::spec::abi::Abi;
-use syntax::attr;
-
-impl<'tcx> TyCtxt<'tcx> {
-    /// Whether the `def_id` counts as const fn in your current crate, considering all active
-    /// feature gates
-    pub fn is_const_fn(self, def_id: DefId) -> bool {
-        self.is_const_fn_raw(def_id)
-            && match self.is_unstable_const_fn(def_id) {
-                Some(feature_name) => {
-                    // has a `rustc_const_unstable` attribute, check whether the user enabled the
-                    // corresponding feature gate.
-                    self.features()
-                        .declared_lib_features
-                        .iter()
-                        .any(|&(sym, _)| sym == feature_name)
-                }
-                // functions without const stability are either stable user written
-                // const fn or the user is using feature gates and we thus don't
-                // care what they do
-                None => true,
-            }
-    }
-
-    /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
-    pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> {
-        if self.is_const_fn_raw(def_id) {
-            let const_stab = self.lookup_const_stability(def_id)?;
-            if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None }
-        } else {
-            None
-        }
-    }
-
-    /// Returns `true` if this function must conform to `min_const_fn`
-    pub fn is_min_const_fn(self, def_id: DefId) -> bool {
-        // Bail out if the signature doesn't contain `const`
-        if !self.is_const_fn_raw(def_id) {
-            return false;
-        }
-
-        if self.features().staged_api {
-            // In order for a libstd function to be considered min_const_fn
-            // it needs to be stable and have no `rustc_const_unstable` attribute.
-            match self.lookup_const_stability(def_id) {
-                // `rustc_const_unstable` functions don't need to conform.
-                Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
-                None => {
-                    if let Some(stab) = self.lookup_stability(def_id) {
-                        if stab.level.is_stable() {
-                            self.sess.span_err(
-                                self.def_span(def_id),
-                                "stable const functions must have either `rustc_const_stable` or \
-                            `rustc_const_unstable` attribute",
-                            );
-                            // While we errored above, because we don't know if we need to conform, we
-                            // err on the "safe" side and require min_const_fn.
-                            true
-                        } else {
-                            // Unstable functions need not conform to min_const_fn.
-                            false
-                        }
-                    } else {
-                        // Internal functions are forced to conform to min_const_fn.
-                        // Annotate the internal function with a const stability attribute if
-                        // you need to use unstable features.
-                        // Note: this is an arbitrary choice that does not affect stability or const
-                        // safety or anything, it just changes whether we need to annotate some
-                        // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
-                        true
-                    }
-                }
-                // Everything else needs to conform, because it would be callable from
-                // other `min_const_fn` functions.
-                _ => true,
-            }
-        } else {
-            // users enabling the `const_fn` feature gate can do what they want
-            !self.features().const_fn
-        }
-    }
-}
-
-pub fn provide(providers: &mut Providers<'_>) {
-    /// Const evaluability whitelist is here to check evaluability at the
-    /// top level beforehand.
-    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
-        match tcx.fn_sig(def_id).abi() {
-            Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
-                Some(tcx.lookup_const_stability(def_id).is_some())
-            }
-            _ => None,
-        }
-    }
-
-    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
-    /// said intrinsic is on the whitelist for being const callable.
-    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-        let hir_id = tcx
-            .hir()
-            .as_local_hir_id(def_id)
-            .expect("Non-local call to local provider is_const_fn");
-
-        let node = tcx.hir().get(hir_id);
-
-        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
-            whitelisted
-        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
-            fn_like.constness() == hir::Constness::Const
-        } else if let hir::Node::Ctor(_) = node {
-            true
-        } else {
-            false
-        }
-    }
-
-    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-        tcx.is_const_fn(def_id)
-            && match tcx.lookup_const_stability(def_id) {
-                Some(stab) => {
-                    if cfg!(debug_assertions) && stab.promotable {
-                        let sig = tcx.fn_sig(def_id);
-                        assert_eq!(
-                            sig.unsafety(),
-                            hir::Unsafety::Normal,
-                            "don't mark const unsafe fns as promotable",
-                            // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
-                        );
-                    }
-                    stab.promotable
-                }
-                None => false,
-            }
-    }
-
-    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-        tcx.is_const_fn(def_id)
-            && tcx
-                .lookup_const_stability(def_id)
-                .map(|stab| stab.allow_const_fn_ptr)
-                .unwrap_or(false)
-    }
-
-    *providers = Providers {
-        is_const_fn_raw,
-        is_promotable_const_fn,
-        const_fn_is_allowed_fn_ptr,
-        ..*providers
-    };
-}
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 86042d8..6b98fdd 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -3,17 +3,12 @@
 use crate::arena::Arena;
 use crate::dep_graph::DepGraph;
 use crate::dep_graph::{self, DepConstructor, DepNode};
-use crate::hir::def::{DefKind, Res};
-use crate::hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE};
 use crate::hir::exports::Export;
 use crate::hir::map as hir_map;
 use crate::hir::map::DefPathHash;
-use crate::hir::{self, HirId, Node, TraitCandidate};
-use crate::hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
-use crate::infer::outlives::free_region_map::FreeRegionMap;
-use crate::lint::{self, Lint};
+use crate::lint::{struct_lint_level, LintSource};
 use crate::middle;
 use crate::middle::cstore::CrateStoreDyn;
 use crate::middle::cstore::EncodedMetadata;
@@ -25,11 +20,9 @@
 use crate::mir::{
     interpret, BodyAndCache, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
 };
-use crate::session::config::CrateType;
-use crate::session::config::{BorrowckMode, OutputFilenames};
-use crate::session::Session;
 use crate::traits;
 use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals};
+use crate::ty::free_region_map::FreeRegionMap;
 use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
 use crate::ty::query;
 use crate::ty::steal::Steal;
@@ -48,9 +41,17 @@
 use crate::ty::{InferConst, ParamConst};
 use crate::ty::{List, TyKind, TyS};
 use crate::util::common::ErrorReported;
+use rustc_data_structures::sync;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE};
+use rustc_hir::{HirId, Node, TraitCandidate};
+use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};
+use rustc_session::config::CrateType;
+use rustc_session::config::{BorrowckMode, OutputFilenames};
+use rustc_session::Session;
 
 use arena::SyncDroplessArena;
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::ShardedHashMap;
@@ -58,8 +59,10 @@
     hash_stable_hashmap, HashStable, StableHasher, StableVec,
 };
 use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal};
+use rustc_errors::DiagnosticBuilder;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
+use rustc_session::lint::{Level, Lint};
 use rustc_session::node_id::NodeMap;
 use rustc_span::source_map::MultiSpan;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -945,7 +948,11 @@
 
     pub sess: &'tcx Session,
 
-    pub lint_store: Lrc<lint::LintStore>,
+    /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
+    ///
+    /// FIXME(Centril): consider `dyn LintStoreMarker` once
+    /// we can upcast to `Any` for some additional type safety.
+    pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
 
     pub dep_graph: DepGraph,
 
@@ -1114,7 +1121,7 @@
     /// reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
-        lint_store: Lrc<lint::LintStore>,
+        lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
         local_providers: ty::query::Providers<'tcx>,
         extern_providers: ty::query::Providers<'tcx>,
         arenas: &'tcx AllArenas,
@@ -1612,10 +1619,10 @@
 
     use crate::dep_graph::TaskDeps;
     use crate::ty::query;
-    use errors::Diagnostic;
     use rustc_data_structures::sync::{self, Lock, Lrc};
     use rustc_data_structures::thin_vec::ThinVec;
     use rustc_data_structures::OnDrop;
+    use rustc_errors::Diagnostic;
     use std::mem;
 
     #[cfg(not(parallel_compiler))]
@@ -2433,7 +2440,7 @@
         let mut projection = place.projection.to_vec();
         projection.push(elem);
 
-        Place { base: place.base, projection: self.intern_place_elems(&projection) }
+        Place { local: place.local, projection: self.intern_place_elems(&projection) }
     }
 
     pub fn intern_existential_predicates(
@@ -2550,57 +2557,29 @@
         iter.intern_with(|xs| self.intern_goals(xs))
     }
 
-    pub fn lint_hir<S: Into<MultiSpan>>(
+    pub fn lint_hir(
         self,
         lint: &'static Lint,
         hir_id: HirId,
-        span: S,
+        span: impl Into<MultiSpan>,
         msg: &str,
     ) {
         self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit()
     }
 
-    pub fn lint_hir_note<S: Into<MultiSpan>>(
-        self,
-        lint: &'static Lint,
-        hir_id: HirId,
-        span: S,
-        msg: &str,
-        note: &str,
-    ) {
-        let mut err = self.struct_span_lint_hir(lint, hir_id, span.into(), msg);
-        err.note(note);
-        err.emit()
-    }
-
-    pub fn lint_node_note<S: Into<MultiSpan>>(
-        self,
-        lint: &'static Lint,
-        id: hir::HirId,
-        span: S,
-        msg: &str,
-        note: &str,
-    ) {
-        let mut err = self.struct_span_lint_hir(lint, id, span.into(), msg);
-        err.note(note);
-        err.emit()
-    }
-
     /// Walks upwards from `id` to find a node which might change lint levels with attributes.
     /// It stops at `bound` and just returns it if reached.
-    pub fn maybe_lint_level_root_bounded(
-        self,
-        mut id: hir::HirId,
-        bound: hir::HirId,
-    ) -> hir::HirId {
+    pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
+        let hir = self.hir();
         loop {
             if id == bound {
                 return bound;
             }
-            if lint::maybe_lint_level_root(self, id) {
+
+            if hir.attrs(id).iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some()) {
                 return id;
             }
-            let next = self.hir().get_parent_node(id);
+            let next = hir.get_parent_node(id);
             if next == id {
                 bug!("lint traversal reached the root of the crate");
             }
@@ -2612,7 +2591,7 @@
         self,
         lint: &'static Lint,
         mut id: hir::HirId,
-    ) -> (lint::Level, lint::LintSource) {
+    ) -> (Level, LintSource) {
         let sets = self.lint_levels(LOCAL_CRATE);
         loop {
             if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
@@ -2626,15 +2605,15 @@
         }
     }
 
-    pub fn struct_span_lint_hir<S: Into<MultiSpan>>(
+    pub fn struct_span_lint_hir(
         self,
         lint: &'static Lint,
         hir_id: HirId,
-        span: S,
+        span: impl Into<MultiSpan>,
         msg: &str,
     ) -> DiagnosticBuilder<'tcx> {
         let (level, src) = self.lint_level_at_node(lint, hir_id);
-        lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
+        struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
     }
 
     pub fn struct_lint_node(
@@ -2644,7 +2623,7 @@
         msg: &str,
     ) -> DiagnosticBuilder<'tcx> {
         let (level, src) = self.lint_level_at_node(lint, id);
-        lint::struct_lint_level(self.sess, lint, level, src, None, msg)
+        struct_lint_level(self.sess, lint, level, src, None, msg)
     }
 
     pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx StableVec<TraitCandidate>> {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index e2ecfd1..f761287 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -1,12 +1,10 @@
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt};
-
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use syntax::ast;
-use syntax::errors::pluralize;
 
 use std::borrow::Cow;
 use std::fmt;
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index f5dce6b..5aa8bd9 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -1,7 +1,7 @@
-use crate::hir::def_id::DefId;
 use crate::ich::StableHashingContext;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::DefId;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::mem;
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index b9aa12b..4a4280b 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -219,7 +219,7 @@
     fn add_const(&mut self, c: &ty::Const<'_>) {
         self.add_ty(c.ty);
         match c.val {
-            ty::ConstKind::Unevaluated(_, substs) => {
+            ty::ConstKind::Unevaluated(_, substs, _) => {
                 self.add_substs(substs);
                 self.add_flags(TypeFlags::HAS_PROJECTION);
             }
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 7004cec..b16db6a 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -31,8 +31,8 @@
 //! These methods return true to indicate that the visitor has found what it is
 //! looking for, and does not need to visit anything else.
 
-use crate::hir::def_id::DefId;
 use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
+use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::fx::FxHashSet;
 use std::collections::BTreeMap;
diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/ty/free_region_map.rs
similarity index 100%
rename from src/librustc/infer/outlives/free_region_map.rs
rename to src/librustc/ty/free_region_map.rs
diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs
index 5a2e191..14ead776 100644
--- a/src/librustc/ty/inhabitedness/def_id_forest.rs
+++ b/src/librustc/ty/inhabitedness/def_id_forest.rs
@@ -1,6 +1,6 @@
 use crate::ty::context::TyCtxt;
 use crate::ty::{DefId, DefIdTree};
-use rustc::hir::CRATE_HIR_ID;
+use rustc_hir::CRATE_HIR_ID;
 use smallvec::SmallVec;
 use std::mem;
 
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 73ca007..144e3bc 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -96,15 +96,11 @@
         // ```
         // forest.is_empty()
         // ```
-        self.ty_inhabitedness_forest(ty).contains(self, module)
+        ty.uninhabited_from(self).contains(self, module)
     }
 
     pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool {
-        !self.ty_inhabitedness_forest(ty).is_empty()
-    }
-
-    fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest {
-        ty.uninhabited_from(self)
+        !ty.uninhabited_from(self).is_empty()
     }
 }
 
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index e315de1..9be50d1 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -1,10 +1,10 @@
-use crate::hir::def::Namespace;
-use crate::hir::def_id::DefId;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::middle::lang_items::DropInPlaceFnLangItem;
 use crate::traits;
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
+use rustc_hir::def::Namespace;
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_target::spec::abi::Abi;
 
@@ -411,7 +411,7 @@
             substs: rcvr_substs,
         }),
         traits::VtableObject(ref data) => {
-            let index = tcx.get_vtable_index_of_object_method(data, def_id);
+            let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
             Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
         }
         traits::VtableBuiltin(..) => {
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 5f59903..acaa4ee 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -12,11 +12,11 @@
 use std::mem;
 use std::ops::Bound;
 
-use crate::hir;
 use crate::ich::StableHashingContext;
 use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
 use crate::ty::subst::Subst;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 
@@ -2507,17 +2507,21 @@
         let extra_args = if sig.abi == RustCall {
             assert!(!sig.c_variadic && extra_args.is_empty());
 
-            match sig.inputs().last().unwrap().kind {
-                ty::Tuple(tupled_arguments) => {
+            if let Some(input) = sig.inputs().last() {
+                if let ty::Tuple(tupled_arguments) = input.kind {
                     inputs = &sig.inputs()[0..sig.inputs().len() - 1];
                     tupled_arguments.iter().map(|k| k.expect_ty()).collect()
-                }
-                _ => {
+                } else {
                     bug!(
                         "argument to function with \"rust-call\" ABI \
-                         is not a tuple"
+                            is not a tuple"
                     );
                 }
+            } else {
+                bug!(
+                    "argument to function with \"rust-call\" ABI \
+                        is not a tuple"
+                );
             }
         } else {
             assert!(sig.c_variadic || extra_args.is_empty());
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 1ce74a6..d1e37a4 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -6,11 +6,9 @@
 pub use self::IntVarValue::*;
 pub use self::Variance::*;
 
-use crate::hir::def::{CtorKind, CtorOf, DefKind, Res};
-use crate::hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use crate::hir::exports::ExportMap;
-use crate::hir::Node;
-use crate::hir::{map as hir_map, GlobMap, TraitMap};
+use crate::hir::map as hir_map;
+
 use crate::ich::Fingerprint;
 use crate::ich::StableHashingContext;
 use crate::infer::canonical::Canonical;
@@ -28,19 +26,26 @@
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use crate::ty::util::{Discr, IntTypeExt};
 use crate::ty::walk::TypeWalker;
-use crate::util::captures::Captures;
 use arena::SyncDroplessArena;
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
-use rustc_macros::HashStable;
-use rustc_session::node_id::{NodeMap, NodeSet};
-
 use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::{GlobMap, Node, TraitMap};
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_macros::HashStable;
 use rustc_serialize::{self, Encodable, Encoder};
+use rustc_session::node_id::{NodeMap, NodeSet};
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::Align;
+use smallvec;
 use std::cell::RefCell;
 use std::cmp::{self, Ordering};
 use std::fmt;
@@ -52,13 +57,6 @@
 use syntax::ast::{self, Ident, Name, NodeId};
 use syntax::attr;
 
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_index::vec::{Idx, IndexVec};
-use smallvec;
-
-use crate::hir;
-
 pub use self::sty::BoundRegion::*;
 pub use self::sty::InferTy::*;
 pub use self::sty::RegionKind;
@@ -89,10 +87,6 @@
 
 pub use self::instance::{Instance, InstanceDef};
 
-pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::type_marked_structural;
-pub use self::structural_match::NonStructuralMatchTy;
-
 pub use self::trait_def::TraitDef;
 
 pub use self::query::queries;
@@ -103,14 +97,15 @@
 #[macro_use]
 pub mod codec;
 pub mod _match;
-mod constness;
 mod erase_regions;
 pub mod error;
 pub mod fast_reject;
 pub mod flags;
 pub mod fold;
+pub mod free_region_map;
 pub mod inhabitedness;
 pub mod layout;
+pub mod normalize_erasing_regions;
 pub mod outlives;
 pub mod print;
 pub mod query;
@@ -120,13 +115,11 @@
 pub mod trait_def;
 pub mod util;
 pub mod walk;
-pub mod wf;
 
 mod context;
 mod diagnostics;
 mod instance;
 mod structural_impls;
-mod structural_match;
 mod sty;
 
 // Data types
@@ -815,13 +808,6 @@
 pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
 pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
 
-#[derive(Copy, Clone, TypeFoldable)]
-pub struct ClosureUpvar<'tcx> {
-    pub res: Res,
-    pub span: Span,
-    pub ty: Ty<'tcx>,
-}
-
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub enum IntVarValue {
     IntType(ast::IntTy),
@@ -3313,7 +3299,7 @@
 
     let node = tcx.hir().get(hir_id);
 
-    let fn_like = hir::map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
+    let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
         bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
     });
 
@@ -3324,8 +3310,6 @@
     context::provide(providers);
     erase_regions::provide(providers);
     layout::provide(providers);
-    util::provide(providers);
-    constness::provide(providers);
     *providers = ty::query::Providers {
         asyncness,
         associated_item,
diff --git a/src/librustc/traits/query/normalize_erasing_regions.rs b/src/librustc/ty/normalize_erasing_regions.rs
similarity index 78%
rename from src/librustc/traits/query/normalize_erasing_regions.rs
rename to src/librustc/ty/normalize_erasing_regions.rs
index 2fa52e8..dc64482 100644
--- a/src/librustc/traits/query/normalize_erasing_regions.rs
+++ b/src/librustc/ty/normalize_erasing_regions.rs
@@ -8,6 +8,7 @@
 //! within. (This underlying query is what is cached.)
 
 use crate::ty::fold::{TypeFoldable, TypeFolder};
+use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt};
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -60,6 +61,29 @@
         let value = self.erase_late_bound_regions(value);
         self.normalize_erasing_regions(param_env, value)
     }
+
+    /// Monomorphizes a type from the AST by first applying the
+    /// in-scope substitutions and then normalizing any associated
+    /// types.
+    pub fn subst_and_normalize_erasing_regions<T>(
+        self,
+        param_substs: SubstsRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+    ) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!(
+            "subst_and_normalize_erasing_regions(\
+             param_substs={:?}, \
+             value={:?}, \
+             param_env={:?})",
+            param_substs, value, param_env,
+        );
+        let substituted = value.subst(self, param_substs);
+        self.normalize_erasing_regions(param_env, substituted)
+    }
 }
 
 struct NormalizeAfterErasingRegionsFolder<'tcx> {
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 383ccbd..b397a2c 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -48,32 +48,29 @@
 impl<'tcx> TyCtxt<'tcx> {
     /// Push onto `out` all the things that must outlive `'a` for the condition
     /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
-    pub fn push_outlives_components(
-        &self,
-        ty0: Ty<'tcx>,
-        out: &mut SmallVec<[Component<'tcx>; 4]>,
-    ) {
-        self.compute_components(ty0, out);
+    pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
+        compute_components(self, ty0, out);
         debug!("components({:?}) = {:?}", ty0, out);
     }
+}
 
-    fn compute_components(&self, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
-        // Descend through the types, looking for the various "base"
-        // components and collecting them into `out`. This is not written
-        // with `collect()` because of the need to sometimes skip subtrees
-        // in the `subtys` iterator (e.g., when encountering a
-        // projection).
-        match ty.kind {
+fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
+    // Descend through the types, looking for the various "base"
+    // components and collecting them into `out`. This is not written
+    // with `collect()` because of the need to sometimes skip subtrees
+    // in the `subtys` iterator (e.g., when encountering a
+    // projection).
+    match ty.kind {
             ty::Closure(def_id, ref substs) => {
-                for upvar_ty in substs.as_closure().upvar_tys(def_id, *self) {
-                    self.compute_components(upvar_ty, out);
+                for upvar_ty in substs.as_closure().upvar_tys(def_id, tcx) {
+                    compute_components(tcx, upvar_ty, out);
                 }
             }
 
             ty::Generator(def_id, ref substs, _) => {
                 // Same as the closure case
-                for upvar_ty in substs.as_generator().upvar_tys(def_id, *self) {
-                    self.compute_components(upvar_ty, out);
+                for upvar_ty in substs.as_generator().upvar_tys(def_id, tcx) {
+                    compute_components(tcx, upvar_ty, out);
                 }
 
                 // We ignore regions in the generator interior as we don't
@@ -110,7 +107,7 @@
                     // fallback case: hard code
                     // OutlivesProjectionComponents.  Continue walking
                     // through and constrain Pi.
-                    let subcomponents = self.capture_components(ty);
+                    let subcomponents = capture_components(tcx, ty);
                     out.push(Component::EscapingProjection(subcomponents));
                 }
             }
@@ -159,20 +156,19 @@
 
                 push_region_constraints(ty, out);
                 for subty in ty.walk_shallow() {
-                    self.compute_components(subty, out);
+                    compute_components(tcx, subty, out);
                 }
             }
         }
-    }
+}
 
-    fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
-        let mut temp = smallvec![];
-        push_region_constraints(ty, &mut temp);
-        for subty in ty.walk_shallow() {
-            self.compute_components(subty, &mut temp);
-        }
-        temp.into_iter().collect()
+fn capture_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
+    let mut temp = smallvec![];
+    push_region_constraints(ty, &mut temp);
+    for subty in ty.walk_shallow() {
+        compute_components(tcx, subty, &mut temp);
     }
+    temp.into_iter().collect()
 }
 
 fn push_region_constraints<'tcx>(ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs
index e58c912..3ade966 100644
--- a/src/librustc/ty/print/mod.rs
+++ b/src/librustc/ty/print/mod.rs
@@ -1,9 +1,9 @@
-use crate::hir::def_id::{CrateNum, DefId};
 use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
 use crate::ty::subst::{GenericArg, Subst};
 use crate::ty::{self, DefIdTree, Ty, TyCtxt};
 
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{CrateNum, DefId};
 
 // `pretty` is a separate module only for organization.
 mod pretty;
diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs
index 7c3579d..7605d44 100644
--- a/src/librustc/ty/print/obsolete.rs
+++ b/src/librustc/ty/print/obsolete.rs
@@ -5,10 +5,11 @@
 //! Note: A lot of this could looks very similar to what's already in `ty::print`.
 //! FIXME(eddyb) implement a custom `PrettyPrinter` for this.
 
-use rustc::hir::def_id::DefId;
+use rustc::bug;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Const, Instance, Ty, TyCtxt};
-use rustc::{bug, hir};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use std::fmt::Write;
 use std::iter;
 
@@ -165,19 +166,12 @@
     }
 
     // Pushes the the name of the specified const to the provided string.
-    // If `debug` is true, usually-unprintable consts (such as `Infer`) will be printed,
-    // as well as the unprintable types of constants (see `push_type_name` for more details).
-    pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
-        if let ty::ConstKind::Value(_) = c.val {
-            // FIXME(const_generics): we could probably do a better job here.
-            write!(output, "{:?}", c).unwrap()
-        } else if debug {
-            write!(output, "{:?}", c).unwrap()
-        } else {
-            bug!("DefPathBasedNames: trying to create const name for unexpected const: {:?}", c,);
-        }
+    // If `debug` is true, the unprintable types of constants will be printed with `fmt::Debug`
+    // (see `push_type_name` for more details).
+    pub fn push_const_name(&self, ct: &Const<'tcx>, output: &mut String, debug: bool) {
+        write!(output, "{}", ct).unwrap();
         output.push_str(": ");
-        self.push_type_name(c.ty, output, debug);
+        self.push_type_name(ct.ty, output, debug);
     }
 
     pub fn push_def_path(&self, def_id: DefId, output: &mut String) {
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 8dafe40..8b1b2bb 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -1,6 +1,3 @@
-use crate::hir;
-use crate::hir::def::{DefKind, Namespace};
-use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
 use crate::middle::region;
@@ -8,6 +5,9 @@
 use crate::ty::layout::{Integer, IntegerExt, Size};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Namespace};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
@@ -841,23 +841,31 @@
 
         match (ct.val, &ct.ty.kind) {
             (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
-            (ty::ConstKind::Unevaluated(did, substs), _) => match self.tcx().def_kind(did) {
-                Some(DefKind::Static) | Some(DefKind::Const) | Some(DefKind::AssocConst) => {
-                    p!(print_value_path(did, substs))
-                }
-                _ => {
-                    if did.is_local() {
-                        let span = self.tcx().def_span(did);
-                        if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
-                            p!(write("{}", snip))
-                        } else {
-                            p!(write("_: "), print(ct.ty))
+            (ty::ConstKind::Unevaluated(did, substs, promoted), _) => {
+                if let Some(promoted) = promoted {
+                    p!(print_value_path(did, substs));
+                    p!(write("::{:?}", promoted));
+                } else {
+                    match self.tcx().def_kind(did) {
+                        Some(DefKind::Static)
+                        | Some(DefKind::Const)
+                        | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
+                        _ => {
+                            if did.is_local() {
+                                let span = self.tcx().def_span(did);
+                                if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
+                                {
+                                    p!(write("{}", snip))
+                                } else {
+                                    p!(write("_: "), print(ct.ty))
+                                }
+                            } else {
+                                p!(write("_: "), print(ct.ty))
+                            }
                         }
-                    } else {
-                        p!(write("_: "), print(ct.ty))
                     }
                 }
-            },
+            }
             (ty::ConstKind::Infer(..), _) => p!(write("_: "), print(ct.ty)),
             (ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
             (ty::ConstKind::Value(value), _) => return self.pretty_print_const_value(value, ct.ty),
@@ -1036,26 +1044,26 @@
     }
 }
 
-impl TyCtxt<'t> {
-    // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
-    // (but also some things just print a `DefId` generally so maybe we need this?)
-    fn guess_def_namespace(self, def_id: DefId) -> Namespace {
-        match self.def_key(def_id).disambiguated_data.data {
-            DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
-                Namespace::TypeNS
-            }
-
-            DefPathData::ValueNs(..)
-            | DefPathData::AnonConst
-            | DefPathData::ClosureExpr
-            | DefPathData::Ctor => Namespace::ValueNS,
-
-            DefPathData::MacroNs(..) => Namespace::MacroNS,
-
-            _ => Namespace::TypeNS,
+// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
+// (but also some things just print a `DefId` generally so maybe we need this?)
+fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
+    match tcx.def_key(def_id).disambiguated_data.data {
+        DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
+            Namespace::TypeNS
         }
-    }
 
+        DefPathData::ValueNs(..)
+        | DefPathData::AnonConst
+        | DefPathData::ClosureExpr
+        | DefPathData::Ctor => Namespace::ValueNS,
+
+        DefPathData::MacroNs(..) => Namespace::MacroNS,
+
+        _ => Namespace::TypeNS,
+    }
+}
+
+impl TyCtxt<'t> {
     /// Returns a string identifying this `DefId`. This string is
     /// suitable for user output.
     pub fn def_path_str(self, def_id: DefId) -> String {
@@ -1063,7 +1071,7 @@
     }
 
     pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
-        let ns = self.guess_def_namespace(def_id);
+        let ns = guess_def_namespace(self, def_id);
         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
         let mut s = String::new();
         let _ = FmtPrinter::new(self, &mut s, ns).print_def_path(def_id, substs);
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index 5af0e78..dbb6a10 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -1,12 +1,11 @@
 use crate::dep_graph::SerializedDepNodeIndex;
 use crate::dep_graph::{DepKind, DepNode};
-use crate::hir::def_id::{CrateNum, DefId};
 use crate::ty::query::plumbing::CycleError;
 use crate::ty::query::queries;
-use crate::ty::query::QueryCache;
-use crate::ty::query::{Query, QueryName};
+use crate::ty::query::{Query, QueryCache};
 use crate::ty::TyCtxt;
 use rustc_data_structures::profiling::ProfileCategory;
+use rustc_hir::def_id::{CrateNum, DefId};
 
 use crate::ich::StableHashingContext;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -20,7 +19,7 @@
 // FIXME(eddyb) false positive, the lifetime parameter is used for `Key`/`Value`.
 #[allow(unused_lifetimes)]
 pub trait QueryConfig<'tcx> {
-    const NAME: QueryName;
+    const NAME: &'static str;
     const CATEGORY: ProfileCategory;
 
     type Key: Eq + Hash + Clone + Debug;
diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs
index 3cf0a07..d64f27d 100644
--- a/src/librustc/ty/query/keys.rs
+++ b/src/librustc/ty/query/keys.rs
@@ -1,13 +1,12 @@
 //! Defines the set of legal keys that can be used in queries.
 
-use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use crate::infer::canonical::Canonical;
 use crate::mir;
 use crate::traits;
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, Ty, TyCtxt};
-
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -143,7 +142,7 @@
     }
 }
 
-impl<'tcx> Key for ty::Const<'tcx> {
+impl<'tcx> Key for &'tcx ty::Const<'tcx> {
     fn query_crate(&self) -> CrateNum {
         LOCAL_CRATE
     }
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 0ec3874..1d41871 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -1,10 +1,7 @@
 use crate::dep_graph::{self, DepNode};
-use crate::hir::def::DefKind;
-use crate::hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex};
 use crate::hir::exports::Export;
-use crate::hir::{self, HirIdSet, ItemLocalId, TraitCandidate};
 use crate::infer::canonical::{self, Canonical};
-use crate::lint;
+use crate::lint::LintLevelMap;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::cstore::{CrateSource, DepKind, NativeLibraryKind};
 use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLibrary};
@@ -38,13 +35,16 @@
 use crate::ty::util::NeedsDrop;
 use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use crate::util::common::ErrorReported;
-use rustc_data_structures::profiling::ProfileCategory::*;
-
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::profiling::ProfileCategory::*;
 use rustc_data_structures::stable_hasher::StableVec;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex};
+use rustc_hir::{HirIdSet, ItemLocalId, TraitCandidate};
 use rustc_index::vec::IndexVec;
 use rustc_target::spec::PanicStrategy;
 
@@ -81,6 +81,9 @@
 mod on_disk_cache;
 pub use self::on_disk_cache::OnDiskCache;
 
+mod profiling_support;
+pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder};
+
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 6758aed..a81fe33 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -1,6 +1,4 @@
 use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
-use crate::hir;
-use crate::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use crate::hir::map::definitions::DefPathHash;
 use crate::ich::{CachingSourceMapView, Fingerprint};
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
@@ -9,11 +7,12 @@
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
-
-use errors::Diagnostic;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::Diagnostic;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_serialize::{
     opaque, Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder,
@@ -199,7 +198,7 @@
             // Encode query results.
             let mut query_result_index = EncodedQueryResultIndex::new();
 
-            tcx.sess.time("encode query results", || {
+            tcx.sess.time("encode_query_results", || {
                 let enc = &mut encoder;
                 let qri = &mut query_result_index;
 
@@ -1054,8 +1053,8 @@
     Q: super::config::QueryDescription<'tcx, Value: Encodable>,
     E: 'a + TyEncoder,
 {
-    let desc = &format!("encode_query_results for {}", ::std::any::type_name::<Q>());
-    let _timer = tcx.sess.prof.generic_pass(desc);
+    let desc = &format!("encode_query_results_for_{}", ::std::any::type_name::<Q>());
+    let _timer = tcx.sess.prof.extra_verbose_generic_activity(desc);
 
     let shards = Q::query_cache(tcx).lock_shards();
     assert!(shards.iter().all(|shard| shard.active.is_empty()));
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index e56955b..84efbe2 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -9,17 +9,15 @@
 use crate::ty::tls;
 use crate::ty::{self, TyCtxt};
 
-use errors::Diagnostic;
-use errors::DiagnosticBuilder;
-use errors::FatalError;
-use errors::Handler;
-use errors::Level;
 #[cfg(not(parallel_compiler))]
 use rustc_data_structures::cold_path;
 use rustc_data_structures::fx::{FxHashMap, FxHasher};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::profiling::TimingGuard;
 use rustc_data_structures::sharded::Sharded;
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, Handler, Level};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::Span;
 use std::collections::hash_map::Entry;
@@ -86,6 +84,19 @@
     /// for some compile-time benchmarks.
     #[inline(always)]
     pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> {
+        // Handling the `query_blocked_prof_timer` is a bit weird because of the
+        // control flow in this function: Blocking is implemented by
+        // awaiting a running job and, once that is done, entering the loop below
+        // again from the top. In that second iteration we will hit the
+        // cache which provides us with the information we need for
+        // finishing the "query-blocked" event.
+        //
+        // We thus allocate `query_blocked_prof_timer` outside the loop,
+        // initialize it during the first iteration and finish it during the
+        // second iteration.
+        #[cfg(parallel_compiler)]
+        let mut query_blocked_prof_timer: Option<TimingGuard<'_>> = None;
+
         let cache = Q::query_cache(tcx);
         loop {
             // We compute the key's hash once and then use it for both the
@@ -99,7 +110,17 @@
             if let Some((_, value)) =
                 lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key)
             {
-                tcx.prof.query_cache_hit(Q::NAME);
+                if unlikely!(tcx.prof.enabled()) {
+                    tcx.prof.query_cache_hit(value.index.into());
+
+                    #[cfg(parallel_compiler)]
+                    {
+                        if let Some(prof_timer) = query_blocked_prof_timer.take() {
+                            prof_timer.finish_with_query_invocation_id(value.index.into());
+                        }
+                    }
+                }
+
                 let result = (value.value.clone(), value.index);
                 #[cfg(debug_assertions)]
                 {
@@ -108,9 +129,6 @@
                 return TryGetJob::JobCompleted(result);
             }
 
-            #[cfg(parallel_compiler)]
-            let query_blocked_prof_timer;
-
             let job = match lock.active.entry((*key).clone()) {
                 Entry::Occupied(entry) => {
                     match *entry.get() {
@@ -120,7 +138,7 @@
                             // self-profiler.
                             #[cfg(parallel_compiler)]
                             {
-                                query_blocked_prof_timer = tcx.prof.query_blocked(Q::NAME);
+                                query_blocked_prof_timer = Some(tcx.prof.query_blocked());
                             }
 
                             job.clone()
@@ -157,11 +175,6 @@
             {
                 let result = job.r#await(tcx, span);
 
-                // This `drop()` is not strictly necessary as the binding
-                // would go out of scope anyway. But it's good to have an
-                // explicit marker of how far the measurement goes.
-                drop(query_blocked_prof_timer);
-
                 if let Err(cycle) = result {
                     return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle));
                 }
@@ -351,7 +364,7 @@
 
     #[inline(never)]
     pub(super) fn get_query<Q: QueryDescription<'tcx>>(self, span: Span, key: Q::Key) -> Q::Value {
-        debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME.as_str(), key, span);
+        debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span);
 
         let job = match JobOwner::try_get(self, span, &key) {
             TryGetJob::NotYetStarted(job) => job,
@@ -370,7 +383,7 @@
         }
 
         if Q::ANON {
-            let prof_timer = self.prof.query_provider(Q::NAME);
+            let prof_timer = self.prof.query_provider();
 
             let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
                 self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -378,7 +391,7 @@
                 })
             });
 
-            drop(prof_timer);
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             self.dep_graph.read_index(dep_node_index);
 
@@ -440,8 +453,9 @@
         let result = if Q::cache_on_disk(self, key.clone(), None)
             && self.sess.opts.debugging_opts.incremental_queries
         {
-            let _prof_timer = self.prof.incr_cache_loading(Q::NAME);
+            let prof_timer = self.prof.incr_cache_loading();
             let result = Q::try_load_from_disk(self, prev_dep_node_index);
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             // We always expect to find a cached result for things that
             // can be forced from `DepNode`.
@@ -461,11 +475,13 @@
         } else {
             // We could not load a result from the on-disk cache, so
             // recompute.
-            let _prof_timer = self.prof.query_provider(Q::NAME);
+            let prof_timer = self.prof.query_provider();
 
             // The dep-graph for this computation is already in-place.
             let result = self.dep_graph.with_ignore(|| Q::compute(self, key));
 
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+
             result
         };
 
@@ -527,7 +543,7 @@
             dep_node
         );
 
-        let prof_timer = self.prof.query_provider(Q::NAME);
+        let prof_timer = self.prof.query_provider();
 
         let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
             self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -545,7 +561,7 @@
             })
         });
 
-        drop(prof_timer);
+        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
         if unlikely!(!diagnostics.is_empty()) {
             if dep_node.kind != crate::dep_graph::DepKind::Null {
@@ -576,17 +592,19 @@
 
         let dep_node = Q::to_dep_node(self, &key);
 
-        if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
-            // A None return from `try_mark_green_and_read` means that this is either
-            // a new dep node or that the dep node has already been marked red.
-            // Either way, we can't call `dep_graph.read()` as we don't have the
-            // DepNodeIndex. We must invoke the query itself. The performance cost
-            // this introduces should be negligible as we'll immediately hit the
-            // in-memory cache, or another query down the line will.
-
-            let _ = self.get_query::<Q>(DUMMY_SP, key);
-        } else {
-            self.prof.query_cache_hit(Q::NAME);
+        match self.dep_graph.try_mark_green_and_read(self, &dep_node) {
+            None => {
+                // A None return from `try_mark_green_and_read` means that this is either
+                // a new dep node or that the dep node has already been marked red.
+                // Either way, we can't call `dep_graph.read()` as we don't have the
+                // DepNodeIndex. We must invoke the query itself. The performance cost
+                // this introduces should be negligible as we'll immediately hit the
+                // in-memory cache, or another query down the line will.
+                let _ = self.get_query::<Q>(DUMMY_SP, key);
+            }
+            Some((_, dep_node_index)) => {
+                self.prof.query_cache_hit(dep_node_index.into());
+            }
         }
     }
 
@@ -818,36 +836,6 @@
         }
 
         #[allow(nonstandard_style)]
-        #[derive(Clone, Copy)]
-        pub enum QueryName {
-            $($name),*
-        }
-
-        impl rustc_data_structures::profiling::QueryName for QueryName {
-            fn discriminant(self) -> std::mem::Discriminant<QueryName> {
-                std::mem::discriminant(&self)
-            }
-
-            fn as_str(self) -> &'static str {
-                QueryName::as_str(&self)
-            }
-        }
-
-        impl QueryName {
-            pub fn register_with_profiler(
-                profiler: &rustc_data_structures::profiling::SelfProfiler,
-            ) {
-                $(profiler.register_query_name(QueryName::$name);)*
-            }
-
-            pub fn as_str(&self) -> &'static str {
-                match self {
-                    $(QueryName::$name => stringify!($name),)*
-                }
-            }
-        }
-
-        #[allow(nonstandard_style)]
         #[derive(Clone, Debug)]
         pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
@@ -887,12 +875,6 @@
                     $(Query::$name(key) => key.default_span(tcx),)*
                 }
             }
-
-            pub fn query_name(&self) -> QueryName {
-                match self {
-                    $(Query::$name(_) => QueryName::$name,)*
-                }
-            }
         }
 
         impl<'a, $tcx> HashStable<StableHashingContext<'a>> for Query<$tcx> {
@@ -927,7 +909,7 @@
             type Key = $K;
             type Value = $V;
 
-            const NAME: QueryName = QueryName::$name;
+            const NAME: &'static str = stringify!($name);
             const CATEGORY: ProfileCategory = $category;
         }
 
@@ -1039,6 +1021,35 @@
             pub fn $name(self, key: $K) -> $V {
                 self.at(DUMMY_SP).$name(key)
             })*
+
+            /// All self-profiling events generated by the query engine use
+            /// virtual `StringId`s for their `event_id`. This method makes all
+            /// those virtual `StringId`s point to actual strings.
+            ///
+            /// If we are recording only summary data, the ids will point to
+            /// just the query names. If we are recording query keys too, we
+            /// allocate the corresponding strings here.
+            pub fn alloc_self_profile_query_strings(self) {
+                use crate::ty::query::profiling_support::{
+                    alloc_self_profile_query_strings_for_query_cache,
+                    QueryKeyStringCache,
+                };
+
+                if !self.prof.enabled() {
+                    return;
+                }
+
+                let mut string_cache = QueryKeyStringCache::new();
+
+                $({
+                    alloc_self_profile_query_strings_for_query_cache(
+                        self,
+                        stringify!($name),
+                        &self.queries.$name,
+                        &mut string_cache,
+                    );
+                })*
+            }
         }
 
         impl TyCtxtAt<$tcx> {
diff --git a/src/librustc/ty/query/profiling_support.rs b/src/librustc/ty/query/profiling_support.rs
new file mode 100644
index 0000000..79b32ba
--- /dev/null
+++ b/src/librustc/ty/query/profiling_support.rs
@@ -0,0 +1,235 @@
+use crate::hir::map::definitions::DefPathData;
+use crate::ty::context::TyCtxt;
+use crate::ty::query::config::QueryConfig;
+use crate::ty::query::plumbing::QueryCache;
+use measureme::{StringComponent, StringId};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::profiling::SelfProfiler;
+use rustc_data_structures::sharded::Sharded;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use std::fmt::Debug;
+use std::io::Write;
+
+pub struct QueryKeyStringCache {
+    def_id_cache: FxHashMap<DefId, StringId>,
+}
+
+impl QueryKeyStringCache {
+    pub fn new() -> QueryKeyStringCache {
+        QueryKeyStringCache { def_id_cache: Default::default() }
+    }
+}
+
+pub struct QueryKeyStringBuilder<'p, 'c, 'tcx> {
+    profiler: &'p SelfProfiler,
+    tcx: TyCtxt<'tcx>,
+    string_cache: &'c mut QueryKeyStringCache,
+}
+
+impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+    pub fn new(
+        profiler: &'p SelfProfiler,
+        tcx: TyCtxt<'tcx>,
+        string_cache: &'c mut QueryKeyStringCache,
+    ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+        QueryKeyStringBuilder { profiler, tcx, string_cache }
+    }
+
+    // The current implementation is rather crude. In the future it might be a
+    // good idea to base this on `ty::print` in order to get nicer and more
+    // efficient query keys.
+    fn def_id_to_string_id(&mut self, def_id: DefId) -> StringId {
+        if let Some(&string_id) = self.string_cache.def_id_cache.get(&def_id) {
+            return string_id;
+        }
+
+        let def_key = self.tcx.def_key(def_id);
+
+        let (parent_string_id, start_index) = match def_key.parent {
+            Some(parent_index) => {
+                let parent_def_id = DefId { index: parent_index, krate: def_id.krate };
+
+                (self.def_id_to_string_id(parent_def_id), 0)
+            }
+            None => (StringId::INVALID, 2),
+        };
+
+        let dis_buffer = &mut [0u8; 16];
+        let name;
+        let dis;
+        let end_index;
+
+        match def_key.disambiguated_data.data {
+            DefPathData::CrateRoot => {
+                name = self.tcx.original_crate_name(def_id.krate).as_str();
+                dis = "";
+                end_index = 3;
+            }
+            other => {
+                name = other.as_symbol().as_str();
+                if def_key.disambiguated_data.disambiguator == 0 {
+                    dis = "";
+                    end_index = 3;
+                } else {
+                    write!(&mut dis_buffer[..], "[{}]", def_key.disambiguated_data.disambiguator)
+                        .unwrap();
+                    let end_of_dis = dis_buffer.iter().position(|&c| c == b']').unwrap();
+                    dis = std::str::from_utf8(&dis_buffer[..end_of_dis + 1]).unwrap();
+                    end_index = 4;
+                }
+            }
+        }
+
+        let components = [
+            StringComponent::Ref(parent_string_id),
+            StringComponent::Value("::"),
+            StringComponent::Value(&name[..]),
+            StringComponent::Value(dis),
+        ];
+
+        let string_id = self.profiler.alloc_string(&components[start_index..end_index]);
+
+        self.string_cache.def_id_cache.insert(def_id, string_id);
+
+        string_id
+    }
+}
+
+pub trait IntoSelfProfilingString {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId;
+}
+
+// The default implementation of `IntoSelfProfilingString` just uses `Debug`
+// which is slow and causes lots of duplication of string data.
+// The specialized impls below take care of making the `DefId` case more
+// efficient.
+impl<T: Debug> IntoSelfProfilingString for T {
+    default fn to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        let s = format!("{:?}", self);
+        builder.profiler.alloc_string(&s[..])
+    }
+}
+
+impl IntoSelfProfilingString for DefId {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(*self)
+    }
+}
+
+impl IntoSelfProfilingString for CrateNum {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
+    }
+}
+
+impl IntoSelfProfilingString for DefIndex {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
+    }
+}
+
+impl<T0, T1> IntoSelfProfilingString for (T0, T1)
+where
+    T0: IntoSelfProfilingString + Debug,
+    T1: IntoSelfProfilingString + Debug,
+{
+    default fn to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        let val0 = self.0.to_self_profile_string(builder);
+        let val1 = self.1.to_self_profile_string(builder);
+
+        let components = &[
+            StringComponent::Value("("),
+            StringComponent::Ref(val0),
+            StringComponent::Value(","),
+            StringComponent::Ref(val1),
+            StringComponent::Value(")"),
+        ];
+
+        builder.profiler.alloc_string(components)
+    }
+}
+
+/// Allocate the self-profiling query strings for a single query cache. This
+/// method is called from `alloc_self_profile_query_strings` which knows all
+/// the queries via macro magic.
+pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>(
+    tcx: TyCtxt<'tcx>,
+    query_name: &'static str,
+    query_cache: &Sharded<QueryCache<'tcx, Q>>,
+    string_cache: &mut QueryKeyStringCache,
+) where
+    Q: QueryConfig<'tcx>,
+{
+    tcx.prof.with_profiler(|profiler| {
+        let event_id_builder = profiler.event_id_builder();
+
+        // Walk the entire query cache and allocate the appropriate
+        // string representations. Each cache entry is uniquely
+        // identified by its dep_node_index.
+        if profiler.query_key_recording_enabled() {
+            let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache);
+
+            let query_name = profiler.get_or_alloc_cached_string(query_name);
+
+            // Since building the string representation of query keys might
+            // need to invoke queries itself, we cannot keep the query caches
+            // locked while doing so. Instead we copy out the
+            // `(query_key, dep_node_index)` pairs and release the lock again.
+            let query_keys_and_indices = {
+                let shards = query_cache.lock_shards();
+                let len = shards.iter().map(|shard| shard.results.len()).sum();
+
+                let mut query_keys_and_indices = Vec::with_capacity(len);
+
+                for shard in &shards {
+                    query_keys_and_indices.extend(
+                        shard.results.iter().map(|(q_key, q_val)| (q_key.clone(), q_val.index)),
+                    );
+                }
+
+                query_keys_and_indices
+            };
+
+            // Now actually allocate the strings. If allocating the strings
+            // generates new entries in the query cache, we'll miss them but
+            // we don't actually care.
+            for (query_key, dep_node_index) in query_keys_and_indices {
+                // Translate the DepNodeIndex into a QueryInvocationId
+                let query_invocation_id = dep_node_index.into();
+
+                // Create the string version of the query-key
+                let query_key = query_key.to_self_profile_string(&mut query_string_builder);
+                let event_id = event_id_builder.from_label_and_arg(query_name, query_key);
+
+                // Doing this in bulk might be a good idea:
+                profiler.map_query_invocation_id_to_string(
+                    query_invocation_id,
+                    event_id.to_string_id(),
+                );
+            }
+        } else {
+            // In this branch we don't allocate query keys
+            let query_name = profiler.get_or_alloc_cached_string(query_name);
+            let event_id = event_id_builder.from_label(query_name).to_string_id();
+
+            let shards = query_cache.lock_shards();
+
+            for shard in shards.iter() {
+                let query_invocation_ids = shard
+                    .results
+                    .values()
+                    .map(|v| v.index)
+                    .map(|dep_node_index| dep_node_index.into());
+
+                profiler
+                    .bulk_map_query_invocation_id_to_single_string(query_invocation_ids, event_id);
+            }
+        }
+    });
+}
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 120f05b..3b9df72 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -4,13 +4,13 @@
 //! types or regions but can be other things. Examples of type relations are
 //! subtyping, type equality, etc.
 
-use crate::hir as ast;
-use crate::hir::def_id::DefId;
 use crate::mir::interpret::{get_slice_bytes, ConstValue};
 use crate::traits;
 use crate::ty::error::{ExpectedFound, TypeError};
 use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_hir as ast;
+use rustc_hir::def_id::DefId;
 use rustc_target::spec::abi;
 use std::iter;
 use std::rc::Rc;
@@ -568,12 +568,12 @@
 
         // FIXME(const_generics): this is wrong, as it is a projection
         (
-            ty::ConstKind::Unevaluated(a_def_id, a_substs),
-            ty::ConstKind::Unevaluated(b_def_id, b_substs),
-        ) if a_def_id == b_def_id => {
+            ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted),
+            ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted),
+        ) if a_def_id == b_def_id && a_promoted == b_promoted => {
             let substs =
                 relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
-            Ok(ty::ConstKind::Unevaluated(a_def_id, &substs))
+            Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted))
         }
         _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
     };
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index c92128a..62e895a 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -2,17 +2,16 @@
 //! traits for various types in the Rust compiler. Most are written by
 //! hand, though we've recently added some macros and proc-macros to help with the tedium.
 
-use crate::hir::def::Namespace;
-use crate::hir::def_id::CRATE_DEF_INDEX;
 use crate::mir::interpret;
 use crate::mir::ProjectionKind;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::{self, InferConst, Lift, Ty, TyCtxt};
-
+use rustc_hir::def::Namespace;
+use rustc_hir::def_id::CRATE_DEF_INDEX;
 use rustc_index::vec::{Idx, IndexVec};
-use smallvec::SmallVec;
 
+use smallvec::SmallVec;
 use std::fmt;
 use std::rc::Rc;
 use std::sync::Arc;
@@ -46,12 +45,6 @@
     }
 }
 
-impl fmt::Debug for ty::ClosureUpvar<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ClosureUpvar({:?},{:?})", self.res, self.ty)
-    }
-}
-
 impl fmt::Debug for ty::UpvarId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let name = ty::tls::with(|tcx| tcx.hir().name(self.var_path.hir_id));
@@ -275,12 +268,12 @@
     ::syntax::ast::FloatTy,
     ::syntax::ast::NodeId,
     ::rustc_span::symbol::Symbol,
-    crate::hir::def::Res,
-    crate::hir::def_id::DefId,
-    crate::hir::InlineAsmInner,
-    crate::hir::MatchSource,
-    crate::hir::Mutability,
-    crate::hir::Unsafety,
+    ::rustc_hir::def::Res,
+    ::rustc_hir::def_id::DefId,
+    ::rustc_hir::InlineAsmInner,
+    ::rustc_hir::MatchSource,
+    ::rustc_hir::Mutability,
+    ::rustc_hir::Unsafety,
     ::rustc_target::spec::abi::Abi,
     crate::mir::Local,
     crate::mir::Promoted,
@@ -1044,8 +1037,8 @@
         match *self {
             ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
             ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
-            ty::ConstKind::Unevaluated(did, substs) => {
-                ty::ConstKind::Unevaluated(did, substs.fold_with(folder))
+            ty::ConstKind::Unevaluated(did, substs, promoted) => {
+                ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted)
             }
             ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => {
                 *self
@@ -1057,7 +1050,7 @@
         match *self {
             ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
             ty::ConstKind::Param(p) => p.visit_with(visitor),
-            ty::ConstKind::Unevaluated(_, substs) => substs.visit_with(visitor),
+            ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor),
             ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
                 false
             }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 3466225..8423612 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -5,19 +5,19 @@
 use self::InferTy::*;
 use self::TyKind::*;
 
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::infer::canonical::Canonical;
 use crate::middle::region;
 use crate::mir::interpret::ConstValue;
 use crate::mir::interpret::Scalar;
+use crate::mir::Promoted;
 use crate::ty::layout::VariantIdx;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable};
 use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS};
-use crate::util::captures::Captures;
-
 use polonius_engine::Atom;
+use rustc_data_structures::captures::Captures;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{kw, Symbol};
@@ -2376,7 +2376,7 @@
 
     #[inline]
     pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> {
-        let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs| {
+        let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| {
             let param_env_and_substs = param_env.with_reveal_all().and(substs);
 
             // Avoid querying `tcx.const_eval(...)` with any e.g. inference vars.
@@ -2388,11 +2388,11 @@
 
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            tcx.const_eval_resolve(param_env, did, substs, None).ok()
+            tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok()
         };
 
         match self.val {
-            ConstKind::Unevaluated(did, substs) => {
+            ConstKind::Unevaluated(did, substs, promoted) => {
                 // HACK(eddyb) when substs contain e.g. inference variables,
                 // attempt using identity substs instead, that will succeed
                 // when the expression doesn't depend on any parameters.
@@ -2402,12 +2402,12 @@
                     let identity_substs = InternalSubsts::identity_for_item(tcx, did);
                     // The `ParamEnv` needs to match the `identity_substs`.
                     let identity_param_env = tcx.param_env(did);
-                    match try_const_eval(did, identity_param_env, identity_substs) {
+                    match try_const_eval(did, identity_param_env, identity_substs, promoted) {
                         Some(ct) => ct.subst(tcx, substs),
                         None => self,
                     }
                 } else {
-                    try_const_eval(did, param_env, substs).unwrap_or(self)
+                    try_const_eval(did, param_env, substs, promoted).unwrap_or(self)
                 }
             }
             _ => self,
@@ -2471,7 +2471,7 @@
 
     /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
     /// variants when the code is monomorphic enough for that.
-    Unevaluated(DefId, SubstsRef<'tcx>),
+    Unevaluated(DefId, SubstsRef<'tcx>, Option<Promoted>),
 
     /// Used to hold computed value.
     Value(ConstValue<'tcx>),
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 0167fae..a005581 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -1,11 +1,11 @@
 // Type substitutions.
 
-use crate::hir::def_id::DefId;
 use crate::infer::canonical::Canonical;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder};
 use rustc_span::{Span, DUMMY_SP};
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 422d1b1..0cf1c39 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -1,11 +1,11 @@
-use crate::hir;
-use crate::hir::def_id::DefId;
 use crate::hir::map::DefPathHash;
 use crate::ich::{self, StableHashingContext};
 use crate::traits::specialization_graph;
 use crate::ty::fast_reject;
 use crate::ty::fold::TypeFoldable;
 use crate::ty::{Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 15fae10..8d22ac9 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -1,24 +1,22 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
-use crate::hir;
-use crate::hir::def::DefKind;
-use crate::hir::def_id::DefId;
 use crate::hir::map::DefPathData;
 use crate::ich::NodeIdHashingMode;
-use crate::middle::lang_items;
 use crate::mir::interpret::{sign_extend, truncate};
-use crate::traits::{self, ObligationCause};
-use crate::ty::layout::{Integer, IntegerExt};
+use crate::ty::layout::{Integer, IntegerExt, Size};
 use crate::ty::query::TyCtxtAt;
 use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use crate::ty::TyKind::*;
 use crate::ty::{self, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable};
 use crate::util::common::ErrorReported;
-
+use rustc_apfloat::Float as _;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use std::{cmp, fmt};
 use syntax::ast;
 use syntax::attr::{self, SignedInt, UnsignedInt};
@@ -45,26 +43,38 @@
     }
 }
 
+fn signed_min(size: Size) -> i128 {
+    sign_extend(1_u128 << (size.bits() - 1), size) as i128
+}
+
+fn signed_max(size: Size) -> i128 {
+    i128::max_value() >> (128 - size.bits())
+}
+
+fn unsigned_max(size: Size) -> u128 {
+    u128::max_value() >> (128 - size.bits())
+}
+
+fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
+    let (int, signed) = match ty.kind {
+        Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
+        Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
+        _ => bug!("non integer discriminant"),
+    };
+    (int.size(), signed)
+}
+
 impl<'tcx> Discr<'tcx> {
     /// Adds `1` to the value and wraps around if the maximum for the type is reached.
     pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self {
         self.checked_add(tcx, 1).0
     }
     pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
-        let (int, signed) = match self.ty.kind {
-            Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
-            Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
-            _ => bug!("non integer discriminant"),
-        };
-
-        let size = int.size();
-        let bit_size = int.size().bits();
-        let shift = 128 - bit_size;
-        if signed {
-            let sext = |u| sign_extend(u, size) as i128;
-            let min = sext(1_u128 << (bit_size - 1));
-            let max = i128::max_value() >> shift;
-            let val = sext(self.val);
+        let (size, signed) = int_size_and_signed(tcx, self.ty);
+        let (val, oflo) = if signed {
+            let min = signed_min(size);
+            let max = signed_max(size);
+            let val = sign_extend(self.val, size) as i128;
             assert!(n < (i128::max_value() as u128));
             let n = n as i128;
             let oflo = val > max - n;
@@ -72,14 +82,15 @@
             // zero the upper bits
             let val = val as u128;
             let val = truncate(val, size);
-            (Self { val: val as u128, ty: self.ty }, oflo)
+            (val, oflo)
         } else {
-            let max = u128::max_value() >> shift;
+            let max = unsigned_max(size);
             let val = self.val;
             let oflo = val > max - n;
             let val = if oflo { n - (max - val) - 1 } else { val + n };
-            (Self { val: val, ty: self.ty }, oflo)
-        }
+            (val, oflo)
+        };
+        (Self { val, ty: self.ty }, oflo)
     }
 }
 
@@ -122,13 +133,6 @@
     }
 }
 
-#[derive(Clone)]
-pub enum CopyImplementationError<'tcx> {
-    InfrigingFields(Vec<&'tcx ty::FieldDef>),
-    NotAnAdt,
-    HasDestructor,
-}
-
 /// Describes whether a type is representable. For types that are not
 /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
 /// distinguish between types that are recursive with themselves and types that
@@ -144,65 +148,6 @@
     SelfRecursive(Vec<Span>),
 }
 
-impl<'tcx> ty::ParamEnv<'tcx> {
-    pub fn can_type_implement_copy(
-        self,
-        tcx: TyCtxt<'tcx>,
-        self_type: Ty<'tcx>,
-    ) -> Result<(), CopyImplementationError<'tcx>> {
-        // FIXME: (@jroesch) float this code up
-        tcx.infer_ctxt().enter(|infcx| {
-            let (adt, substs) = match self_type.kind {
-                // These types used to have a builtin impl.
-                // Now libcore provides that impl.
-                ty::Uint(_)
-                | ty::Int(_)
-                | ty::Bool
-                | ty::Float(_)
-                | ty::Char
-                | ty::RawPtr(..)
-                | ty::Never
-                | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
-
-                ty::Adt(adt, substs) => (adt, substs),
-
-                _ => return Err(CopyImplementationError::NotAnAdt),
-            };
-
-            let mut infringing = Vec::new();
-            for variant in &adt.variants {
-                for field in &variant.fields {
-                    let ty = field.ty(tcx, substs);
-                    if ty.references_error() {
-                        continue;
-                    }
-                    let span = tcx.def_span(field.did);
-                    let cause = ObligationCause { span, ..ObligationCause::dummy() };
-                    let ctx = traits::FulfillmentContext::new();
-                    match traits::fully_normalize(&infcx, ctx, cause, self, &ty) {
-                        Ok(ty) => {
-                            if !infcx.type_is_copy_modulo_regions(self, ty, span) {
-                                infringing.push(field);
-                            }
-                        }
-                        Err(errors) => {
-                            infcx.report_fulfillment_errors(&errors, None, false);
-                        }
-                    };
-                }
-            }
-            if !infringing.is_empty() {
-                return Err(CopyImplementationError::InfrigingFields(infringing));
-            }
-            if adt.has_dtor(tcx) {
-                return Err(CopyImplementationError::HasDestructor);
-            }
-
-            Ok(())
-        })
-    }
-}
-
 impl<'tcx> TyCtxt<'tcx> {
     /// Creates a hash of the type `Ty` which will be the same no matter what crate
     /// context it's calculated within. This is used by the `type_id` intrinsic.
@@ -393,70 +338,6 @@
         (a, b)
     }
 
-    /// Given a set of predicates that apply to an object type, returns
-    /// the region bounds that the (erased) `Self` type must
-    /// outlive. Precisely *because* the `Self` type is erased, the
-    /// parameter `erased_self_ty` must be supplied to indicate what type
-    /// has been used to represent `Self` in the predicates
-    /// themselves. This should really be a unique type; `FreshTy(0)` is a
-    /// popular choice.
-    ///
-    /// N.B., in some cases, particularly around higher-ranked bounds,
-    /// this function returns a kind of conservative approximation.
-    /// That is, all regions returned by this function are definitely
-    /// required, but there may be other region bounds that are not
-    /// returned, as well as requirements like `for<'a> T: 'a`.
-    ///
-    /// Requires that trait definitions have been processed so that we can
-    /// elaborate predicates and walk supertraits.
-    //
-    // FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's
-    // what this code should accept.
-    pub fn required_region_bounds(
-        self,
-        erased_self_ty: Ty<'tcx>,
-        predicates: Vec<ty::Predicate<'tcx>>,
-    ) -> Vec<ty::Region<'tcx>> {
-        debug!(
-            "required_region_bounds(erased_self_ty={:?}, predicates={:?})",
-            erased_self_ty, predicates
-        );
-
-        assert!(!erased_self_ty.has_escaping_bound_vars());
-
-        traits::elaborate_predicates(self, predicates)
-            .filter_map(|predicate| {
-                match predicate {
-                    ty::Predicate::Projection(..)
-                    | ty::Predicate::Trait(..)
-                    | ty::Predicate::Subtype(..)
-                    | ty::Predicate::WellFormed(..)
-                    | ty::Predicate::ObjectSafe(..)
-                    | ty::Predicate::ClosureKind(..)
-                    | ty::Predicate::RegionOutlives(..)
-                    | ty::Predicate::ConstEvaluatable(..) => None,
-                    ty::Predicate::TypeOutlives(predicate) => {
-                        // Search for a bound of the form `erased_self_ty
-                        // : 'a`, but be wary of something like `for<'a>
-                        // erased_self_ty : 'a` (we interpret a
-                        // higher-ranked bound like that as 'static,
-                        // though at present the code in `fulfill.rs`
-                        // considers such bounds to be unsatisfiable, so
-                        // it's kind of a moot point since you could never
-                        // construct such an object, but this seems
-                        // correct even if that code changes).
-                        let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
-                        if t == &erased_self_ty && !r.has_escaping_bound_vars() {
-                            Some(*r)
-                        } else {
-                            None
-                        }
-                    }
-                }
-            })
-            .collect()
-    }
-
     /// Calculate the destructor of a given type.
     pub fn calculate_dtor(
         self,
@@ -665,8 +546,6 @@
 
         if self.is_mutable_static(def_id) {
             self.mk_mut_ptr(static_ty)
-        } else if self.is_foreign_item(def_id) {
-            self.mk_imm_ptr(static_ty)
         } else {
             self.mk_imm_ref(self.lifetimes.re_erased, static_ty)
         }
@@ -755,6 +634,44 @@
 }
 
 impl<'tcx> ty::TyS<'tcx> {
+    /// Returns the maximum value for the given numeric type (including `char`s)
+    /// or returns `None` if the type is not numeric.
+    pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
+        let val = match self.kind {
+            ty::Int(_) | ty::Uint(_) => {
+                let (size, signed) = int_size_and_signed(tcx, self);
+                let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
+                Some(val)
+            }
+            ty::Char => Some(std::char::MAX as u128),
+            ty::Float(fty) => Some(match fty {
+                ast::FloatTy::F32 => ::rustc_apfloat::ieee::Single::INFINITY.to_bits(),
+                ast::FloatTy::F64 => ::rustc_apfloat::ieee::Double::INFINITY.to_bits(),
+            }),
+            _ => None,
+        };
+        val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
+    }
+
+    /// Returns the minimum value for the given numeric type (including `char`s)
+    /// or returns `None` if the type is not numeric.
+    pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
+        let val = match self.kind {
+            ty::Int(_) | ty::Uint(_) => {
+                let (size, signed) = int_size_and_signed(tcx, self);
+                let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 };
+                Some(val)
+            }
+            ty::Char => Some(0),
+            ty::Float(fty) => Some(match fty {
+                ast::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(),
+                ast::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(),
+            }),
+            _ => None,
+        };
+        val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
+    }
+
     /// Checks whether values of this type `T` are *moved* or *copied*
     /// when referenced -- this amounts to a check for whether `T:
     /// Copy`, but note that we **don't** consider lifetimes when
@@ -1006,128 +923,9 @@
     }
 }
 
-fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, lang_items::CopyTraitLangItem)
-}
-
-fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, lang_items::SizedTraitLangItem)
-}
-
-fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, lang_items::FreezeTraitLangItem)
-}
-
-fn is_item_raw<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-    item: lang_items::LangItem,
-) -> bool {
-    let (param_env, ty) = query.into_parts();
-    let trait_def_id = tcx.require_lang_item(item, None);
-    tcx.infer_ctxt().enter(|infcx| {
-        traits::type_known_to_meet_bound_modulo_regions(
-            &infcx,
-            param_env,
-            ty,
-            trait_def_id,
-            DUMMY_SP,
-        )
-    })
-}
-
 #[derive(Clone, HashStable)]
 pub struct NeedsDrop(pub bool);
 
-fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> NeedsDrop {
-    let (param_env, ty) = query.into_parts();
-
-    let needs_drop = |ty: Ty<'tcx>| -> bool { tcx.needs_drop_raw(param_env.and(ty)).0 };
-
-    assert!(!ty.needs_infer());
-
-    NeedsDrop(match ty.kind {
-        // Fast-path for primitive types
-        ty::Infer(ty::FreshIntTy(_))
-        | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Bool
-        | ty::Int(_)
-        | ty::Uint(_)
-        | ty::Float(_)
-        | ty::Never
-        | ty::FnDef(..)
-        | ty::FnPtr(_)
-        | ty::Char
-        | ty::GeneratorWitness(..)
-        | ty::RawPtr(_)
-        | ty::Ref(..)
-        | ty::Str => false,
-
-        // Foreign types can never have destructors
-        ty::Foreign(..) => false,
-
-        // `ManuallyDrop` doesn't have a destructor regardless of field types.
-        ty::Adt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false,
-
-        // Issue #22536: We first query `is_copy_modulo_regions`.  It sees a
-        // normalized version of the type, and therefore will definitely
-        // know whether the type implements Copy (and thus needs no
-        // cleanup/drop/zeroing) ...
-        _ if ty.is_copy_modulo_regions(tcx, param_env, DUMMY_SP) => false,
-
-        // ... (issue #22536 continued) but as an optimization, still use
-        // prior logic of asking for the structural "may drop".
-
-        // FIXME(#22815): Note that this is a conservative heuristic;
-        // it may report that the type "may drop" when actual type does
-        // not actually have a destructor associated with it. But since
-        // the type absolutely did not have the `Copy` bound attached
-        // (see above), it is sound to treat it as having a destructor.
-
-        // User destructors are the only way to have concrete drop types.
-        ty::Adt(def, _) if def.has_dtor(tcx) => true,
-
-        // Can refer to a type which may drop.
-        // FIXME(eddyb) check this against a ParamEnv.
-        ty::Dynamic(..)
-        | ty::Projection(..)
-        | ty::Param(_)
-        | ty::Bound(..)
-        | ty::Placeholder(..)
-        | ty::Opaque(..)
-        | ty::Infer(_)
-        | ty::Error => true,
-
-        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-
-        // Zero-length arrays never contain anything to drop.
-        ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false,
-
-        // Structural recursion.
-        ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
-
-        ty::Closure(def_id, ref substs) => {
-            substs.as_closure().upvar_tys(def_id, tcx).any(needs_drop)
-        }
-
-        // Pessimistically assume that all generators will require destructors
-        // as we don't know if a destructor is a noop or not until after the MIR
-        // state transformation pass
-        ty::Generator(..) => true,
-
-        ty::Tuple(..) => ty.tuple_fields().any(needs_drop),
-
-        // unions don't have destructors because of the child types,
-        // only if they manually implement `Drop` (handled above).
-        ty::Adt(def, _) if def.is_union() => false,
-
-        ty::Adt(def, substs) => def
-            .variants
-            .iter()
-            .any(|variant| variant.fields.iter().any(|field| needs_drop(field.ty(tcx, substs)))),
-    })
-}
-
 pub enum ExplicitSelf<'tcx> {
     ByValue,
     ByReference(ty::Region<'tcx>, hir::Mutability),
@@ -1176,13 +974,3 @@
         }
     }
 }
-
-pub fn provide(providers: &mut ty::query::Providers<'_>) {
-    *providers = ty::query::Providers {
-        is_copy_raw,
-        is_sized_raw,
-        is_freeze_raw,
-        needs_drop_raw,
-        ..*providers
-    };
-}
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index 9e0dd8e..da08fbc 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -81,7 +81,8 @@
         | ty::Bound(..)
         | ty::Foreign(..) => {}
         ty::Array(ty, len) => {
-            if let ty::ConstKind::Unevaluated(_, substs) = len.val {
+            if let ty::ConstKind::Unevaluated(_, substs, promoted) = len.val {
+                assert!(promoted.is_none());
                 stack.extend(substs.types().rev());
             }
             stack.push(len.ty);
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 9574685..19b43bf 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -5,15 +5,10 @@
 use std::fmt::Debug;
 use std::time::{Duration, Instant};
 
-use rustc_span::symbol::{sym, Symbol};
-
 #[cfg(test)]
 mod tests;
 
-// The name of the associated type for `Fn` return types.
-pub const FN_OUTPUT_NAME: Symbol = sym::Output;
-
-pub use errors::ErrorReported;
+pub use rustc_errors::ErrorReported;
 
 pub fn to_readable_str(mut val: usize) -> String {
     let mut groups = vec![];
diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml
deleted file mode 100644
index df117de..0000000
--- a/src/librustc_asan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_asan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_asan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
deleted file mode 100644
index e276dc1..0000000
--- a/src/librustc_asan/build.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("asan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-        native.fixup_sanitizer_lib_name("asan");
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_asan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_ast_lowering/Cargo.toml b/src/librustc_ast_lowering/Cargo.toml
index 76980df..408e9a7 100644
--- a/src/librustc_ast_lowering/Cargo.toml
+++ b/src/librustc_ast_lowering/Cargo.toml
@@ -12,6 +12,7 @@
 [dependencies]
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 rustc = { path = "../librustc" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_index = { path = "../librustc_index" }
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index 591e869..9a229e7 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -1,16 +1,16 @@
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
 
 use rustc::bug;
-use rustc::hir;
-use rustc::hir::def::Res;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::Res;
 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast::*;
 use syntax::attr;
 use syntax::ptr::P as AstP;
-use syntax::{span_err, struct_span_err};
 
 impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -202,14 +202,19 @@
             ExprKind::Mac(_) => panic!("Shouldn't exist here"),
         };
 
-        hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: e.span, attrs: e.attrs.clone() }
+        hir::Expr {
+            hir_id: self.lower_node_id(e.id),
+            kind,
+            span: e.span,
+            attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
+        }
     }
 
     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
         match u {
-            UnOp::Deref => hir::UnDeref,
-            UnOp::Not => hir::UnNot,
-            UnOp::Neg => hir::UnNeg,
+            UnOp::Deref => hir::UnOp::UnDeref,
+            UnOp::Not => hir::UnOp::UnNot,
+            UnOp::Neg => hir::UnOp::UnNeg,
         }
     }
 
@@ -685,12 +690,13 @@
         match generator_kind {
             Some(hir::GeneratorKind::Gen) => {
                 if !decl.inputs.is_empty() {
-                    span_err!(
+                    struct_span_err!(
                         self.sess,
                         fn_decl_span,
                         E0628,
                         "generators cannot have explicit parameters"
-                    );
+                    )
+                    .emit();
                 }
                 Some(movability)
             }
@@ -699,7 +705,8 @@
             }
             None => {
                 if movability == Movability::Static {
-                    span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static");
+                    struct_span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static")
+                        .emit();
                 }
                 None
             }
@@ -946,7 +953,13 @@
         match self.generator_kind {
             Some(hir::GeneratorKind::Gen) => {}
             Some(hir::GeneratorKind::Async(_)) => {
-                span_err!(self.sess, span, E0727, "`async` generators are not yet supported",);
+                struct_span_err!(
+                    self.sess,
+                    span,
+                    E0727,
+                    "`async` generators are not yet supported"
+                )
+                .emit();
                 return hir::ExprKind::Err;
             }
             None => self.generator_kind = Some(hir::GeneratorKind::Gen),
@@ -1374,7 +1387,7 @@
                     stmts: &[],
                     expr: Some(expr),
                     hir_id,
-                    rules: hir::UnsafeBlock(hir::CompilerGenerated),
+                    rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
                     span,
                     targeted_by_break: false,
                 }),
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 7e7e2d1..beb53a1 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -3,10 +3,11 @@
 
 use rustc::arena::Arena;
 use rustc::bug;
-use rustc::hir;
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::DefId;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
 use rustc_session::node_id::NodeMap;
 use rustc_span::source_map::{respan, DesugaringKind};
 use rustc_span::symbol::{kw, sym};
@@ -14,7 +15,6 @@
 use rustc_target::spec::abi;
 use syntax::ast::*;
 use syntax::attr;
-use syntax::struct_span_err;
 use syntax::visit::{self, Visitor};
 
 use log::debug;
@@ -25,19 +25,16 @@
     pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
 }
 
-impl<'a, 'lowering, 'hir> ItemLowerer<'a, 'lowering, 'hir> {
-    fn with_trait_impl_ref<F>(&mut self, trait_impl_ref: &Option<TraitRef>, f: F)
-    where
-        F: FnOnce(&mut Self),
-    {
+impl ItemLowerer<'_, '_, '_> {
+    fn with_trait_impl_ref(&mut self, impl_ref: &Option<TraitRef>, f: impl FnOnce(&mut Self)) {
         let old = self.lctx.is_in_trait_impl;
-        self.lctx.is_in_trait_impl = if let &None = trait_impl_ref { false } else { true };
+        self.lctx.is_in_trait_impl = if let &None = impl_ref { false } else { true };
         f(self);
         self.lctx.is_in_trait_impl = old;
     }
 }
 
-impl<'a, 'lowering, 'hir> Visitor<'a> for ItemLowerer<'a, 'lowering, 'hir> {
+impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
     fn visit_mod(&mut self, m: &'a Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
         let hir_id = self.lctx.lower_node_id(n);
 
@@ -71,6 +68,12 @@
             self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
                 let this = &mut ItemLowerer { lctx: this };
                 if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.kind {
+                    if opt_trait_ref.as_ref().map(|tr| tr.constness.is_some()).unwrap_or(false) {
+                        this.lctx
+                            .diagnostic()
+                            .span_err(item.span, "const trait impls are not yet implemented");
+                    }
+
                     this.with_trait_impl_ref(opt_trait_ref, |this| visit::walk_item(this, item));
                 } else {
                     visit::walk_item(this, item);
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 5694bed..d30d0bd 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 //! Lowers the AST to the HIR.
 //!
 //! Since the AST and HIR are fairly similar, this is mostly a simple procedure,
@@ -33,41 +31,41 @@
 //! in the HIR, especially for multiple identifiers.
 
 #![feature(array_value_iter)]
+#![feature(crate_visibility_modifier)]
 
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
-use rustc::hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX};
-use rustc::hir::map::{DefKey, DefPathData, Definitions};
-use rustc::hir::{self, ConstArg, GenericArg, ParamName};
-use rustc::lint;
-use rustc::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
-use rustc::middle::cstore::CrateStore;
-use rustc::session::config::nightly_options;
-use rustc::session::Session;
-use rustc::util::captures::Captures;
-use rustc::util::common::FN_OUTPUT_NAME;
+use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions};
+use rustc::hir::map::Map;
 use rustc::{bug, span_bug};
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_error_codes::*;
-use rustc_errors::Applicability;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
+use rustc_hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::intravisit;
+use rustc_hir::{ConstArg, GenericArg, ParamName};
 use rustc_index::vec::IndexVec;
+use rustc_session::config::nightly_options;
+use rustc_session::lint::{builtin, BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::node_id::NodeMap;
+use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
-use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind, Spanned};
+use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 use syntax::ast;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::print::pprust;
-use syntax::ptr::P as AstP;
 use syntax::sess::ParseSess;
 use syntax::token::{self, Nonterminal, Token};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::{self, Visitor};
-use syntax::{help, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use log::{debug, trace};
 use smallvec::{smallvec, SmallVec};
@@ -83,6 +81,8 @@
 
 mod expr;
 mod item;
+mod pat;
+mod path;
 
 const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 
@@ -170,7 +170,9 @@
 }
 
 pub trait Resolver {
-    fn cstore(&self) -> &dyn CrateStore;
+    fn def_key(&mut self, id: DefId) -> DefKey;
+
+    fn item_generics_num_lifetimes(&self, def: DefId, sess: &Session) -> usize;
 
     /// Obtains resolution for a `NodeId` with a single resolution.
     fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
@@ -195,7 +197,7 @@
         ns: Namespace,
     ) -> (ast::Path, Res<NodeId>);
 
-    fn lint_buffer(&mut self) -> &mut lint::LintBuffer;
+    fn lint_buffer(&mut self) -> &mut LintBuffer;
 
     fn next_node_id(&mut self) -> NodeId;
 }
@@ -265,7 +267,7 @@
     // incr. comp. yet.
     dep_graph.assert_ignored();
 
-    let _prof_timer = sess.prof.generic_activity("hir_lowering");
+    let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
 
     LoweringContext {
         crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
@@ -430,10 +432,11 @@
                 }
             }
 
-            fn with_hir_id_owner<F, T>(&mut self, owner: Option<NodeId>, f: F) -> T
-            where
-                F: FnOnce(&mut Self) -> T,
-            {
+            fn with_hir_id_owner<T>(
+                &mut self,
+                owner: Option<NodeId>,
+                f: impl FnOnce(&mut Self) -> T,
+            ) -> T {
                 let old = mem::replace(&mut self.hir_id_owner, owner);
                 let r = f(self);
                 self.hir_id_owner = old;
@@ -441,7 +444,7 @@
             }
         }
 
-        impl<'tcx, 'lowering, 'hir> Visitor<'tcx> for MiscCollector<'tcx, 'lowering, 'hir> {
+        impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
             fn visit_pat(&mut self, p: &'tcx Pat) {
                 if let PatKind::Paren(..) | PatKind::Rest = p.kind {
                     // Doesn't generate a HIR node
@@ -574,10 +577,11 @@
         lowered
     }
 
-    fn lower_node_id_generic<F>(&mut self, ast_node_id: NodeId, alloc_hir_id: F) -> hir::HirId
-    where
-        F: FnOnce(&mut Self) -> hir::HirId,
-    {
+    fn lower_node_id_generic(
+        &mut self,
+        ast_node_id: NodeId,
+        alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId,
+    ) -> hir::HirId {
         if ast_node_id == DUMMY_NODE_ID {
             return hir::DUMMY_HIR_ID;
         }
@@ -601,10 +605,7 @@
         }
     }
 
-    fn with_hir_id_owner<F, T>(&mut self, owner: NodeId, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
         let counter = self
             .item_local_id_counters
             .insert(owner, HIR_ID_COUNTER_LOCKED)
@@ -733,15 +734,12 @@
     /// Presuming that in-band lifetimes are enabled, then
     /// `self.anonymous_lifetime_mode` will be updated to match the
     /// parameter while `f` is running (and restored afterwards).
-    fn collect_in_band_defs<T, F>(
+    fn collect_in_band_defs<T>(
         &mut self,
         parent_id: DefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
-        f: F,
-    ) -> (Vec<hir::GenericParam<'hir>>, T)
-    where
-        F: FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
-    {
+        f: impl FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
+    ) -> (Vec<hir::GenericParam<'hir>>, T) {
         assert!(!self.is_collecting_in_band_lifetimes);
         assert!(self.lifetimes_to_define.is_empty());
         let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode;
@@ -844,10 +842,11 @@
     // This is used to track which lifetimes have already been defined, and
     // which are new in-band lifetimes that need to have a definition created
     // for them.
-    fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &[GenericParam], f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_in_scope_lifetime_defs<T>(
+        &mut self,
+        params: &[GenericParam],
+        f: impl FnOnce(&mut Self) -> T,
+    ) -> T {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
             GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())),
@@ -867,16 +866,13 @@
     /// Presuming that in-band lifetimes are enabled, then
     /// `self.anonymous_lifetime_mode` will be updated to match the
     /// parameter while `f` is running (and restored afterwards).
-    fn add_in_band_defs<F, T>(
+    fn add_in_band_defs<T>(
         &mut self,
         generics: &Generics,
         parent_id: DefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
-        f: F,
-    ) -> (hir::Generics<'hir>, T)
-    where
-        F: FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
-    {
+        f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
+    ) -> (hir::Generics<'hir>, T) {
         let (in_band_defs, (mut lowered_generics, res)) =
             self.with_in_scope_lifetime_defs(&generics.params, |this| {
                 this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
@@ -914,10 +910,7 @@
         (lowered_generics, res)
     }
 
-    fn with_dyn_type_scope<T, F>(&mut self, in_scope: bool, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {
         let was_in_dyn_type = self.is_in_dyn_type;
         self.is_in_dyn_type = in_scope;
 
@@ -928,10 +921,7 @@
         result
     }
 
-    fn with_new_scopes<T, F>(&mut self, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
@@ -946,14 +936,6 @@
         ret
     }
 
-    fn def_key(&mut self, id: DefId) -> DefKey {
-        if id.is_local() {
-            self.resolver.definitions().def_key(id.index)
-        } else {
-            self.resolver.cstore().def_key(id)
-        }
-    }
-
     fn lower_attrs(&mut self, attrs: &[Attribute]) -> &'hir [Attribute] {
         self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)))
     }
@@ -1345,10 +1327,9 @@
                         );
                         if pos == ImplTraitPosition::Binding && nightly_options::is_nightly_build()
                         {
-                            help!(
-                                err,
+                            err.help(
                                 "add `#![feature(impl_trait_in_bindings)]` to the crate \
-                                   attributes to enable"
+                                   attributes to enable",
                             );
                         }
                         err.emit();
@@ -1482,11 +1463,11 @@
             output_lifetime_params: Vec<hir::GenericParam<'hir>>,
         }
 
-        impl<'r, 'a, 'v, 'hir> hir::intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            fn nested_visit_map<'this>(
-                &'this mut self,
-            ) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
-                hir::intravisit::NestedVisitorMap::None
+        impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
+            type Map = Map<'v>;
+
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+                intravisit::NestedVisitorMap::None
             }
 
             fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
@@ -1494,10 +1475,10 @@
                 if parameters.parenthesized {
                     let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
                     self.collect_elided_lifetimes = false;
-                    hir::intravisit::walk_generic_args(self, span, parameters);
+                    intravisit::walk_generic_args(self, span, parameters);
                     self.collect_elided_lifetimes = old_collect_elided_lifetimes;
                 } else {
-                    hir::intravisit::walk_generic_args(self, span, parameters);
+                    intravisit::walk_generic_args(self, span, parameters);
                 }
             }
 
@@ -1510,12 +1491,12 @@
                     // Record the "stack height" of `for<'a>` lifetime bindings
                     // to be able to later fully undo their introduction.
                     let old_len = self.currently_bound_lifetimes.len();
-                    hir::intravisit::walk_ty(self, t);
+                    intravisit::walk_ty(self, t);
                     self.currently_bound_lifetimes.truncate(old_len);
 
                     self.collect_elided_lifetimes = old_collect_elided_lifetimes;
                 } else {
-                    hir::intravisit::walk_ty(self, t)
+                    intravisit::walk_ty(self, t)
                 }
             }
 
@@ -1527,7 +1508,7 @@
                 // Record the "stack height" of `for<'a>` lifetime bindings
                 // to be able to later fully undo their introduction.
                 let old_len = self.currently_bound_lifetimes.len();
-                hir::intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
+                intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
                 self.currently_bound_lifetimes.truncate(old_len);
             }
 
@@ -1540,7 +1521,7 @@
                     self.currently_bound_lifetimes.push(lt_name);
                 }
 
-                hir::intravisit::walk_generic_param(self, param);
+                intravisit::walk_generic_param(self, param);
             }
 
             fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
@@ -1621,7 +1602,7 @@
         };
 
         for bound in bounds {
-            hir::intravisit::walk_param_bound(&mut lifetime_collector, &bound);
+            intravisit::walk_param_bound(&mut lifetime_collector, &bound);
         }
 
         let ImplTraitLifetimeCollector { output_lifetimes, output_lifetime_params, .. } =
@@ -1633,403 +1614,6 @@
         )
     }
 
-    fn lower_qpath(
-        &mut self,
-        id: NodeId,
-        qself: &Option<QSelf>,
-        p: &Path,
-        param_mode: ParamMode,
-        mut itctx: ImplTraitContext<'_, 'hir>,
-    ) -> hir::QPath<'hir> {
-        let qself_position = qself.as_ref().map(|q| q.position);
-        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
-
-        let partial_res =
-            self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
-
-        let proj_start = p.segments.len() - partial_res.unresolved_segments();
-        let path = self.arena.alloc(hir::Path {
-            res: self.lower_res(partial_res.base_res()),
-            segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
-                |(i, segment)| {
-                    let param_mode = match (qself_position, param_mode) {
-                        (Some(j), ParamMode::Optional) if i < j => {
-                            // This segment is part of the trait path in a
-                            // qualified path - one of `a`, `b` or `Trait`
-                            // in `<X as a::b::Trait>::T::U::method`.
-                            ParamMode::Explicit
-                        }
-                        _ => param_mode,
-                    };
-
-                    // Figure out if this is a type/trait segment,
-                    // which may need lifetime elision performed.
-                    let parent_def_id = |this: &mut Self, def_id: DefId| DefId {
-                        krate: def_id.krate,
-                        index: this.def_key(def_id).parent.expect("missing parent"),
-                    };
-                    let type_def_id = match partial_res.base_res() {
-                        Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
-                            Some(parent_def_id(self, def_id))
-                        }
-                        Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
-                            Some(parent_def_id(self, def_id))
-                        }
-                        Res::Def(DefKind::Struct, def_id)
-                        | Res::Def(DefKind::Union, def_id)
-                        | Res::Def(DefKind::Enum, def_id)
-                        | Res::Def(DefKind::TyAlias, def_id)
-                        | Res::Def(DefKind::Trait, def_id)
-                            if i + 1 == proj_start =>
-                        {
-                            Some(def_id)
-                        }
-                        _ => None,
-                    };
-                    let parenthesized_generic_args = match partial_res.base_res() {
-                        // `a::b::Trait(Args)`
-                        Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
-                            ParenthesizedGenericArgs::Ok
-                        }
-                        // `a::b::Trait(Args)::TraitItem`
-                        Res::Def(DefKind::Method, _)
-                        | Res::Def(DefKind::AssocConst, _)
-                        | Res::Def(DefKind::AssocTy, _)
-                            if i + 2 == proj_start =>
-                        {
-                            ParenthesizedGenericArgs::Ok
-                        }
-                        // Avoid duplicated errors.
-                        Res::Err => ParenthesizedGenericArgs::Ok,
-                        // An error
-                        _ => ParenthesizedGenericArgs::Err,
-                    };
-
-                    let num_lifetimes = type_def_id.map_or(0, |def_id| {
-                        if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
-                            return n;
-                        }
-                        assert!(!def_id.is_local());
-                        let item_generics = self
-                            .resolver
-                            .cstore()
-                            .item_generics_cloned_untracked(def_id, self.sess);
-                        let n = item_generics.own_counts().lifetimes;
-                        self.type_def_lifetime_params.insert(def_id, n);
-                        n
-                    });
-                    self.lower_path_segment(
-                        p.span,
-                        segment,
-                        param_mode,
-                        num_lifetimes,
-                        parenthesized_generic_args,
-                        itctx.reborrow(),
-                        None,
-                    )
-                },
-            )),
-            span: p.span,
-        });
-
-        // Simple case, either no projections, or only fully-qualified.
-        // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
-        if partial_res.unresolved_segments() == 0 {
-            return hir::QPath::Resolved(qself, path);
-        }
-
-        // Create the innermost type that we're projecting from.
-        let mut ty = if path.segments.is_empty() {
-            // If the base path is empty that means there exists a
-            // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
-            qself.expect("missing QSelf for <T>::...")
-        } else {
-            // Otherwise, the base path is an implicit `Self` type path,
-            // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
-            // `<I as Iterator>::Item::default`.
-            let new_id = self.next_id();
-            self.arena.alloc(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)))
-        };
-
-        // Anything after the base path are associated "extensions",
-        // out of which all but the last one are associated types,
-        // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
-        // * base path is `std::vec::Vec<T>`
-        // * "extensions" are `IntoIter`, `Item` and `clone`
-        // * type nodes are:
-        //   1. `std::vec::Vec<T>` (created above)
-        //   2. `<std::vec::Vec<T>>::IntoIter`
-        //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
-        // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
-        for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
-            let segment = self.arena.alloc(self.lower_path_segment(
-                p.span,
-                segment,
-                param_mode,
-                0,
-                ParenthesizedGenericArgs::Err,
-                itctx.reborrow(),
-                None,
-            ));
-            let qpath = hir::QPath::TypeRelative(ty, segment);
-
-            // It's finished, return the extension of the right node type.
-            if i == p.segments.len() - 1 {
-                return qpath;
-            }
-
-            // Wrap the associated extension in another type node.
-            let new_id = self.next_id();
-            ty = self.arena.alloc(self.ty_path(new_id, p.span, qpath));
-        }
-
-        // We should've returned in the for loop above.
-        span_bug!(
-            p.span,
-            "lower_qpath: no final extension segment in {}..{}",
-            proj_start,
-            p.segments.len()
-        )
-    }
-
-    fn lower_path_extra(
-        &mut self,
-        res: Res,
-        p: &Path,
-        param_mode: ParamMode,
-        explicit_owner: Option<NodeId>,
-    ) -> &'hir hir::Path<'hir> {
-        self.arena.alloc(hir::Path {
-            res,
-            segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
-                self.lower_path_segment(
-                    p.span,
-                    segment,
-                    param_mode,
-                    0,
-                    ParenthesizedGenericArgs::Err,
-                    ImplTraitContext::disallowed(),
-                    explicit_owner,
-                )
-            })),
-            span: p.span,
-        })
-    }
-
-    fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> &'hir hir::Path<'hir> {
-        let res = self.expect_full_res(id);
-        let res = self.lower_res(res);
-        self.lower_path_extra(res, p, param_mode, None)
-    }
-
-    fn lower_path_segment(
-        &mut self,
-        path_span: Span,
-        segment: &PathSegment,
-        param_mode: ParamMode,
-        expected_lifetimes: usize,
-        parenthesized_generic_args: ParenthesizedGenericArgs,
-        itctx: ImplTraitContext<'_, 'hir>,
-        explicit_owner: Option<NodeId>,
-    ) -> hir::PathSegment<'hir> {
-        let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
-            let msg = "parenthesized type parameters may only be used with a `Fn` trait";
-            match **generic_args {
-                GenericArgs::AngleBracketed(ref data) => {
-                    self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
-                }
-                GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
-                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
-                    ParenthesizedGenericArgs::Err => {
-                        let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
-                        err.span_label(data.span, "only `Fn` traits may use parentheses");
-                        if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
-                            // Do not suggest going from `Trait()` to `Trait<>`
-                            if data.inputs.len() > 0 {
-                                if let Some(split) = snippet.find('(') {
-                                    let trait_name = &snippet[0..split];
-                                    let args = &snippet[split + 1..snippet.len() - 1];
-                                    err.span_suggestion(
-                                        data.span,
-                                        "use angle brackets instead",
-                                        format!("{}<{}>", trait_name, args),
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                }
-                            }
-                        };
-                        err.emit();
-                        (
-                            self.lower_angle_bracketed_parameter_data(
-                                &data.as_angle_bracketed_args(),
-                                param_mode,
-                                itctx,
-                            )
-                            .0,
-                            false,
-                        )
-                    }
-                },
-            }
-        } else {
-            self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx)
-        };
-
-        let has_lifetimes = generic_args.args.iter().any(|arg| match arg {
-            GenericArg::Lifetime(_) => true,
-            _ => false,
-        });
-        let first_generic_span = generic_args
-            .args
-            .iter()
-            .map(|a| a.span())
-            .chain(generic_args.bindings.iter().map(|b| b.span))
-            .next();
-        if !generic_args.parenthesized && !has_lifetimes {
-            generic_args.args = self
-                .elided_path_lifetimes(path_span, expected_lifetimes)
-                .map(|lt| GenericArg::Lifetime(lt))
-                .chain(generic_args.args.into_iter())
-                .collect();
-            if expected_lifetimes > 0 && param_mode == ParamMode::Explicit {
-                let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
-                let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
-                let no_bindings = generic_args.bindings.is_empty();
-                let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings {
-                    // If there are no (non-implicit) generic args or associated type
-                    // bindings, our suggestion includes the angle brackets.
-                    (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion))
-                } else {
-                    // Otherwise (sorry, this is kind of gross) we need to infer the
-                    // place to splice in the `'_, ` from the generics that do exist.
-                    let first_generic_span = first_generic_span
-                        .expect("already checked that non-lifetime args or bindings exist");
-                    (false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion))
-                };
-                match self.anonymous_lifetime_mode {
-                    // In create-parameter mode we error here because we don't want to support
-                    // deprecated impl elision in new features like impl elision and `async fn`,
-                    // both of which work using the `CreateParameter` mode:
-                    //
-                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
-                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
-                    AnonymousLifetimeMode::CreateParameter => {
-                        let mut err = struct_span_err!(
-                            self.sess,
-                            path_span,
-                            E0726,
-                            "implicit elided lifetime not allowed here"
-                        );
-                        crate::lint::builtin::add_elided_lifetime_in_path_suggestion(
-                            &self.sess,
-                            &mut err,
-                            expected_lifetimes,
-                            path_span,
-                            incl_angl_brckt,
-                            insertion_sp,
-                            suggestion,
-                        );
-                        err.emit();
-                    }
-                    AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
-                        self.resolver.lint_buffer().buffer_lint_with_diagnostic(
-                            ELIDED_LIFETIMES_IN_PATHS,
-                            CRATE_NODE_ID,
-                            path_span,
-                            "hidden lifetime parameters in types are deprecated",
-                            builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-                                expected_lifetimes,
-                                path_span,
-                                incl_angl_brckt,
-                                insertion_sp,
-                                suggestion,
-                            ),
-                        );
-                    }
-                }
-            }
-        }
-
-        let res = self.expect_full_res(segment.id);
-        let id = if let Some(owner) = explicit_owner {
-            self.lower_node_id_with_owner(segment.id, owner)
-        } else {
-            self.lower_node_id(segment.id)
-        };
-        debug!(
-            "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
-            segment.ident, segment.id, id,
-        );
-
-        hir::PathSegment {
-            ident: segment.ident,
-            hir_id: Some(id),
-            res: Some(self.lower_res(res)),
-            infer_args,
-            args: if generic_args.is_empty() {
-                None
-            } else {
-                Some(self.arena.alloc(generic_args.into_generic_args(self.arena)))
-            },
-        }
-    }
-
-    fn lower_angle_bracketed_parameter_data(
-        &mut self,
-        data: &AngleBracketedArgs,
-        param_mode: ParamMode,
-        mut itctx: ImplTraitContext<'_, 'hir>,
-    ) -> (GenericArgsCtor<'hir>, bool) {
-        let &AngleBracketedArgs { ref args, ref constraints, .. } = data;
-        let has_non_lt_args = args.iter().any(|arg| match arg {
-            ast::GenericArg::Lifetime(_) => false,
-            ast::GenericArg::Type(_) => true,
-            ast::GenericArg::Const(_) => true,
-        });
-        (
-            GenericArgsCtor {
-                args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
-                bindings: self.arena.alloc_from_iter(
-                    constraints.iter().map(|b| self.lower_assoc_ty_constraint(b, itctx.reborrow())),
-                ),
-                parenthesized: false,
-            },
-            !has_non_lt_args && param_mode == ParamMode::Optional,
-        )
-    }
-
-    fn lower_parenthesized_parameter_data(
-        &mut self,
-        data: &ParenthesizedArgs,
-    ) -> (GenericArgsCtor<'hir>, bool) {
-        // Switch to `PassThrough` mode for anonymous lifetimes; this
-        // means that we permit things like `&Ref<T>`, where `Ref` has
-        // a hidden lifetime parameter. This is needed for backwards
-        // compatibility, even in contexts like an impl header where
-        // we generally don't permit such things (see #51008).
-        self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
-            let &ParenthesizedArgs { ref inputs, ref output, span } = data;
-            let inputs = this.arena.alloc_from_iter(
-                inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
-            );
-            let output_ty = match output {
-                FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
-                FunctionRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
-            };
-            let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
-            let binding = hir::TypeBinding {
-                hir_id: this.next_id(),
-                ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
-                span: output_ty.span,
-                kind: hir::TypeBindingKind::Equality { ty: output_ty },
-            };
-            (
-                GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
-                false,
-            )
-        })
-    }
-
     fn lower_local(&mut self, l: &Local) -> (hir::Local<'hir>, SmallVec<[NodeId; 1]>) {
         let mut ids = SmallVec::<[NodeId; 1]>::new();
         if self.sess.features_untracked().impl_trait_in_bindings {
@@ -2144,12 +1728,14 @@
         } else {
             match decl.output {
                 FunctionRetTy::Ty(ref ty) => match in_band_ty_params {
-                    Some((def_id, _)) if impl_trait_return_allow => {
-                        hir::Return(self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id))))
-                    }
-                    _ => hir::Return(self.lower_ty(ty, ImplTraitContext::disallowed())),
+                    Some((def_id, _)) if impl_trait_return_allow => hir::FunctionRetTy::Return(
+                        self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id))),
+                    ),
+                    _ => hir::FunctionRetTy::Return(
+                        self.lower_ty(ty, ImplTraitContext::disallowed()),
+                    ),
                 },
-                FunctionRetTy::Default(span) => hir::DefaultReturn(span),
+                FunctionRetTy::Default(span) => hir::FunctionRetTy::DefaultReturn(span),
             }
         };
 
@@ -2383,12 +1969,7 @@
         // "<Output = T>"
         let future_params = self.arena.alloc(hir::GenericArgs {
             args: &[],
-            bindings: arena_vec![self; hir::TypeBinding {
-                ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
-                kind: hir::TypeBindingKind::Equality { ty: output_ty },
-                hir_id: self.next_id(),
-                span,
-            }],
+            bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
             parenthesized: false,
         });
 
@@ -2575,6 +2156,10 @@
         p: &PolyTraitRef,
         mut itctx: ImplTraitContext<'_, 'hir>,
     ) -> hir::PolyTraitRef<'hir> {
+        if p.trait_ref.constness.is_some() {
+            self.diagnostic().span_err(p.span, "`?const` on trait bounds is not yet implemented");
+        }
+
         let bound_generic_params = self.lower_generic_params(
             &p.bound_generic_params,
             &NodeMap::default(),
@@ -2644,250 +2229,6 @@
         self.expr_block(block, AttrVec::new())
     }
 
-    fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
-        let node = match p.kind {
-            PatKind::Wild => hir::PatKind::Wild,
-            PatKind::Ident(ref binding_mode, ident, ref sub) => {
-                let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
-                let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
-                node
-            }
-            PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
-            PatKind::TupleStruct(ref path, ref pats) => {
-                let qpath = self.lower_qpath(
-                    p.id,
-                    &None,
-                    path,
-                    ParamMode::Optional,
-                    ImplTraitContext::disallowed(),
-                );
-                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
-                hir::PatKind::TupleStruct(qpath, pats, ddpos)
-            }
-            PatKind::Or(ref pats) => {
-                hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
-            }
-            PatKind::Path(ref qself, ref path) => {
-                let qpath = self.lower_qpath(
-                    p.id,
-                    qself,
-                    path,
-                    ParamMode::Optional,
-                    ImplTraitContext::disallowed(),
-                );
-                hir::PatKind::Path(qpath)
-            }
-            PatKind::Struct(ref path, ref fields, etc) => {
-                let qpath = self.lower_qpath(
-                    p.id,
-                    &None,
-                    path,
-                    ParamMode::Optional,
-                    ImplTraitContext::disallowed(),
-                );
-
-                let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
-                    hir_id: self.next_id(),
-                    ident: f.ident,
-                    pat: self.lower_pat(&f.pat),
-                    is_shorthand: f.is_shorthand,
-                    span: f.span,
-                }));
-                hir::PatKind::Struct(qpath, fs, etc)
-            }
-            PatKind::Tuple(ref pats) => {
-                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
-                hir::PatKind::Tuple(pats, ddpos)
-            }
-            PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
-            PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
-            PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
-                self.lower_expr(e1),
-                self.lower_expr(e2),
-                self.lower_range_end(end),
-            ),
-            PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
-            PatKind::Rest => {
-                // If we reach here the `..` pattern is not semantically allowed.
-                self.ban_illegal_rest_pat(p.span)
-            }
-            PatKind::Paren(ref inner) => return self.lower_pat(inner),
-            PatKind::Mac(_) => panic!("Shouldn't exist here"),
-        };
-
-        self.pat_with_node_id_of(p, node)
-    }
-
-    fn lower_pat_tuple(
-        &mut self,
-        pats: &[AstP<Pat>],
-        ctx: &str,
-    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
-        let mut elems = Vec::with_capacity(pats.len());
-        let mut rest = None;
-
-        let mut iter = pats.iter().enumerate();
-        for (idx, pat) in iter.by_ref() {
-            // Interpret the first `..` pattern as a sub-tuple pattern.
-            // Note that unlike for slice patterns,
-            // where `xs @ ..` is a legal sub-slice pattern,
-            // it is not a legal sub-tuple pattern.
-            if pat.is_rest() {
-                rest = Some((idx, pat.span));
-                break;
-            }
-            // It was not a sub-tuple pattern so lower it normally.
-            elems.push(self.lower_pat(pat));
-        }
-
-        for (_, pat) in iter {
-            // There was a previous sub-tuple pattern; make sure we don't allow more...
-            if pat.is_rest() {
-                // ...but there was one again, so error.
-                self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
-            } else {
-                elems.push(self.lower_pat(pat));
-            }
-        }
-
-        (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
-    }
-
-    /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
-    /// `hir::PatKind::Slice(before, slice, after)`.
-    ///
-    /// When encountering `($binding_mode $ident @)? ..` (`slice`),
-    /// this is interpreted as a sub-slice pattern semantically.
-    /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
-    fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind<'hir> {
-        let mut before = Vec::new();
-        let mut after = Vec::new();
-        let mut slice = None;
-        let mut prev_rest_span = None;
-
-        let mut iter = pats.iter();
-        // Lower all the patterns until the first occurence of a sub-slice pattern.
-        for pat in iter.by_ref() {
-            match pat.kind {
-                // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
-                PatKind::Rest => {
-                    prev_rest_span = Some(pat.span);
-                    slice = Some(self.pat_wild_with_node_id_of(pat));
-                    break;
-                }
-                // Found a sub-slice pattern `$binding_mode $ident @ ..`.
-                // Record, lower it to `$binding_mode $ident @ _`, and stop here.
-                PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
-                    prev_rest_span = Some(sub.span);
-                    let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
-                    let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
-                    slice = Some(self.pat_with_node_id_of(pat, node));
-                    break;
-                }
-                // It was not a subslice pattern so lower it normally.
-                _ => before.push(self.lower_pat(pat)),
-            }
-        }
-
-        // Lower all the patterns after the first sub-slice pattern.
-        for pat in iter {
-            // There was a previous subslice pattern; make sure we don't allow more.
-            let rest_span = match pat.kind {
-                PatKind::Rest => Some(pat.span),
-                PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
-                    // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
-                    after.push(self.pat_wild_with_node_id_of(pat));
-                    Some(sub.span)
-                }
-                _ => None,
-            };
-            if let Some(rest_span) = rest_span {
-                // We have e.g., `[a, .., b, ..]`. That's no good, error!
-                self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
-            } else {
-                // Lower the pattern normally.
-                after.push(self.lower_pat(pat));
-            }
-        }
-
-        hir::PatKind::Slice(
-            self.arena.alloc_from_iter(before),
-            slice,
-            self.arena.alloc_from_iter(after),
-        )
-    }
-
-    fn lower_pat_ident(
-        &mut self,
-        p: &Pat,
-        binding_mode: &BindingMode,
-        ident: Ident,
-        lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
-    ) -> hir::PatKind<'hir> {
-        match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
-            // `None` can occur in body-less function signatures
-            res @ None | res @ Some(Res::Local(_)) => {
-                let canonical_id = match res {
-                    Some(Res::Local(id)) => id,
-                    _ => p.id,
-                };
-
-                hir::PatKind::Binding(
-                    self.lower_binding_mode(binding_mode),
-                    self.lower_node_id(canonical_id),
-                    ident,
-                    lower_sub(self),
-                )
-            }
-            Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
-                None,
-                self.arena.alloc(hir::Path {
-                    span: ident.span,
-                    res: self.lower_res(res),
-                    segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
-                }),
-            )),
-        }
-    }
-
-    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
-        self.pat_with_node_id_of(p, hir::PatKind::Wild)
-    }
-
-    /// Construct a `Pat` with the `HirId` of `p.id` lowered.
-    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
-        self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
-    }
-
-    /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
-    fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
-        self.diagnostic()
-            .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
-            .span_label(sp, &format!("can only be used once per {} pattern", ctx))
-            .span_label(prev_sp, "previously used here")
-            .emit();
-    }
-
-    /// Used to ban the `..` pattern in places it shouldn't be semantically.
-    fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
-        self.diagnostic()
-            .struct_span_err(sp, "`..` patterns are not allowed here")
-            .note("only allowed in tuple, tuple struct, and slice patterns")
-            .emit();
-
-        // We're not in a list context so `..` can be reasonably treated
-        // as `_` because it should always be valid and roughly matches the
-        // intent of `..` (notice that the rest of a single slot is that slot).
-        hir::PatKind::Wild
-    }
-
-    fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
-        match *e {
-            RangeEnd::Included(_) => hir::RangeEnd::Included,
-            RangeEnd::Excluded => hir::RangeEnd::Excluded,
-        }
-    }
-
     fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
         self.with_new_scopes(|this| hir::AnonConst {
             hir_id: this.lower_node_id(c.id),
@@ -2940,24 +2281,17 @@
 
     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
         match *b {
-            BlockCheckMode::Default => hir::DefaultBlock,
-            BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(self.lower_unsafe_source(u)),
-        }
-    }
-
-    fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
-        match *b {
-            BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
-            BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
-            BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
-            BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
+            BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
+            BlockCheckMode::Unsafe(u) => {
+                hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
+            }
         }
     }
 
     fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
         match u {
-            CompilerGenerated => hir::CompilerGenerated,
-            UserProvided => hir::UserProvided,
+            CompilerGenerated => hir::UnsafeSource::CompilerGenerated,
+            UserProvided => hir::UnsafeSource::UserProvided,
         }
     }
 
@@ -3004,7 +2338,7 @@
             stmts,
             expr,
             hir_id: self.next_id(),
-            rules: hir::DefaultBlock,
+            rules: hir::BlockCheckMode::DefaultBlock,
             span,
             targeted_by_break: false,
         };
@@ -3282,7 +2616,7 @@
                 id,
                 span,
                 "trait objects without an explicit `dyn` are deprecated",
-                builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
+                BuiltinLintDiagnostics::BareTraitObject(span, is_global),
             )
         }
     }
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
new file mode 100644
index 0000000..6cf640a
--- /dev/null
+++ b/src/librustc_ast_lowering/pat.rs
@@ -0,0 +1,263 @@
+use super::{ImplTraitContext, LoweringContext, ParamMode};
+
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_span::{source_map::Spanned, Span};
+use syntax::ast::*;
+use syntax::ptr::P;
+
+impl<'a, 'hir> LoweringContext<'a, 'hir> {
+    crate fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
+        let node = match p.kind {
+            PatKind::Wild => hir::PatKind::Wild,
+            PatKind::Ident(ref binding_mode, ident, ref sub) => {
+                let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
+                let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
+                node
+            }
+            PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
+            PatKind::TupleStruct(ref path, ref pats) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    &None,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::disallowed(),
+                );
+                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
+                hir::PatKind::TupleStruct(qpath, pats, ddpos)
+            }
+            PatKind::Or(ref pats) => {
+                hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
+            }
+            PatKind::Path(ref qself, ref path) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    qself,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::disallowed(),
+                );
+                hir::PatKind::Path(qpath)
+            }
+            PatKind::Struct(ref path, ref fields, etc) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    &None,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::disallowed(),
+                );
+
+                let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
+                    hir_id: self.next_id(),
+                    ident: f.ident,
+                    pat: self.lower_pat(&f.pat),
+                    is_shorthand: f.is_shorthand,
+                    span: f.span,
+                }));
+                hir::PatKind::Struct(qpath, fs, etc)
+            }
+            PatKind::Tuple(ref pats) => {
+                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
+                hir::PatKind::Tuple(pats, ddpos)
+            }
+            PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
+            PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
+            PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
+                e1.as_deref().map(|e| self.lower_expr(e)),
+                e2.as_deref().map(|e| self.lower_expr(e)),
+                self.lower_range_end(end, e2.is_some()),
+            ),
+            PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
+            PatKind::Rest => {
+                // If we reach here the `..` pattern is not semantically allowed.
+                self.ban_illegal_rest_pat(p.span)
+            }
+            PatKind::Paren(ref inner) => return self.lower_pat(inner),
+            PatKind::Mac(_) => panic!("Shouldn't exist here"),
+        };
+
+        self.pat_with_node_id_of(p, node)
+    }
+
+    fn lower_pat_tuple(
+        &mut self,
+        pats: &[P<Pat>],
+        ctx: &str,
+    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
+        let mut elems = Vec::with_capacity(pats.len());
+        let mut rest = None;
+
+        let mut iter = pats.iter().enumerate();
+        for (idx, pat) in iter.by_ref() {
+            // Interpret the first `..` pattern as a sub-tuple pattern.
+            // Note that unlike for slice patterns,
+            // where `xs @ ..` is a legal sub-slice pattern,
+            // it is not a legal sub-tuple pattern.
+            if pat.is_rest() {
+                rest = Some((idx, pat.span));
+                break;
+            }
+            // It was not a sub-tuple pattern so lower it normally.
+            elems.push(self.lower_pat(pat));
+        }
+
+        for (_, pat) in iter {
+            // There was a previous sub-tuple pattern; make sure we don't allow more...
+            if pat.is_rest() {
+                // ...but there was one again, so error.
+                self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
+            } else {
+                elems.push(self.lower_pat(pat));
+            }
+        }
+
+        (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
+    }
+
+    /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
+    /// `hir::PatKind::Slice(before, slice, after)`.
+    ///
+    /// When encountering `($binding_mode $ident @)? ..` (`slice`),
+    /// this is interpreted as a sub-slice pattern semantically.
+    /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
+    fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
+        let mut before = Vec::new();
+        let mut after = Vec::new();
+        let mut slice = None;
+        let mut prev_rest_span = None;
+
+        let mut iter = pats.iter();
+        // Lower all the patterns until the first occurence of a sub-slice pattern.
+        for pat in iter.by_ref() {
+            match pat.kind {
+                // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
+                PatKind::Rest => {
+                    prev_rest_span = Some(pat.span);
+                    slice = Some(self.pat_wild_with_node_id_of(pat));
+                    break;
+                }
+                // Found a sub-slice pattern `$binding_mode $ident @ ..`.
+                // Record, lower it to `$binding_mode $ident @ _`, and stop here.
+                PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
+                    prev_rest_span = Some(sub.span);
+                    let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
+                    let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
+                    slice = Some(self.pat_with_node_id_of(pat, node));
+                    break;
+                }
+                // It was not a subslice pattern so lower it normally.
+                _ => before.push(self.lower_pat(pat)),
+            }
+        }
+
+        // Lower all the patterns after the first sub-slice pattern.
+        for pat in iter {
+            // There was a previous subslice pattern; make sure we don't allow more.
+            let rest_span = match pat.kind {
+                PatKind::Rest => Some(pat.span),
+                PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
+                    // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
+                    after.push(self.pat_wild_with_node_id_of(pat));
+                    Some(sub.span)
+                }
+                _ => None,
+            };
+            if let Some(rest_span) = rest_span {
+                // We have e.g., `[a, .., b, ..]`. That's no good, error!
+                self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
+            } else {
+                // Lower the pattern normally.
+                after.push(self.lower_pat(pat));
+            }
+        }
+
+        hir::PatKind::Slice(
+            self.arena.alloc_from_iter(before),
+            slice,
+            self.arena.alloc_from_iter(after),
+        )
+    }
+
+    fn lower_pat_ident(
+        &mut self,
+        p: &Pat,
+        binding_mode: &BindingMode,
+        ident: Ident,
+        lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
+    ) -> hir::PatKind<'hir> {
+        match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
+            // `None` can occur in body-less function signatures
+            res @ None | res @ Some(Res::Local(_)) => {
+                let canonical_id = match res {
+                    Some(Res::Local(id)) => id,
+                    _ => p.id,
+                };
+
+                hir::PatKind::Binding(
+                    self.lower_binding_mode(binding_mode),
+                    self.lower_node_id(canonical_id),
+                    ident,
+                    lower_sub(self),
+                )
+            }
+            Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
+                None,
+                self.arena.alloc(hir::Path {
+                    span: ident.span,
+                    res: self.lower_res(res),
+                    segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
+                }),
+            )),
+        }
+    }
+
+    fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
+        match *b {
+            BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
+            BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
+            BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
+            BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
+        }
+    }
+
+    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
+        self.pat_with_node_id_of(p, hir::PatKind::Wild)
+    }
+
+    /// Construct a `Pat` with the `HirId` of `p.id` lowered.
+    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
+        self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
+    }
+
+    /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
+    fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
+        self.diagnostic()
+            .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
+            .span_label(sp, &format!("can only be used once per {} pattern", ctx))
+            .span_label(prev_sp, "previously used here")
+            .emit();
+    }
+
+    /// Used to ban the `..` pattern in places it shouldn't be semantically.
+    fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
+        self.diagnostic()
+            .struct_span_err(sp, "`..` patterns are not allowed here")
+            .note("only allowed in tuple, tuple struct, and slice patterns")
+            .emit();
+
+        // We're not in a list context so `..` can be reasonably treated
+        // as `_` because it should always be valid and roughly matches the
+        // intent of `..` (notice that the rest of a single slot is that slot).
+        hir::PatKind::Wild
+    }
+
+    fn lower_range_end(&mut self, e: &RangeEnd, has_end: bool) -> hir::RangeEnd {
+        match *e {
+            RangeEnd::Excluded if has_end => hir::RangeEnd::Excluded,
+            // No end; so `X..` behaves like `RangeFrom`.
+            RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included,
+        }
+    }
+}
diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs
new file mode 100644
index 0000000..65347d3
--- /dev/null
+++ b/src/librustc_ast_lowering/path.rs
@@ -0,0 +1,423 @@
+use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
+use super::{GenericArgsCtor, ParenthesizedGenericArgs};
+
+use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
+use rustc::span_bug;
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, Applicability};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, PartialRes, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::GenericArg;
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_span::Span;
+use syntax::ast::{self, *};
+
+use log::debug;
+use smallvec::smallvec;
+
+impl<'a, 'hir> LoweringContext<'a, 'hir> {
+    crate fn lower_qpath(
+        &mut self,
+        id: NodeId,
+        qself: &Option<QSelf>,
+        p: &Path,
+        param_mode: ParamMode,
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::QPath<'hir> {
+        let qself_position = qself.as_ref().map(|q| q.position);
+        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
+
+        let partial_res =
+            self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
+
+        let proj_start = p.segments.len() - partial_res.unresolved_segments();
+        let path = self.arena.alloc(hir::Path {
+            res: self.lower_res(partial_res.base_res()),
+            segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
+                |(i, segment)| {
+                    let param_mode = match (qself_position, param_mode) {
+                        (Some(j), ParamMode::Optional) if i < j => {
+                            // This segment is part of the trait path in a
+                            // qualified path - one of `a`, `b` or `Trait`
+                            // in `<X as a::b::Trait>::T::U::method`.
+                            ParamMode::Explicit
+                        }
+                        _ => param_mode,
+                    };
+
+                    // Figure out if this is a type/trait segment,
+                    // which may need lifetime elision performed.
+                    let parent_def_id = |this: &mut Self, def_id: DefId| DefId {
+                        krate: def_id.krate,
+                        index: this.resolver.def_key(def_id).parent.expect("missing parent"),
+                    };
+                    let type_def_id = match partial_res.base_res() {
+                        Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
+                            Some(parent_def_id(self, def_id))
+                        }
+                        Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
+                            Some(parent_def_id(self, def_id))
+                        }
+                        Res::Def(DefKind::Struct, def_id)
+                        | Res::Def(DefKind::Union, def_id)
+                        | Res::Def(DefKind::Enum, def_id)
+                        | Res::Def(DefKind::TyAlias, def_id)
+                        | Res::Def(DefKind::Trait, def_id)
+                            if i + 1 == proj_start =>
+                        {
+                            Some(def_id)
+                        }
+                        _ => None,
+                    };
+                    let parenthesized_generic_args = match partial_res.base_res() {
+                        // `a::b::Trait(Args)`
+                        Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
+                            ParenthesizedGenericArgs::Ok
+                        }
+                        // `a::b::Trait(Args)::TraitItem`
+                        Res::Def(DefKind::Method, _)
+                        | Res::Def(DefKind::AssocConst, _)
+                        | Res::Def(DefKind::AssocTy, _)
+                            if i + 2 == proj_start =>
+                        {
+                            ParenthesizedGenericArgs::Ok
+                        }
+                        // Avoid duplicated errors.
+                        Res::Err => ParenthesizedGenericArgs::Ok,
+                        // An error
+                        _ => ParenthesizedGenericArgs::Err,
+                    };
+
+                    let num_lifetimes = type_def_id.map_or(0, |def_id| {
+                        if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
+                            return n;
+                        }
+                        assert!(!def_id.is_local());
+                        let n = self.resolver.item_generics_num_lifetimes(def_id, self.sess);
+                        self.type_def_lifetime_params.insert(def_id, n);
+                        n
+                    });
+                    self.lower_path_segment(
+                        p.span,
+                        segment,
+                        param_mode,
+                        num_lifetimes,
+                        parenthesized_generic_args,
+                        itctx.reborrow(),
+                        None,
+                    )
+                },
+            )),
+            span: p.span,
+        });
+
+        // Simple case, either no projections, or only fully-qualified.
+        // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
+        if partial_res.unresolved_segments() == 0 {
+            return hir::QPath::Resolved(qself, path);
+        }
+
+        // Create the innermost type that we're projecting from.
+        let mut ty = if path.segments.is_empty() {
+            // If the base path is empty that means there exists a
+            // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
+            qself.expect("missing QSelf for <T>::...")
+        } else {
+            // Otherwise, the base path is an implicit `Self` type path,
+            // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
+            // `<I as Iterator>::Item::default`.
+            let new_id = self.next_id();
+            self.arena.alloc(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)))
+        };
+
+        // Anything after the base path are associated "extensions",
+        // out of which all but the last one are associated types,
+        // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
+        // * base path is `std::vec::Vec<T>`
+        // * "extensions" are `IntoIter`, `Item` and `clone`
+        // * type nodes are:
+        //   1. `std::vec::Vec<T>` (created above)
+        //   2. `<std::vec::Vec<T>>::IntoIter`
+        //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
+        // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
+        for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
+            let segment = self.arena.alloc(self.lower_path_segment(
+                p.span,
+                segment,
+                param_mode,
+                0,
+                ParenthesizedGenericArgs::Err,
+                itctx.reborrow(),
+                None,
+            ));
+            let qpath = hir::QPath::TypeRelative(ty, segment);
+
+            // It's finished, return the extension of the right node type.
+            if i == p.segments.len() - 1 {
+                return qpath;
+            }
+
+            // Wrap the associated extension in another type node.
+            let new_id = self.next_id();
+            ty = self.arena.alloc(self.ty_path(new_id, p.span, qpath));
+        }
+
+        // We should've returned in the for loop above.
+        span_bug!(
+            p.span,
+            "lower_qpath: no final extension segment in {}..{}",
+            proj_start,
+            p.segments.len()
+        )
+    }
+
+    crate fn lower_path_extra(
+        &mut self,
+        res: Res,
+        p: &Path,
+        param_mode: ParamMode,
+        explicit_owner: Option<NodeId>,
+    ) -> &'hir hir::Path<'hir> {
+        self.arena.alloc(hir::Path {
+            res,
+            segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
+                self.lower_path_segment(
+                    p.span,
+                    segment,
+                    param_mode,
+                    0,
+                    ParenthesizedGenericArgs::Err,
+                    ImplTraitContext::disallowed(),
+                    explicit_owner,
+                )
+            })),
+            span: p.span,
+        })
+    }
+
+    crate fn lower_path(
+        &mut self,
+        id: NodeId,
+        p: &Path,
+        param_mode: ParamMode,
+    ) -> &'hir hir::Path<'hir> {
+        let res = self.expect_full_res(id);
+        let res = self.lower_res(res);
+        self.lower_path_extra(res, p, param_mode, None)
+    }
+
+    crate fn lower_path_segment(
+        &mut self,
+        path_span: Span,
+        segment: &PathSegment,
+        param_mode: ParamMode,
+        expected_lifetimes: usize,
+        parenthesized_generic_args: ParenthesizedGenericArgs,
+        itctx: ImplTraitContext<'_, 'hir>,
+        explicit_owner: Option<NodeId>,
+    ) -> hir::PathSegment<'hir> {
+        let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
+            let msg = "parenthesized type parameters may only be used with a `Fn` trait";
+            match **generic_args {
+                GenericArgs::AngleBracketed(ref data) => {
+                    self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
+                }
+                GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
+                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
+                    ParenthesizedGenericArgs::Err => {
+                        let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
+                        err.span_label(data.span, "only `Fn` traits may use parentheses");
+                        if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
+                            // Do not suggest going from `Trait()` to `Trait<>`
+                            if data.inputs.len() > 0 {
+                                if let Some(split) = snippet.find('(') {
+                                    let trait_name = &snippet[0..split];
+                                    let args = &snippet[split + 1..snippet.len() - 1];
+                                    err.span_suggestion(
+                                        data.span,
+                                        "use angle brackets instead",
+                                        format!("{}<{}>", trait_name, args),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                            }
+                        };
+                        err.emit();
+                        (
+                            self.lower_angle_bracketed_parameter_data(
+                                &data.as_angle_bracketed_args(),
+                                param_mode,
+                                itctx,
+                            )
+                            .0,
+                            false,
+                        )
+                    }
+                },
+            }
+        } else {
+            self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx)
+        };
+
+        let has_lifetimes = generic_args.args.iter().any(|arg| match arg {
+            GenericArg::Lifetime(_) => true,
+            _ => false,
+        });
+        let first_generic_span = generic_args
+            .args
+            .iter()
+            .map(|a| a.span())
+            .chain(generic_args.bindings.iter().map(|b| b.span))
+            .next();
+        if !generic_args.parenthesized && !has_lifetimes {
+            generic_args.args = self
+                .elided_path_lifetimes(path_span, expected_lifetimes)
+                .map(|lt| GenericArg::Lifetime(lt))
+                .chain(generic_args.args.into_iter())
+                .collect();
+            if expected_lifetimes > 0 && param_mode == ParamMode::Explicit {
+                let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
+                let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
+                let no_bindings = generic_args.bindings.is_empty();
+                let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings {
+                    // If there are no (non-implicit) generic args or associated type
+                    // bindings, our suggestion includes the angle brackets.
+                    (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion))
+                } else {
+                    // Otherwise (sorry, this is kind of gross) we need to infer the
+                    // place to splice in the `'_, ` from the generics that do exist.
+                    let first_generic_span = first_generic_span
+                        .expect("already checked that non-lifetime args or bindings exist");
+                    (false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion))
+                };
+                match self.anonymous_lifetime_mode {
+                    // In create-parameter mode we error here because we don't want to support
+                    // deprecated impl elision in new features like impl elision and `async fn`,
+                    // both of which work using the `CreateParameter` mode:
+                    //
+                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
+                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
+                    AnonymousLifetimeMode::CreateParameter => {
+                        let mut err = struct_span_err!(
+                            self.sess,
+                            path_span,
+                            E0726,
+                            "implicit elided lifetime not allowed here"
+                        );
+                        rustc::lint::add_elided_lifetime_in_path_suggestion(
+                            &self.sess,
+                            &mut err,
+                            expected_lifetimes,
+                            path_span,
+                            incl_angl_brckt,
+                            insertion_sp,
+                            suggestion,
+                        );
+                        err.emit();
+                    }
+                    AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
+                        self.resolver.lint_buffer().buffer_lint_with_diagnostic(
+                            ELIDED_LIFETIMES_IN_PATHS,
+                            CRATE_NODE_ID,
+                            path_span,
+                            "hidden lifetime parameters in types are deprecated",
+                            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                                expected_lifetimes,
+                                path_span,
+                                incl_angl_brckt,
+                                insertion_sp,
+                                suggestion,
+                            ),
+                        );
+                    }
+                }
+            }
+        }
+
+        let res = self.expect_full_res(segment.id);
+        let id = if let Some(owner) = explicit_owner {
+            self.lower_node_id_with_owner(segment.id, owner)
+        } else {
+            self.lower_node_id(segment.id)
+        };
+        debug!(
+            "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
+            segment.ident, segment.id, id,
+        );
+
+        hir::PathSegment {
+            ident: segment.ident,
+            hir_id: Some(id),
+            res: Some(self.lower_res(res)),
+            infer_args,
+            args: if generic_args.is_empty() {
+                None
+            } else {
+                Some(self.arena.alloc(generic_args.into_generic_args(self.arena)))
+            },
+        }
+    }
+
+    fn lower_angle_bracketed_parameter_data(
+        &mut self,
+        data: &AngleBracketedArgs,
+        param_mode: ParamMode,
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> (GenericArgsCtor<'hir>, bool) {
+        let &AngleBracketedArgs { ref args, ref constraints, .. } = data;
+        let has_non_lt_args = args.iter().any(|arg| match arg {
+            ast::GenericArg::Lifetime(_) => false,
+            ast::GenericArg::Type(_) => true,
+            ast::GenericArg::Const(_) => true,
+        });
+        (
+            GenericArgsCtor {
+                args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
+                bindings: self.arena.alloc_from_iter(
+                    constraints.iter().map(|b| self.lower_assoc_ty_constraint(b, itctx.reborrow())),
+                ),
+                parenthesized: false,
+            },
+            !has_non_lt_args && param_mode == ParamMode::Optional,
+        )
+    }
+
+    fn lower_parenthesized_parameter_data(
+        &mut self,
+        data: &ParenthesizedArgs,
+    ) -> (GenericArgsCtor<'hir>, bool) {
+        // Switch to `PassThrough` mode for anonymous lifetimes; this
+        // means that we permit things like `&Ref<T>`, where `Ref` has
+        // a hidden lifetime parameter. This is needed for backwards
+        // compatibility, even in contexts like an impl header where
+        // we generally don't permit such things (see #51008).
+        self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
+            let &ParenthesizedArgs { ref inputs, ref output, span } = data;
+            let inputs = this.arena.alloc_from_iter(
+                inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
+            );
+            let output_ty = match output {
+                FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
+                FunctionRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
+            };
+            let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
+            let binding = this.output_ty_binding(output_ty.span, output_ty);
+            (
+                GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
+                false,
+            )
+        })
+    }
+
+    /// An associated type binding `Output = $ty`.
+    crate fn output_ty_binding(
+        &mut self,
+        span: Span,
+        ty: &'hir hir::Ty<'hir>,
+    ) -> hir::TypeBinding<'hir> {
+        let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME);
+        let kind = hir::TypeBindingKind::Equality { ty };
+        hir::TypeBinding { hir_id: self.next_id(), span, ident, kind }
+    }
+}
diff --git a/src/librustc_ast_passes/Cargo.toml b/src/librustc_ast_passes/Cargo.toml
new file mode 100644
index 0000000..2d45e28
--- /dev/null
+++ b/src/librustc_ast_passes/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_ast_passes"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_ast_passes"
+path = "lib.rs"
+
+[dependencies]
+log = "0.4"
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_error_codes = { path = "../librustc_error_codes" }
+rustc_feature = { path = "../librustc_feature" }
+rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
+syntax = { path = "../libsyntax" }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
similarity index 88%
rename from src/librustc_passes/ast_validation.rs
rename to src/librustc_ast_passes/ast_validation.rs
index 038c428..c915b7b 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -6,11 +6,12 @@
 // This pass is supposed to perform only simple checks not requiring name resolution
 // or type checking or some other kind of complex analysis.
 
-use errors::{Applicability, FatalError};
-use rustc::lint;
-use rustc::session::Session;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{struct_span_err, Applicability, FatalError};
 use rustc_parse::validate_attr;
+use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
+use rustc_session::lint::LintBuffer;
+use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -20,10 +21,28 @@
 use syntax::expand::is_proc_macro_attr;
 use syntax::print::pprust;
 use syntax::visit::{self, Visitor};
-use syntax::{span_err, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use rustc_error_codes::*;
 
+/// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
+#[derive(Clone, Copy)]
+enum BoundContext {
+    ImplTrait,
+    TraitBounds,
+    TraitObject,
+}
+
+impl BoundContext {
+    fn description(&self) -> &'static str {
+        match self {
+            Self::ImplTrait => "`impl Trait`",
+            Self::TraitBounds => "supertraits",
+            Self::TraitObject => "trait objects",
+        }
+    }
+}
+
 struct AstValidator<'a> {
     session: &'a Session,
     has_proc_macro_decls: bool,
@@ -33,6 +52,12 @@
     /// e.g., `impl Iterator<Item = impl Debug>`.
     outer_impl_trait: Option<Span>,
 
+    /// Keeps track of the `BoundContext` as we recurse.
+    ///
+    /// This is used to forbid `?const Trait` bounds in, e.g.,
+    /// `impl Iterator<Item = Box<dyn ?const Trait>`.
+    bound_context: Option<BoundContext>,
+
     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
     /// or `Foo::Bar<impl Trait>`
     is_impl_trait_banned: bool,
@@ -41,7 +66,7 @@
     /// certain positions.
     is_assoc_ty_bound_banned: bool,
 
-    lint_buffer: &'a mut lint::LintBuffer,
+    lint_buffer: &'a mut LintBuffer,
 }
 
 impl<'a> AstValidator<'a> {
@@ -59,10 +84,20 @@
 
     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.outer_impl_trait, outer);
-        f(self);
+        if outer.is_some() {
+            self.with_bound_context(BoundContext::ImplTrait, |this| f(this));
+        } else {
+            f(self)
+        }
         self.outer_impl_trait = old;
     }
 
+    fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) {
+        let old = self.bound_context.replace(ctx);
+        f(self);
+        self.bound_context = old;
+    }
+
     fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
         match constraint.kind {
             AssocTyConstraintKind::Equality { .. } => {}
@@ -84,6 +119,9 @@
             TyKind::ImplTrait(..) => {
                 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
             }
+            TyKind::TraitObject(..) => {
+                self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t));
+            }
             TyKind::Path(ref qself, ref path) => {
                 // We allow these:
                 //  - `Option<impl Trait>`
@@ -121,7 +159,7 @@
         }
     }
 
-    fn err_handler(&self) -> &errors::Handler {
+    fn err_handler(&self) -> &rustc_errors::Handler {
         &self.session.diagnostic()
     }
 
@@ -192,6 +230,7 @@
         }
     }
 
+    // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
     fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
         for bound in bounds {
             if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
@@ -371,7 +410,7 @@
 
 fn validate_generics_order<'a>(
     sess: &Session,
-    handler: &errors::Handler,
+    handler: &rustc_errors::Handler,
     generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
     pos: GenericPosition,
     span: Span,
@@ -470,7 +509,13 @@
                 self.check_fn_decl(fn_decl);
             }
             ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
-                span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
+                struct_span_err!(
+                    self.session,
+                    expr.span,
+                    E0472,
+                    "asm! is unsupported on this target"
+                )
+                .emit();
             }
             _ => {}
         }
@@ -498,12 +543,13 @@
                 for bound in bounds {
                     if let GenericBound::Outlives(ref lifetime) = *bound {
                         if any_lifetime_bounds {
-                            span_err!(
+                            struct_span_err!(
                                 self.session,
                                 lifetime.ident.span,
                                 E0226,
                                 "only a single explicit lifetime bound is permitted"
-                            );
+                            )
+                            .emit();
                             break;
                         }
                         any_lifetime_bounds = true;
@@ -575,7 +621,13 @@
                         .emit();
                 }
                 if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
-                    span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
+                    struct_span_err!(
+                        self.session,
+                        item.span,
+                        E0198,
+                        "negative impls cannot be unsafe"
+                    )
+                    .emit();
                 }
                 for impl_item in impl_items {
                     self.invalid_visibility(&impl_item.vis, None);
@@ -591,7 +643,13 @@
                     Some("place qualifiers on individual impl items instead"),
                 );
                 if unsafety == Unsafety::Unsafe {
-                    span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
+                    struct_span_err!(
+                        self.session,
+                        item.span,
+                        E0197,
+                        "inherent impls cannot be unsafe"
+                    )
+                    .emit();
                 }
                 if polarity == ImplPolarity::Negative {
                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
@@ -678,6 +736,18 @@
                     }
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
+
+                // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
+                // context for the supertraits.
+                self.visit_vis(&item.vis);
+                self.visit_ident(item.ident);
+                self.visit_generics(generics);
+                self.with_bound_context(BoundContext::TraitBounds, |this| {
+                    walk_list!(this, visit_param_bound, bounds);
+                });
+                walk_list!(self, visit_trait_item, trait_items);
+                walk_list!(self, visit_attribute, &item.attrs);
+                return;
             }
             ItemKind::Mod(_) => {
                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
@@ -822,14 +892,41 @@
         visit::walk_generic_param(self, param);
     }
 
+    fn visit_param_bound(&mut self, bound: &'a GenericBound) {
+        if let GenericBound::Trait(poly, maybe_bound) = bound {
+            match poly.trait_ref.constness {
+                Some(Constness::NotConst) => {
+                    if *maybe_bound == TraitBoundModifier::Maybe {
+                        self.err_handler()
+                            .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
+                    }
+
+                    if let Some(ctx) = self.bound_context {
+                        let msg = format!("`?const` is not permitted in {}", ctx.description());
+                        self.err_handler().span_err(bound.span(), &msg);
+                    }
+                }
+
+                Some(Constness::Const) => panic!("Parser should reject bare `const` on bounds"),
+                None => {}
+            }
+        }
+
+        visit::walk_param_bound(self, bound)
+    }
+
     fn visit_pat(&mut self, pat: &'a Pat) {
         match pat.kind {
             PatKind::Lit(ref expr) => {
                 self.check_expr_within_pat(expr, false);
             }
             PatKind::Range(ref start, ref end, _) => {
-                self.check_expr_within_pat(start, true);
-                self.check_expr_within_pat(end, true);
+                if let Some(expr) = start {
+                    self.check_expr_within_pat(expr, true);
+                }
+                if let Some(expr) = end {
+                    self.check_expr_within_pat(expr, true);
+                }
             }
             _ => {}
         }
@@ -896,7 +993,7 @@
                 Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
                     if mut_ident {
                         self.lint_buffer.buffer_lint(
-                            lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                            PATTERNS_IN_FNS_WITHOUT_BODY,
                             ti.id,
                             span,
                             "patterns aren't allowed in methods without bodies",
@@ -925,11 +1022,12 @@
     }
 }
 
-pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
+pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
     let mut validator = AstValidator {
         session,
         has_proc_macro_decls: false,
         outer_impl_trait: None,
+        bound_context: None,
         is_impl_trait_banned: false,
         is_assoc_ty_bound_banned: false,
         lint_buffer: lints,
diff --git a/src/libsyntax/feature_gate/check.rs b/src/librustc_ast_passes/feature_gate.rs
similarity index 70%
rename from src/libsyntax/feature_gate/check.rs
rename to src/librustc_ast_passes/feature_gate.rs
index 0e94a72..e6f4535 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -1,51 +1,32 @@
-use crate::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
-use crate::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
-use crate::attr;
-use crate::sess::ParseSess;
-use crate::visit::{self, FnKind, Visitor};
-
-use errors::{Applicability, DiagnosticBuilder, Handler};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_error_codes::*;
-use rustc_feature::{find_feature_issue, GateIssue};
+use rustc_errors::{struct_span_err, Handler};
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
-use rustc_feature::{Feature, Features, State as FeatureState, UnstableFeatures};
-use rustc_feature::{
-    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
-};
-use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_feature::{Features, GateIssue, UnstableFeatures};
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+use syntax::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
+use syntax::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
+use syntax::attr;
+use syntax::sess::{feature_err, feature_err_issue, ParseSess};
+use syntax::visit::{self, FnKind, Visitor};
 
 use log::debug;
 
 macro_rules! gate_feature_fn {
-    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
-        let (cx, has_feature, span, name, explain, level) =
-            (&*$cx, $has_feature, $span, $name, $explain, $level);
+    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
+        let (cx, has_feature, span, name, explain) = (&*$cx, $has_feature, $span, $name, $explain);
         let has_feature: bool = has_feature(&$cx.features);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
         if !has_feature && !span.allows_unstable($name) {
-            leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
-                .emit();
+            feature_err_issue(cx.parse_sess, name, span, GateIssue::Language, explain).emit();
         }
     }};
 }
 
-macro_rules! gate_feature {
+macro_rules! gate_feature_post {
     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
-        gate_feature_fn!(
-            $cx,
-            |x: &Features| x.$feature,
-            $span,
-            sym::$feature,
-            $explain,
-            GateStrength::Hard
-        )
-    };
-    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
-        gate_feature_fn!($cx, |x: &Features| x.$feature, $span, sym::$feature, $explain, $level)
+        gate_feature_fn!($cx, |x: &Features| x.$feature, $span, sym::$feature, $explain)
     };
 }
 
@@ -53,92 +34,11 @@
     PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
 }
 
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum GateStrength {
-    /// A hard error. (Most feature gates should use this.)
-    Hard,
-    /// Only a warning. (Use this only as backwards-compatibility demands.)
-    Soft,
-}
-
-pub fn feature_err<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    explain: &str,
-) -> DiagnosticBuilder<'a> {
-    feature_err_issue(sess, feature, span, GateIssue::Language, explain)
-}
-
-pub fn feature_err_issue<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    issue: GateIssue,
-    explain: &str,
-) -> DiagnosticBuilder<'a> {
-    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
-}
-
-fn leveled_feature_err<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    issue: GateIssue,
-    explain: &str,
-    level: GateStrength,
-) -> DiagnosticBuilder<'a> {
-    let diag = &sess.span_diagnostic;
-
-    let mut err = match level {
-        GateStrength::Hard => {
-            diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658))
-        }
-        GateStrength::Soft => diag.struct_span_warn(span, explain),
-    };
-
-    if let Some(n) = find_feature_issue(feature, issue) {
-        err.note(&format!(
-            "for more information, see https://github.com/rust-lang/rust/issues/{}",
-            n,
-        ));
-    }
-
-    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
-    if sess.unstable_features.is_nightly_build() {
-        err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
-    }
-
-    // If we're on stable and only emitting a "soft" warning, add a note to
-    // clarify that the feature isn't "on" (rather than being on but
-    // warning-worthy).
-    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
-        err.help("a nightly build of the compiler is required to enable this feature");
-    }
-
-    err
-}
-
 struct PostExpansionVisitor<'a> {
     parse_sess: &'a ParseSess,
     features: &'a Features,
 }
 
-macro_rules! gate_feature_post {
-    ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
-        let (cx, span) = ($cx, $span);
-        if !span.allows_unstable(sym::$feature) {
-            gate_feature!(cx, $feature, span, $explain)
-        }
-    }};
-    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
-        let (cx, span) = ($cx, $span);
-        if !span.allows_unstable(sym::$feature) {
-            gate_feature!(cx, $feature, span, $explain, $level)
-        }
-    }};
-}
-
 impl<'a> PostExpansionVisitor<'a> {
     fn check_abi(&self, abi: ast::StrLit) {
         let ast::StrLit { symbol_unescaped, span, .. } = abi;
@@ -330,7 +230,7 @@
             attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
         // Check feature gates for built-in attributes.
         if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info {
-            gate_feature_fn!(self, has_feature, attr.span, name, descr, GateStrength::Hard);
+            gate_feature_fn!(self, has_feature, attr.span, name, descr);
         }
         // Check unstable flavors of the `#[doc]` attribute.
         if attr.check_name(sym::doc) {
@@ -338,7 +238,7 @@
                 macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
                     $(if nested_meta.check_name(sym::$name) {
                         let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental");
-                        gate_feature!(self, $feature, attr.span, msg);
+                        gate_feature_post!(self, $feature, attr.span, msg);
                     })*
                 }}
 
@@ -726,173 +626,6 @@
     }
 }
 
-pub fn get_features(
-    span_handler: &Handler,
-    krate_attrs: &[ast::Attribute],
-    crate_edition: Edition,
-    allow_features: &Option<Vec<String>>,
-) -> Features {
-    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
-        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
-        err.span_label(span, "feature has been removed");
-        if let Some(reason) = reason {
-            err.note(reason);
-        }
-        err.emit();
-    }
-
-    let mut features = Features::default();
-    let mut edition_enabled_features = FxHashMap::default();
-
-    for &edition in ALL_EDITIONS {
-        if edition <= crate_edition {
-            // The `crate_edition` implies its respective umbrella feature-gate
-            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
-            edition_enabled_features.insert(edition.feature_name(), edition);
-        }
-    }
-
-    for feature in active_features_up_to(crate_edition) {
-        feature.set(&mut features, DUMMY_SP);
-        edition_enabled_features.insert(feature.name, crate_edition);
-    }
-
-    // Process the edition umbrella feature-gates first, to ensure
-    // `edition_enabled_features` is completed before it's queried.
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        for mi in list {
-            if !mi.is_word() {
-                continue;
-            }
-
-            let name = mi.name_or_empty();
-
-            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
-            if let Some(edition) = edition {
-                if edition <= crate_edition {
-                    continue;
-                }
-
-                for feature in active_features_up_to(edition) {
-                    // FIXME(Manishearth) there is currently no way to set
-                    // lib features by edition
-                    feature.set(&mut features, DUMMY_SP);
-                    edition_enabled_features.insert(feature.name, edition);
-                }
-            }
-        }
-    }
-
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        let bad_input = |span| {
-            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
-        };
-
-        for mi in list {
-            let name = match mi.ident() {
-                Some(ident) if mi.is_word() => ident.name,
-                Some(ident) => {
-                    bad_input(mi.span())
-                        .span_suggestion(
-                            mi.span(),
-                            "expected just one word",
-                            format!("{}", ident.name),
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
-                    continue;
-                }
-                None => {
-                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
-                    continue;
-                }
-            };
-
-            if let Some(edition) = edition_enabled_features.get(&name) {
-                struct_span_warn!(
-                    span_handler,
-                    mi.span(),
-                    E0705,
-                    "the feature `{}` is included in the Rust {} edition",
-                    name,
-                    edition,
-                )
-                .emit();
-                continue;
-            }
-
-            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
-                // Handled in the separate loop above.
-                continue;
-            }
-
-            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
-            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
-            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
-                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
-                    state
-                {
-                    feature_removed(span_handler, mi.span(), *reason);
-                    continue;
-                }
-            }
-
-            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
-                let since = Some(Symbol::intern(since));
-                features.declared_lang_features.push((name, mi.span(), since));
-                continue;
-            }
-
-            if let Some(allowed) = allow_features.as_ref() {
-                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
-                    span_err!(
-                        span_handler,
-                        mi.span(),
-                        E0725,
-                        "the feature `{}` is not in the list of allowed features",
-                        name
-                    );
-                    continue;
-                }
-            }
-
-            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
-                f.set(&mut features, mi.span());
-                features.declared_lang_features.push((name, mi.span(), None));
-                continue;
-            }
-
-            features.declared_lib_features.push((name, mi.span()));
-        }
-    }
-
-    features
-}
-
-fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
-    ACTIVE_FEATURES.iter().filter(move |feature| {
-        if let Some(feature_edition) = feature.edition { feature_edition <= edition } else { false }
-    })
-}
-
 pub fn check_crate(
     krate: &ast::Crate,
     parse_sess: &ParseSess,
@@ -906,7 +639,7 @@
     macro_rules! gate_all {
         ($gate:ident, $msg:literal) => {
             for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
-                gate_feature!(&visitor, $gate, *span, $msg);
+                gate_feature_post!(&visitor, $gate, *span, $msg);
             }
         };
     }
@@ -916,6 +649,9 @@
     gate_all!(or_patterns, "or-patterns syntax is experimental");
     gate_all!(const_extern_fn, "`const extern fn` definitions are unstable");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
+    gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
+    gate_all!(const_trait_impl, "const trait impls are experimental");
+    gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
@@ -925,7 +661,7 @@
             // disabling these uses of early feature-gatings.
             if false {
                 for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
-                    gate_feature!(&visitor, $gate, *span, $msg);
+                    gate_feature_post!(&visitor, $gate, *span, $msg);
                 }
             }
         };
@@ -953,13 +689,14 @@
 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) {
     if !unstable.is_nightly_build() {
         for attr in krate.attrs.iter().filter(|attr| attr.check_name(sym::feature)) {
-            span_err!(
+            struct_span_err!(
                 span_handler,
                 attr.span,
                 E0554,
                 "`#![feature]` may not be used on the {} release channel",
                 option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
-            );
+            )
+            .emit();
         }
     }
 }
diff --git a/src/librustc_ast_passes/lib.rs b/src/librustc_ast_passes/lib.rs
new file mode 100644
index 0000000..eadbc48
--- /dev/null
+++ b/src/librustc_ast_passes/lib.rs
@@ -0,0 +1,9 @@
+//! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
+//! parsed by `rustc_parse` and then lowered, after the passes in this crate,
+//! by `rustc_ast_lowering`.
+
+#![feature(slice_patterns)]
+
+pub mod ast_validation;
+pub mod feature_gate;
+pub mod show_span;
diff --git a/src/libsyntax/show_span.rs b/src/librustc_ast_passes/show_span.rs
similarity index 88%
rename from src/libsyntax/show_span.rs
rename to src/librustc_ast_passes/show_span.rs
index fb64123..4596e8f 100644
--- a/src/libsyntax/show_span.rs
+++ b/src/librustc_ast_passes/show_span.rs
@@ -5,9 +5,9 @@
 
 use std::str::FromStr;
 
-use crate::ast;
-use crate::visit;
-use crate::visit::Visitor;
+use syntax::ast;
+use syntax::visit;
+use syntax::visit::Visitor;
 
 enum Mode {
     Expression,
@@ -29,7 +29,7 @@
 }
 
 struct ShowSpanVisitor<'a> {
-    span_diagnostic: &'a errors::Handler,
+    span_diagnostic: &'a rustc_errors::Handler,
     mode: Mode,
 }
 
@@ -60,7 +60,7 @@
     }
 }
 
-pub fn run(span_diagnostic: &errors::Handler, mode: &str, krate: &ast::Crate) {
+pub fn run(span_diagnostic: &rustc_errors::Handler, mode: &str, krate: &ast::Crate) {
     let mode = match mode.parse().ok() {
         Some(mode) => mode,
         None => return,
diff --git a/src/librustc_builtin_macros/Cargo.toml b/src/librustc_builtin_macros/Cargo.toml
index f56cc93..f291eaf 100644
--- a/src/librustc_builtin_macros/Cargo.toml
+++ b/src/librustc_builtin_macros/Cargo.toml
@@ -10,13 +10,14 @@
 doctest = false
 
 [dependencies]
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 fmt_macros = { path = "../libfmt_macros" }
 log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_parse = { path = "../librustc_parse" }
 rustc_target = { path = "../librustc_target" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
 rustc_expand = { path = "../librustc_expand" }
diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index a136a07..a6b45e0 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -2,7 +2,7 @@
 //
 use State::*;
 
-use errors::{DiagnosticBuilder, PResult};
+use rustc_errors::{struct_span_err, DiagnosticBuilder, PResult};
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -11,7 +11,6 @@
 use syntax::ptr::P;
 use syntax::token::{self, Token};
 use syntax::tokenstream::{self, TokenStream};
-use syntax::{span_err, struct_span_err};
 
 use rustc_error_codes::*;
 
@@ -173,12 +172,13 @@
                         Some('=') => None,
                         Some('+') => Some(Symbol::intern(&format!("={}", ch.as_str()))),
                         _ => {
-                            span_err!(
-                                cx,
+                            struct_span_err!(
+                                cx.parse_sess.span_diagnostic,
                                 span,
                                 E0661,
                                 "output operand constraint lacks '=' or '+'"
-                            );
+                            )
+                            .emit();
                             None
                         }
                     };
@@ -202,9 +202,21 @@
                     let constraint = parse_asm_str(&mut p)?;
 
                     if constraint.as_str().starts_with("=") {
-                        span_err!(cx, p.prev_span, E0662, "input operand constraint contains '='");
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
+                            p.prev_span,
+                            E0662,
+                            "input operand constraint contains '='"
+                        )
+                        .emit();
                     } else if constraint.as_str().starts_with("+") {
-                        span_err!(cx, p.prev_span, E0663, "input operand constraint contains '+'");
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
+                            p.prev_span,
+                            E0663,
+                            "input operand constraint contains '+'"
+                        )
+                        .emit();
                     }
 
                     p.expect(&token::OpenDelim(token::Paren))?;
@@ -225,12 +237,13 @@
                     if OPTIONS.iter().any(|&opt| s == opt) {
                         cx.span_warn(p.prev_span, "expected a clobber, found an option");
                     } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") {
-                        span_err!(
-                            cx,
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
                             p.prev_span,
                             E0664,
                             "clobber should not be surrounded by braces"
-                        );
+                        )
+                        .emit();
                     }
 
                     clobs.push(s);
diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs
index 9043db4..a992b6e 100644
--- a/src/librustc_builtin_macros/assert.rs
+++ b/src/librustc_builtin_macros/assert.rs
@@ -1,4 +1,4 @@
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
@@ -106,7 +106,7 @@
     let custom_message =
         if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
             let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal");
-            let comma_span = cx.source_map().next_point(parser.prev_span);
+            let comma_span = parser.prev_span.shrink_to_hi();
             err.span_suggestion_short(
                 comma_span,
                 "try adding a comma",
diff --git a/src/librustc_builtin_macros/cfg.rs b/src/librustc_builtin_macros/cfg.rs
index 62a4dc0..cee62a5 100644
--- a/src/librustc_builtin_macros/cfg.rs
+++ b/src/librustc_builtin_macros/cfg.rs
@@ -1,8 +1,8 @@
-/// The compiler code necessary to support the cfg! extension, which expands to
-/// a literal `true` or `false` based on whether the given cfg matches the
-/// current compilation environment.
-use errors::DiagnosticBuilder;
+//! The compiler code necessary to support the cfg! extension, which expands to
+//! a literal `true` or `false` based on whether the given cfg matches the
+//! current compilation environment.
 
+use rustc_errors::DiagnosticBuilder;
 use rustc_expand::base::{self, *};
 use rustc_span::Span;
 use syntax::ast;
diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs
index f40d6d7..72c41ad 100644
--- a/src/librustc_builtin_macros/deriving/default.rs
+++ b/src/librustc_builtin_macros/deriving/default.rs
@@ -2,12 +2,12 @@
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
+use rustc_errors::struct_span_err;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use syntax::ast::{Expr, MetaItem};
 use syntax::ptr::P;
-use syntax::span_err;
 
 use rustc_error_codes::*;
 
@@ -74,7 +74,13 @@
             }
         },
         StaticEnum(..) => {
-            span_err!(cx, trait_span, E0665, "`Default` cannot be derived for enums, only structs");
+            struct_span_err!(
+                cx.parse_sess.span_diagnostic,
+                trait_span,
+                E0665,
+                "`Default` cannot be derived for enums, only structs"
+            )
+            .emit();
             // let compilation continue
             DummyResult::raw_expr(trait_span, true)
         }
diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs
index e2662fa..6fca74e 100644
--- a/src/librustc_builtin_macros/format.rs
+++ b/src/librustc_builtin_macros/format.rs
@@ -3,10 +3,8 @@
 
 use fmt_macros as parse;
 
-use errors::pluralize;
-use errors::Applicability;
-use errors::DiagnosticBuilder;
-
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
 use rustc_expand::base::{self, *};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
@@ -15,7 +13,6 @@
 use syntax::token;
 use syntax::tokenstream::TokenStream;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 
diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs
index 2bcd76e..052e62e 100644
--- a/src/librustc_builtin_macros/global_asm.rs
+++ b/src/librustc_builtin_macros/global_asm.rs
@@ -1,14 +1,14 @@
-/// Module-level assembly support.
-///
-/// The macro defined here allows you to specify "top-level",
-/// "file-scoped", or "module-level" assembly. These synonyms
-/// all correspond to LLVM's module-level inline assembly instruction.
-///
-/// For example, `global_asm!("some assembly here")` codegens to
-/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
-/// therefore apply.
-use errors::DiagnosticBuilder;
+//! Module-level assembly support.
+//!
+//! The macro defined here allows you to specify "top-level",
+//! "file-scoped", or "module-level" assembly. These synonyms
+//! all correspond to LLVM's module-level inline assembly instruction.
+//!
+//! For example, `global_asm!("some assembly here")` codegens to
+//! LLVM's `module asm "some assembly here"`. All of LLVM's caveats
+//! therefore apply.
 
+use rustc_errors::DiagnosticBuilder;
 use rustc_expand::base::{self, *};
 use rustc_span::source_map::respan;
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs
index 44968d6..ae70608 100644
--- a/src/librustc_builtin_macros/proc_macro_harness.rs
+++ b/src/librustc_builtin_macros/proc_macro_harness.rs
@@ -40,7 +40,7 @@
 struct CollectProcMacros<'a> {
     macros: Vec<ProcMacro>,
     in_root: bool,
-    handler: &'a errors::Handler,
+    handler: &'a rustc_errors::Handler,
     is_proc_macro_crate: bool,
     is_test_crate: bool,
 }
@@ -53,7 +53,7 @@
     has_proc_macro_decls: bool,
     is_test_crate: bool,
     num_crate_types: usize,
-    handler: &errors::Handler,
+    handler: &rustc_errors::Handler,
 ) -> ast::Crate {
     let ecfg = ExpansionConfig::default("proc_macro".to_string());
     let mut cx = ExtCtxt::new(sess, ecfg, resolver);
diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs
index 19a766d..dc85a92 100644
--- a/src/librustc_builtin_macros/source_util.rs
+++ b/src/librustc_builtin_macros/source_util.rs
@@ -1,15 +1,15 @@
 use rustc_expand::base::{self, *};
 use rustc_expand::panictry;
 use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
+use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::symbol::Symbol;
+use rustc_span::{self, Pos, Span};
 use syntax::ast;
-use syntax::early_buffered_lints::INCOMPLETE_INCLUDE;
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::token;
 use syntax::tokenstream::TokenStream;
 
-use rustc_span::{self, Pos, Span};
 use smallvec::SmallVec;
 
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index eddf492..17d180d 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -40,7 +40,7 @@
     resolver: &mut dyn Resolver,
     should_test: bool,
     krate: &mut ast::Crate,
-    span_diagnostic: &errors::Handler,
+    span_diagnostic: &rustc_errors::Handler,
     features: &Features,
     panic_strategy: PanicStrategy,
     platform_panic_strategy: PanicStrategy,
@@ -351,7 +351,7 @@
     attr::contains_name(&i.attrs, sym::rustc_test_marker)
 }
 
-fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
+fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
     let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?;
     test_attr.meta_item_list().map(|meta_list| {
         if meta_list.len() != 1 {
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index ec4967e..3ff5495 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -23,6 +23,7 @@
 rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_fs_util = { path = "../librustc_fs_util" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_index = { path = "../librustc_index" }
 rustc_llvm = { path = "../librustc_llvm" }
@@ -30,5 +31,4 @@
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
-rustc_expand = { path = "../librustc_expand" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index 14e2009..e816bde 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -4,10 +4,10 @@
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 
-use rustc::hir;
 use rustc_codegen_ssa::mir::operand::OperandValue;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
+use rustc_hir as hir;
 use rustc_span::Span;
 
 use libc::{c_char, c_uint};
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index a782628..4ed4e8a 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -2,7 +2,6 @@
 
 use std::ffi::CString;
 
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::session::config::{OptLevel, Sanitizer};
 use rustc::session::Session;
@@ -13,6 +12,7 @@
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_target::abi::call::Conv;
 use rustc_target::spec::PanicStrategy;
 
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index ca95a31..b5895b5 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -8,7 +8,6 @@
 use log::{debug, info};
 use rustc::bug;
 use rustc::dep_graph::WorkProduct;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::session::config::{self, Lto};
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
@@ -18,6 +17,7 @@
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, RLIB_BYTECODE_EXTENSION};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{FatalError, Handler};
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_session::cgu_reuse_tracker::CguReuse;
 
 use std::ffi::{CStr, CString};
@@ -120,12 +120,13 @@
                 info!("adding bytecode {}", name);
                 let bc_encoded = data.data();
 
-                let (bc, id) = cgcx.prof.generic_pass(&format!("decode {}", name)).run(|| {
-                    match DecodedBytecode::new(bc_encoded) {
+                let (bc, id) = cgcx
+                    .prof
+                    .extra_verbose_generic_activity(&format!("decode {}", name))
+                    .run(|| match DecodedBytecode::new(bc_encoded) {
                         Ok(b) => Ok((b.bytecode(), b.identifier().to_string())),
                         Err(e) => Err(diag_handler.fatal(&e)),
-                    }
-                })?;
+                    })?;
                 let bc = SerializedModule::FromRlib(bc);
                 upstream_modules.push((bc, CString::new(id).unwrap()));
             }
@@ -280,8 +281,9 @@
         // save and persist everything with the original module.
         let mut linker = Linker::new(llmod);
         for (bc_decoded, name) in serialized_modules {
+            let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_link_module");
             info!("linking {:?}", name);
-            cgcx.prof.generic_pass(&format!("ll link {:?}", name)).run(|| {
+            cgcx.prof.extra_verbose_generic_activity(&format!("ll link {:?}", name)).run(|| {
                 let data = bc_decoded.data();
                 linker.add(&data).map_err(|()| {
                     let msg = format!("failed to load bc of {:?}", name);
@@ -633,7 +635,7 @@
         }
 
         cgcx.prof
-            .generic_pass("LTO passes")
+            .extra_verbose_generic_activity("LTO_passes")
             .run(|| llvm::LLVMRunPassManager(pm, module.module_llvm.llmod()));
 
         llvm::LLVMDisposePassManager(pm);
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index fa4d8a8..4be7b84 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -12,7 +12,6 @@
 use crate::ModuleLlvm;
 use log::debug;
 use rustc::bug;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
@@ -22,6 +21,7 @@
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_errors::{FatalError, Handler};
 use rustc_fs_util::{link_or_copy, path_to_c_string};
+use rustc_hir::def_id::LOCAL_CRATE;
 
 use libc::{c_char, c_int, c_uint, c_void, size_t};
 use std::ffi::CString;
@@ -424,13 +424,23 @@
 
         // Finally, run the actual optimization passes
         {
+            let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_function_passes");
             let desc = &format!("llvm function passes [{}]", module_name.unwrap());
-            let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None };
+            let _timer = if config.time_module {
+                Some(cgcx.prof.extra_verbose_generic_activity(desc))
+            } else {
+                None
+            };
             llvm::LLVMRustRunFunctionPassManager(fpm, llmod);
         }
         {
+            let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_module_passes");
             let desc = &format!("llvm module passes [{}]", module_name.unwrap());
-            let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None };
+            let _timer = if config.time_module {
+                Some(cgcx.prof.extra_verbose_generic_activity(desc))
+            } else {
+                None
+            };
             llvm::LLVMRunPassManager(mpm, llmod);
         }
 
@@ -556,7 +566,11 @@
 
         {
             let desc = &format!("codegen passes [{}]", module_name.unwrap());
-            let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None };
+            let _timer = if config.time_module {
+                Some(cgcx.prof.extra_verbose_generic_activity(desc))
+            } else {
+                None
+            };
 
             if config.emit_ir {
                 let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_ir");
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index cb44a56..d3b524c 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -13,7 +13,7 @@
 //!   but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int,
 //!   int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.
 
-use super::{LlvmCodegenBackend, ModuleLlvm};
+use super::ModuleLlvm;
 
 use crate::builder::Builder;
 use crate::common;
@@ -29,7 +29,6 @@
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::session::config::DebugInfo;
 use rustc::ty::TyCtxt;
-use rustc_codegen_ssa::back::write::submit_codegened_module_to_llvm;
 use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
 use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::*;
@@ -100,8 +99,7 @@
 pub fn compile_codegen_unit(
     tcx: TyCtxt<'tcx>,
     cgu_name: Symbol,
-    tx_to_llvm_workers: &std::sync::mpsc::Sender<Box<dyn std::any::Any + Send>>,
-) {
+) -> (ModuleCodegen<ModuleLlvm>, u64) {
     let prof_timer = tcx.prof.generic_activity("codegen_module");
     let start_time = Instant::now();
 
@@ -115,8 +113,6 @@
     // the time we needed for codegenning it.
     let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
 
-    submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tx_to_llvm_workers, module, cost);
-
     fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
         let cgu = tcx.codegen_unit(cgu_name);
         // Instantiate monomorphizations without filling out definitions yet...
@@ -164,6 +160,8 @@
             kind: ModuleKind::Regular,
         }
     }
+
+    (module, cost)
 }
 
 pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 8bf2383..357b0b6 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -7,7 +7,6 @@
 use crate::value::Value;
 use libc::{c_char, c_uint};
 use log::debug;
-use rustc::hir::def_id::DefId;
 use rustc::session::config;
 use rustc::ty::layout::{self, Align, Size, TyLayout};
 use rustc::ty::{self, Ty, TyCtxt};
@@ -19,6 +18,7 @@
 use rustc_codegen_ssa::MemFlags;
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::def_id::DefId;
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
 use std::ffi::CStr;
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index bccf3f5..38090cb 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -7,8 +7,6 @@
 use crate::value::Value;
 use libc::c_uint;
 use log::debug;
-use rustc::hir::def_id::DefId;
-use rustc::hir::{self, Node};
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::interpret::{read_target_uint, Allocation, ConstValue, ErrorHandled, Pointer};
 use rustc::mir::mono::MonoItem;
@@ -16,6 +14,9 @@
 use rustc::ty::{self, Instance, Ty};
 use rustc::{bug, span_bug};
 use rustc_codegen_ssa::traits::*;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::Node;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::HasDataLayout;
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 746b76a..50a35fe 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -5,7 +5,6 @@
 use crate::llvm_util;
 use crate::value::Value;
 use rustc::dep_graph::DepGraphSafe;
-use rustc::hir;
 
 use crate::type_::Type;
 use rustc_codegen_ssa::traits::*;
@@ -24,6 +23,7 @@
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::Unsafety;
 use rustc_target::spec::{HasTargetSpec, Target};
 
 use crate::abi::Abi;
@@ -143,6 +143,10 @@
     data_layout.replace("-Fi8-", "-")
 }
 
+fn strip_x86_address_spaces(data_layout: String) -> String {
+    data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-")
+}
+
 pub unsafe fn create_module(
     tcx: TyCtxt<'_>,
     llcx: &'ll llvm::Context,
@@ -156,6 +160,11 @@
     if llvm_util::get_major_version() < 9 {
         target_data_layout = strip_function_ptr_alignment(target_data_layout);
     }
+    if llvm_util::get_major_version() < 10 {
+        if sess.target.target.arch == "x86" || sess.target.target.arch == "x86_64" {
+            target_data_layout = strip_x86_address_spaces(target_data_layout);
+        }
+    }
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
@@ -415,7 +424,7 @@
             iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
             tcx.types.never,
             false,
-            hir::Unsafety::Unsafe,
+            Unsafety::Unsafe,
             Abi::C,
         ));
 
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index a1e81c1..d1f70ad 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -20,8 +20,6 @@
 use crate::value::Value;
 
 use log::debug;
-use rustc::hir::def::CtorKind;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::ich::NodeIdHashingMode;
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::interpret::truncate;
@@ -41,6 +39,8 @@
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_fs_util::path_to_c_string;
+use rustc_hir::def::CtorKind;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::symbol::{Interner, Symbol};
 use rustc_span::{self, FileName, Span};
@@ -1286,9 +1286,9 @@
     let generator_layout = body.generator_layout.as_ref().unwrap();
     let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
 
-    let state_arg = mir::PlaceBase::Local(mir::Local::new(1));
+    let state_arg = mir::Local::new(1);
     for var in &body.var_debug_info {
-        if var.place.base != state_arg {
+        if var.place.local != state_arg {
             continue;
         }
         match var.place.projection[..] {
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 0edfd34..0462dcf 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -13,9 +13,9 @@
 use crate::llvm::debuginfo::{
     DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DISPFlags, DIScope, DIType,
 };
-use rustc::hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 
 use crate::abi::FnAbi;
 use crate::builder::Builder;
diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs
index 77b47ef..582f495 100644
--- a/src/librustc_codegen_llvm/debuginfo/namespace.rs
+++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs
@@ -7,8 +7,8 @@
 use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::DIScope;
-use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
+use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::small_c_str::SmallCStr;
 
diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs
index 53497e3..4e17387 100644
--- a/src/librustc_codegen_llvm/debuginfo/utils.rs
+++ b/src/librustc_codegen_llvm/debuginfo/utils.rs
@@ -3,8 +3,8 @@
 use super::namespace::item_namespace;
 use super::CrateDebugContext;
 
-use rustc::hir::def_id::DefId;
 use rustc::ty::DefIdTree;
+use rustc_hir::def_id::DefId;
 
 use crate::common::CodegenCx;
 use crate::llvm;
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 1c71463..8ea50a9 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -7,7 +7,6 @@
 use crate::type_of::LayoutLlvmExt;
 use crate::va_arg::emit_va_arg;
 use crate::value::Value;
-use rustc::hir;
 use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf, Primitive};
 use rustc::ty::{self, Ty};
 use rustc::{bug, span_bug};
@@ -17,6 +16,7 @@
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::MemFlags;
+use rustc_hir as hir;
 use rustc_target::abi::HasDataLayout;
 use syntax::ast;
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 349cff7..a616812 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -19,6 +19,7 @@
 #![feature(link_args)]
 #![feature(static_nobundle)]
 #![feature(trusted_len)]
+#![recursion_limit = "256"]
 
 use back::write::{create_informational_target_machine, create_target_machine};
 use rustc_span::symbol::Symbol;
@@ -108,9 +109,8 @@
         &self,
         tcx: TyCtxt<'_>,
         cgu_name: Symbol,
-        tx: &std::sync::mpsc::Sender<Box<dyn Any + Send>>,
-    ) {
-        base::compile_codegen_unit(tcx, cgu_name, tx);
+    ) -> (ModuleCodegen<ModuleLlvm>, u64) {
+        base::compile_codegen_unit(tcx, cgu_name)
     }
     fn target_machine_factory(
         &self,
@@ -283,7 +283,7 @@
             rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results);
         }
 
-        sess.time("serialize work products", move || {
+        sess.time("serialize_work_products", move || {
             rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
         });
 
@@ -300,7 +300,7 @@
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
-        sess.time("linking", || {
+        sess.time("link_crate", || {
             use crate::back::archive::LlvmArchiveBuilder;
             use rustc_codegen_ssa::back::link::link_binary;
 
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index b3c58b2..52613fe 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -46,7 +46,7 @@
 }
 
 unsafe fn configure_llvm(sess: &Session) {
-    let n_args = sess.opts.cg.llvm_args.len();
+    let n_args = sess.opts.cg.llvm_args.len() + sess.target.target.options.llvm_args.len();
     let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
     let mut llvm_args = Vec::with_capacity(n_args + 1);
 
@@ -56,14 +56,11 @@
         full_arg.trim().split(|c: char| c == '=' || c.is_whitespace()).next().unwrap_or("")
     }
 
-    let user_specified_args: FxHashSet<_> = sess
-        .opts
-        .cg
-        .llvm_args
-        .iter()
-        .map(|s| llvm_arg_to_arg_name(s))
-        .filter(|s| s.len() > 0)
-        .collect();
+    let cg_opts = sess.opts.cg.llvm_args.iter();
+    let tg_opts = sess.target.target.options.llvm_args.iter();
+
+    let user_specified_args: FxHashSet<_> =
+        cg_opts.chain(tg_opts).map(|s| llvm_arg_to_arg_name(s)).filter(|s| s.len() > 0).collect();
 
     {
         // This adds the given argument to LLVM. Unless `force` is true
diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs
index 681bc1f..97393e6 100644
--- a/src/librustc_codegen_llvm/mono_item.rs
+++ b/src/librustc_codegen_llvm/mono_item.rs
@@ -5,11 +5,11 @@
 use crate::llvm;
 use crate::type_of::LayoutLlvmExt;
 use log::debug;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::ty::layout::{FnAbiExt, LayoutOf};
 use rustc::ty::{Instance, TypeFoldable};
 use rustc_codegen_ssa::traits::*;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 
 pub use rustc::mir::mono::MonoItem;
 
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index 7eb1ae2..eb192b2 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -28,6 +28,7 @@
 rustc_data_structures = { path = "../librustc_data_structures"}
 rustc_errors = { path = "../librustc_errors" }
 rustc_fs_util = { path = "../librustc_fs_util" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_index = { path = "../librustc_index" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 2151c05..53ee599 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -1,4 +1,3 @@
-use rustc::hir::def_id::CrateNum;
 use rustc::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind};
 use rustc::middle::dependency_format::Linkage;
 use rustc::session::config::{
@@ -10,6 +9,7 @@
 use rustc::session::{filesearch, Session};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
+use rustc_hir::def_id::CrateNum;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
 
@@ -53,6 +53,7 @@
     crate_name: &str,
     target_cpu: &str,
 ) {
+    let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-codegen, as they will error.
@@ -71,9 +72,11 @@
             );
         }
 
-        for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
-            check_file_is_writeable(obj, sess);
-        }
+        sess.time("link_binary_check_files_are_writeable", || {
+            for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+                check_file_is_writeable(obj, sess);
+            }
+        });
 
         let tmpdir = TempFileBuilder::new()
             .prefix("rustc")
@@ -84,6 +87,7 @@
             let out_filename = out_filename(sess, crate_type, outputs, crate_name);
             match crate_type {
                 config::CrateType::Rlib => {
+                    let _timer = sess.timer("link_rlib");
                     link_rlib::<B>(
                         sess,
                         codegen_results,
@@ -118,29 +122,34 @@
     }
 
     // Remove the temporary object file and metadata if we aren't saving temps
-    if !sess.opts.cg.save_temps {
-        if sess.opts.output_types.should_codegen() && !preserve_objects_for_their_debuginfo(sess) {
-            for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+    sess.time("link_binary_remove_temps", || {
+        if !sess.opts.cg.save_temps {
+            if sess.opts.output_types.should_codegen()
+                && !preserve_objects_for_their_debuginfo(sess)
+            {
+                for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+                    remove(sess, obj);
+                }
+            }
+            for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref())
+            {
                 remove(sess, obj);
             }
-        }
-        for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
-            remove(sess, obj);
-        }
-        if let Some(ref metadata_module) = codegen_results.metadata_module {
-            if let Some(ref obj) = metadata_module.object {
-                remove(sess, obj);
+            if let Some(ref metadata_module) = codegen_results.metadata_module {
+                if let Some(ref obj) = metadata_module.object {
+                    remove(sess, obj);
+                }
+            }
+            if let Some(ref allocator_module) = codegen_results.allocator_module {
+                if let Some(ref obj) = allocator_module.object {
+                    remove(sess, obj);
+                }
+                if let Some(ref bc) = allocator_module.bytecode_compressed {
+                    remove(sess, bc);
+                }
             }
         }
-        if let Some(ref allocator_module) = codegen_results.allocator_module {
-            if let Some(ref obj) = allocator_module.object {
-                remove(sess, obj);
-            }
-            if let Some(ref bc) = allocator_module.bytecode_compressed {
-                remove(sess, bc);
-            }
-        }
-    }
+    });
 }
 
 // The third parameter is for env vars, used on windows to set up the
@@ -531,6 +540,7 @@
 
     {
         let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu);
+        link_sanitizer_runtime(sess, crate_type, &mut *linker);
         link_args::<B>(
             &mut *linker,
             flavor,
@@ -577,7 +587,7 @@
     let mut i = 0;
     loop {
         i += 1;
-        prog = sess.time("running linker", || exec_linker(sess, &mut cmd, out_filename, tmpdir));
+        prog = sess.time("run_linker", || exec_linker(sess, &mut cmd, out_filename, tmpdir));
         let output = match prog {
             Ok(ref output) => output,
             Err(_) => break,
@@ -735,6 +745,47 @@
     }
 }
 
+fn link_sanitizer_runtime(sess: &Session, crate_type: config::CrateType, linker: &mut dyn Linker) {
+    let sanitizer = match &sess.opts.debugging_opts.sanitizer {
+        Some(s) => s,
+        None => return,
+    };
+
+    if crate_type != config::CrateType::Executable {
+        return;
+    }
+
+    let name = match sanitizer {
+        Sanitizer::Address => "asan",
+        Sanitizer::Leak => "lsan",
+        Sanitizer::Memory => "msan",
+        Sanitizer::Thread => "tsan",
+    };
+
+    let default_sysroot = filesearch::get_or_default_sysroot();
+    let default_tlib =
+        filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple());
+
+    match sess.opts.target_triple.triple() {
+        "x86_64-apple-darwin" => {
+            // On Apple platforms, the sanitizer is always built as a dylib, and
+            // LLVM will link to `@rpath/*.dylib`, so we need to specify an
+            // rpath to the library as well (the rpath should be absolute, see
+            // PR #41352 for details).
+            let libname = format!("rustc_rt.{}", name);
+            let rpath = default_tlib.to_str().expect("non-utf8 component in path");
+            linker.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]);
+            linker.link_dylib(Symbol::intern(&libname));
+        }
+        "x86_64-unknown-linux-gnu" => {
+            let filename = format!("librustc_rt.{}.a", name);
+            let path = default_tlib.join(&filename);
+            linker.link_whole_rlib(&path);
+        }
+        _ => {}
+    }
+}
+
 /// Returns a boolean indicating whether the specified crate should be ignored
 /// during LTO.
 ///
@@ -1415,12 +1466,6 @@
             _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
                 add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
             }
-            _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum)
-                && crate_type == config::CrateType::Executable =>
-            {
-                // Link the sanitizer runtimes only if we are actually producing an executable
-                link_sanitizer_runtime::<B>(cmd, sess, codegen_results, tmpdir, cnum);
-            }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
             _ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
@@ -1457,47 +1502,6 @@
         }
     }
 
-    // We must link the sanitizer runtime using -Wl,--whole-archive but since
-    // it's packed in a .rlib, it contains stuff that are not objects that will
-    // make the linker error. So we must remove those bits from the .rlib before
-    // linking it.
-    fn link_sanitizer_runtime<'a, B: ArchiveBuilder<'a>>(
-        cmd: &mut dyn Linker,
-        sess: &'a Session,
-        codegen_results: &CodegenResults,
-        tmpdir: &Path,
-        cnum: CrateNum,
-    ) {
-        let src = &codegen_results.crate_info.used_crate_source[&cnum];
-        let cratepath = &src.rlib.as_ref().unwrap().0;
-
-        if sess.target.target.options.is_like_osx {
-            // On Apple platforms, the sanitizer is always built as a dylib, and
-            // LLVM will link to `@rpath/*.dylib`, so we need to specify an
-            // rpath to the library as well (the rpath should be absolute, see
-            // PR #41352 for details).
-            //
-            // FIXME: Remove this logic into librustc_*san once Cargo supports it
-            let rpath = cratepath.parent().unwrap();
-            let rpath = rpath.to_str().expect("non-utf8 component in path");
-            cmd.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]);
-        }
-
-        let dst = tmpdir.join(cratepath.file_name().unwrap());
-        let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
-        archive.update_symbols();
-
-        for f in archive.src_files() {
-            if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME {
-                archive.remove_file(&f);
-            }
-        }
-
-        archive.build();
-
-        cmd.link_whole_rlib(&dst);
-    }
-
     // Adds the static "rlib" versions of all crates to the command line.
     // There's a bit of magic which happens here specifically related to LTO and
     // dynamic libraries. Specifically:
@@ -1562,7 +1566,7 @@
         let name = cratepath.file_name().unwrap().to_str().unwrap();
         let name = &name[3..name.len() - 5]; // chop off lib/.rlib
 
-        sess.prof.generic_pass(&format!("altering {}.rlib", name)).run(|| {
+        sess.prof.extra_verbose_generic_activity(&format!("altering {}.rlib", name)).run(|| {
             let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
             archive.update_symbols();
 
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index fb9ba2a..11f5d30 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -9,11 +9,11 @@
 use std::io::{self, BufWriter};
 use std::path::{Path, PathBuf};
 
-use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc::middle::dependency_format::Linkage;
 use rustc::session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel};
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_serialize::{json, Encoder};
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkerFlavor, LldFlavor};
diff --git a/src/librustc_codegen_ssa/back/rpath.rs b/src/librustc_codegen_ssa/back/rpath.rs
index b09fd83..9d19cc2 100644
--- a/src/librustc_codegen_ssa/back/rpath.rs
+++ b/src/librustc_codegen_ssa/back/rpath.rs
@@ -3,8 +3,8 @@
 use std::fs;
 use std::path::{Path, PathBuf};
 
-use rustc::hir::def_id::CrateNum;
 use rustc::middle::cstore::LibSource;
+use rustc_hir::def_id::CrateNum;
 
 pub struct RPathConfig<'a> {
     pub used_crates: &'a [(CrateNum, LibSource)],
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 0f54557..a406b5f 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -1,9 +1,6 @@
 use std::collections::hash_map::Entry::*;
 use std::sync::Arc;
 
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::Node;
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
 use rustc::session::config;
@@ -13,6 +10,9 @@
 use rustc::ty::{SymbolName, TyCtxt};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::Node;
 use rustc_index::vec::IndexVec;
 use syntax::expand::allocator::ALLOCATOR_METHODS;
 
@@ -345,7 +345,7 @@
     if is_extern && !std_internal {
         let target = &tcx.sess.target.target.llvm_target;
         // WebAssembly cannot export data symbols, so reduce their export level
-        if target.contains("wasm32") || target.contains("emscripten") {
+        if target.contains("emscripten") {
             if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) =
                 tcx.hir().get_if_local(sym_def_id)
             {
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 44ed297..801bfde 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -11,7 +11,6 @@
 use crate::traits::*;
 use jobserver::{Acquired, Client};
 use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId};
-use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::config::{
     self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath,
@@ -26,6 +25,7 @@
 use rustc_errors::emitter::Emitter;
 use rustc_errors::{DiagnosticId, FatalError, Handler, Level};
 use rustc_fs_util::link_or_copy;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental::{
     copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
 };
@@ -479,6 +479,8 @@
         return work_products;
     }
 
+    let _timer = sess.timer("incr_comp_copy_cgu_workproducts");
+
     for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
         let mut files = vec![];
 
@@ -900,7 +902,7 @@
         worker_id: usize,
     },
     Done {
-        result: Result<CompiledModule, ()>,
+        result: Result<CompiledModule, Option<WorkerFatalError>>,
         worker_id: usize,
     },
     CodegenDone {
@@ -1472,9 +1474,12 @@
                     main_thread_worker_state = MainThreadWorkerState::Idle;
                 }
                 // If the thread failed that means it panicked, so we abort immediately.
-                Message::Done { result: Err(()), worker_id: _ } => {
+                Message::Done { result: Err(None), worker_id: _ } => {
                     bug!("worker thread panicked");
                 }
+                Message::Done { result: Err(Some(WorkerFatalError)), worker_id: _ } => {
+                    return Err(());
+                }
                 Message::CodegenItem => bug!("the coordinator should not receive codegen requests"),
             }
         }
@@ -1511,36 +1516,43 @@
         llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
     ) {
         if config.time_module && llvm_start_time.is_none() {
-            *llvm_start_time = Some(prof.generic_pass("LLVM passes"));
+            *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes"));
         }
     }
 }
 
 pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
 
+/// `FatalError` is explicitly not `Send`.
+#[must_use]
+pub struct WorkerFatalError;
+
 fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
     thread::spawn(move || {
         // Set up a destructor which will fire off a message that we're done as
         // we exit.
         struct Bomb<B: ExtraBackendMethods> {
             coordinator_send: Sender<Box<dyn Any + Send>>,
-            result: Option<WorkItemResult<B>>,
+            result: Option<Result<WorkItemResult<B>, FatalError>>,
             worker_id: usize,
         }
         impl<B: ExtraBackendMethods> Drop for Bomb<B> {
             fn drop(&mut self) {
                 let worker_id = self.worker_id;
                 let msg = match self.result.take() {
-                    Some(WorkItemResult::Compiled(m)) => {
+                    Some(Ok(WorkItemResult::Compiled(m))) => {
                         Message::Done::<B> { result: Ok(m), worker_id }
                     }
-                    Some(WorkItemResult::NeedsFatLTO(m)) => {
+                    Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
                         Message::NeedsFatLTO::<B> { result: m, worker_id }
                     }
-                    Some(WorkItemResult::NeedsThinLTO(name, thin_buffer)) => {
+                    Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
                         Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
                     }
-                    None => Message::Done::<B> { result: Err(()), worker_id },
+                    Some(Err(FatalError)) => {
+                        Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+                    }
+                    None => Message::Done::<B> { result: Err(None), worker_id },
                 };
                 drop(self.coordinator_send.send(Box::new(msg)));
             }
@@ -1560,7 +1572,7 @@
         // surface that there was an error in this worker.
         bomb.result = {
             let _prof_timer = cgcx.prof.generic_activity(work.profiling_event_id());
-            execute_work_item(&cgcx, work).ok()
+            Some(execute_work_item(&cgcx, work))
         };
     });
 }
@@ -1679,7 +1691,6 @@
                         d.code(code);
                     }
                     handler.emit_diagnostic(&d);
-                    handler.abort_if_errors_and_should_abort();
                 }
                 Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => {
                     sess.span_err(ExpnId::from_u32(cookie).expn_data().call_site, &msg)
@@ -1715,8 +1726,11 @@
 
 impl<B: ExtraBackendMethods> OngoingCodegen<B> {
     pub fn join(self, sess: &Session) -> (CodegenResults, FxHashMap<WorkProductId, WorkProduct>) {
+        let _timer = sess.timer("finish_ongoing_codegen");
+
         self.shared_emitter_main.check(sess, true);
-        let compiled_modules = match self.future.join() {
+        let future = self.future;
+        let compiled_modules = sess.time("join_worker_thread", || match future.join() {
             Ok(Ok(compiled_modules)) => compiled_modules,
             Ok(Err(())) => {
                 sess.abort_if_errors();
@@ -1725,7 +1739,7 @@
             Err(_) => {
                 bug!("panic during codegen/LLVM phase");
             }
-        };
+        });
 
         sess.cgu_reuse_tracker.check_expected_reuse(sess.diagnostic());
 
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 6750b7e..efd5600 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -14,8 +14,8 @@
 //!   int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.
 
 use crate::back::write::{
-    start_async_codegen, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm,
-    OngoingCodegen,
+    start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm,
+    submit_pre_lto_module_to_llvm, OngoingCodegen,
 };
 use crate::common::{IntPredicate, RealPredicate, TypeKind};
 use crate::meth;
@@ -25,8 +25,6 @@
 use crate::traits::*;
 use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind};
 
-use rustc::hir;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::cstore::{self, LinkagePreference};
@@ -42,6 +40,9 @@
 use rustc_codegen_utils::{check_for_rustc_errors_attr, symbol_names_test};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::profiling::print_time_passes_entry;
+use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::Idx;
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_span::Span;
@@ -85,7 +86,7 @@
         }
         op => bug!(
             "comparison_op_to_icmp_predicate: expected comparison operator, \
-                  found {:?}",
+             found {:?}",
             op
         ),
     }
@@ -102,7 +103,7 @@
         op => {
             bug!(
                 "comparison_op_to_fcmp_predicate: expected comparison operator, \
-                  found {:?}",
+                 found {:?}",
                 op
             );
         }
@@ -519,7 +520,7 @@
 
         ongoing_codegen.codegen_finished(tcx);
 
-        assert_and_save_dep_graph(tcx);
+        finalize_tcx(tcx);
 
         ongoing_codegen.check_for_errors(tcx.sess);
 
@@ -566,7 +567,7 @@
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
         let mut modules = backend.new_metadata(tcx, &llmod_id);
         tcx.sess
-            .time("write allocator module", || backend.codegen_allocator(tcx, &mut modules, kind));
+            .time("write_allocator_module", || backend.codegen_allocator(tcx, &mut modules, kind));
 
         Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator })
     } else {
@@ -582,7 +583,7 @@
         let metadata_cgu_name =
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
         let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name);
-        tcx.sess.time("write compressed metadata", || {
+        tcx.sess.time("write_compressed_metadata", || {
             backend.write_compressed_metadata(
                 tcx,
                 &ongoing_codegen.metadata,
@@ -606,20 +607,83 @@
         codegen_units
     };
 
-    let mut total_codegen_time = Duration::new(0, 0);
+    let total_codegen_time = Lock::new(Duration::new(0, 0));
 
-    for cgu in codegen_units.into_iter() {
+    // The non-parallel compiler can only translate codegen units to LLVM IR
+    // on a single thread, leading to a staircase effect where the N LLVM
+    // threads have to wait on the single codegen threads to generate work
+    // for them. The parallel compiler does not have this restriction, so
+    // we can pre-load the LLVM queue in parallel before handing off
+    // coordination to the OnGoingCodegen scheduler.
+    //
+    // This likely is a temporary measure. Once we don't have to support the
+    // non-parallel compiler anymore, we can compile CGUs end-to-end in
+    // parallel and get rid of the complicated scheduling logic.
+    let pre_compile_cgus = |cgu_reuse: &[CguReuse]| {
+        if cfg!(parallel_compiler) {
+            tcx.sess.time("compile_first_CGU_batch", || {
+                // Try to find one CGU to compile per thread.
+                let cgus: Vec<_> = cgu_reuse
+                    .iter()
+                    .enumerate()
+                    .filter(|&(_, reuse)| reuse == &CguReuse::No)
+                    .take(tcx.sess.threads())
+                    .collect();
+
+                // Compile the found CGUs in parallel.
+                par_iter(cgus)
+                    .map(|(i, _)| {
+                        let start_time = Instant::now();
+                        let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
+                        let mut time = total_codegen_time.lock();
+                        *time += start_time.elapsed();
+                        (i, module)
+                    })
+                    .collect()
+            })
+        } else {
+            FxHashMap::default()
+        }
+    };
+
+    let mut cgu_reuse = Vec::new();
+    let mut pre_compiled_cgus: Option<FxHashMap<usize, _>> = None;
+
+    for (i, cgu) in codegen_units.iter().enumerate() {
         ongoing_codegen.wait_for_signal_to_codegen_item();
         ongoing_codegen.check_for_errors(tcx.sess);
 
-        let cgu_reuse = determine_cgu_reuse(tcx, &cgu);
+        // Do some setup work in the first iteration
+        if pre_compiled_cgus.is_none() {
+            // Calculate the CGU reuse
+            cgu_reuse = tcx.sess.time("find_cgu_reuse", || {
+                codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect()
+            });
+            // Pre compile some CGUs
+            pre_compiled_cgus = Some(pre_compile_cgus(&cgu_reuse));
+        }
+
+        let cgu_reuse = cgu_reuse[i];
         tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse);
 
         match cgu_reuse {
             CguReuse::No => {
-                let start_time = Instant::now();
-                backend.compile_codegen_unit(tcx, cgu.name(), &ongoing_codegen.coordinator_send);
-                total_codegen_time += start_time.elapsed();
+                let (module, cost) =
+                    if let Some(cgu) = pre_compiled_cgus.as_mut().unwrap().remove(&i) {
+                        cgu
+                    } else {
+                        let start_time = Instant::now();
+                        let module = backend.compile_codegen_unit(tcx, cgu.name());
+                        let mut time = total_codegen_time.lock();
+                        *time += start_time.elapsed();
+                        module
+                    };
+                submit_codegened_module_to_llvm(
+                    &backend,
+                    &ongoing_codegen.coordinator_send,
+                    module,
+                    cost,
+                );
                 false
             }
             CguReuse::PreLto => {
@@ -652,7 +716,11 @@
 
     // Since the main thread is sometimes blocked during codegen, we keep track
     // -Ztime-passes output manually.
-    print_time_passes_entry(tcx.sess.time_passes(), "codegen to LLVM IR", total_codegen_time);
+    print_time_passes_entry(
+        tcx.sess.time_passes(),
+        "codegen_to_LLVM_IR",
+        total_codegen_time.into_inner(),
+    );
 
     ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
 
@@ -660,7 +728,8 @@
 
     ongoing_codegen.check_for_errors(tcx.sess);
 
-    assert_and_save_dep_graph(tcx);
+    finalize_tcx(tcx);
+
     ongoing_codegen.into_inner()
 }
 
@@ -711,10 +780,16 @@
     }
 }
 
-fn assert_and_save_dep_graph(tcx: TyCtxt<'_>) {
-    tcx.sess.time("assert dep graph", || ::rustc_incremental::assert_dep_graph(tcx));
+fn finalize_tcx(tcx: TyCtxt<'_>) {
+    tcx.sess.time("assert_dep_graph", || ::rustc_incremental::assert_dep_graph(tcx));
+    tcx.sess.time("serialize_dep_graph", || ::rustc_incremental::save_dep_graph(tcx));
 
-    tcx.sess.time("serialize dep graph", || ::rustc_incremental::save_dep_graph(tcx));
+    // We assume that no queries are run past here. If there are new queries
+    // after this point, they'll show up as "<unknown>" in self-profiling data.
+    {
+        let _prof_timer = tcx.prof.generic_activity("self_profile_alloc_query_strings");
+        tcx.alloc_self_profile_query_strings();
+    }
 }
 
 impl CrateInfo {
@@ -723,7 +798,6 @@
             panic_runtime: None,
             compiler_builtins: None,
             profiler_runtime: None,
-            sanitizer_runtime: None,
             is_no_builtins: Default::default(),
             native_libraries: Default::default(),
             used_libraries: tcx.native_libraries(LOCAL_CRATE),
@@ -759,9 +833,6 @@
             if tcx.is_profiler_runtime(cnum) {
                 info.profiler_runtime = Some(cnum);
             }
-            if tcx.is_sanitizer_runtime(cnum) {
-                info.sanitizer_runtime = Some(cnum);
-            }
             if tcx.is_no_builtins(cnum) {
                 info.is_no_builtins.insert(cnum);
             }
diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs
index e0505da..e4531a7 100644
--- a/src/librustc_codegen_ssa/common.rs
+++ b/src/librustc_codegen_ssa/common.rs
@@ -2,15 +2,16 @@
 
 use rustc::session::Session;
 use rustc::ty::{Ty, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_span::Span;
 
 use crate::base;
 use crate::traits::*;
-use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::LangItem;
+use rustc_hir::def_id::DefId;
 
 use crate::traits::BuilderMethods;
-use rustc::hir;
+use rustc_hir as hir;
 
 use rustc_error_codes::*;
 
@@ -196,5 +197,5 @@
 }
 
 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
-    span_err!(a, b, E0511, "{}", c);
+    struct_span_err!(a, b, E0511, "{}", c).emit();
 }
diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs
index 4d18f49..8dd3520 100644
--- a/src/librustc_codegen_ssa/debuginfo/type_names.rs
+++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs
@@ -1,8 +1,9 @@
 // Type Names for Debug Info.
 
-use rustc::hir::{self, def_id::DefId};
 use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 
 // Compute the name of the type as it should be stored in debuginfo. Does not do
 // any caching, i.e., calling the function twice with the same type will also do
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index fd31361..ee527ec 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -21,11 +21,8 @@
 extern crate log;
 #[macro_use]
 extern crate rustc;
-#[macro_use]
-extern crate syntax;
 
 use rustc::dep_graph::WorkProduct;
-use rustc::hir::def_id::CrateNum;
 use rustc::middle::cstore::{CrateSource, LibSource, NativeLibrary};
 use rustc::middle::dependency_format::Dependencies;
 use rustc::middle::lang_items::LangItem;
@@ -34,6 +31,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
+use rustc_hir::def_id::CrateNum;
 use rustc_span::symbol::Symbol;
 use std::path::{Path, PathBuf};
 
@@ -124,7 +122,6 @@
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
     pub profiler_runtime: Option<CrateNum>,
-    pub sanitizer_runtime: Option<CrateNum>,
     pub is_no_builtins: FxHashSet<CrateNum>,
     pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
     pub crate_name: FxHashMap<CrateNum, String>,
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 0ceb44d..c3affd2 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -14,7 +14,6 @@
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_span::DUMMY_SP;
 
 pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
@@ -129,17 +128,13 @@
             };
             if is_consume {
                 let base_ty =
-                    mir::Place::ty_from(place_ref.base, proj_base, *self.fx.mir, cx.tcx());
+                    mir::Place::ty_from(place_ref.local, proj_base, *self.fx.mir, cx.tcx());
                 let base_ty = self.fx.monomorphize(&base_ty);
 
                 // ZSTs don't require any actual memory access.
                 let elem_ty = base_ty.projection_ty(cx.tcx(), elem).ty;
                 let elem_ty = self.fx.monomorphize(&elem_ty);
-                let span = if let mir::PlaceBase::Local(index) = place_ref.base {
-                    self.fx.mir.local_decls[*index].source_info.span
-                } else {
-                    DUMMY_SP
-                };
+                let span = self.fx.mir.local_decls[*place_ref.local].source_info.span;
                 if cx.spanned_layout_of(elem_ty, span).is_zst() {
                     return;
                 }
@@ -179,9 +174,7 @@
                     // We use `NonUseContext::VarDebugInfo` for the base,
                     // which might not force the base local to memory,
                     // so we have to do it manually.
-                    if let mir::PlaceBase::Local(local) = place_ref.base {
-                        self.visit_local(&local, context, location);
-                    }
+                    self.visit_local(place_ref.local, context, location);
                 }
             }
 
@@ -192,7 +185,7 @@
             }
 
             self.process_place(
-                &mir::PlaceRef { base: place_ref.base, projection: proj_base },
+                &mir::PlaceRef { local: place_ref.local, projection: proj_base },
                 base_context,
                 location,
             );
@@ -219,8 +212,8 @@
                 };
             }
 
-            self.visit_place_base(place_ref.base, context, location);
-            self.visit_projection(place_ref.base, place_ref.projection, context, location);
+            self.visit_place_base(place_ref.local, context, location);
+            self.visit_projection(place_ref.local, place_ref.projection, context, location);
         }
     }
 }
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index a1d4c0c..9169010 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -10,8 +10,8 @@
 use crate::MemFlags;
 
 use rustc::middle::lang_items;
+use rustc::mir;
 use rustc::mir::interpret::PanicInfo;
-use rustc::mir::{self, PlaceBase, Static, StaticKind};
 use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf};
 use rustc::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_index::vec::Idx;
@@ -609,53 +609,17 @@
                     // checked by const-qualification, which also
                     // promotes any complex rvalues to constants.
                     if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") {
-                        match arg {
-                            // The shuffle array argument is usually not an explicit constant,
-                            // but specified directly in the code. This means it gets promoted
-                            // and we can then extract the value by evaluating the promoted.
-                            mir::Operand::Copy(place) | mir::Operand::Move(place) => {
-                                if let mir::PlaceRef {
-                                    base:
-                                        &PlaceBase::Static(box Static {
-                                            kind: StaticKind::Promoted(promoted, substs),
-                                            ty,
-                                            def_id,
-                                        }),
-                                    projection: &[],
-                                } = place.as_ref()
-                                {
-                                    let c = bx.tcx().const_eval_promoted(
-                                        Instance::new(def_id, self.monomorphize(&substs)),
-                                        promoted,
-                                    );
-                                    let (llval, ty) = self.simd_shuffle_indices(
-                                        &bx,
-                                        terminator.source_info.span,
-                                        ty,
-                                        c,
-                                    );
-                                    return OperandRef {
-                                        val: Immediate(llval),
-                                        layout: bx.layout_of(ty),
-                                    };
-                                } else {
-                                    span_bug!(span, "shuffle indices must be constant");
-                                }
-                            }
-
-                            mir::Operand::Constant(constant) => {
-                                let c = self.eval_mir_constant(constant);
-                                let (llval, ty) = self.simd_shuffle_indices(
-                                    &bx,
-                                    constant.span,
-                                    constant.literal.ty,
-                                    c,
-                                );
-                                return OperandRef {
-                                    val: Immediate(llval),
-                                    layout: bx.layout_of(ty),
-                                };
-                            }
+                        if let mir::Operand::Constant(constant) = arg {
+                            let c = self.eval_mir_constant(constant);
+                            let (llval, ty) = self.simd_shuffle_indices(
+                                &bx,
+                                constant.span,
+                                constant.literal.ty,
+                                c,
+                            );
+                            return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty) };
+                        } else {
+                            span_bug!(span, "shuffle indices must be constant");
                         }
                     }
 
@@ -1147,7 +1111,7 @@
         } else {
             self.codegen_place(
                 bx,
-                &mir::PlaceRef { base: &dest.base, projection: &dest.projection },
+                &mir::PlaceRef { local: &dest.local, projection: &dest.projection },
             )
         };
         if fn_ret.is_indirect() {
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index f508ed9..3ce916d 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -20,7 +20,7 @@
             // use `get_static` to get at their id.
             // FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics
             // always produce `&STATIC`. This may also simplify how const eval works with statics.
-            ty::ConstKind::Unevaluated(def_id, substs) if self.cx.tcx().is_static(def_id) => {
+            ty::ConstKind::Unevaluated(def_id, substs, None) if self.cx.tcx().is_static(def_id) => {
                 assert!(substs.is_empty(), "we don't support generic statics yet");
                 let static_ = bx.get_static(def_id);
                 // we treat operands referring to statics as if they were `&STATIC` instead
@@ -40,16 +40,18 @@
         constant: &mir::Constant<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
         match constant.literal.val {
-            ty::ConstKind::Unevaluated(def_id, substs) => {
+            ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
                 let substs = self.monomorphize(&substs);
                 self.cx
                     .tcx()
-                    .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, None)
+                    .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None)
                     .map_err(|err| {
-                        self.cx
-                            .tcx()
-                            .sess
-                            .span_err(constant.span, "erroneous constant encountered");
+                        if promoted.is_none() {
+                            self.cx
+                                .tcx()
+                                .sess
+                                .span_err(constant.span, "erroneous constant encountered");
+                        }
                         err
                     })
             }
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
index 4b4a2f4..e0aec5d 100644
--- a/src/librustc_codegen_ssa/mir/debuginfo.rs
+++ b/src/librustc_codegen_ssa/mir/debuginfo.rs
@@ -1,9 +1,9 @@
 use crate::traits::*;
-use rustc::hir::def_id::CrateNum;
 use rustc::mir;
 use rustc::session::config::DebugInfo;
 use rustc::ty::layout::{LayoutOf, Size};
 use rustc::ty::TyCtxt;
+use rustc_hir::def_id::CrateNum;
 use rustc_index::vec::IndexVec;
 
 use rustc_span::symbol::kw;
@@ -258,9 +258,7 @@
     if tcx.sess.opts.debuginfo == DebugInfo::Full || !tcx.sess.fewer_names() {
         let mut per_local = IndexVec::from_elem(vec![], &body.local_decls);
         for var in &body.var_debug_info {
-            if let mir::PlaceBase::Local(local) = var.place.base {
-                per_local[local].push(var);
-            }
+            per_local[var.place.local].push(var);
         }
         Some(per_local)
     } else {
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index d530696..a155a6e 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -373,44 +373,40 @@
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
 
-        if let mir::PlaceBase::Local(index) = place_ref.base {
-            match self.locals[*index] {
-                LocalRef::Operand(Some(mut o)) => {
-                    // Moves out of scalar and scalar pair fields are trivial.
-                    for elem in place_ref.projection.iter() {
-                        match elem {
-                            mir::ProjectionElem::Field(ref f, _) => {
-                                o = o.extract_field(bx, f.index());
-                            }
-                            mir::ProjectionElem::Index(_)
-                            | mir::ProjectionElem::ConstantIndex { .. } => {
-                                // ZSTs don't require any actual memory access.
-                                // FIXME(eddyb) deduplicate this with the identical
-                                // checks in `codegen_consume` and `extract_field`.
-                                let elem = o.layout.field(bx.cx(), 0);
-                                if elem.is_zst() {
-                                    o = OperandRef::new_zst(bx, elem);
-                                } else {
-                                    return None;
-                                }
-                            }
-                            _ => return None,
+        match self.locals[*place_ref.local] {
+            LocalRef::Operand(Some(mut o)) => {
+                // Moves out of scalar and scalar pair fields are trivial.
+                for elem in place_ref.projection.iter() {
+                    match elem {
+                        mir::ProjectionElem::Field(ref f, _) => {
+                            o = o.extract_field(bx, f.index());
                         }
+                        mir::ProjectionElem::Index(_)
+                        | mir::ProjectionElem::ConstantIndex { .. } => {
+                            // ZSTs don't require any actual memory access.
+                            // FIXME(eddyb) deduplicate this with the identical
+                            // checks in `codegen_consume` and `extract_field`.
+                            let elem = o.layout.field(bx.cx(), 0);
+                            if elem.is_zst() {
+                                o = OperandRef::new_zst(bx, elem);
+                            } else {
+                                return None;
+                            }
+                        }
+                        _ => return None,
                     }
+                }
 
-                    Some(o)
-                }
-                LocalRef::Operand(None) => {
-                    bug!("use of {:?} before def", place_ref);
-                }
-                LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
-                    // watch out for locals that do not have an
-                    // alloca; they are handled somewhat differently
-                    None
-                }
+                Some(o)
             }
-        } else {
-            None
+            LocalRef::Operand(None) => {
+                bug!("use of {:?} before def", place_ref);
+            }
+            LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
+                // watch out for locals that do not have an
+                // alloca; they are handled somewhat differently
+                None
+            }
         }
     }
 
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 7399db1..5e03a35 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -9,7 +9,7 @@
 use rustc::mir;
 use rustc::mir::tcx::PlaceTy;
 use rustc::ty::layout::{self, Align, HasTyCtxt, LayoutOf, TyLayout, VariantIdx};
-use rustc::ty::{self, Instance, Ty};
+use rustc::ty::{self, Ty};
 
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceRef<'tcx, V> {
@@ -37,15 +37,6 @@
         PlaceRef { llval, llextra: None, layout, align }
     }
 
-    fn new_thin_place<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
-        bx: &mut Bx,
-        llval: V,
-        layout: TyLayout<'tcx>,
-    ) -> PlaceRef<'tcx, V> {
-        assert!(!bx.cx().type_has_metadata(layout.ty));
-        PlaceRef { llval, llextra: None, layout, align: layout.align.abi }
-    }
-
     // FIXME(eddyb) pass something else for the name so no work is done
     // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
     pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
@@ -424,76 +415,26 @@
         let tcx = self.cx.tcx();
 
         let result = match place_ref {
-            mir::PlaceRef { base: mir::PlaceBase::Local(index), projection: [] } => {
-                match self.locals[*index] {
-                    LocalRef::Place(place) => {
-                        return place;
-                    }
-                    LocalRef::UnsizedPlace(place) => {
-                        return bx.load_operand(place).deref(cx);
-                    }
-                    LocalRef::Operand(..) => {
-                        bug!("using operand local {:?} as place", place_ref);
-                    }
+            mir::PlaceRef { local, projection: [] } => match self.locals[**local] {
+                LocalRef::Place(place) => {
+                    return place;
                 }
-            }
-            mir::PlaceRef {
-                base:
-                    mir::PlaceBase::Static(box mir::Static {
-                        ty,
-                        kind: mir::StaticKind::Promoted(promoted, substs),
-                        def_id,
-                    }),
-                projection: [],
-            } => {
-                let instance = Instance::new(*def_id, self.monomorphize(substs));
-                let layout = cx.layout_of(self.monomorphize(&ty));
-                match bx.tcx().const_eval_promoted(instance, *promoted) {
-                    Ok(val) => match val.val {
-                        ty::ConstKind::Value(mir::interpret::ConstValue::ByRef {
-                            alloc,
-                            offset,
-                        }) => bx.cx().from_const_alloc(layout, alloc, offset),
-                        _ => bug!("promoteds should have an allocation: {:?}", val),
-                    },
-                    Err(_) => {
-                        // This is unreachable as long as runtime
-                        // and compile-time agree perfectly.
-                        // With floats that won't always be true,
-                        // so we generate a (safe) abort.
-                        bx.abort();
-                        // We still have to return a place but it doesn't matter,
-                        // this code is unreachable.
-                        let llval =
-                            bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout)));
-                        PlaceRef::new_sized(llval, layout)
-                    }
+                LocalRef::UnsizedPlace(place) => {
+                    return bx.load_operand(place).deref(cx);
                 }
-            }
-            mir::PlaceRef {
-                base:
-                    mir::PlaceBase::Static(box mir::Static {
-                        ty,
-                        kind: mir::StaticKind::Static,
-                        def_id,
-                    }),
-                projection: [],
-            } => {
-                // NB: The layout of a static may be unsized as is the case when working
-                // with a static that is an extern_type.
-                let layout = cx.layout_of(self.monomorphize(&ty));
-                let static_ = bx.get_static(*def_id);
-                PlaceRef::new_thin_place(bx, static_, layout)
-            }
-            mir::PlaceRef { base, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => {
+                LocalRef::Operand(..) => {
+                    bug!("using operand local {:?} as place", place_ref);
+                }
+            },
+            mir::PlaceRef { local, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => {
                 // Load the pointer from its location.
-                self.codegen_consume(bx, &mir::PlaceRef { base, projection: proj_base })
+                self.codegen_consume(bx, &mir::PlaceRef { local, projection: proj_base })
                     .deref(bx.cx())
             }
-            mir::PlaceRef { base, projection: [proj_base @ .., elem] } => {
+            mir::PlaceRef { local, projection: [proj_base @ .., elem] } => {
                 // FIXME turn this recursion into iteration
                 let cg_base =
-                    self.codegen_place(bx, &mir::PlaceRef { base, projection: proj_base });
+                    self.codegen_place(bx, &mir::PlaceRef { local, projection: proj_base });
 
                 match elem {
                     mir::ProjectionElem::Deref => bug!(),
@@ -558,7 +499,7 @@
 
     pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
-        let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, *self.mir, tcx);
+        let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx);
         self.monomorphize(&place_ty.ty)
     }
 }
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index 48ba641..574c06d 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -1,4 +1,5 @@
 use rustc::mir;
+use rustc_errors::struct_span_err;
 
 use super::FunctionCx;
 use super::LocalRef;
@@ -81,12 +82,13 @@
                         if let OperandValue::Immediate(_) = op.val {
                             acc.push(op.immediate());
                         } else {
-                            span_err!(
+                            struct_span_err!(
                                 bx.sess(),
                                 span.to_owned(),
                                 E0669,
                                 "invalid value for constraint in inline assembly"
-                            );
+                            )
+                            .emit();
                         }
                         acc
                     },
@@ -100,12 +102,13 @@
                         statement.source_info.span,
                     );
                     if !res {
-                        span_err!(
+                        struct_span_err!(
                             bx.sess(),
                             statement.source_info.span,
                             E0668,
                             "malformed inline assembly"
-                        );
+                        )
+                        .emit();
                     }
                 }
                 bx
diff --git a/src/librustc_codegen_ssa/mono_item.rs b/src/librustc_codegen_ssa/mono_item.rs
index c57da41..ae211ca 100644
--- a/src/librustc_codegen_ssa/mono_item.rs
+++ b/src/librustc_codegen_ssa/mono_item.rs
@@ -1,8 +1,8 @@
 use crate::base;
 use crate::traits::*;
-use rustc::hir;
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::ty::layout::HasTyCtxt;
+use rustc_hir as hir;
 
 use rustc::mir::mono::MonoItem;
 
diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs
index 6af63ed..d31b063 100644
--- a/src/librustc_codegen_ssa/traits/asm.rs
+++ b/src/librustc_codegen_ssa/traits/asm.rs
@@ -1,6 +1,6 @@
 use super::BackendTypes;
 use crate::mir::place::PlaceRef;
-use rustc::hir::{GlobalAsm, InlineAsmInner};
+use rustc_hir::{GlobalAsm, InlineAsmInner};
 use rustc_span::Span;
 
 pub trait AsmBuilderMethods<'tcx>: BackendTypes {
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index e0d0a2f..bc3a752 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -1,5 +1,6 @@
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
+use crate::ModuleCodegen;
 
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::{config, Session};
@@ -10,7 +11,6 @@
 use rustc_span::symbol::Symbol;
 use syntax::expand::allocator::AllocatorKind;
 
-use std::sync::mpsc;
 use std::sync::Arc;
 
 pub trait BackendTypes {
@@ -34,7 +34,7 @@
 {
 }
 
-pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send {
+pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync {
     fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module;
     fn write_compressed_metadata<'tcx>(
         &self,
@@ -48,12 +48,13 @@
         mods: &mut Self::Module,
         kind: AllocatorKind,
     );
+    /// This generates the codegen unit and returns it along with
+    /// a `u64` giving an estimate of the unit's processing cost.
     fn compile_codegen_unit(
         &self,
         tcx: TyCtxt<'_>,
         cgu_name: Symbol,
-        tx_to_llvm_workers: &mpsc::Sender<Box<dyn std::any::Any + Send>>,
-    );
+    ) -> (ModuleCodegen<Self::Module>, u64);
     // If find_features is true this won't access `sess.crate_types` by assuming
     // that `is_pie_binary` is false. When we discover LLVM target features
     // `sess.crate_types` is uninitialized so we cannot access it.
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index c2e8bad..d2784f5 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -1,9 +1,9 @@
 use super::BackendTypes;
 use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
-use rustc::hir::def_id::CrateNum;
 use rustc::mir;
 use rustc::ty::layout::Size;
 use rustc::ty::{Instance, Ty};
+use rustc_hir::def_id::CrateNum;
 use rustc_span::{SourceFile, Span};
 use rustc_target::abi::call::FnAbi;
 use syntax::ast::Name;
diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs
index 1dd2c74..c2ab5f5 100644
--- a/src/librustc_codegen_ssa/traits/declare.rs
+++ b/src/librustc_codegen_ssa/traits/declare.rs
@@ -1,7 +1,7 @@
 use super::BackendTypes;
-use rustc::hir::def_id::DefId;
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::ty::{Instance, Ty};
+use rustc_hir::def_id::DefId;
 use rustc_target::abi::call::FnAbi;
 
 pub trait DeclareMethods<'tcx>: BackendTypes {
diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs
index 5c108f9..40c9dde 100644
--- a/src/librustc_codegen_ssa/traits/statics.rs
+++ b/src/librustc_codegen_ssa/traits/statics.rs
@@ -1,6 +1,6 @@
 use super::BackendTypes;
-use rustc::hir::def_id::DefId;
 use rustc::ty::layout::Align;
+use rustc_hir::def_id::DefId;
 
 pub trait StaticMethods: BackendTypes {
     fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml
index 404e556..8361a19 100644
--- a/src/librustc_codegen_utils/Cargo.toml
+++ b/src/librustc_codegen_utils/Cargo.toml
@@ -17,6 +17,7 @@
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc = { path = "../librustc" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_metadata = { path = "../librustc_metadata" }
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index 399db7a..6b802bf 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -15,9 +15,9 @@
 #[macro_use]
 extern crate rustc;
 
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::symbol::sym;
 
 pub mod codegen_backend;
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index e479573..450dcd3 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -87,13 +87,13 @@
 //! virtually impossible. Thus, symbol hash generation exclusively relies on
 //! DefPaths which are much more robust in the face of changes to the code base.
 
-use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::hir::Node;
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::mono::{InstantiationMode, MonoItem};
 use rustc::session::config::SymbolManglingVersion;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Instance, TyCtxt};
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::Node;
 
 use rustc_span::symbol::Symbol;
 
diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs
index 29869a1..4f5b9ce 100644
--- a/src/librustc_codegen_utils/symbol_names/legacy.rs
+++ b/src/librustc_codegen_utils/symbol_names/legacy.rs
@@ -1,4 +1,3 @@
-use rustc::hir::def_id::CrateNum;
 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
 use rustc::ich::NodeIdHashingMode;
 use rustc::mir::interpret::{ConstValue, Scalar};
@@ -7,6 +6,7 @@
 use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common::record_time;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::CrateNum;
 
 use log::debug;
 
diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs
index 045d06a..ff4e128 100644
--- a/src/librustc_codegen_utils/symbol_names/v0.rs
+++ b/src/librustc_codegen_utils/symbol_names/v0.rs
@@ -1,11 +1,11 @@
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId};
 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
 use rustc::ty::print::{Print, Printer};
 use rustc::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{FloatTy, IntTy, UintTy};
 
diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs
index 0a76093..8f2f262 100644
--- a/src/librustc_codegen_utils/symbol_names_test.rs
+++ b/src/librustc_codegen_utils/symbol_names_test.rs
@@ -4,8 +4,8 @@
 //! def-path. This is used for unit testing the code that generates
 //! paths etc in all kinds of annoying scenarios.
 
-use rustc::hir;
 use rustc::ty::{Instance, TyCtxt};
+use rustc_hir as hir;
 use rustc_span::symbol::{sym, Symbol};
 
 const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 7fa40b8..19db983 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -26,7 +26,7 @@
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_index = { path = "../librustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
-measureme = "0.5"
+measureme = "0.7.1"
 
 [dependencies.parking_lot]
 version = "0.9"
diff --git a/src/librustc_data_structures/binary_search_util/mod.rs b/src/librustc_data_structures/binary_search_util/mod.rs
index 6d1e1ab..ede5757 100644
--- a/src/librustc_data_structures/binary_search_util/mod.rs
+++ b/src/librustc_data_structures/binary_search_util/mod.rs
@@ -14,35 +14,55 @@
         Ok(mid) => mid,
         Err(_) => return &[],
     };
+    let size = data.len();
 
-    // We get back *some* element with the given key -- so
-    // search backwards to find the *first* one.
-    //
-    // (It'd be more efficient to use a "galloping" search
-    // here, but it's not really worth it for small-ish
-    // amounts of data.)
+    // We get back *some* element with the given key -- so do
+    // a galloping search backwards to find the *first* one.
     let mut start = mid;
-    while start > 0 {
-        if key_fn(&data[start - 1]) == *key {
-            start -= 1;
-        } else {
+    let mut previous = mid;
+    let mut step = 1;
+    loop {
+        start = start.saturating_sub(step);
+        if start == 0 || key_fn(&data[start]) != *key {
             break;
         }
+        previous = start;
+        step *= 2;
+    }
+    step = previous - start;
+    while step > 1 {
+        let half = step / 2;
+        let mid = start + half;
+        if key_fn(&data[mid]) != *key {
+            start = mid;
+        }
+        step -= half;
+    }
+    // adjust by one if we have overshot
+    if start < size && key_fn(&data[start]) != *key {
+        start += 1;
     }
 
     // Now search forward to find the *last* one.
-    //
-    // (It'd be more efficient to use a "galloping" search
-    // here, but it's not really worth it for small-ish
-    // amounts of data.)
-    let mut end = mid + 1;
-    let max = data.len();
-    while end < max {
-        if key_fn(&data[end]) == *key {
-            end += 1;
-        } else {
+    let mut end = mid;
+    let mut previous = mid;
+    let mut step = 1;
+    loop {
+        end = end.saturating_add(step).min(size);
+        if end == size || key_fn(&data[end]) != *key {
             break;
         }
+        previous = end;
+        step *= 2;
+    }
+    step = end - previous;
+    while step > 1 {
+        let half = step / 2;
+        let mid = end - half;
+        if key_fn(&data[mid]) != *key {
+            end = mid;
+        }
+        step -= half;
     }
 
     &data[start..end]
diff --git a/src/librustc/util/captures.rs b/src/librustc_data_structures/captures.rs
similarity index 100%
rename from src/librustc/util/captures.rs
rename to src/librustc_data_structures/captures.rs
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index d1b7ee9..51a38a7 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -67,6 +67,7 @@
 pub mod base_n;
 pub mod binary_search_util;
 pub mod box_region;
+pub mod captures;
 pub mod const_cstr;
 pub mod flock;
 pub mod fx;
diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs
index 840a260..8deb43d 100644
--- a/src/librustc_data_structures/profiling.rs
+++ b/src/librustc_data_structures/profiling.rs
@@ -1,6 +1,90 @@
+//! # Rust Compiler Self-Profiling
+//!
+//! This module implements the basic framework for the compiler's self-
+//! profiling support. It provides the `SelfProfiler` type which enables
+//! recording "events". An event is something that starts and ends at a given
+//! point in time and has an ID and a kind attached to it. This allows for
+//! tracing the compiler's activity.
+//!
+//! Internally this module uses the custom tailored [measureme][mm] crate for
+//! efficiently recording events to disk in a compact format that can be
+//! post-processed and analyzed by the suite of tools in the `measureme`
+//! project. The highest priority for the tracing framework is on incurring as
+//! little overhead as possible.
+//!
+//!
+//! ## Event Overview
+//!
+//! Events have a few properties:
+//!
+//! - The `event_kind` designates the broad category of an event (e.g. does it
+//!   correspond to the execution of a query provider or to loading something
+//!   from the incr. comp. on-disk cache, etc).
+//! - The `event_id` designates the query invocation or function call it
+//!   corresponds to, possibly including the query key or function arguments.
+//! - Each event stores the ID of the thread it was recorded on.
+//! - The timestamp stores beginning and end of the event, or the single point
+//!   in time it occurred at for "instant" events.
+//!
+//!
+//! ## Event Filtering
+//!
+//! Event generation can be filtered by event kind. Recording all possible
+//! events generates a lot of data, much of which is not needed for most kinds
+//! of analysis. So, in order to keep overhead as low as possible for a given
+//! use case, the `SelfProfiler` will only record the kinds of events that
+//! pass the filter specified as a command line argument to the compiler.
+//!
+//!
+//! ## `event_id` Assignment
+//!
+//! As far as `measureme` is concerned, `event_id`s are just strings. However,
+//! it would incur too much overhead to generate and persist each `event_id`
+//! string at the point where the event is recorded. In order to make this more
+//! efficient `measureme` has two features:
+//!
+//! - Strings can share their content, so that re-occurring parts don't have to
+//!   be copied over and over again. One allocates a string in `measureme` and
+//!   gets back a `StringId`. This `StringId` is then used to refer to that
+//!   string. `measureme` strings are actually DAGs of string components so that
+//!   arbitrary sharing of substrings can be done efficiently. This is useful
+//!   because `event_id`s contain lots of redundant text like query names or
+//!   def-path components.
+//!
+//! - `StringId`s can be "virtual" which means that the client picks a numeric
+//!   ID according to some application-specific scheme and can later make that
+//!   ID be mapped to an actual string. This is used to cheaply generate
+//!   `event_id`s while the events actually occur, causing little timing
+//!   distortion, and then later map those `StringId`s, in bulk, to actual
+//!   `event_id` strings. This way the largest part of the tracing overhead is
+//!   localized to one contiguous chunk of time.
+//!
+//! How are these `event_id`s generated in the compiler? For things that occur
+//! infrequently (e.g. "generic activities"), we just allocate the string the
+//! first time it is used and then keep the `StringId` in a hash table. This
+//! is implemented in `SelfProfiler::get_or_alloc_cached_string()`.
+//!
+//! For queries it gets more interesting: First we need a unique numeric ID for
+//! each query invocation (the `QueryInvocationId`). This ID is used as the
+//! virtual `StringId` we use as `event_id` for a given event. This ID has to
+//! be available both when the query is executed and later, together with the
+//! query key, when we allocate the actual `event_id` strings in bulk.
+//!
+//! We could make the compiler generate and keep track of such an ID for each
+//! query invocation but luckily we already have something that fits all the
+//! the requirements: the query's `DepNodeIndex`. So we use the numeric value
+//! of the `DepNodeIndex` as `event_id` when recording the event and then,
+//! just before the query context is dropped, we walk the entire query cache
+//! (which stores the `DepNodeIndex` along with the query key for each
+//! invocation) and allocate the corresponding strings together with a mapping
+//! for `DepNodeIndex as StringId`.
+//!
+//! [mm]: https://github.com/rust-lang/measureme/
+
+use crate::fx::FxHashMap;
+
 use std::error::Error;
 use std::fs;
-use std::mem::{self, Discriminant};
 use std::path::Path;
 use std::process;
 use std::sync::Arc;
@@ -8,9 +92,8 @@
 use std::time::{Duration, Instant};
 use std::u32;
 
-use crate::cold_path;
-
-use measureme::StringId;
+use measureme::{EventId, EventIdBuilder, SerializableString, StringId};
+use parking_lot::RwLock;
 
 /// MmapSerializatioSink is faster on macOS and Linux
 /// but FileSerializationSink is faster on Windows
@@ -21,11 +104,6 @@
 
 type Profiler = measureme::Profiler<SerializationSink>;
 
-pub trait QueryName: Sized + Copy {
-    fn discriminant(self) -> Discriminant<Self>;
-    fn as_str(self) -> &'static str;
-}
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
 pub enum ProfileCategory {
     Parsing,
@@ -44,15 +122,13 @@
         const QUERY_CACHE_HITS   = 1 << 2;
         const QUERY_BLOCKED      = 1 << 3;
         const INCR_CACHE_LOADS   = 1 << 4;
-        const SPARSE_PASS   = 1 << 5;
-        const GENERIC_PASS   = 1 << 6;
+
+        const QUERY_KEYS         = 1 << 5;
 
         const DEFAULT = Self::GENERIC_ACTIVITIES.bits |
                         Self::QUERY_PROVIDERS.bits |
                         Self::QUERY_BLOCKED.bits |
-                        Self::INCR_CACHE_LOADS.bits |
-                        Self::SPARSE_PASS.bits |
-                        Self::GENERIC_PASS.bits;
+                        Self::INCR_CACHE_LOADS.bits;
 
         // empty() and none() aren't const-fns unfortunately
         const NONE = 0;
@@ -63,19 +139,21 @@
 const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
     ("none", EventFilter::NONE),
     ("all", EventFilter::ALL),
-    ("sparse-pass", EventFilter::SPARSE_PASS),
-    ("generic-pass", EventFilter::GENERIC_PASS),
     ("generic-activity", EventFilter::GENERIC_ACTIVITIES),
     ("query-provider", EventFilter::QUERY_PROVIDERS),
     ("query-cache-hit", EventFilter::QUERY_CACHE_HITS),
     ("query-blocked", EventFilter::QUERY_BLOCKED),
     ("incr-cache-load", EventFilter::INCR_CACHE_LOADS),
+    ("query-keys", EventFilter::QUERY_KEYS),
 ];
 
 fn thread_id_to_u32(tid: ThreadId) -> u32 {
-    unsafe { mem::transmute::<ThreadId, u64>(tid) as u32 }
+    unsafe { std::mem::transmute::<ThreadId, u64>(tid) as u32 }
 }
 
+/// Something that uniquely identifies a query invocation.
+pub struct QueryInvocationId(pub u32);
+
 /// A reference to the SelfProfiler. It can be cloned and sent across thread
 /// boundaries at will.
 #[derive(Clone)]
@@ -89,110 +167,99 @@
     // actually enabled.
     event_filter_mask: EventFilter,
 
-    // Print sparse passes to stdout
-    verbose_sparse: bool,
+    // Print verbose generic activities to stdout
+    print_verbose_generic_activities: bool,
 
-    // Print generic passes to stdout
-    verbose_generic: bool,
+    // Print extra verbose generic activities to stdout
+    print_extra_verbose_generic_activities: bool,
 }
 
 impl SelfProfilerRef {
     pub fn new(
         profiler: Option<Arc<SelfProfiler>>,
-        verbose_sparse: bool,
-        verbose_generic: bool,
+        print_verbose_generic_activities: bool,
+        print_extra_verbose_generic_activities: bool,
     ) -> SelfProfilerRef {
         // If there is no SelfProfiler then the filter mask is set to NONE,
         // ensuring that nothing ever tries to actually access it.
-        let mut event_filter_mask =
+        let event_filter_mask =
             profiler.as_ref().map(|p| p.event_filter_mask).unwrap_or(EventFilter::NONE);
 
-        if verbose_sparse {
-            event_filter_mask |= EventFilter::SPARSE_PASS;
+        SelfProfilerRef {
+            profiler,
+            event_filter_mask,
+            print_verbose_generic_activities,
+            print_extra_verbose_generic_activities,
         }
-
-        if verbose_generic {
-            event_filter_mask |= EventFilter::GENERIC_PASS;
-        }
-
-        SelfProfilerRef { profiler, event_filter_mask, verbose_sparse, verbose_generic }
     }
 
-    #[inline(always)]
-    fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
-    where
-        F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>,
-    {
-        self.handle_event(
-            event_filter,
-            || f(self.profiler.as_ref().unwrap()),
-            || TimingGuard::none(),
-        )
-    }
-
-    // This shim makes sure that cold calls only get executed if the filter mask
+    // This shim makes sure that calls only get executed if the filter mask
     // lets them pass. It also contains some trickery to make sure that
     // code is optimized for non-profiling compilation sessions, i.e. anything
     // past the filter check is never inlined so it doesn't clutter the fast
     // path.
     #[inline(always)]
-    fn handle_event<R>(
-        &self,
-        event_filter: EventFilter,
-        cold: impl FnOnce() -> R,
-        hot: impl FnOnce() -> R,
-    ) -> R {
+    fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
+    where
+        F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>,
+    {
+        #[inline(never)]
+        fn cold_call<F>(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_>
+        where
+            F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>,
+        {
+            let profiler = profiler_ref.profiler.as_ref().unwrap();
+            f(&**profiler)
+        }
+
         if unlikely!(self.event_filter_mask.contains(event_filter)) {
-            cold_path(|| cold())
+            cold_call(self, f)
         } else {
-            hot()
+            TimingGuard::none()
         }
     }
 
-    /// Start profiling a sparse pass. Profiling continues until the
-    /// VerboseTimingGuard returned from this call is dropped.
+    /// Start profiling a verbose generic activity. Profiling continues until the
+    /// VerboseTimingGuard returned from this call is dropped. In addition to recording
+    /// a measureme event, "verbose" generic activities also print a timing entry to
+    /// stdout if the compiler is invoked with -Ztime or -Ztime-passes.
     #[inline(always)]
-    pub fn sparse_pass<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> {
-        self.handle_event(
-            EventFilter::SPARSE_PASS,
-            || {
-                VerboseTimingGuard::start(
-                    self.profiler
-                        .as_ref()
-                        .map(|profiler| (&**profiler, profiler.sparse_pass_event_kind)),
-                    event_id,
-                    self.verbose_sparse,
-                )
-            },
-            || VerboseTimingGuard::none(),
+    pub fn verbose_generic_activity<'a>(
+        &'a self,
+        event_id: &'static str,
+    ) -> VerboseTimingGuard<'a> {
+        VerboseTimingGuard::start(
+            event_id,
+            self.print_verbose_generic_activities,
+            self.generic_activity(event_id),
         )
     }
 
-    /// Start profiling a generic pass. Profiling continues until the
-    /// VerboseTimingGuard returned from this call is dropped.
+    /// Start profiling a extra verbose generic activity. Profiling continues until the
+    /// VerboseTimingGuard returned from this call is dropped. In addition to recording
+    /// a measureme event, "extra verbose" generic activities also print a timing entry to
+    /// stdout if the compiler is invoked with -Ztime-passes.
     #[inline(always)]
-    pub fn generic_pass<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> {
-        self.handle_event(
-            EventFilter::GENERIC_PASS,
-            || {
-                VerboseTimingGuard::start(
-                    self.profiler
-                        .as_ref()
-                        .map(|profiler| (&**profiler, profiler.generic_pass_event_kind)),
-                    event_id,
-                    self.verbose_generic,
-                )
-            },
-            || VerboseTimingGuard::none(),
+    pub fn extra_verbose_generic_activity<'a>(
+        &'a self,
+        event_id: &'a str,
+    ) -> VerboseTimingGuard<'a> {
+        // FIXME: This does not yet emit a measureme event
+        // because callers encode arguments into `event_id`.
+        VerboseTimingGuard::start(
+            event_id,
+            self.print_extra_verbose_generic_activities,
+            TimingGuard::none(),
         )
     }
 
     /// Start profiling a generic activity. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn generic_activity(&self, event_id: &str) -> TimingGuard<'_> {
+    pub fn generic_activity(&self, event_id: &'static str) -> TimingGuard<'_> {
         self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
-            let event_id = profiler.profiler.alloc_string(event_id);
+            let event_id = profiler.get_or_alloc_cached_string(event_id);
+            let event_id = EventId::from_label(event_id);
             TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
         })
     }
@@ -200,19 +267,18 @@
     /// Start profiling a query provider. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn query_provider(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn query_provider(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::QUERY_PROVIDERS, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.query_event_kind, event_id)
+            TimingGuard::start(profiler, profiler.query_event_kind, EventId::INVALID)
         })
     }
 
     /// Record a query in-memory cache hit.
     #[inline(always)]
-    pub fn query_cache_hit(&self, query_name: impl QueryName) {
+    pub fn query_cache_hit(&self, query_invocation_id: QueryInvocationId) {
         self.instant_query_event(
             |profiler| profiler.query_cache_hit_event_kind,
-            query_name,
+            query_invocation_id,
             EventFilter::QUERY_CACHE_HITS,
         );
     }
@@ -221,10 +287,9 @@
     /// Profiling continues until the TimingGuard returned from this call is
     /// dropped.
     #[inline(always)]
-    pub fn query_blocked(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn query_blocked(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::QUERY_BLOCKED, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.query_blocked_event_kind, event_id)
+            TimingGuard::start(profiler, profiler.query_blocked_event_kind, EventId::INVALID)
         })
     }
 
@@ -232,10 +297,13 @@
     /// incremental compilation on-disk cache. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn incr_cache_loading(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn incr_cache_loading(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.incremental_load_result_event_kind, event_id)
+            TimingGuard::start(
+                profiler,
+                profiler.incremental_load_result_event_kind,
+                EventId::INVALID,
+            )
         })
     }
 
@@ -243,32 +311,42 @@
     fn instant_query_event(
         &self,
         event_kind: fn(&SelfProfiler) -> StringId,
-        query_name: impl QueryName,
+        query_invocation_id: QueryInvocationId,
         event_filter: EventFilter,
     ) {
         drop(self.exec(event_filter, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
+            let event_id = StringId::new_virtual(query_invocation_id.0);
             let thread_id = thread_id_to_u32(std::thread::current().id());
 
-            profiler.profiler.record_instant_event(event_kind(profiler), event_id, thread_id);
+            profiler.profiler.record_instant_event(
+                event_kind(profiler),
+                EventId::from_virtual(event_id),
+                thread_id,
+            );
 
             TimingGuard::none()
         }));
     }
 
-    pub fn register_queries(&self, f: impl FnOnce(&SelfProfiler)) {
+    pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) {
         if let Some(profiler) = &self.profiler {
             f(&profiler)
         }
     }
+
+    #[inline]
+    pub fn enabled(&self) -> bool {
+        self.profiler.is_some()
+    }
 }
 
 pub struct SelfProfiler {
     profiler: Profiler,
     event_filter_mask: EventFilter,
+
+    string_cache: RwLock<FxHashMap<&'static str, StringId>>,
+
     query_event_kind: StringId,
-    sparse_pass_event_kind: StringId,
-    generic_pass_event_kind: StringId,
     generic_activity_event_kind: StringId,
     incremental_load_result_event_kind: StringId,
     query_blocked_event_kind: StringId,
@@ -289,8 +367,6 @@
         let profiler = Profiler::new(&path)?;
 
         let query_event_kind = profiler.alloc_string("Query");
-        let sparse_pass_event_kind = profiler.alloc_string("SparsePass");
-        let generic_pass_event_kind = profiler.alloc_string("GenericPass");
         let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
         let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
         let query_blocked_event_kind = profiler.alloc_string("QueryBlocked");
@@ -332,9 +408,8 @@
         Ok(SelfProfiler {
             profiler,
             event_filter_mask,
+            string_cache: RwLock::new(FxHashMap::default()),
             query_event_kind,
-            sparse_pass_event_kind,
-            generic_pass_event_kind,
             generic_activity_event_kind,
             incremental_load_result_event_kind,
             query_blocked_event_kind,
@@ -342,16 +417,51 @@
         })
     }
 
-    fn get_query_name_string_id(query_name: impl QueryName) -> StringId {
-        let discriminant =
-            unsafe { mem::transmute::<Discriminant<_>, u64>(query_name.discriminant()) };
-
-        StringId::reserved(discriminant as u32)
+    /// Allocates a new string in the profiling data. Does not do any caching
+    /// or deduplication.
+    pub fn alloc_string<STR: SerializableString + ?Sized>(&self, s: &STR) -> StringId {
+        self.profiler.alloc_string(s)
     }
 
-    pub fn register_query_name(&self, query_name: impl QueryName) {
-        let id = SelfProfiler::get_query_name_string_id(query_name);
-        self.profiler.alloc_string_with_reserved_id(id, query_name.as_str());
+    /// Gets a `StringId` for the given string. This method makes sure that
+    /// any strings going through it will only be allocated once in the
+    /// profiling data.
+    pub fn get_or_alloc_cached_string(&self, s: &'static str) -> StringId {
+        // Only acquire a read-lock first since we assume that the string is
+        // already present in the common case.
+        {
+            let string_cache = self.string_cache.read();
+
+            if let Some(&id) = string_cache.get(s) {
+                return id;
+            }
+        }
+
+        let mut string_cache = self.string_cache.write();
+        // Check if the string has already been added in the small time window
+        // between dropping the read lock and acquiring the write lock.
+        *string_cache.entry(s).or_insert_with(|| self.profiler.alloc_string(s))
+    }
+
+    pub fn map_query_invocation_id_to_string(&self, from: QueryInvocationId, to: StringId) {
+        let from = StringId::new_virtual(from.0);
+        self.profiler.map_virtual_to_concrete_string(from, to);
+    }
+
+    pub fn bulk_map_query_invocation_id_to_single_string<I>(&self, from: I, to: StringId)
+    where
+        I: Iterator<Item = QueryInvocationId> + ExactSizeIterator,
+    {
+        let from = from.map(|qid| StringId::new_virtual(qid.0));
+        self.profiler.bulk_map_virtual_to_single_concrete_string(from, to);
+    }
+
+    pub fn query_key_recording_enabled(&self) -> bool {
+        self.event_filter_mask.contains(EventFilter::QUERY_KEYS)
+    }
+
+    pub fn event_id_builder(&self) -> EventIdBuilder<'_, SerializationSink> {
+        EventIdBuilder::new(&self.profiler)
     }
 }
 
@@ -363,7 +473,7 @@
     pub fn start(
         profiler: &'a SelfProfiler,
         event_kind: StringId,
-        event_id: StringId,
+        event_id: EventId,
     ) -> TimingGuard<'a> {
         let thread_id = thread_id_to_u32(std::thread::current().id());
         let raw_profiler = &profiler.profiler;
@@ -373,9 +483,24 @@
     }
 
     #[inline]
+    pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) {
+        if let Some(guard) = self.0 {
+            let event_id = StringId::new_virtual(query_invocation_id.0);
+            let event_id = EventId::from_virtual(event_id);
+            guard.finish_with_override_event_id(event_id);
+        }
+    }
+
+    #[inline]
     pub fn none() -> TimingGuard<'a> {
         TimingGuard(None)
     }
+
+    #[inline(always)]
+    pub fn run<R>(self, f: impl FnOnce() -> R) -> R {
+        let _timer = self;
+        f()
+    }
 }
 
 #[must_use]
@@ -386,19 +511,11 @@
 }
 
 impl<'a> VerboseTimingGuard<'a> {
-    pub fn start(
-        profiler: Option<(&'a SelfProfiler, StringId)>,
-        event_id: &'a str,
-        verbose: bool,
-    ) -> Self {
-        let _guard = profiler.map_or(TimingGuard::none(), |(profiler, event_kind)| {
-            let event = profiler.profiler.alloc_string(event_id);
-            TimingGuard::start(profiler, event_kind, event)
-        });
+    pub fn start(event_id: &'a str, verbose: bool, _guard: TimingGuard<'a>) -> Self {
         VerboseTimingGuard {
             event_id,
             _guard,
-            start: if verbose { Some(Instant::now()) } else { None },
+            start: if unlikely!(verbose) { Some(Instant::now()) } else { None },
         }
     }
 
@@ -407,10 +524,6 @@
         let _timer = self;
         f()
     }
-
-    fn none() -> Self {
-        VerboseTimingGuard { event_id: "", start: None, _guard: TimingGuard::none() }
-    }
 }
 
 impl Drop for VerboseTimingGuard<'_> {
@@ -485,8 +598,8 @@
             cb: DWORD,
         ) -> BOOL;
     }
-    let mut pmc: PROCESS_MEMORY_COUNTERS = unsafe { mem::zeroed() };
-    pmc.cb = mem::size_of_val(&pmc) as DWORD;
+    let mut pmc: PROCESS_MEMORY_COUNTERS = unsafe { std::mem::zeroed() };
+    pmc.cb = std::mem::size_of_val(&pmc) as DWORD;
     match unsafe { GetProcessMemoryInfo(GetCurrentProcess(), &mut pmc, pmc.cb) } {
         0 => None,
         _ => Some(pmc.WorkingSetSize as usize),
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 99436f4..37449f9 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -10,7 +10,6 @@
 crate-type = ["dylib"]
 
 [dependencies]
-graphviz = { path = "../libgraphviz" }
 lazy_static = "1.0"
 log = "0.4"
 env_logger = { version = "0.7", default-features = false }
@@ -18,8 +17,9 @@
 rustc_target = { path = "../librustc_target" }
 rustc_lint = { path = "../librustc_lint" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_parse = { path = "../librustc_parse" }
@@ -29,7 +29,6 @@
 rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_interface = { path = "../librustc_interface" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
-rustc_resolve = { path = "../librustc_resolve" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 379e9bd..072b85d 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -23,11 +23,7 @@
 
 pub extern crate rustc_plugin_impl as plugin;
 
-//use rustc_resolve as resolve;
-use errors::{registry::Registry, PResult};
-use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::lint;
-use rustc::lint::Lint;
+use rustc::lint::{Lint, LintId};
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::config::nightly_options;
 use rustc::session::config::{ErrorOutputType, Input, OutputType, PrintRequest};
@@ -38,9 +34,12 @@
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::profiling::print_time_passes_entry;
 use rustc_data_structures::sync::SeqCst;
+use rustc_errors::{registry::Registry, PResult};
 use rustc_feature::{find_gated_cfg, UnstableFeatures};
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::get_builtin_codegen_backend;
 use rustc_interface::{interface, Queries};
+use rustc_lint::LintStore;
 use rustc_metadata::locator;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
@@ -369,7 +368,7 @@
                 queries.global_ctxt()?.peek_mut().enter(|tcx| {
                     let result = tcx.analysis(LOCAL_CRATE);
 
-                    sess.time("save analysis", || {
+                    sess.time("save_analysis", || {
                         save::process_crate(
                             tcx,
                             &expanded_crate,
@@ -389,6 +388,7 @@
                 })?;
             } else {
                 // Drop AST after creating GlobalCtxt to free memory
+                let _timer = sess.prof.generic_activity("drop_ast");
                 mem::drop(queries.expansion()?.take());
             }
 
@@ -413,6 +413,7 @@
         })?;
 
         if let Some(linker) = linker {
+            let _timer = sess.timer("link");
             linker.link()?
         }
 
@@ -809,7 +810,7 @@
     );
 }
 
-fn describe_lints(sess: &Session, lint_store: &lint::LintStore, loaded_plugins: bool) {
+fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
     println!(
         "
 Available lint options:
@@ -830,8 +831,8 @@
     }
 
     fn sort_lint_groups(
-        lints: Vec<(&'static str, Vec<lint::LintId>, bool)>,
-    ) -> Vec<(&'static str, Vec<lint::LintId>)> {
+        lints: Vec<(&'static str, Vec<LintId>, bool)>,
+    ) -> Vec<(&'static str, Vec<LintId>)> {
         let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
         lints.sort_by_key(|l| l.0);
         lints
@@ -890,7 +891,7 @@
     println!("    {}  {}", padded("----"), "---------");
     println!("    {}  {}", padded("warnings"), "all lints that are set to issue warnings");
 
-    let print_lint_groups = |lints: Vec<(&'static str, Vec<lint::LintId>)>| {
+    let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>| {
         for (name, to) in lints {
             let name = name.to_lowercase().replace("_", "-");
             let desc = to
@@ -1134,7 +1135,7 @@
 /// the panic into a `Result` instead.
 pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> {
     catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
-        if value.is::<errors::FatalErrorMarker>() {
+        if value.is::<rustc_errors::FatalErrorMarker>() {
             ErrorReported
         } else {
             panic::resume_unwind(value);
@@ -1163,22 +1164,21 @@
     // Separate the output with an empty line
     eprintln!();
 
-    let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
-        errors::ColorConfig::Auto,
+    let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
+        rustc_errors::ColorConfig::Auto,
         None,
         false,
         false,
         None,
         false,
     ));
-    let handler = errors::Handler::with_emitter(true, None, emitter);
+    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
 
     // a .span_bug or .bug call has already printed what
     // it wants to print.
-    if !info.payload().is::<errors::ExplicitBug>() {
-        let d = errors::Diagnostic::new(errors::Level::Bug, "unexpected panic");
+    if !info.payload().is::<rustc_errors::ExplicitBug>() {
+        let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
         handler.emit_diagnostic(&d);
-        handler.abort_if_errors_and_should_abort();
     }
 
     let mut xs: Vec<Cow<'static, str>> = vec![
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 84fa5fb..8804a05 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -1,13 +1,13 @@
 //! The various pretty-printing routines.
 
-use rustc::hir;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir::map as hir_map;
-use rustc::hir::print as pprust_hir;
 use rustc::session::config::{Input, PpMode, PpSourceMode};
 use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
 use rustc::util::common::ErrorReported;
+use rustc_hir as hir;
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::print as pprust_hir;
 use rustc_mir::util::{write_mir_graphviz, write_mir_pretty};
 
 use rustc_span::FileName;
diff --git a/src/librustc_error_codes/error_codes/E0038.md b/src/librustc_error_codes/error_codes/E0038.md
index 25e380b..b2cc2a2 100644
--- a/src/librustc_error_codes/error_codes/E0038.md
+++ b/src/librustc_error_codes/error_codes/E0038.md
@@ -136,7 +136,7 @@
 generates does not grow drastically, since the compiler will only generate an
 implementation if the function is called with unparametrized substitutions
 (i.e., substitutions where none of the substituted types are themselves
-parametrized).
+parameterized).
 
 However, with trait objects we have to make a table containing _every_ object
 that implements the trait. Now, if it has type parameters, we need to add
diff --git a/src/librustc_error_codes/error_codes/E0084.md b/src/librustc_error_codes/error_codes/E0084.md
index 2388bc6..38ce9b4 100644
--- a/src/librustc_error_codes/error_codes/E0084.md
+++ b/src/librustc_error_codes/error_codes/E0084.md
@@ -20,7 +20,7 @@
 }
 ```
 
-or you remove the integer represention of your enum:
+or you remove the integer representation of your enum:
 
 ```
 enum NightsWatch {}
diff --git a/src/librustc_error_codes/error_codes/E0178.md b/src/librustc_error_codes/error_codes/E0178.md
index 07980ad..0c6f918 100644
--- a/src/librustc_error_codes/error_codes/E0178.md
+++ b/src/librustc_error_codes/error_codes/E0178.md
@@ -1,16 +1,27 @@
-In types, the `+` type operator has low precedence, so it is often necessary
-to use parentheses.
+The `+` type operator was used in an ambiguous context.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0178
 trait Foo {}
 
 struct Bar<'a> {
-    w: &'a Foo + Copy,   // error, use &'a (Foo + Copy)
-    x: &'a Foo + 'a,     // error, use &'a (Foo + 'a)
-    y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
-    z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
+    x: &'a Foo + 'a,     // error!
+    y: &'a mut Foo + 'a, // error!
+    z: fn() -> Foo + 'a, // error!
+}
+```
+
+In types, the `+` type operator has low precedence, so it is often necessary
+to use parentheses:
+
+```
+trait Foo {}
+
+struct Bar<'a> {
+    x: &'a (Foo + 'a),     // ok!
+    y: &'a mut (Foo + 'a), // ok!
+    z: fn() -> (Foo + 'a), // ok!
 }
 ```
 
diff --git a/src/librustc_error_codes/error_codes/E0184.md b/src/librustc_error_codes/error_codes/E0184.md
index e7fa8df..4624f9e 100644
--- a/src/librustc_error_codes/error_codes/E0184.md
+++ b/src/librustc_error_codes/error_codes/E0184.md
@@ -1,6 +1,20 @@
-Explicitly implementing both Drop and Copy for a type is currently disallowed.
-This feature can make some sense in theory, but the current implementation is
-incorrect and can lead to memory unsafety (see [issue #20126][iss20126]), so
-it has been disabled for now.
+The `Copy` trait was implemented on a type with a `Drop` implementation.
+
+Erroneous code example:
+
+```compile_fail,E0184
+#[derive(Copy)]
+struct Foo; // error!
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+    }
+}
+```
+
+Explicitly implementing both `Drop` and `Copy` trait on a type is currently
+disallowed. This feature can make some sense in theory, but the current
+implementation is incorrect and can lead to memory unsafety (see
+[issue #20126][iss20126]), so it has been disabled for now.
 
 [iss20126]: https://github.com/rust-lang/rust/issues/20126
diff --git a/src/librustc_error_codes/error_codes/E0185.md b/src/librustc_error_codes/error_codes/E0185.md
index f0ad2af..944a93e 100644
--- a/src/librustc_error_codes/error_codes/E0185.md
+++ b/src/librustc_error_codes/error_codes/E0185.md
@@ -2,7 +2,7 @@
 implementation of the trait declared the same function to be a method (i.e., to
 take a `self` parameter).
 
-Here's an example of this error:
+Erroneous code example:
 
 ```compile_fail,E0185
 trait Foo {
@@ -17,3 +17,19 @@
     fn foo(&self) {}
 }
 ```
+
+When a type implements a trait's associated function, it has to use the same
+signature. So in this case, since `Foo::foo` does not take any argument and
+does not return anything, its implementation on `Bar` should be the same:
+
+```
+trait Foo {
+    fn foo();
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo() {} // ok!
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0186.md b/src/librustc_error_codes/error_codes/E0186.md
index 9135d5c..7db1e84 100644
--- a/src/librustc_error_codes/error_codes/E0186.md
+++ b/src/librustc_error_codes/error_codes/E0186.md
@@ -2,7 +2,7 @@
 `self` parameter), but an implementation of the trait declared the same function
 to be static.
 
-Here's an example of this error:
+Erroneous code example:
 
 ```compile_fail,E0186
 trait Foo {
@@ -17,3 +17,19 @@
     fn foo() {}
 }
 ```
+
+When a type implements a trait's associated function, it has to use the same
+signature. So in this case, since `Foo::foo` takes `self` as argument and
+does not return anything, its implementation on `Bar` should be the same:
+
+```
+trait Foo {
+    fn foo(&self);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(&self) {} // ok!
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0307.md b/src/librustc_error_codes/error_codes/E0307.md
index 1779e5d..c628d17 100644
--- a/src/librustc_error_codes/error_codes/E0307.md
+++ b/src/librustc_error_codes/error_codes/E0307.md
@@ -36,7 +36,7 @@
 }
 ```
 
-E0307 will be emitted by the compiler when using an invalid reciver type,
+E0307 will be emitted by the compiler when using an invalid receiver type,
 like in the following example:
 
 ```compile_fail,E0307
diff --git a/src/librustc_error_codes/error_codes/E0373.md b/src/librustc_error_codes/error_codes/E0373.md
index 47e3a48..808363e 100644
--- a/src/librustc_error_codes/error_codes/E0373.md
+++ b/src/librustc_error_codes/error_codes/E0373.md
@@ -31,7 +31,7 @@
 may well have disappeared by the time we try to use them. Even if we call
 `thr.join()` within foo (which blocks until `thr` has completed, ensuring the
 stack frame won't disappear), we will not succeed: the compiler cannot prove
-that this behaviour is safe, and so won't let us do it.
+that this behavior is safe, and so won't let us do it.
 
 The solution to this problem is usually to switch to using a `move` closure.
 This approach moves (or copies, where possible) data into the closure, rather
diff --git a/src/librustc_error_codes/error_codes/E0426.md b/src/librustc_error_codes/error_codes/E0426.md
index 15e7fb0..275a83e 100644
--- a/src/librustc_error_codes/error_codes/E0426.md
+++ b/src/librustc_error_codes/error_codes/E0426.md
@@ -8,7 +8,7 @@
 }
 ```
 
-Please verify you spelt or declare the label correctly. Example:
+Please verify you spelled or declared the label correctly. Example:
 
 ```
 'a: loop {
diff --git a/src/librustc_error_codes/error_codes/E0566.md b/src/librustc_error_codes/error_codes/E0566.md
index 62fb66f..3dcd801 100644
--- a/src/librustc_error_codes/error_codes/E0566.md
+++ b/src/librustc_error_codes/error_codes/E0566.md
@@ -2,8 +2,8 @@
 
 Erroneous code example:
 
-```
-#[repr(u32, u64)] // warning!
+```compile_fail,E0566
+#[repr(u32, u64)]
 enum Repr { A }
 ```
 
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 79ec9ad..73f66d5 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -385,3 +385,22 @@
         }
     }
 }
+
+#[macro_export]
+macro_rules! struct_span_err {
+    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+        $session.struct_span_err_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::error_code!($code),
+        )
+    })
+}
+
+#[macro_export]
+macro_rules! error_code {
+    ($code:ident) => {{
+        let _ = $code;
+        $crate::DiagnosticId::Error(stringify!($code).to_owned())
+    }};
+}
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 541b89e..526b4e2 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1530,7 +1530,7 @@
 
             // This offset and the ones below need to be signed to account for replacement code
             // that is shorter than the original code.
-            let mut offset: isize = 0;
+            let mut offsets: Vec<(usize, isize)> = Vec::new();
             // Only show an underline in the suggestions if the suggestion is not the
             // entirety of the code being shown and the displayed code is not multiline.
             if show_underline {
@@ -1550,12 +1550,19 @@
                         .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
                         .sum();
 
+                    let offset: isize = offsets
+                        .iter()
+                        .filter_map(
+                            |(start, v)| if span_start_pos <= *start { None } else { Some(v) },
+                        )
+                        .sum();
                     let underline_start = (span_start_pos + start) as isize + offset;
                     let underline_end = (span_start_pos + start + sub_len) as isize + offset;
+                    assert!(underline_start >= 0 && underline_end >= 0);
                     for p in underline_start..underline_end {
                         buffer.putc(
                             row_num,
-                            max_line_num_len + 3 + p as usize,
+                            ((max_line_num_len + 3) as isize + p) as usize,
                             '^',
                             Style::UnderlinePrimary,
                         );
@@ -1565,7 +1572,7 @@
                         for p in underline_start - 1..underline_start + 1 {
                             buffer.putc(
                                 row_num,
-                                max_line_num_len + 3 + p as usize,
+                                ((max_line_num_len + 3) as isize + p) as usize,
                                 '-',
                                 Style::UnderlineSecondary,
                             );
@@ -1582,8 +1589,9 @@
                     // length of the code to be substituted
                     let snippet_len = span_end_pos as isize - span_start_pos as isize;
                     // For multiple substitutions, use the position *after* the previous
-                    // substitutions have happened.
-                    offset += full_sub_len - snippet_len;
+                    // substitutions have happened, only when further substitutions are
+                    // located strictly after.
+                    offsets.push((span_end_pos, full_sub_len - snippet_len));
                 }
                 row_num += 1;
             }
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 2279ed8..e24e871 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -182,7 +182,7 @@
 
                 // Find the bounding span.
                 let lo = substitution.parts.iter().map(|part| part.span.lo()).min().unwrap();
-                let hi = substitution.parts.iter().map(|part| part.span.hi()).min().unwrap();
+                let hi = substitution.parts.iter().map(|part| part.span.hi()).max().unwrap();
                 let bounding_span = Span::with_root_ctxt(lo, hi);
                 let lines = cm.span_to_lines(bounding_span).unwrap();
                 assert!(!lines.lines.is_empty());
@@ -278,7 +278,6 @@
     err_count: usize,
     deduplicated_err_count: usize,
     emitter: Box<dyn Emitter + sync::Send>,
-    continue_after_error: bool,
     delayed_span_bugs: Vec<Diagnostic>,
 
     /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
@@ -402,7 +401,6 @@
                 err_count: 0,
                 deduplicated_err_count: 0,
                 emitter,
-                continue_after_error: true,
                 delayed_span_bugs: Vec::new(),
                 taught_diagnostics: Default::default(),
                 emitted_diagnostic_codes: Default::default(),
@@ -412,10 +410,6 @@
         }
     }
 
-    pub fn set_continue_after_error(&self, continue_after_error: bool) {
-        self.inner.borrow_mut().continue_after_error = continue_after_error;
-    }
-
     // This is here to not allow mutation of flags;
     // as of this writing it's only used in tests in librustc.
     pub fn can_emit_warnings(&self) -> bool {
@@ -672,10 +666,6 @@
         self.inner.borrow_mut().abort_if_errors()
     }
 
-    pub fn abort_if_errors_and_should_abort(&self) {
-        self.inner.borrow_mut().abort_if_errors_and_should_abort()
-    }
-
     /// `true` if we haven't taught a diagnostic with this code already.
     /// The caller must then teach the user about such a diagnostic.
     ///
@@ -696,7 +686,6 @@
     fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
         let mut inner = self.inner.borrow_mut();
         inner.emit_diagnostic(diag.set_span(sp));
-        inner.abort_if_errors_and_should_abort();
     }
 
     pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
@@ -830,14 +819,6 @@
         self.has_errors() || !self.delayed_span_bugs.is_empty()
     }
 
-    fn abort_if_errors_and_should_abort(&mut self) {
-        self.emit_stashed_diagnostics();
-
-        if self.has_errors() && !self.continue_after_error {
-            FatalError.raise();
-        }
-    }
-
     fn abort_if_errors(&mut self) {
         self.emit_stashed_diagnostics();
 
@@ -853,7 +834,6 @@
 
     fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
         self.emit_diagnostic(diag.set_span(sp));
-        self.abort_if_errors_and_should_abort();
     }
 
     fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
diff --git a/src/librustc_expand/Cargo.toml b/src/librustc_expand/Cargo.toml
index f9c15fb..d04dd07 100644
--- a/src/librustc_expand/Cargo.toml
+++ b/src/librustc_expand/Cargo.toml
@@ -14,10 +14,12 @@
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 log = "0.4"
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_ast_passes = { path = "../librustc_ast_passes" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index fe08c85..52ba14d 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -1,9 +1,15 @@
 use crate::expand::{self, AstFragment, Invocation};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{self, Lrc};
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
 use rustc_span::edition::Edition;
+use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
+use smallvec::{smallvec, SmallVec};
 use syntax::ast::{self, Attribute, Name, NodeId, PatKind};
 use syntax::attr::{self, Deprecation, HasAttrs, Stability};
 use syntax::mut_visit::{self, MutVisitor};
@@ -13,13 +19,6 @@
 use syntax::tokenstream::{self, TokenStream};
 use syntax::visit::Visitor;
 
-use errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::{self, Lrc};
-use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
-use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
-use smallvec::{smallvec, SmallVec};
-
 use std::default::Default;
 use std::iter;
 use std::path::PathBuf;
diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs
index 11f94ab..bd3d6b5 100644
--- a/src/librustc_expand/build.rs
+++ b/src/librustc_expand/build.rs
@@ -110,7 +110,7 @@
     }
 
     pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
-        ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
+        ast::TraitRef { path, constness: None, ref_id: ast::DUMMY_NODE_ID }
     }
 
     pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef {
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index 6eead11..3254d0c 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -5,6 +5,8 @@
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::proc_macro::collect_derives;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
 use rustc_parse::configure;
 use rustc_parse::parser::Parser;
@@ -16,20 +18,16 @@
 use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
 use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
 use syntax::attr::{self, is_builtin_attr, HasAttrs};
-use syntax::feature_gate::{self, feature_err};
 use syntax::mut_visit::*;
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::sess::ParseSess;
+use syntax::sess::{feature_err, ParseSess};
 use syntax::token;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::util::map_in_place::MapInPlace;
 use syntax::visit::{self, Visitor};
 
-use errors::{Applicability, FatalError, PResult};
 use smallvec::{smallvec, SmallVec};
-
-use rustc_data_structures::sync::Lrc;
 use std::io::ErrorKind;
 use std::ops::DerefMut;
 use std::path::PathBuf;
@@ -1063,7 +1061,7 @@
     fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
         let features = self.cx.ecfg.features.unwrap();
         for attr in attrs.iter() {
-            feature_gate::check_attribute(attr, self.cx.parse_sess, features);
+            rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.parse_sess, features);
             validate_attr::check_meta(self.cx.parse_sess, attr);
 
             // macros are expanded before any lint passes so this warning has to be hardcoded
diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs
index feba7f6..4fe7c26 100644
--- a/src/librustc_expand/lib.rs
+++ b/src/librustc_expand/lib.rs
@@ -13,7 +13,7 @@
 #[macro_export]
 macro_rules! panictry {
     ($e:expr) => {{
-        use errors::FatalError;
+        use rustc_errors::FatalError;
         use std::result::Result::{Err, Ok};
         match $e {
             Ok(e) => e,
diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs
index 992764a..47865b2 100644
--- a/src/librustc_expand/mbe/macro_check.rs
+++ b/src/librustc_expand/mbe/macro_check.rs
@@ -106,14 +106,14 @@
 //! bound.
 use crate::mbe::{KleeneToken, TokenTree};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
+use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym};
+use rustc_span::{symbol::Ident, MultiSpan, Span};
 use syntax::ast::NodeId;
-use syntax::early_buffered_lints::META_VARIABLE_MISUSE;
-use syntax::sess::ParseSess;
 use syntax::token::{DelimToken, Token, TokenKind};
 
-use rustc_data_structures::fx::FxHashMap;
-use rustc_span::{symbol::Ident, MultiSpan, Span};
 use smallvec::SmallVec;
 
 /// Stack represented as linked list.
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index c0e34a3..246f660 100644
--- a/src/librustc_expand/mbe/macro_parser.rs
+++ b/src/librustc_expand/mbe/macro_parser.rs
@@ -85,7 +85,7 @@
 use syntax::token::{self, DocComment, Nonterminal, Token};
 use syntax::tokenstream::TokenStream;
 
-use errors::{FatalError, PResult};
+use rustc_errors::{FatalError, PResult};
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
 
@@ -696,7 +696,7 @@
                         if parser.token.span.is_dummy() {
                             parser.token.span
                         } else {
-                            sess.source_map().next_point(parser.token.span)
+                            parser.token.span.shrink_to_hi()
                         },
                     ),
                     "missing tokens in macro arguments",
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 6e96534..d72317a 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -8,6 +8,9 @@
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult};
 use crate::mbe::transcribe::transcribe;
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, DiagnosticBuilder, FatalError};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
 use rustc_parse::Directory;
@@ -22,17 +25,11 @@
 use syntax::token::{self, NtTT, Token, TokenKind::*};
 use syntax::tokenstream::{DelimSpan, TokenStream};
 
-use errors::{DiagnosticBuilder, FatalError};
 use log::debug;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use std::{mem, slice};
 
-use errors::Applicability;
-
 const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
                                         `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
                                         `literal`, `path`, `meta`, `tt`, `item` and `vis`";
diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs
index 4fd68a8..104a523 100644
--- a/src/librustc_expand/mbe/transcribe.rs
+++ b/src/librustc_expand/mbe/transcribe.rs
@@ -2,19 +2,17 @@
 use crate::mbe;
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::pluralize;
+use rustc_span::hygiene::{ExpnId, Transparency};
+use rustc_span::Span;
 use syntax::ast::{Ident, Mac};
 use syntax::mut_visit::{self, MutVisitor};
 use syntax::token::{self, NtTT, Token};
 use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
 
 use smallvec::{smallvec, SmallVec};
-
-use errors::pluralize;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
-use rustc_span::hygiene::{ExpnId, Transparency};
-use rustc_span::Span;
-
 use std::mem;
 
 // A Marker adds the given mark to the syntax context.
diff --git a/src/librustc_expand/parse/lexer/tests.rs b/src/librustc_expand/parse/lexer/tests.rs
index 835f0b0..2ef81d8 100644
--- a/src/librustc_expand/parse/lexer/tests.rs
+++ b/src/librustc_expand/parse/lexer/tests.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{emitter::EmitterWriter, Handler};
 use rustc_parse::lexer::StringReader;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::symbol::Symbol;
@@ -8,7 +9,6 @@
 use syntax::util::comments::is_doc_comment;
 use syntax::with_default_globals;
 
-use errors::{emitter::EmitterWriter, Handler};
 use std::io;
 use std::path::PathBuf;
 
diff --git a/src/librustc_expand/parse/tests.rs b/src/librustc_expand/parse/tests.rs
index 25cd5da..b79e289 100644
--- a/src/librustc_expand/parse/tests.rs
+++ b/src/librustc_expand/parse/tests.rs
@@ -1,6 +1,6 @@
 use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse};
 
-use errors::PResult;
+use rustc_errors::PResult;
 use rustc_parse::new_parser_from_source_str;
 use rustc_span::source_map::FilePathMapping;
 use rustc_span::symbol::{kw, sym, Symbol};
diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs
index 25e2bbb..cb6249e 100644
--- a/src/librustc_expand/proc_macro.rs
+++ b/src/librustc_expand/proc_macro.rs
@@ -1,15 +1,14 @@
 use crate::base::{self, *};
 use crate::proc_macro_server;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, FatalError};
 use rustc_span::symbol::sym;
+use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
-use syntax::errors::{Applicability, FatalError};
 use syntax::token;
 use syntax::tokenstream::{self, TokenStream};
 
-use rustc_data_structures::sync::Lrc;
-use rustc_span::{Span, DUMMY_SP};
-
 const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
 
 pub struct BangProcMacro {
diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs
index cf5749f..d441613 100644
--- a/src/librustc_expand/proc_macro_server.rs
+++ b/src/librustc_expand/proc_macro_server.rs
@@ -1,5 +1,7 @@
 use crate::base::ExtCtxt;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::Diagnostic;
 use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -11,9 +13,6 @@
 use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
 use syntax::util::comments;
 
-use errors::Diagnostic;
-use rustc_data_structures::sync::Lrc;
-
 use pm::bridge::{server, TokenTree};
 use pm::{Delimiter, Level, LineColumn, Spacing};
 use std::ops::Bound;
@@ -265,13 +264,13 @@
     }
 }
 
-impl ToInternal<errors::Level> for Level {
-    fn to_internal(self) -> errors::Level {
+impl ToInternal<rustc_errors::Level> for Level {
+    fn to_internal(self) -> rustc_errors::Level {
         match self {
-            Level::Error => errors::Level::Error,
-            Level::Warning => errors::Level::Warning,
-            Level::Note => errors::Level::Note,
-            Level::Help => errors::Level::Help,
+            Level::Error => rustc_errors::Level::Error,
+            Level::Warning => rustc_errors::Level::Warning,
+            Level::Note => rustc_errors::Level::Note,
+            Level::Help => rustc_errors::Level::Help,
             _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
         }
     }
diff --git a/src/librustc_expand/tests.rs b/src/librustc_expand/tests.rs
index 18dc605..82ab74a 100644
--- a/src/librustc_expand/tests.rs
+++ b/src/librustc_expand/tests.rs
@@ -6,9 +6,9 @@
 use syntax::tokenstream::TokenStream;
 use syntax::with_default_globals;
 
-use errors::emitter::EmitterWriter;
-use errors::{Handler, PResult};
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::emitter::EmitterWriter;
+use rustc_errors::{Handler, PResult};
 
 use std::io;
 use std::io::prelude::*;
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 8cb1684..319cd88 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -192,9 +192,6 @@
     /// Allows using the `unadjusted` ABI; perma-unstable.
     (active, abi_unadjusted, "1.16.0", None, None),
 
-    /// Allows identifying crates that contain sanitizer runtimes.
-    (active, sanitizer_runtime, "1.17.0", None, None),
-
     /// Used to identify crates that contain the profiler runtime.
     (active, profiler_runtime, "1.18.0", None, None),
 
@@ -534,6 +531,9 @@
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
 
+    /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
+    (active, half_open_range_patterns, "1.41.0", Some(67264), None),
+
     /// Allows using `&mut` in constant functions.
     (active, const_mut_refs, "1.41.0", Some(57349), None),
 
@@ -544,6 +544,12 @@
     /// For example, you can write `x @ Some(y)`.
     (active, bindings_after_at, "1.41.0", Some(65490), None),
 
+    /// Allows `impl const Trait for T` syntax.
+    (active, const_trait_impl, "1.42.0", Some(67792), None),
+
+    /// Allows `T: ?const Trait` syntax in bounds.
+    (active, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -559,4 +565,6 @@
     sym::or_patterns,
     sym::let_chains,
     sym::raw_dylib,
+    sym::const_trait_impl,
+    sym::const_trait_bound_opt_out,
 ];
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index 3cbf96b..a38726e 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -410,11 +410,6 @@
         which contains compiler-rt intrinsics and will never be stable",
     ),
     gated!(
-        sanitizer_runtime, Whitelisted, template!(Word),
-        "the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime \
-        of a sanitizer and will never be stable",
-    ),
-    gated!(
         profiler_runtime, Whitelisted, template!(Word),
         "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
         which contains the profiler runtime and will never be stable",
diff --git a/src/librustc_feature/lib.rs b/src/librustc_feature/lib.rs
index 71a4642..01546f7 100644
--- a/src/librustc_feature/lib.rs
+++ b/src/librustc_feature/lib.rs
@@ -1,7 +1,8 @@
 //! # Feature gates
 //!
 //! This crate declares the set of past and present unstable features in the compiler.
-//! Feature gate checking itself is done in `libsyntax/feature_gate/check.rs` at the moment.
+//! Feature gate checking itself is done in `librustc_ast_passes/feature_gate.rs`
+//! at the moment.
 //!
 //! Features are enabled in programs via the crate-level attributes of
 //! `#![feature(...)]` with a comma-separated list of features.
diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs
index 1eeedd7..d5b6fe8 100644
--- a/src/librustc_feature/removed.rs
+++ b/src/librustc_feature/removed.rs
@@ -74,6 +74,8 @@
     (removed, pushpop_unsafe, "1.2.0", None, None, None),
     (removed, needs_allocator, "1.4.0", Some(27389), None,
      Some("subsumed by `#![feature(allocator_internals)]`")),
+    /// Allows identifying crates that contain sanitizer runtimes.
+    (removed, sanitizer_runtime, "1.17.0", None, None, None),
     (removed, proc_macro_mod, "1.27.0", Some(54727), None,
      Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
     (removed, proc_macro_expr, "1.27.0", Some(54727), None,
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 2303a85..550e365 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -905,7 +905,7 @@
     Lit(&'hir Expr<'hir>),
 
     /// A range pattern (e.g., `1..=2` or `1..2`).
-    Range(&'hir Expr<'hir>, &'hir Expr<'hir>, RangeEnd),
+    Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
 
     /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
     ///
@@ -1875,6 +1875,9 @@
     OpaqueTy(GenericBounds<'hir>),
 }
 
+// The name of the associated type for `Fn` return types.
+pub const FN_OUTPUT_NAME: Symbol = sym::Output;
+
 /// Bind a type to an associated type (i.e., `A = Foo`).
 ///
 /// Bindings like `A: Debug` are represented as a special type `A =
diff --git a/src/librustc_hir/hir_id.rs b/src/librustc_hir/hir_id.rs
index 4629464..6d2ec44 100644
--- a/src/librustc_hir/hir_id.rs
+++ b/src/librustc_hir/hir_id.rs
@@ -56,7 +56,6 @@
 rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId);
 rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId);
 
-use rustc_index::vec::Idx;
 rustc_index::newtype_index! {
     /// An `ItemLocalId` uniquely identifies something within a given "item-like";
     /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc_hir/intravisit.rs
similarity index 95%
rename from src/librustc/hir/intravisit.rs
rename to src/librustc_hir/intravisit.rs
index 780b0e3..3dbc525 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -31,21 +31,18 @@
 //! This order consistency is required in a few places in rustc, for
 //! example generator inference, and possibly also HIR borrowck.
 
-use crate::hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
-use crate::hir::map::Map;
 use crate::hir::*;
-
+use crate::hir_id::CRATE_HIR_ID;
+use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
 use rustc_span::Span;
 use syntax::ast::{Attribute, Ident, Label, Name};
+use syntax::walk_list;
 
 pub struct DeepVisitor<'v, V> {
     visitor: &'v mut V,
 }
 
-impl<'v, 'hir, V> DeepVisitor<'v, V>
-where
-    V: Visitor<'hir> + 'v,
-{
+impl<'v, V> DeepVisitor<'v, V> {
     pub fn new(base: &'v mut V) -> Self {
         DeepVisitor { visitor: base }
     }
@@ -122,6 +119,14 @@
     }
 }
 
+/// An abstract representation of the HIR `rustc::hir::map::Map`.
+pub trait Map<'hir> {
+    fn body(&self, id: BodyId) -> &'hir Body<'hir>;
+    fn item(&self, id: HirId) -> &'hir Item<'hir>;
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
+}
+
 /// Specifies what nested things a visitor wants to visit. The most
 /// common choice is `OnlyBodies`, which will cause the visitor to
 /// visit fn bodies for fns that it encounters, but skip over nested
@@ -129,7 +134,7 @@
 ///
 /// See the comments on `ItemLikeVisitor` for more details on the overall
 /// visit strategy.
-pub enum NestedVisitorMap<'this, 'tcx> {
+pub enum NestedVisitorMap<'this, M> {
     /// Do not visit any nested things. When you add a new
     /// "non-nested" thing, you will want to audit such uses to see if
     /// they remain valid.
@@ -146,20 +151,20 @@
     /// to use `visit_all_item_likes()` as an outer loop,
     /// and to have the visitor that visits the contents of each item
     /// using this setting.
-    OnlyBodies(&'this Map<'tcx>),
+    OnlyBodies(&'this M),
 
     /// Visits all nested things, including item-likes.
     ///
     /// **This is an unusual choice.** It is used when you want to
     /// process everything within their lexical context. Typically you
     /// kick off the visit by doing `walk_krate()`.
-    All(&'this Map<'tcx>),
+    All(&'this M),
 }
 
-impl<'this, 'tcx> NestedVisitorMap<'this, 'tcx> {
+impl<'this, M> NestedVisitorMap<'this, M> {
     /// Returns the map to use for an "intra item-like" thing (if any).
     /// E.g., function body.
-    pub fn intra(self) -> Option<&'this Map<'tcx>> {
+    fn intra(self) -> Option<&'this M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(map) => Some(map),
@@ -169,7 +174,7 @@
 
     /// Returns the map to use for an "item-like" thing (if any).
     /// E.g., item, impl-item.
-    pub fn inter(self) -> Option<&'this Map<'tcx>> {
+    fn inter(self) -> Option<&'this M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(_) => None,
@@ -195,6 +200,8 @@
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
 pub trait Visitor<'v>: Sized {
+    type Map: Map<'v>;
+
     ///////////////////////////////////////////////////////////////////////////
     // Nested items.
 
@@ -214,7 +221,7 @@
     /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
     /// added in the future, we will see the panic in your code and
     /// fix it appropriately.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>;
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map>;
 
     /// Invoked when a nested item is encountered. By default does
     /// nothing unless you override `nested_visit_map` to return other than
@@ -226,10 +233,8 @@
     /// but cannot supply a `Map`; see `nested_visit_map` for advice.
     #[allow(unused_variables)]
     fn visit_nested_item(&mut self, id: ItemId) {
-        let opt_item = self.nested_visit_map().inter().map(|map| map.expect_item(id.id));
-        if let Some(item) = opt_item {
-            self.visit_item(item);
-        }
+        let opt_item = self.nested_visit_map().inter().map(|map| map.item(id.id));
+        walk_list!(self, visit_item, opt_item);
     }
 
     /// Like `visit_nested_item()`, but for trait items. See
@@ -238,9 +243,7 @@
     #[allow(unused_variables)]
     fn visit_nested_trait_item(&mut self, id: TraitItemId) {
         let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id));
-        if let Some(item) = opt_item {
-            self.visit_trait_item(item);
-        }
+        walk_list!(self, visit_trait_item, opt_item);
     }
 
     /// Like `visit_nested_item()`, but for impl items. See
@@ -249,9 +252,7 @@
     #[allow(unused_variables)]
     fn visit_nested_impl_item(&mut self, id: ImplItemId) {
         let opt_item = self.nested_visit_map().inter().map(|map| map.impl_item(id));
-        if let Some(item) = opt_item {
-            self.visit_impl_item(item);
-        }
+        walk_list!(self, visit_impl_item, opt_item);
     }
 
     /// Invoked to visit the body of a function, method or closure. Like
@@ -260,9 +261,7 @@
     /// the body.
     fn visit_nested_body(&mut self, id: BodyId) {
         let opt_body = self.nested_visit_map().intra().map(|map| map.body(id));
-        if let Some(body) = opt_body {
-            self.visit_body(body);
-        }
+        walk_list!(self, visit_body, opt_body);
     }
 
     fn visit_param(&mut self, param: &'v Param<'v>) {
@@ -496,21 +495,16 @@
     }
 }
 
-pub fn walk_poly_trait_ref<'v, V>(
+pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
     visitor: &mut V,
     trait_ref: &'v PolyTraitRef<'v>,
     _modifier: TraitBoundModifier,
-) where
-    V: Visitor<'v>,
-{
+) {
     walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
     visitor.visit_trait_ref(&trait_ref.trait_ref);
 }
 
-pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef<'v>)
-where
-    V: Visitor<'v>,
-{
+pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) {
     visitor.visit_id(trait_ref.hir_ref_id);
     visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
 }
@@ -688,9 +682,7 @@
 ) {
     match *qpath {
         QPath::Resolved(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(qself);
-            }
+            walk_list!(visitor, visit_ty, maybe_qself);
             visitor.visit_path(path, id)
         }
         QPath::TypeRelative(ref qself, ref segment) => {
@@ -712,9 +704,7 @@
     segment: &'v PathSegment<'v>,
 ) {
     visitor.visit_ident(segment.ident);
-    if let Some(id) = segment.hir_id {
-        visitor.visit_id(id);
-    }
+    walk_list!(visitor, visit_id, segment.hir_id);
     if let Some(ref args) = segment.args {
         visitor.visit_generic_args(path_span, args);
     }
@@ -776,8 +766,8 @@
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visitor.visit_expr(lower_bound);
-            visitor.visit_expr(upper_bound)
+            walk_list!(visitor, visit_expr, lower_bound);
+            walk_list!(visitor, visit_expr, upper_bound);
         }
         PatKind::Wild => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
@@ -867,7 +857,7 @@
 }
 
 pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy<'v>) {
-    if let Return(ref output_ty) = *ret_ty {
+    if let FunctionRetTy::Return(ref output_ty) = *ret_ty {
         visitor.visit_ty(output_ty)
     }
 }
@@ -1003,9 +993,7 @@
     visitor: &mut V,
     struct_definition: &'v VariantData<'v>,
 ) {
-    if let Some(ctor_hir_id) = struct_definition.ctor_hir_id() {
-        visitor.visit_id(ctor_hir_id);
-    }
+    walk_list!(visitor, visit_id, struct_definition.ctor_hir_id());
     walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
@@ -1125,15 +1113,11 @@
             visitor.visit_qpath(qpath, expression.hir_id, expression.span);
         }
         ExprKind::Break(ref destination, ref opt_expr) => {
-            if let Some(ref label) = destination.label {
-                visitor.visit_label(label);
-            }
+            walk_list!(visitor, visit_label, &destination.label);
             walk_list!(visitor, visit_expr, opt_expr);
         }
         ExprKind::Continue(ref destination) => {
-            if let Some(ref label) = destination.label {
-                visitor.visit_label(label);
-            }
+            walk_list!(visitor, visit_label, &destination.label);
         }
         ExprKind::Ret(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs
index 8bf2e62..f54fa29 100644
--- a/src/librustc_hir/lib.rs
+++ b/src/librustc_hir/lib.rs
@@ -3,7 +3,7 @@
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
 
 #![feature(crate_visibility_modifier)]
-#![feature(const_fn)]
+#![feature(const_fn)] // For the unsizing cast on `&[]`
 #![feature(in_band_lifetimes)]
 #![feature(specialization)]
 #![recursion_limit = "256"]
@@ -15,6 +15,7 @@
 pub mod def_id;
 mod hir;
 pub mod hir_id;
+pub mod intravisit;
 pub mod itemlikevisit;
 pub mod pat_util;
 pub mod print;
diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs
index 571bab2..759f423 100644
--- a/src/librustc_hir/print.rs
+++ b/src/librustc_hir/print.rs
@@ -1767,13 +1767,17 @@
             }
             PatKind::Lit(ref e) => self.print_expr(&e),
             PatKind::Range(ref begin, ref end, ref end_kind) => {
-                self.print_expr(&begin);
-                self.s.space();
+                if let Some(expr) = begin {
+                    self.print_expr(expr);
+                    self.s.space();
+                }
                 match *end_kind {
                     RangeEnd::Included => self.s.word("..."),
                     RangeEnd::Excluded => self.s.word(".."),
                 }
-                self.print_expr(&end);
+                if let Some(expr) = end {
+                    self.print_expr(expr);
+                }
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
                 self.s.word("[");
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index 3e55708..09b33a6 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -15,6 +15,7 @@
 rand = "0.7"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index 738dfa7..9490128 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -36,12 +36,13 @@
 use graphviz as dot;
 use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter};
 use rustc::dep_graph::{DepGraphQuery, DepKind, DepNode};
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast;
@@ -159,7 +160,9 @@
 }
 
 impl Visitor<'tcx> for IfThisChanged<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index b6ce12c..70abb38 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -21,9 +21,9 @@
 //! allows for doing a more fine-grained check to see if pre- or post-lto data
 //! was re-used.
 
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::mir::mono::CodegenUnitNameBuilder;
 use rustc::ty::TyCtxt;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_session::cgu_reuse_tracker::*;
 use rustc_span::symbol::{sym, Symbol};
 use std::collections::BTreeSet;
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 4d08cce..ddfed53 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -14,15 +14,16 @@
 //! the required condition is not met.
 
 use rustc::dep_graph::{label_strs, DepNode};
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::Node as HirNode;
-use rustc::hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
+use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::Node as HirNode;
+use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use std::iter::FromIterator;
@@ -547,7 +548,9 @@
 }
 
 impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
         intravisit::NestedVisitorMap::All(&self.tcx.hir())
     }
 
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index adf8f57..ba20006 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -190,6 +190,8 @@
         return;
     }
 
+    let _timer = sess.timer("incr_comp_prepare_session_directory");
+
     debug!("prepare_session_directory");
 
     // {incr-comp-dir}/{crate-name-and-disambiguator}
@@ -306,6 +308,8 @@
         return;
     }
 
+    let _timer = sess.timer("incr_comp_finalize_session_directory");
+
     let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
 
     if sess.has_errors_or_delayed_span_bugs() {
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index cb06dae..6c57f79 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -102,6 +102,8 @@
         return MaybeAsync::Sync(LoadResult::Ok { data: Default::default() });
     }
 
+    let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph");
+
     // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`.
     // Fortunately, we just checked that this isn't the case.
     let path = dep_graph_path_from(&sess.incr_comp_session_dir());
@@ -159,7 +161,7 @@
     }
 
     MaybeAsync::Async(std::thread::spawn(move || {
-        let _prof_timer = prof.generic_pass("background load prev dep-graph");
+        let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
 
         match load_data(report_incremental_info, &path) {
             LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 9487f02..588e639 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -32,15 +32,15 @@
         join(
             move || {
                 if tcx.sess.opts.debugging_opts.incremental_queries {
-                    sess.time("persist query result cache", || {
+                    sess.time("incr_comp_persist_result_cache", || {
                         save_in(sess, query_cache_path, |e| encode_query_cache(tcx, e));
                     });
                 }
             },
             || {
-                sess.time("persist dep-graph", || {
+                sess.time("incr_comp_persist_dep_graph", || {
                     save_in(sess, dep_graph_path, |e| {
-                        sess.time("encode dep-graph", || encode_dep_graph(tcx, e))
+                        sess.time("incr_comp_encode_dep_graph", || encode_dep_graph(tcx, e))
                     });
                 });
             },
@@ -142,7 +142,8 @@
     tcx.sess.opts.dep_tracking_hash().encode(encoder).unwrap();
 
     // Encode the graph data.
-    let serialized_graph = tcx.sess.time("getting serialized graph", || tcx.dep_graph.serialize());
+    let serialized_graph =
+        tcx.sess.time("incr_comp_serialize_dep_graph", || tcx.dep_graph.serialize());
 
     if tcx.sess.opts.debugging_opts.incremental_info {
         #[derive(Clone)]
@@ -223,7 +224,7 @@
         println!("[incremental]");
     }
 
-    tcx.sess.time("encoding serialized graph", || {
+    tcx.sess.time("incr_comp_encode_serialized_dep_graph", || {
         serialized_graph.encode(encoder).unwrap();
     });
 }
@@ -244,7 +245,7 @@
 }
 
 fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut Encoder) {
-    tcx.sess.time("serialize query result cache", || {
+    tcx.sess.time("incr_comp_serialize_result_cache", || {
         tcx.serialize_query_result_cache(encoder).unwrap();
     })
 }
diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs
index 1f6a330..d14bafb 100644
--- a/src/librustc_index/vec.rs
+++ b/src/librustc_index/vec.rs
@@ -120,13 +120,13 @@
         impl $type {
             $v const MAX_AS_U32: u32 = $max;
 
-            $v const MAX: $type = $type::from_u32_const($max);
+            $v const MAX: Self = Self::from_u32_const($max);
 
             #[inline]
             $v fn from_usize(value: usize) -> Self {
                 assert!(value <= ($max as usize));
                 unsafe {
-                    $type::from_u32_unchecked(value as u32)
+                    Self::from_u32_unchecked(value as u32)
                 }
             }
 
@@ -134,7 +134,7 @@
             $v fn from_u32(value: u32) -> Self {
                 assert!(value <= $max);
                 unsafe {
-                    $type::from_u32_unchecked(value)
+                    Self::from_u32_unchecked(value)
                 }
             }
 
@@ -152,13 +152,13 @@
                 ];
 
                 unsafe {
-                    $type { private: value }
+                    Self { private: value }
                 }
             }
 
             #[inline]
             $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
-                $type { private: value }
+                Self { private: value }
             }
 
             /// Extracts the value of this index as an integer.
@@ -184,14 +184,14 @@
             type Output = Self;
 
             fn add(self, other: usize) -> Self {
-                Self::new(self.index() + other)
+                Self::from_usize(self.index() + other)
             }
         }
 
-        impl Idx for $type {
+        impl $crate::vec::Idx for $type {
             #[inline]
             fn new(value: usize) -> Self {
-                Self::from(value)
+                Self::from_usize(value)
             }
 
             #[inline]
@@ -204,39 +204,39 @@
             #[inline]
             fn steps_between(start: &Self, end: &Self) -> Option<usize> {
                 <usize as ::std::iter::Step>::steps_between(
-                    &Idx::index(*start),
-                    &Idx::index(*end),
+                    &Self::index(*start),
+                    &Self::index(*end),
                 )
             }
 
             #[inline]
             fn replace_one(&mut self) -> Self {
-                ::std::mem::replace(self, Self::new(1))
+                ::std::mem::replace(self, Self::from_u32(1))
             }
 
             #[inline]
             fn replace_zero(&mut self) -> Self {
-                ::std::mem::replace(self, Self::new(0))
+                ::std::mem::replace(self, Self::from_u32(0))
             }
 
             #[inline]
             fn add_one(&self) -> Self {
-                Self::new(Idx::index(*self) + 1)
+                Self::from_usize(Self::index(*self) + 1)
             }
 
             #[inline]
             fn sub_one(&self) -> Self {
-                Self::new(Idx::index(*self) - 1)
+                Self::from_usize(Self::index(*self) - 1)
             }
 
             #[inline]
             fn add_usize(&self, u: usize) -> Option<Self> {
-                Idx::index(*self).checked_add(u).map(Self::new)
+                Self::index(*self).checked_add(u).map(Self::from_usize)
             }
 
             #[inline]
             fn sub_usize(&self, u: usize) -> Option<Self> {
-                Idx::index(*self).checked_sub(u).map(Self::new)
+                Self::index(*self).checked_sub(u).map(Self::from_usize)
             }
         }
 
@@ -257,14 +257,14 @@
         impl From<usize> for $type {
             #[inline]
             fn from(value: usize) -> Self {
-                $type::from_usize(value)
+                Self::from_usize(value)
             }
         }
 
         impl From<u32> for $type {
             #[inline]
             fn from(value: u32) -> Self {
-                $type::from_u32(value)
+                Self::from_u32(value)
             }
         }
 
@@ -409,7 +409,7 @@
     (@decodable $type:ident) => (
         impl ::rustc_serialize::Decodable for $type {
             fn decode<D: ::rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
-                d.read_u32().map(Self::from)
+                d.read_u32().map(Self::from_u32)
             }
         }
     );
@@ -500,7 +500,7 @@
                    const $name:ident = $constant:expr,
                    $($tokens:tt)*) => (
         $(#[doc = $doc])*
-        pub const $name: $type = $type::from_u32_const($constant);
+        $v const $name: $type = $type::from_u32_const($constant);
         $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
@@ -839,3 +839,6 @@
         I::new(n)
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustc_index/vec/tests.rs b/src/librustc_index/vec/tests.rs
new file mode 100644
index 0000000..15c43c7
--- /dev/null
+++ b/src/librustc_index/vec/tests.rs
@@ -0,0 +1,51 @@
+#![allow(dead_code)]
+newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA });
+
+#[test]
+fn index_size_is_optimized() {
+    use std::mem::size_of;
+
+    assert_eq!(size_of::<MyIdx>(), 4);
+    // Uses 0xFFFF_FFFB
+    assert_eq!(size_of::<Option<MyIdx>>(), 4);
+    // Uses 0xFFFF_FFFC
+    assert_eq!(size_of::<Option<Option<MyIdx>>>(), 4);
+    // Uses 0xFFFF_FFFD
+    assert_eq!(size_of::<Option<Option<Option<MyIdx>>>>(), 4);
+    // Uses 0xFFFF_FFFE
+    assert_eq!(size_of::<Option<Option<Option<Option<MyIdx>>>>>(), 4);
+    // Uses 0xFFFF_FFFF
+    assert_eq!(size_of::<Option<Option<Option<Option<Option<MyIdx>>>>>>(), 4);
+    // Uses a tag
+    assert_eq!(size_of::<Option<Option<Option<Option<Option<Option<MyIdx>>>>>>>(), 8);
+}
+
+#[test]
+fn range_iterator_iterates_forwards() {
+    let range = MyIdx::from_u32(1)..MyIdx::from_u32(4);
+    assert_eq!(
+        range.collect::<Vec<_>>(),
+        [MyIdx::from_u32(1), MyIdx::from_u32(2), MyIdx::from_u32(3)]
+    );
+}
+
+#[test]
+fn range_iterator_iterates_backwards() {
+    let range = MyIdx::from_u32(1)..MyIdx::from_u32(4);
+    assert_eq!(
+        range.rev().collect::<Vec<_>>(),
+        [MyIdx::from_u32(3), MyIdx::from_u32(2), MyIdx::from_u32(1)]
+    );
+}
+
+#[test]
+fn range_count_is_correct() {
+    let range = MyIdx::from_u32(1)..MyIdx::from_u32(4);
+    assert_eq!(range.count(), 3);
+}
+
+#[test]
+fn range_size_hint_is_correct() {
+    let range = MyIdx::from_u32(1)..MyIdx::from_u32(4);
+    assert_eq!(range.size_hint(), (3, Some(3)));
+}
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index be60b75..98f7def 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -17,10 +17,12 @@
 rustc_builtin_macros = { path = "../librustc_builtin_macros" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc = { path = "../librustc" }
 rustc_ast_lowering = { path = "../librustc_ast_lowering" }
+rustc_ast_passes = { path = "../librustc_ast_passes" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_traits = { path = "../librustc_traits" }
 rustc_data_structures = { path = "../librustc_data_structures" }
@@ -30,6 +32,7 @@
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
+rustc_mir_build = { path = "../librustc_mir_build" }
 rustc_passes = { path = "../librustc_passes" }
 rustc_typeck = { path = "../librustc_typeck" }
 rustc_lint = { path = "../librustc_lint" }
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index c444994..9cd9eb6 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -12,6 +12,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::OnDrop;
 use rustc_errors::registry::Registry;
+use rustc_lint::LintStore;
 use rustc_parse::new_parser_from_source_str;
 use rustc_span::edition;
 use rustc_span::source_map::{FileLoader, FileName, SourceMap};
@@ -36,7 +37,7 @@
     pub(crate) output_dir: Option<PathBuf>,
     pub(crate) output_file: Option<PathBuf>,
     pub(crate) crate_name: Option<String>,
-    pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
+    pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
     pub(crate) override_queries:
         Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>,
 }
@@ -136,7 +137,7 @@
     ///
     /// Note that if you find a Some here you probably want to call that function in the new
     /// function being registered.
-    pub register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
+    pub register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
 
     /// This is a callback from the driver that is called just after we have populated
     /// the list of queries.
@@ -177,11 +178,17 @@
         override_queries: config.override_queries,
     };
 
-    let _sess_abort_error = OnDrop(|| {
-        compiler.sess.diagnostic().print_error_count(registry);
-    });
+    let r = {
+        let _sess_abort_error = OnDrop(|| {
+            compiler.sess.diagnostic().print_error_count(registry);
+        });
 
-    f(&compiler)
+        f(&compiler)
+    };
+
+    let prof = compiler.sess.prof.clone();
+    prof.generic_activity("drop_compiler").run(move || drop(compiler));
+    r
 }
 
 pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index cd632c3..5f0d9ed 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -5,8 +5,7 @@
 use log::{info, log_enabled, warn};
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc::hir::map;
 use rustc::lint;
 use rustc::middle;
 use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
@@ -26,10 +25,13 @@
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
 use rustc_errors::PResult;
 use rustc_expand::base::ExtCtxt;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental;
+use rustc_lint::LintStore;
 use rustc_mir as mir;
+use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
-use rustc_passes::{self, ast_validation, hir_stats, layout_test};
+use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
 use rustc_privacy;
 use rustc_resolve::{Resolver, ResolverArenas};
@@ -37,7 +39,6 @@
 use rustc_span::FileName;
 use rustc_traits;
 use rustc_typeck as typeck;
-use syntax::early_buffered_lints::BufferedEarlyLint;
 use syntax::mut_visit::MutVisitor;
 use syntax::util::node_count::NodeCounter;
 use syntax::{self, ast, visit};
@@ -54,16 +55,13 @@
 use std::{env, fs, iter, mem};
 
 pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
-    sess.diagnostic().set_continue_after_error(sess.opts.debugging_opts.continue_parse_after_error);
-    let krate = sess.time("parsing", || match input {
+    let krate = sess.time("parse_crate", || match input {
         Input::File(file) => parse_crate_from_file(file, &sess.parse_sess),
         Input::Str { input, name } => {
             parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess)
         }
     })?;
 
-    sess.diagnostic().set_continue_after_error(true);
-
     if sess.opts.debugging_opts.ast_json_noexpand {
         println!("{}", json::as_json(&krate));
     }
@@ -74,7 +72,7 @@
     }
 
     if let Some(ref s) = sess.opts.debugging_opts.show_span {
-        syntax::show_span::run(sess.diagnostic(), s, &krate);
+        rustc_ast_passes::show_span::run(sess.diagnostic(), s, &krate);
     }
 
     if sess.opts.debugging_opts.hir_stats {
@@ -104,7 +102,7 @@
 /// Returns `None` if we're aborting after handling -W help.
 pub fn configure_and_expand(
     sess: Lrc<Session>,
-    lint_store: Lrc<lint::LintStore>,
+    lint_store: Lrc<LintStore>,
     metadata_loader: Box<MetadataLoaderDyn>,
     krate: ast::Crate,
     crate_name: &str,
@@ -154,11 +152,11 @@
 pub fn register_plugins<'a>(
     sess: &'a Session,
     metadata_loader: &'a dyn MetadataLoader,
-    register_lints: impl Fn(&Session, &mut lint::LintStore),
+    register_lints: impl Fn(&Session, &mut LintStore),
     mut krate: ast::Crate,
     crate_name: &str,
-) -> Result<(ast::Crate, Lrc<lint::LintStore>)> {
-    krate = sess.time("attributes injection", || {
+) -> Result<(ast::Crate, Lrc<LintStore>)> {
+    krate = sess.time("attributes_injection", || {
         rustc_builtin_macros::cmdline_attrs::inject(
             krate,
             &sess.parse_sess,
@@ -183,9 +181,7 @@
     rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator);
 
     if sess.opts.incremental.is_some() {
-        sess.time("garbage-collect incremental cache directory", || {
-            let _prof_timer =
-                sess.prof.generic_activity("incr_comp_garbage_collect_session_directories");
+        sess.time("incr_comp_garbage_collect_session_directories", || {
             if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
                 warn!(
                     "Error while trying to garbage collect incremental \
@@ -196,7 +192,7 @@
         });
     }
 
-    sess.time("recursion limit", || {
+    sess.time("recursion_limit", || {
         middle::recursion_limit::update_limits(sess, &krate);
     });
 
@@ -207,8 +203,8 @@
     register_lints(&sess, &mut lint_store);
 
     let registrars =
-        sess.time("plugin loading", || plugin::load::load_plugins(sess, metadata_loader, &krate));
-    sess.time("plugin registration", || {
+        sess.time("plugin_loading", || plugin::load::load_plugins(sess, metadata_loader, &krate));
+    sess.time("plugin_registration", || {
         let mut registry = plugin::Registry { lint_store: &mut lint_store };
         for registrar in registrars {
             registrar(&mut registry);
@@ -220,13 +216,13 @@
 
 fn configure_and_expand_inner<'a>(
     sess: &'a Session,
-    lint_store: &'a lint::LintStore,
+    lint_store: &'a LintStore,
     mut krate: ast::Crate,
     crate_name: &str,
     resolver_arenas: &'a ResolverArenas<'a>,
     metadata_loader: &'a MetadataLoaderDyn,
 ) -> Result<(ast::Crate, Resolver<'a>)> {
-    sess.time("pre-AST-expansion lint checks", || {
+    sess.time("pre_AST_expansion_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
             lint_store,
@@ -240,7 +236,7 @@
     let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
     rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition());
 
-    krate = sess.time("crate injection", || {
+    krate = sess.time("crate_injection", || {
         let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
         let (krate, name) = rustc_builtin_macros::standard_library_imports::inject(
             krate,
@@ -257,7 +253,7 @@
     util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer());
 
     // Expand all macros
-    krate = sess.time("expansion", || {
+    krate = sess.time("macro_expand_crate", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
         // dependencies. It's up to us to tell the system where to find all the
         // dependent dlls. Note that this uses cfg!(windows) as opposed to
@@ -302,11 +298,11 @@
         let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
 
         // Expand macros now!
-        let krate = sess.time("expand crate", || ecx.monotonic_expander().expand_crate(krate));
+        let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
 
         // The rest is error reporting
 
-        sess.time("check unused macros", || {
+        sess.time("check_unused_macros", || {
             ecx.check_unused_macros();
         });
 
@@ -325,7 +321,7 @@
         krate
     });
 
-    sess.time("maybe building test harness", || {
+    sess.time("maybe_building_test_harness", || {
         rustc_builtin_macros::test_harness::inject(
             &sess.parse_sess,
             &mut resolver,
@@ -349,8 +345,8 @@
         util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
     }
 
-    let has_proc_macro_decls = sess.time("AST validation", || {
-        ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
+    let has_proc_macro_decls = sess.time("AST_validation", || {
+        rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
     });
 
     let crate_types = sess.crate_types.borrow();
@@ -371,7 +367,7 @@
         msg.warn("The generated documentation may be incorrect");
         msg.emit()
     } else {
-        krate = sess.time("maybe creating a macro crate", || {
+        krate = sess.time("maybe_create_a_macro_crate", || {
             let num_crate_types = crate_types.len();
             let is_test_crate = sess.opts.test;
             rustc_builtin_macros::proc_macro_harness::inject(
@@ -401,13 +397,11 @@
         println!("{}", json::as_json(&krate));
     }
 
-    sess.time("name resolution", || {
-        resolver.resolve_crate(&krate);
-    });
+    resolver.resolve_crate(&krate);
 
     // Needs to go *after* expansion to be able to check the results of macro expansion.
-    sess.time("complete gated feature checking", || {
-        syntax::feature_gate::check_crate(
+    sess.time("complete_gated_feature_checking", || {
+        rustc_ast_passes::feature_gate::check_crate(
             &krate,
             &sess.parse_sess,
             &sess.features_untracked(),
@@ -418,8 +412,8 @@
     // Add all buffered lints from the `ParseSess` to the `Session`.
     sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
         info!("{} parse sess buffered_lints", buffered_lints.len());
-        for BufferedEarlyLint { id, span, msg, lint_id } in buffered_lints.drain(..) {
-            resolver.lint_buffer().buffer_lint(lint_id, id, span, &msg);
+        for early_lint in buffered_lints.drain(..) {
+            resolver.lint_buffer().add_early_lint(early_lint);
         }
     });
 
@@ -428,31 +422,29 @@
 
 pub fn lower_to_hir<'res, 'tcx>(
     sess: &'tcx Session,
-    lint_store: &lint::LintStore,
+    lint_store: &LintStore,
     resolver: &'res mut Resolver<'_>,
     dep_graph: &'res DepGraph,
     krate: &'res ast::Crate,
     arena: &'tcx Arena<'tcx>,
-) -> Result<hir::map::Forest<'tcx>> {
+) -> Result<map::Forest<'tcx>> {
     // Lower AST to HIR.
-    let hir_forest = sess.time("lowering AST -> HIR", || {
-        let hir_crate = rustc_ast_lowering::lower_crate(
-            sess,
-            &dep_graph,
-            &krate,
-            resolver,
-            rustc_parse::nt_to_tokenstream,
-            arena,
-        );
+    let hir_crate = rustc_ast_lowering::lower_crate(
+        sess,
+        &dep_graph,
+        &krate,
+        resolver,
+        rustc_parse::nt_to_tokenstream,
+        arena,
+    );
 
-        if sess.opts.debugging_opts.hir_stats {
-            hir_stats::print_hir_stats(&hir_crate);
-        }
+    if sess.opts.debugging_opts.hir_stats {
+        hir_stats::print_hir_stats(&hir_crate);
+    }
 
-        hir::map::Forest::new(hir_crate, &dep_graph)
-    });
+    let hir_forest = map::Forest::new(hir_crate, &dep_graph);
 
-    sess.time("early lint checks", || {
+    sess.time("early_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
             lint_store,
@@ -620,6 +612,8 @@
     boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
     crate_name: &str,
 ) -> Result<OutputFilenames> {
+    let _timer = sess.timer("prepare_outputs");
+
     // FIXME: rustdoc passes &[] instead of &krate.attrs here
     let outputs = util::build_output_filenames(
         &compiler.input,
@@ -676,8 +670,9 @@
     providers.analysis = analysis;
     proc_macro_decls::provide(providers);
     plugin::build::provide(providers);
-    hir::provide(providers);
+    rustc::hir::provide(providers);
     mir::provide(providers);
+    mir_build::provide(providers);
     rustc_privacy::provide(providers);
     typeck::provide(providers);
     ty::provide(providers);
@@ -713,8 +708,8 @@
 
 pub fn create_global_ctxt<'tcx>(
     compiler: &'tcx Compiler,
-    lint_store: Lrc<lint::LintStore>,
-    hir_forest: &'tcx hir::map::Forest<'tcx>,
+    lint_store: Lrc<LintStore>,
+    hir_forest: &'tcx map::Forest<'tcx>,
     mut resolver_outputs: ResolverOutputs,
     outputs: OutputFilenames,
     crate_name: &str,
@@ -726,12 +721,9 @@
     let defs = mem::take(&mut resolver_outputs.definitions);
 
     // Construct the HIR map.
-    let hir_map = sess.time("indexing HIR", || {
-        hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs)
-    });
+    let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs);
 
-    let query_result_on_disk_cache =
-        sess.time("load query result cache", || rustc_incremental::load_query_result_cache(sess));
+    let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
 
     let codegen_backend = compiler.codegen_backend();
     let mut local_providers = ty::query::Providers::default();
@@ -746,25 +738,27 @@
         callback(sess, &mut local_providers, &mut extern_providers);
     }
 
-    let gcx = global_ctxt.init_locking(|| {
-        TyCtxt::create_global_ctxt(
-            sess,
-            lint_store,
-            local_providers,
-            extern_providers,
-            &all_arenas,
-            arena,
-            resolver_outputs,
-            hir_map,
-            query_result_on_disk_cache,
-            &crate_name,
-            &outputs,
-        )
+    let gcx = sess.time("setup_global_ctxt", || {
+        global_ctxt.init_locking(|| {
+            TyCtxt::create_global_ctxt(
+                sess,
+                lint_store,
+                local_providers,
+                extern_providers,
+                &all_arenas,
+                arena,
+                resolver_outputs,
+                hir_map,
+                query_result_on_disk_cache,
+                &crate_name,
+                &outputs,
+            )
+        })
     });
 
     // Do some initialization of the DepGraph that can only be done with the tcx available.
     ty::tls::enter_global(&gcx, |tcx| {
-        tcx.sess.time("dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
+        tcx.sess.time("dep_graph_tcx_init", || rustc_incremental::dep_graph_tcx_init(tcx));
     });
 
     QueryContext(gcx)
@@ -778,17 +772,17 @@
     let sess = tcx.sess;
     let mut entry_point = None;
 
-    sess.time("misc checking 1", || {
+    sess.time("misc_checking_1", || {
         parallel!(
             {
                 entry_point = sess
-                    .time("looking for entry point", || rustc_passes::entry::find_entry_point(tcx));
+                    .time("looking_for_entry_point", || rustc_passes::entry::find_entry_point(tcx));
 
-                sess.time("looking for plugin registrar", || {
+                sess.time("looking_for_plugin_registrar", || {
                     plugin::build::find_plugin_registrar(tcx)
                 });
 
-                sess.time("looking for derive registrar", || proc_macro_decls::find(tcx));
+                sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx));
             },
             {
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
@@ -805,17 +799,17 @@
     // passes are timed inside typeck
     typeck::check_crate(tcx)?;
 
-    sess.time("misc checking 2", || {
+    sess.time("misc_checking_2", || {
         parallel!(
             {
-                sess.time("match checking", || {
+                sess.time("match_checking", || {
                     tcx.par_body_owners(|def_id| {
                         tcx.ensure().check_match(def_id);
                     });
                 });
             },
             {
-                sess.time("liveness checking + intrinsic checking", || {
+                sess.time("liveness_and_intrinsic_checking", || {
                     par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
                         // this must run before MIR dump, because
                         // "not all control paths return a value" is reported here.
@@ -831,21 +825,21 @@
         );
     });
 
-    sess.time("MIR borrow checking", || {
+    sess.time("MIR_borrow_checking", || {
         tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id));
     });
 
-    sess.time("dumping Chalk-like clauses", || {
+    sess.time("dumping_chalk_like_clauses", || {
         rustc_traits::lowering::dump_program_clauses(tcx);
     });
 
-    sess.time("MIR effect checking", || {
+    sess.time("MIR_effect_checking", || {
         for def_id in tcx.body_owners() {
             mir::transform::check_unsafety::check_unsafety(tcx, def_id)
         }
     });
 
-    sess.time("layout testing", || layout_test::test_layout(tcx));
+    sess.time("layout_testing", || layout_test::test_layout(tcx));
 
     // Avoid overwhelming user with errors if borrow checking failed.
     // I'm not sure how helpful this is, to be honest, but it avoids a
@@ -856,28 +850,25 @@
         return Err(ErrorReported);
     }
 
-    sess.time("misc checking 3", || {
+    sess.time("misc_checking_3", || {
         parallel!(
             {
-                sess.time("privacy access levels", || {
-                    tcx.ensure().privacy_access_levels(LOCAL_CRATE);
-                });
+                tcx.ensure().privacy_access_levels(LOCAL_CRATE);
+
                 parallel!(
                     {
-                        sess.time("private in public", || {
-                            tcx.ensure().check_private_in_public(LOCAL_CRATE);
-                        });
+                        tcx.ensure().check_private_in_public(LOCAL_CRATE);
                     },
                     {
-                        sess.time("death checking", || rustc_passes::dead::check_crate(tcx));
+                        sess.time("death_checking", || rustc_passes::dead::check_crate(tcx));
                     },
                     {
-                        sess.time("unused lib feature checking", || {
+                        sess.time("unused_lib_feature_checking", || {
                             rustc_passes::stability::check_unused_or_stable_features(tcx)
                         });
                     },
                     {
-                        sess.time("lint checking", || {
+                        sess.time("lint_checking", || {
                             rustc_lint::check_crate(tcx, || {
                                 rustc_lint::BuiltinCombinedLateLintPass::new()
                             });
@@ -886,7 +877,7 @@
                 );
             },
             {
-                sess.time("privacy checking modules", || {
+                sess.time("privacy_checking_modules", || {
                     par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
                         tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
                     });
@@ -929,6 +920,8 @@
         MetadataKind::Uncompressed | MetadataKind::Compressed => tcx.encode_metadata(),
     };
 
+    let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata");
+
     let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
     if need_metadata_file {
         let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str();
@@ -971,10 +964,9 @@
         tcx.print_debug_stats();
     }
 
-    let (metadata, need_metadata_module) =
-        tcx.sess.time("metadata encoding and writing", || encode_and_write_metadata(tcx, outputs));
+    let (metadata, need_metadata_module) = encode_and_write_metadata(tcx, outputs);
 
-    let codegen = tcx.sess.time("codegen", move || {
+    let codegen = tcx.sess.time("codegen_crate", move || {
         codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
     });
 
diff --git a/src/librustc_interface/proc_macro_decls.rs b/src/librustc_interface/proc_macro_decls.rs
index beb4790..9238f88 100644
--- a/src/librustc_interface/proc_macro_decls.rs
+++ b/src/librustc_interface/proc_macro_decls.rs
@@ -1,8 +1,8 @@
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 use syntax::attr;
 
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index c0a75e7..bd9717d 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -3,10 +3,7 @@
 
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::hir;
-use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::lint;
-use rustc::lint::LintStore;
+use rustc::hir::map;
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::session::Session;
 use rustc::ty::steal::Steal;
@@ -14,7 +11,9 @@
 use rustc::util::common::ErrorReported;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_incremental::DepGraphFuture;
+use rustc_lint::LintStore;
 use std::any::Any;
 use std::cell::{Ref, RefCell, RefMut};
 use std::mem;
@@ -76,7 +75,7 @@
     register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
     expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
     dep_graph: Query<DepGraph>,
-    lower_to_hir: Query<(&'tcx hir::map::Forest<'tcx>, Steal<ResolverOutputs>)>,
+    lower_to_hir: Query<(&'tcx map::Forest<'tcx>, Steal<ResolverOutputs>)>,
     prepare_outputs: Query<OutputFilenames>,
     global_ctxt: Query<QueryContext<'tcx>>,
     ongoing_codegen: Query<Box<dyn Any>>,
@@ -133,7 +132,7 @@
             let crate_name = self.crate_name()?.peek().clone();
             let krate = self.parse()?.take();
 
-            let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {};
+            let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};
             let result = passes::register_plugins(
                 self.session(),
                 &*self.codegen_backend().metadata_loader(),
@@ -176,6 +175,7 @@
         self.expansion.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let (krate, lint_store) = self.register_plugins()?.take();
+            let _timer = self.session().timer("configure_and_expand");
             passes::configure_and_expand(
                 self.session().clone(),
                 lint_store.clone(),
@@ -195,7 +195,7 @@
                 None => DepGraph::new_disabled(),
                 Some(future) => {
                     let (prev_graph, prev_work_products) =
-                        self.session().time("blocked while dep-graph loading finishes", || {
+                        self.session().time("blocked_on_dep_graph_loading", || {
                             future
                                 .open()
                                 .unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
@@ -211,7 +211,7 @@
 
     pub fn lower_to_hir(
         &'tcx self,
-    ) -> Result<&Query<(&'tcx hir::map::Forest<'tcx>, Steal<ResolverOutputs>)>> {
+    ) -> Result<&Query<(&'tcx map::Forest<'tcx>, Steal<ResolverOutputs>)>> {
         self.lower_to_hir.compute(|| {
             let expansion_result = self.expansion()?;
             let peeked = expansion_result.peek();
@@ -256,6 +256,7 @@
             let lint_store = self.expansion()?.peek().2.clone();
             let hir = self.lower_to_hir()?.peek();
             let (ref hir_forest, ref resolver_outputs) = &*hir;
+            let _timer = self.session().timer("create_global_ctxt");
             Ok(passes::create_global_ctxt(
                 self.compiler,
                 lint_store,
@@ -312,14 +313,19 @@
 
 impl Linker {
     pub fn link(self) -> Result<()> {
-        self.codegen_backend
+        let r = self
+            .codegen_backend
             .join_codegen_and_link(
                 self.ongoing_codegen,
                 &self.sess,
                 &self.dep_graph,
                 &self.prepare_outputs,
             )
-            .map_err(|_| ErrorReported)
+            .map_err(|_| ErrorReported);
+        let prof = self.sess.prof.clone();
+        let dep_graph = self.dep_graph;
+        prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph));
+        r
     }
 }
 
@@ -328,6 +334,7 @@
     where
         F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T,
     {
+        let mut _timer = None;
         let queries = Queries::new(&self);
         let ret = f(&queries);
 
@@ -337,6 +344,8 @@
             }
         }
 
+        _timer = Some(self.session().timer("free_global_ctxt"));
+
         ret
     }
 
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index 25ab765..ec75a1c 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -2,7 +2,7 @@
 
 use crate::interface::parse_cfgspecs;
 
-use rustc::lint;
+use rustc::lint::Level;
 use rustc::middle::cstore;
 use rustc::session::config::{build_configuration, build_session_options, to_crate_config};
 use rustc::session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
@@ -186,24 +186,24 @@
     let mut v3 = Options::default();
 
     v1.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("c"), lint::Deny),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("c"), Level::Deny),
+        (String::from("d"), Level::Forbid),
     ];
 
     v2.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("X"), lint::Deny),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("X"), Level::Deny),
+        (String::from("d"), Level::Forbid),
     ];
 
     v3.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("c"), lint::Forbid),
-        (String::from("d"), lint::Deny),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("c"), Level::Forbid),
+        (String::from("d"), Level::Deny),
     ];
 
     assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
@@ -222,17 +222,17 @@
     let mut v2 = Options::default();
 
     v1.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("c"), lint::Deny),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("c"), Level::Deny),
+        (String::from("d"), Level::Forbid),
     ];
 
     v2.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("c"), lint::Deny),
-        (String::from("b"), lint::Warn),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("c"), Level::Deny),
+        (String::from("b"), Level::Warn),
+        (String::from("d"), Level::Forbid),
     ];
 
     assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
@@ -602,10 +602,6 @@
     assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
     opts = reference.clone();
-    opts.debugging_opts.continue_parse_after_error = true;
-    assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
-
-    opts = reference.clone();
     opts.debugging_opts.force_overflow_checks = Some(true);
     assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index c15dc2f..2fafd3a 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -1,8 +1,5 @@
 use log::info;
 use rustc::lint;
-use rustc::session::config::{ErrorOutputType, Input, OutputFilenames};
-use rustc::session::CrateDisambiguator;
-use rustc::session::{self, config, early_error, filesearch, DiagnosticOutput, Session};
 use rustc::ty;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -14,6 +11,11 @@
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_resolve::{self, Resolver};
+use rustc_session as session;
+use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::CrateDisambiguator;
+use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
 use rustc_span::symbol::{sym, Symbol};
@@ -71,10 +73,6 @@
         lint_caps,
     );
 
-    sess.prof.register_queries(|profiler| {
-        rustc::ty::query::QueryName::register_with_profiler(&profiler);
-    });
-
     let codegen_backend = get_codegen_backend(&sess);
 
     let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
@@ -424,7 +422,7 @@
     CrateDisambiguator::from(hasher.finish::<Fingerprint>())
 }
 
-pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut lint::LintBuffer) {
+pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut LintBuffer) {
     // Unconditionally collect crate types from attributes to make them used
     for a in attrs.iter() {
         if a.check_name(sym::crate_type) {
@@ -446,7 +444,7 @@
                             ast::CRATE_NODE_ID,
                             span,
                             "invalid `crate_type` value",
-                            lint::builtin::BuiltinLintDiagnostics::UnknownCrateTypes(
+                            BuiltinLintDiagnostics::UnknownCrateTypes(
                                 span,
                                 "did you mean".to_string(),
                                 format!("\"{}\"", candidate),
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index a40c5d1..abf9f96 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -12,11 +12,13 @@
 log = "0.4"
 unicode-security = "0.0.2"
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_error_codes = { path = "../librustc_error_codes" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_index = { path = "../librustc_index" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs
index 6beedb0..fb11b67 100644
--- a/src/librustc_lint/array_into_iter.rs
+++ b/src/librustc_lint/array_into_iter.rs
@@ -1,14 +1,10 @@
-use crate::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
-use rustc::{
-    hir,
-    lint::FutureIncompatibleInfo,
-    ty::{
-        self,
-        adjustment::{Adjust, Adjustment},
-    },
-};
+use crate::{LateContext, LateLintPass, LintContext};
+use rustc::ty;
+use rustc::ty::adjustment::{Adjust, Adjustment};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::symbol::sym;
-use syntax::errors::Applicability;
 
 declare_lint! {
     pub ARRAY_INTO_ITER,
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 5e107b2..6aa809a 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -21,41 +21,37 @@
 //! If you define a new `LateLintPass`, you will also need to add it to the
 //! `late_lint_methods!` invocation in `lib.rs`.
 
-use std::fmt::Write;
-
-use lint::{EarlyContext, EarlyLintPass, LateLintPass, LintPass};
-use lint::{LateContext, LintArray, LintContext};
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::DefId;
-use rustc::hir::{HirIdSet, Node};
-use rustc::lint;
-use rustc::lint::FutureIncompatibleInfo;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc::hir::map::Map;
+use rustc::traits::misc::can_type_implement_copy;
 use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt};
-
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::Stability;
 use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType};
-
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{GenericParamKind, PatKind};
+use rustc_hir::{HirIdSet, Node};
+use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span};
 use syntax::ast::{self, Expr};
 use syntax::attr::{self, HasAttrs};
-use syntax::errors::{Applicability, DiagnosticBuilder};
 use syntax::print::pprust::{self, expr_to_string};
-use syntax::ptr::P;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::FnKind;
 
-use rustc::hir::{self, GenericParamKind, PatKind};
-
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
 use log::debug;
+use std::fmt::Write;
 
 // hardwired lints from librustc
-pub use lint::builtin::*;
+pub use rustc_session::lint::builtin::*;
 
 declare_lint! {
     WHILE_TRUE,
@@ -557,7 +553,7 @@
         if ty.is_copy_modulo_regions(cx.tcx, param_env, item.span) {
             return;
         }
-        if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() {
+        if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() {
             cx.span_lint(
                 MISSING_COPY_IMPLEMENTATIONS,
                 item.span,
@@ -1089,12 +1085,14 @@
         // bound.  Let's see if this type does that.
 
         // We use a HIR visitor to walk the type.
-        use rustc::hir::intravisit::{self, Visitor};
+        use rustc_hir::intravisit::{self, Visitor};
         struct WalkAssocTypes<'a, 'db> {
             err: &'a mut DiagnosticBuilder<'db>,
         }
         impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> {
-            fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
+            type Map = Map<'v>;
+
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
                 intravisit::NestedVisitorMap::None
             }
 
@@ -1307,11 +1305,13 @@
 
         /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
         /// corresponding to the ellipsis.
-        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P<Expr>, &P<Expr>, Span)> {
+        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> {
             match &pat.kind {
-                PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => {
-                    Some((a, b, *span))
-                }
+                PatKind::Range(
+                    a,
+                    Some(b),
+                    Spanned { span, node: RangeEnd::Included(DotDotDot) },
+                ) => Some((a.as_deref(), b, *span)),
                 _ => None,
             }
         }
@@ -1326,11 +1326,16 @@
             let suggestion = "use `..=` for an inclusive range";
             if parenthesise {
                 self.node_id = Some(pat.id);
+                let end = expr_to_string(&end);
+                let replace = match start {
+                    Some(start) => format!("&({}..={})", expr_to_string(&start), end),
+                    None => format!("&(..={})", end),
+                };
                 let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg);
                 err.span_suggestion(
                     pat.span,
                     suggestion,
-                    format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)),
+                    replace,
                     Applicability::MachineApplicable,
                 );
                 err.emit();
@@ -1807,7 +1812,7 @@
 }
 
 declare_lint_pass!(
-    /// Check for used feature gates in `INCOMPLETE_FEATURES` in `feature_gate.rs`.
+    /// Check for used feature gates in `INCOMPLETE_FEATURES` in `librustc_feature/active.rs`.
     IncompleteFeatures => [INCOMPLETE_FEATURES]
 );
 
diff --git a/src/librustc/lint/context.rs b/src/librustc_lint/context.rs
similarity index 85%
rename from src/librustc/lint/context.rs
rename to src/librustc_lint/context.rs
index ca6a7be..2b514c3 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc_lint/context.rs
@@ -16,26 +16,28 @@
 
 use self::TargetLint::*;
 
-use crate::hir;
-use crate::hir::def_id::{CrateNum, DefId};
-use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
-use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
-use crate::lint::{EarlyLintPassObject, LateLintPassObject};
-use crate::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
-use crate::middle::privacy::AccessLevels;
-use crate::session::Session;
-use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
-use crate::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
-use errors::DiagnosticBuilder;
+use crate::levels::LintLevelsBuilder;
+use crate::passes::{EarlyLintPassObject, LateLintPassObject};
+use rustc::hir::map::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc::lint::add_elided_lifetime_in_path_suggestion;
+use rustc::middle::privacy::AccessLevels;
+use rustc::middle::stability;
+use rustc::ty::layout::{LayoutError, LayoutOf, TyLayout};
+use rustc::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
-use rustc_span::{symbol::Symbol, MultiSpan, Span};
-use std::slice;
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
+use rustc_session::Session;
+use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
+use std::slice;
 
 /// Information about the registered lints.
 ///
@@ -64,17 +66,6 @@
     lint_groups: FxHashMap<&'static str, LintGroup>,
 }
 
-/// Lints that are buffered up early on in the `Session` before the
-/// `LintLevels` is calculated
-#[derive(PartialEq, Debug)]
-pub struct BufferedEarlyLint {
-    pub lint_id: LintId,
-    pub ast_id: ast::NodeId,
-    pub span: MultiSpan,
-    pub msg: String,
-    pub diagnostic: BuiltinLintDiagnostics,
-}
-
 /// The target of the `by_name` map, which accounts for renaming/deprecation.
 enum TargetLint {
     /// A direct lint target
@@ -290,7 +281,8 @@
             CheckLintNameResult::Ok(_) => None,
             CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
             CheckLintNameResult::NoLint(suggestion) => {
-                let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name);
+                let mut err =
+                    struct_span_err!(sess, DUMMY_SP, E0602, "unknown lint: `{}`", lint_name);
 
                 if let Some(suggestion) = suggestion {
                     err.help(&format!("did you mean: `{}`", suggestion));
@@ -494,7 +486,85 @@
         diagnostic: BuiltinLintDiagnostics,
     ) {
         let mut db = self.lookup(lint, span, msg);
-        diagnostic.run(self.sess(), &mut db);
+
+        let sess = self.sess();
+        match diagnostic {
+            BuiltinLintDiagnostics::Normal => (),
+            BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
+                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
+                    Ok(s) if is_global => {
+                        (format!("dyn ({})", s), Applicability::MachineApplicable)
+                    }
+                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
+                    Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
+                };
+                db.span_suggestion(span, "use `dyn`", sugg, app);
+            }
+            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
+                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
+                    Ok(ref s) => {
+                        // FIXME(Manishearth) ideally the emitting code
+                        // can tell us whether or not this is global
+                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
+
+                        (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
+                    }
+                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
+                };
+                db.span_suggestion(span, "use `crate`", sugg, app);
+            }
+            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
+                db.span_label(
+                    span,
+                    "names from parent modules are not accessible without an explicit import",
+                );
+            }
+            BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
+                db.span_note(span_def, "the macro is defined here");
+            }
+            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                n,
+                path_span,
+                incl_angl_brckt,
+                insertion_span,
+                anon_lts,
+            ) => {
+                add_elided_lifetime_in_path_suggestion(
+                    sess,
+                    &mut db,
+                    n,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_span,
+                    anon_lts,
+                );
+            }
+            BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
+                db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
+            }
+            BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
+                if !replaces.is_empty() {
+                    db.tool_only_multipart_suggestion(
+                        &message,
+                        replaces,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
+                for (span, is_imported) in spans {
+                    let introduced = if is_imported { "imported" } else { "defined" };
+                    db.span_label(
+                        span,
+                        format!("the item `{}` is already {} here", ident, introduced),
+                    );
+                }
+            }
+            BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
+                stability::deprecation_suggestion(&mut db, suggestion, span)
+            }
+        }
+
         db.emit();
     }
 
@@ -563,7 +633,7 @@
             sess,
             krate,
             lint_store,
-            builder: LintLevelSets::builder(sess, warn_about_weird_lints, lint_store),
+            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store),
             buffered,
         }
     }
diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs
index a099568..490114b 100644
--- a/src/librustc_lint/early.rs
+++ b/src/librustc_lint/early.rs
@@ -14,17 +14,16 @@
 //! upon. As the ast is traversed, this keeps track of the current lint level
 //! for all lint attributes.
 
-use rustc::lint::{EarlyContext, LintStore};
-use rustc::lint::{EarlyLintPass, EarlyLintPassObject};
-use rustc::lint::{LintBuffer, LintContext, LintPass};
-use rustc::session::Session;
-
+use crate::context::{EarlyContext, LintContext, LintStore};
+use crate::passes::{EarlyLintPass, EarlyLintPassObject};
+use rustc_session::lint::{LintBuffer, LintPass};
+use rustc_session::Session;
 use rustc_span::Span;
-use std::slice;
 use syntax::ast;
 use syntax::visit as ast_visit;
 
 use log::debug;
+use std::slice;
 
 macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
@@ -291,7 +290,7 @@
     )
 }
 
-early_lint_methods!(early_lint_pass_impl, []);
+crate::early_lint_methods!(early_lint_pass_impl, []);
 
 fn early_lint_crate<T: EarlyLintPass>(
     sess: &Session,
@@ -350,16 +349,19 @@
         }
     } else {
         for pass in &mut passes {
-            buffered = sess.time(&format!("running lint: {}", pass.name()), || {
-                early_lint_crate(
-                    sess,
-                    lint_store,
-                    krate,
-                    EarlyLintPassObjects { lints: slice::from_mut(pass) },
-                    buffered,
-                    pre_expansion,
-                )
-            });
+            buffered = sess
+                .prof
+                .extra_verbose_generic_activity(&format!("running lint: {}", pass.name()))
+                .run(|| {
+                    early_lint_crate(
+                        sess,
+                        lint_store,
+                        krate,
+                        EarlyLintPassObjects { lints: slice::from_mut(pass) },
+                        buffered,
+                        pre_expansion,
+                    )
+                });
         }
     }
 
diff --git a/src/librustc/lint/internal.rs b/src/librustc_lint/internal.rs
similarity index 96%
rename from src/librustc/lint/internal.rs
rename to src/librustc_lint/internal.rs
index f7dfbab..2f8393b 100644
--- a/src/librustc/lint/internal.rs
+++ b/src/librustc_lint/internal.rs
@@ -1,13 +1,11 @@
 //! Some lints that are only useful in the compiler or crates that use compiler internals, such as
 //! Clippy.
 
-use crate::hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
-use crate::lint::{
-    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
-};
-use errors::Applicability;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_session::declare_tool_lint;
+use rustc_errors::Applicability;
+use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
+use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast::{Ident, Item, ItemKind};
 
diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs
index e66de9c..30a3788 100644
--- a/src/librustc_lint/late.rs
+++ b/src/librustc_lint/late.rs
@@ -14,22 +14,29 @@
 //! upon. As the ast is traversed, this keeps track of the current lint level
 //! for all lint attributes.
 
-use rustc::hir;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::intravisit as hir_visit;
-use rustc::hir::intravisit::Visitor;
-use rustc::lint::LateContext;
-use rustc::lint::LintPass;
-use rustc::lint::{LateLintPass, LateLintPassObject};
+use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
+use rustc::hir::map::Map;
 use rustc::ty::{self, TyCtxt};
-
 use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::intravisit as hir_visit;
+use rustc_hir::intravisit::Visitor;
+use rustc_session::lint::LintPass;
 use rustc_span::Span;
-use std::slice;
 use syntax::ast;
+use syntax::walk_list;
 
 use log::debug;
-use syntax::walk_list;
+use std::any::Any;
+use std::slice;
+
+/// Extract the `LintStore` from the query context.
+/// This function exists because we've erased `LintStore` as `dyn Any` in the context.
+crate fn unerased_lint_store<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx LintStore {
+    let store: &dyn Any = &*tcx.lint_store;
+    store.downcast_ref().unwrap()
+}
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
@@ -87,10 +94,12 @@
 impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
     for LateContextAndPass<'a, 'tcx, T>
 {
+    type Map = Map<'tcx>;
+
     /// Because lints are scoped lexically, we want to walk nested
     /// items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, Self::Map> {
         hir_visit::NestedVisitorMap::All(&self.context.tcx.hir())
     }
 
@@ -340,7 +349,7 @@
     )
 }
 
-late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
+crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
 
 fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
     tcx: TyCtxt<'tcx>,
@@ -354,7 +363,7 @@
         tables: &ty::TypeckTables::empty(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
-        lint_store: &tcx.lint_store,
+        lint_store: unerased_lint_store(tcx),
         last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
         generics: None,
         only_module: true,
@@ -384,7 +393,7 @@
     late_lint_mod_pass(tcx, module_def_id, builtin_lints);
 
     let mut passes: Vec<_> =
-        tcx.lint_store.late_module_passes.iter().map(|pass| (pass)()).collect();
+        unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
 
     if !passes.is_empty() {
         late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
@@ -401,7 +410,7 @@
         tables: &ty::TypeckTables::empty(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
-        lint_store: &tcx.lint_store,
+        lint_store: unerased_lint_store(tcx),
         last_node_with_lint_attrs: hir::CRATE_HIR_ID,
         generics: None,
         only_module: false,
@@ -422,7 +431,7 @@
 }
 
 fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
-    let mut passes = tcx.lint_store.late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
+    let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
 
     if !tcx.sess.opts.debugging_opts.no_interleave_lints {
         if !passes.is_empty() {
@@ -432,18 +441,27 @@
         late_lint_pass_crate(tcx, builtin_lints);
     } else {
         for pass in &mut passes {
-            tcx.sess.time(&format!("running late lint: {}", pass.name()), || {
-                late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
-            });
+            tcx.sess
+                .prof
+                .extra_verbose_generic_activity(&format!("running late lint: {}", pass.name()))
+                .run(|| {
+                    late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
+                });
         }
 
         let mut passes: Vec<_> =
-            tcx.lint_store.late_module_passes.iter().map(|pass| (pass)()).collect();
+            unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
 
         for pass in &mut passes {
-            tcx.sess.time(&format!("running late module lint: {}", pass.name()), || {
-                late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
-            });
+            tcx.sess
+                .prof
+                .extra_verbose_generic_activity(&format!(
+                    "running late module lint: {}",
+                    pass.name()
+                ))
+                .run(|| {
+                    late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
+                });
         }
     }
 }
@@ -455,13 +473,13 @@
 ) {
     join(
         || {
-            tcx.sess.time("crate lints", || {
+            tcx.sess.time("crate_lints", || {
                 // Run whole crate non-incremental lints
                 late_lint_crate(tcx, builtin_lints());
             });
         },
         || {
-            tcx.sess.time("module lints", || {
+            tcx.sess.time("module_lints", || {
                 // Run per-module lints
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
                     tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs
index c148d39..bbc3e57 100644
--- a/src/librustc_lint/levels.rs
+++ b/src/librustc_lint/levels.rs
@@ -1,21 +1,33 @@
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
-use rustc::hir::intravisit;
-use rustc::lint::{LintLevelMap, LintLevelSets, LintLevelsBuilder, LintStore};
+use crate::context::{CheckLintNameResult, LintStore};
+use crate::late::unerased_lint_store;
+use rustc::hir::map::Map;
+use rustc::lint::struct_lint_level;
+use rustc::lint::{LintLevelMap, LintLevelSets, LintSet, LintSource};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_hir::hir_id::HirId;
+use rustc_hir::intravisit;
+use rustc_session::lint::{builtin, Level, Lint};
+use rustc_session::Session;
+use rustc_span::{sym, MultiSpan, Symbol};
 use syntax::ast;
+use syntax::attr;
+use syntax::print::pprust;
+use syntax::sess::feature_err;
+use syntax::unwrap_or;
 
-pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
+use std::cmp;
 
 fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
     assert_eq!(cnum, LOCAL_CRATE);
-    let store = &tcx.lint_store;
-    let mut builder = LintLevelMapBuilder {
-        levels: LintLevelSets::builder(tcx.sess, false, &store),
-        tcx: tcx,
-        store: store,
-    };
+    let store = unerased_lint_store(tcx);
+    let levels = LintLevelsBuilder::new(tcx.sess, false, &store);
+    let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
 
     let push = builder.levels.push(&krate.attrs, &store);
@@ -29,6 +41,378 @@
     tcx.arena.alloc(builder.levels.build_map())
 }
 
+pub struct LintLevelsBuilder<'a> {
+    sess: &'a Session,
+    sets: LintLevelSets,
+    id_to_set: FxHashMap<HirId, u32>,
+    cur: u32,
+    warn_about_weird_lints: bool,
+}
+
+pub struct BuilderPush {
+    prev: u32,
+    pub changed: bool,
+}
+
+impl<'a> LintLevelsBuilder<'a> {
+    pub fn new(sess: &'a Session, warn_about_weird_lints: bool, store: &LintStore) -> Self {
+        let mut builder = LintLevelsBuilder {
+            sess,
+            sets: LintLevelSets::new(),
+            cur: 0,
+            id_to_set: Default::default(),
+            warn_about_weird_lints,
+        };
+        builder.process_command_line(sess, store);
+        assert_eq!(builder.sets.list.len(), 1);
+        builder
+    }
+
+    fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
+        let mut specs = FxHashMap::default();
+        self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
+
+        for &(ref lint_name, level) in &sess.opts.lint_opts {
+            store.check_lint_name_cmdline(sess, &lint_name, level);
+
+            // If the cap is less than this specified level, e.g., if we've got
+            // `--cap-lints allow` but we've also got `-D foo` then we ignore
+            // this specification as the lint cap will set it to allow anyway.
+            let level = cmp::min(level, self.sets.lint_cap);
+
+            let lint_flag_val = Symbol::intern(lint_name);
+            let ids = match store.find_lints(&lint_name) {
+                Ok(ids) => ids,
+                Err(_) => continue, // errors handled in check_lint_name_cmdline above
+            };
+            for id in ids {
+                let src = LintSource::CommandLine(lint_flag_val);
+                specs.insert(id, (level, src));
+            }
+        }
+
+        self.sets.list.push(LintSet::CommandLine { specs });
+    }
+
+    /// Pushes a list of AST lint attributes onto this context.
+    ///
+    /// This function will return a `BuilderPush` object which should be passed
+    /// to `pop` when this scope for the attributes provided is exited.
+    ///
+    /// This function will perform a number of tasks:
+    ///
+    /// * It'll validate all lint-related attributes in `attrs`
+    /// * It'll mark all lint-related attributes as used
+    /// * Lint levels will be updated based on the attributes provided
+    /// * Lint attributes are validated, e.g., a #[forbid] can't be switched to
+    ///   #[allow]
+    ///
+    /// Don't forget to call `pop`!
+    pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush {
+        let mut specs = FxHashMap::default();
+        let sess = self.sess;
+        let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
+        for attr in attrs {
+            let level = match Level::from_symbol(attr.name_or_empty()) {
+                None => continue,
+                Some(lvl) => lvl,
+            };
+
+            let meta = unwrap_or!(attr.meta(), continue);
+            attr::mark_used(attr);
+
+            let mut metas = unwrap_or!(meta.meta_item_list(), continue);
+
+            if metas.is_empty() {
+                // FIXME (#55112): issue unused-attributes lint for `#[level()]`
+                continue;
+            }
+
+            // Before processing the lint names, look for a reason (RFC 2383)
+            // at the end.
+            let mut reason = None;
+            let tail_li = &metas[metas.len() - 1];
+            if let Some(item) = tail_li.meta_item() {
+                match item.kind {
+                    ast::MetaItemKind::Word => {} // actual lint names handled later
+                    ast::MetaItemKind::NameValue(ref name_value) => {
+                        if item.path == sym::reason {
+                            // found reason, reslice meta list to exclude it
+                            metas = &metas[0..metas.len() - 1];
+                            // FIXME (#55112): issue unused-attributes lint if we thereby
+                            // don't have any lint names (`#[level(reason = "foo")]`)
+                            if let ast::LitKind::Str(rationale, _) = name_value.kind {
+                                if !self.sess.features_untracked().lint_reasons {
+                                    feature_err(
+                                        &self.sess.parse_sess,
+                                        sym::lint_reasons,
+                                        item.span,
+                                        "lint reasons are experimental",
+                                    )
+                                    .emit();
+                                }
+                                reason = Some(rationale);
+                            } else {
+                                bad_attr(name_value.span)
+                                    .span_label(name_value.span, "reason must be a string literal")
+                                    .emit();
+                            }
+                        } else {
+                            bad_attr(item.span)
+                                .span_label(item.span, "bad attribute argument")
+                                .emit();
+                        }
+                    }
+                    ast::MetaItemKind::List(_) => {
+                        bad_attr(item.span).span_label(item.span, "bad attribute argument").emit();
+                    }
+                }
+            }
+
+            for li in metas {
+                let meta_item = match li.meta_item() {
+                    Some(meta_item) if meta_item.is_word() => meta_item,
+                    _ => {
+                        let sp = li.span();
+                        let mut err = bad_attr(sp);
+                        let mut add_label = true;
+                        if let Some(item) = li.meta_item() {
+                            if let ast::MetaItemKind::NameValue(_) = item.kind {
+                                if item.path == sym::reason {
+                                    err.span_label(sp, "reason in lint attribute must come last");
+                                    add_label = false;
+                                }
+                            }
+                        }
+                        if add_label {
+                            err.span_label(sp, "bad attribute argument");
+                        }
+                        err.emit();
+                        continue;
+                    }
+                };
+                let tool_name = if meta_item.path.segments.len() > 1 {
+                    let tool_ident = meta_item.path.segments[0].ident;
+                    if !attr::is_known_lint_tool(tool_ident) {
+                        struct_span_err!(
+                            sess,
+                            tool_ident.span,
+                            E0710,
+                            "an unknown tool name found in scoped lint: `{}`",
+                            pprust::path_to_string(&meta_item.path),
+                        )
+                        .emit();
+                        continue;
+                    }
+
+                    Some(tool_ident.name)
+                } else {
+                    None
+                };
+                let name = meta_item.path.segments.last().expect("empty lint name").ident.name;
+                match store.check_lint_name(&name.as_str(), tool_name) {
+                    CheckLintNameResult::Ok(ids) => {
+                        let src = LintSource::Node(name, li.span(), reason);
+                        for id in ids {
+                            specs.insert(*id, (level, src));
+                        }
+                    }
+
+                    CheckLintNameResult::Tool(result) => {
+                        match result {
+                            Ok(ids) => {
+                                let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
+                                let src = LintSource::Node(
+                                    Symbol::intern(complete_name),
+                                    li.span(),
+                                    reason,
+                                );
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((Some(ids), new_lint_name)) => {
+                                let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                                let (lvl, src) =
+                                    self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
+                                let msg = format!(
+                                    "lint name `{}` is deprecated \
+                                     and may not have an effect in the future. \
+                                     Also `cfg_attr(cargo-clippy)` won't be necessary anymore",
+                                    name
+                                );
+                                struct_lint_level(
+                                    self.sess,
+                                    lint,
+                                    lvl,
+                                    src,
+                                    Some(li.span().into()),
+                                    &msg,
+                                )
+                                .span_suggestion(
+                                    li.span(),
+                                    "change it to",
+                                    new_lint_name.to_string(),
+                                    Applicability::MachineApplicable,
+                                )
+                                .emit();
+
+                                let src = LintSource::Node(
+                                    Symbol::intern(&new_lint_name),
+                                    li.span(),
+                                    reason,
+                                );
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((None, _)) => {
+                                // If Tool(Err(None, _)) is returned, then either the lint does not
+                                // exist in the tool or the code was not compiled with the tool and
+                                // therefore the lint was never added to the `LintStore`. To detect
+                                // this is the responsibility of the lint tool.
+                            }
+                        }
+                    }
+
+                    _ if !self.warn_about_weird_lints => {}
+
+                    CheckLintNameResult::Warning(msg, renamed) => {
+                        let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                        let (level, src) =
+                            self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
+                        let mut err = struct_lint_level(
+                            self.sess,
+                            lint,
+                            level,
+                            src,
+                            Some(li.span().into()),
+                            &msg,
+                        );
+                        if let Some(new_name) = renamed {
+                            err.span_suggestion(
+                                li.span(),
+                                "use the new name",
+                                new_name,
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                        err.emit();
+                    }
+                    CheckLintNameResult::NoLint(suggestion) => {
+                        let lint = builtin::UNKNOWN_LINTS;
+                        let (level, src) =
+                            self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
+                        let msg = format!("unknown lint: `{}`", name);
+                        let mut db = struct_lint_level(
+                            self.sess,
+                            lint,
+                            level,
+                            src,
+                            Some(li.span().into()),
+                            &msg,
+                        );
+
+                        if let Some(suggestion) = suggestion {
+                            db.span_suggestion(
+                                li.span(),
+                                "did you mean",
+                                suggestion.to_string(),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+
+                        db.emit();
+                    }
+                }
+            }
+        }
+
+        for (id, &(level, ref src)) in specs.iter() {
+            if level == Level::Forbid {
+                continue;
+            }
+            let forbid_src = match self.sets.get_lint_id_level(*id, self.cur, None) {
+                (Some(Level::Forbid), src) => src,
+                _ => continue,
+            };
+            let forbidden_lint_name = match forbid_src {
+                LintSource::Default => id.to_string(),
+                LintSource::Node(name, _, _) => name.to_string(),
+                LintSource::CommandLine(name) => name.to_string(),
+            };
+            let (lint_attr_name, lint_attr_span) = match *src {
+                LintSource::Node(name, span, _) => (name, span),
+                _ => continue,
+            };
+            let mut diag_builder = struct_span_err!(
+                self.sess,
+                lint_attr_span,
+                E0453,
+                "{}({}) overruled by outer forbid({})",
+                level.as_str(),
+                lint_attr_name,
+                forbidden_lint_name
+            );
+            diag_builder.span_label(lint_attr_span, "overruled by previous forbid");
+            match forbid_src {
+                LintSource::Default => {}
+                LintSource::Node(_, forbid_source_span, reason) => {
+                    diag_builder.span_label(forbid_source_span, "`forbid` level set here");
+                    if let Some(rationale) = reason {
+                        diag_builder.note(&rationale.as_str());
+                    }
+                }
+                LintSource::CommandLine(_) => {
+                    diag_builder.note("`forbid` lint level was set on command line");
+                }
+            }
+            diag_builder.emit();
+            // don't set a separate error for every lint in the group
+            break;
+        }
+
+        let prev = self.cur;
+        if specs.len() > 0 {
+            self.cur = self.sets.list.len() as u32;
+            self.sets.list.push(LintSet::Node { specs: specs, parent: prev });
+        }
+
+        BuilderPush { prev: prev, changed: prev != self.cur }
+    }
+
+    /// Called after `push` when the scope of a set of attributes are exited.
+    pub fn pop(&mut self, push: BuilderPush) {
+        self.cur = push.prev;
+    }
+
+    /// Used to emit a lint-related diagnostic based on the current state of
+    /// this lint context.
+    pub fn struct_lint(
+        &self,
+        lint: &'static Lint,
+        span: Option<MultiSpan>,
+        msg: &str,
+    ) -> DiagnosticBuilder<'a> {
+        let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess);
+        struct_lint_level(self.sess, lint, level, src, span, msg)
+    }
+
+    /// Registers the ID provided with the current set of lints stored in
+    /// this context.
+    pub fn register_id(&mut self, id: HirId) {
+        self.id_to_set.insert(id, self.cur);
+    }
+
+    pub fn build(self) -> LintLevelSets {
+        self.sets
+    }
+
+    pub fn build_map(self) -> LintLevelMap {
+        LintLevelMap { sets: self.sets, id_to_set: self.id_to_set }
+    }
+}
+
 struct LintLevelMapBuilder<'a, 'tcx> {
     levels: LintLevelsBuilder<'tcx>,
     tcx: TyCtxt<'tcx>,
@@ -50,7 +434,9 @@
 }
 
 impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
         intravisit::NestedVisitorMap::All(&self.tcx.hir())
     }
 
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 2a3b90f..78e9d0f 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -1,9 +1,25 @@
-//! # Lints in the Rust compiler
+//! Lints, aka compiler warnings.
 //!
-//! This currently only contains the definitions and implementations
-//! of most of the lints that `rustc` supports directly, it does not
-//! contain the infrastructure for defining/registering lints. That is
-//! available in `rustc::lint` and `rustc_driver::plugin` respectively.
+//! A 'lint' check is a kind of miscellaneous constraint that a user _might_
+//! want to enforce, but might reasonably want to permit as well, on a
+//! module-by-module basis. They contrast with static constraints enforced by
+//! other phases of the compiler, which are generally required to hold in order
+//! to compile the program at all.
+//!
+//! Most lints can be written as `LintPass` instances. These run after
+//! all other analyses. The `LintPass`es built into rustc are defined
+//! within `rustc_session::lint::builtin`,
+//! which has further comments on how to add such a lint.
+//! rustc can also load user-defined lint plugins via the plugin mechanism.
+//!
+//! Some of rustc's lints are defined elsewhere in the compiler and work by
+//! calling `add_lint()` on the overall `Session` object. This works when
+//! it happens before the main lint pass, which emits the lints stored by
+//! `add_lint()`. To emit lints after the main lint pass (from codegen, for
+//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
+//! in `context.rs`.
+//!
+//! Some code also exists in `rustc_session::lint`, `rustc::lint`.
 //!
 //! ## Note
 //!
@@ -14,6 +30,8 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
+#![feature(never_type)]
 #![feature(nll)]
 #![recursion_limit = "256"]
 
@@ -24,44 +42,47 @@
 
 mod array_into_iter;
 pub mod builtin;
+mod context;
 mod early;
+mod internal;
 mod late;
 mod levels;
 mod non_ascii_idents;
 mod nonstandard_style;
+mod passes;
 mod redundant_semicolon;
 mod types;
 mod unused;
 
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::lint;
-use rustc::lint::builtin::{
+use rustc::ty::query::Providers;
+use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::{
     BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
     INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS,
 };
-use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
-use rustc::ty::query::Providers;
-use rustc::ty::TyCtxt;
-
 use rustc_span::Span;
 use syntax::ast;
 
-use lint::LintId;
-
 use array_into_iter::ArrayIntoIter;
 use builtin::*;
+use internal::*;
 use non_ascii_idents::*;
 use nonstandard_style::*;
 use redundant_semicolon::*;
-use rustc::lint::internal::*;
 use types::*;
 use unused::*;
 
-/// Useful for other parts of the compiler.
+/// Useful for other parts of the compiler / Clippy.
 pub use builtin::SoftLints;
+pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore};
 pub use early::check_ast_crate;
 pub use late::check_crate;
+pub use passes::{EarlyLintPass, LateLintPass};
+pub use rustc_session::lint::Level::{self, *};
+pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId};
+pub use rustc_session::lint::{LintArray, LintPass};
 
 pub fn provide(providers: &mut Providers<'_>) {
     levels::provide(providers);
@@ -178,8 +199,8 @@
 
 late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]);
 
-pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> lint::LintStore {
-    let mut lint_store = lint::LintStore::new();
+pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintStore {
+    let mut lint_store = LintStore::new();
 
     register_builtins(&mut lint_store, no_interleave_lints);
     if internal_lints {
@@ -192,7 +213,7 @@
 /// Tell the `LintStore` about all the built-in lints (the ones
 /// defined in this crate and the ones defined in
 /// `rustc::lint::builtin`).
-fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) {
+fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
     macro_rules! add_lint_group {
         ($name:expr, $($lint:ident),*) => (
             store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]);
@@ -389,7 +410,7 @@
     store.register_removed("plugin_as_library", "plugins have been deprecated and retired");
 }
 
-fn register_internals(store: &mut lint::LintStore) {
+fn register_internals(store: &mut LintStore) {
     store.register_lints(&DefaultHashTypes::get_lints());
     store.register_early_pass(|| box DefaultHashTypes::new());
     store.register_lints(&LintPassImpl::get_lints());
diff --git a/src/librustc_lint/non_ascii_idents.rs b/src/librustc_lint/non_ascii_idents.rs
index f30d0bc..3c85a1b 100644
--- a/src/librustc_lint/non_ascii_idents.rs
+++ b/src/librustc_lint/non_ascii_idents.rs
@@ -1,4 +1,4 @@
-use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use crate::{EarlyContext, EarlyLintPass, LintContext};
 use syntax::ast;
 
 declare_lint! {
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index a97061c..a2b7884 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -1,16 +1,15 @@
-use lint::{EarlyContext, LateContext, LintArray, LintContext};
-use lint::{EarlyLintPass, LateLintPass, LintPass};
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::intravisit::FnKind;
-use rustc::hir::{self, GenericParamKind, PatKind};
-use rustc::lint;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::ty;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{GenericParamKind, PatKind};
 use rustc_span::symbol::sym;
 use rustc_span::{symbol::Ident, BytePos, Span};
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
-use syntax::errors::Applicability;
 
 #[derive(PartialEq)]
 pub enum MethodLateContext {
@@ -142,6 +141,12 @@
         }
     }
 
+    fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
+        if let ast::AssocItemKind::TyAlias(..) = it.kind {
+            self.check_case(cx, "associated type", &it.ident);
+        }
+    }
+
     fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
         self.check_case(cx, "variant", &v.ident);
     }
diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs
new file mode 100644
index 0000000..7e5d670
--- /dev/null
+++ b/src/librustc_lint/passes.rs
@@ -0,0 +1,284 @@
+use crate::context::{EarlyContext, LateContext};
+
+use rustc_data_structures::sync;
+use rustc_hir as hir;
+use rustc_session::lint::builtin::HardwiredLints;
+use rustc_session::lint::LintPass;
+use rustc_span::Span;
+use syntax::ast;
+
+#[macro_export]
+macro_rules! late_lint_methods {
+    ($macro:path, $args:tt, [$hir:tt]) => (
+        $macro!($args, [$hir], [
+            fn check_param(a: &$hir hir::Param<$hir>);
+            fn check_body(a: &$hir hir::Body<$hir>);
+            fn check_body_post(a: &$hir hir::Body<$hir>);
+            fn check_name(a: Span, b: ast::Name);
+            fn check_crate(a: &$hir hir::Crate<$hir>);
+            fn check_crate_post(a: &$hir hir::Crate<$hir>);
+            fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
+            fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
+            fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
+            fn check_foreign_item_post(a: &$hir hir::ForeignItem<$hir>);
+            fn check_item(a: &$hir hir::Item<$hir>);
+            fn check_item_post(a: &$hir hir::Item<$hir>);
+            fn check_local(a: &$hir hir::Local<$hir>);
+            fn check_block(a: &$hir hir::Block<$hir>);
+            fn check_block_post(a: &$hir hir::Block<$hir>);
+            fn check_stmt(a: &$hir hir::Stmt<$hir>);
+            fn check_arm(a: &$hir hir::Arm<$hir>);
+            fn check_pat(a: &$hir hir::Pat<$hir>);
+            fn check_expr(a: &$hir hir::Expr<$hir>);
+            fn check_expr_post(a: &$hir hir::Expr<$hir>);
+            fn check_ty(a: &$hir hir::Ty<$hir>);
+            fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
+            fn check_generics(a: &$hir hir::Generics<$hir>);
+            fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>);
+            fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>, b: hir::TraitBoundModifier);
+            fn check_fn(
+                a: rustc_hir::intravisit::FnKind<$hir>,
+                b: &$hir hir::FnDecl<$hir>,
+                c: &$hir hir::Body<$hir>,
+                d: Span,
+                e: hir::HirId);
+            fn check_fn_post(
+                a: rustc_hir::intravisit::FnKind<$hir>,
+                b: &$hir hir::FnDecl<$hir>,
+                c: &$hir hir::Body<$hir>,
+                d: Span,
+                e: hir::HirId
+            );
+            fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
+            fn check_trait_item_post(a: &$hir hir::TraitItem<$hir>);
+            fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
+            fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
+            fn check_struct_def(a: &$hir hir::VariantData<$hir>);
+            fn check_struct_def_post(a: &$hir hir::VariantData<$hir>);
+            fn check_struct_field(a: &$hir hir::StructField<$hir>);
+            fn check_variant(a: &$hir hir::Variant<$hir>);
+            fn check_variant_post(a: &$hir hir::Variant<$hir>);
+            fn check_lifetime(a: &$hir hir::Lifetime);
+            fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
+            fn check_attribute(a: &$hir ast::Attribute);
+
+            /// Called when entering a syntax node that can have lint attributes such
+            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
+            fn enter_lint_attrs(a: &$hir [ast::Attribute]);
+
+            /// Counterpart to `enter_lint_attrs`.
+            fn exit_lint_attrs(a: &$hir [ast::Attribute]);
+        ]);
+    )
+}
+
+/// Trait for types providing lint checks.
+///
+/// Each `check` method checks a single syntax node, and should not
+/// invoke methods recursively (unlike `Visitor`). By default they
+/// do nothing.
+//
+// FIXME: eliminate the duplication with `Visitor`. But this also
+// contains a few lint-specific methods with no equivalent in `Visitor`.
+
+macro_rules! expand_lint_pass_methods {
+    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
+    )
+}
+
+macro_rules! declare_late_lint_pass {
+    ([], [$hir:tt], [$($methods:tt)*]) => (
+        pub trait LateLintPass<'a, $hir>: LintPass {
+            expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]);
+        }
+    )
+}
+
+late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
+
+impl LateLintPass<'_, '_> for HardwiredLints {}
+
+#[macro_export]
+macro_rules! expand_combined_late_lint_pass_method {
+    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$passes.$name $params;)*
+    })
+}
+
+#[macro_export]
+macro_rules! expand_combined_late_lint_pass_methods {
+    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(fn $name(&mut self, context: &LateContext<'a, 'tcx>, $($param: $arg),*) {
+            expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
+        })*
+    )
+}
+
+#[macro_export]
+macro_rules! declare_combined_late_lint_pass {
+    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
+        #[allow(non_snake_case)]
+        $v struct $name {
+            $($passes: $passes,)*
+        }
+
+        impl $name {
+            $v fn new() -> Self {
+                Self {
+                    $($passes: $constructor,)*
+                }
+            }
+
+            $v fn get_lints() -> LintArray {
+                let mut lints = Vec::new();
+                $(lints.extend_from_slice(&$passes::get_lints());)*
+                lints
+            }
+        }
+
+        impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name {
+            expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
+        }
+
+        #[allow(rustc::lint_pass_impl_without_macro)]
+        impl LintPass for $name {
+            fn name(&self) -> &'static str {
+                panic!()
+            }
+        }
+    )
+}
+
+#[macro_export]
+macro_rules! early_lint_methods {
+    ($macro:path, $args:tt) => (
+        $macro!($args, [
+            fn check_param(a: &ast::Param);
+            fn check_ident(a: ast::Ident);
+            fn check_crate(a: &ast::Crate);
+            fn check_crate_post(a: &ast::Crate);
+            fn check_mod(a: &ast::Mod, b: Span, c: ast::NodeId);
+            fn check_mod_post(a: &ast::Mod, b: Span, c: ast::NodeId);
+            fn check_foreign_item(a: &ast::ForeignItem);
+            fn check_foreign_item_post(a: &ast::ForeignItem);
+            fn check_item(a: &ast::Item);
+            fn check_item_post(a: &ast::Item);
+            fn check_local(a: &ast::Local);
+            fn check_block(a: &ast::Block);
+            fn check_block_post(a: &ast::Block);
+            fn check_stmt(a: &ast::Stmt);
+            fn check_arm(a: &ast::Arm);
+            fn check_pat(a: &ast::Pat);
+            fn check_pat_post(a: &ast::Pat);
+            fn check_expr(a: &ast::Expr);
+            fn check_expr_post(a: &ast::Expr);
+            fn check_ty(a: &ast::Ty);
+            fn check_generic_param(a: &ast::GenericParam);
+            fn check_generics(a: &ast::Generics);
+            fn check_where_predicate(a: &ast::WherePredicate);
+            fn check_poly_trait_ref(a: &ast::PolyTraitRef,
+                                    b: &ast::TraitBoundModifier);
+            fn check_fn(a: syntax::visit::FnKind<'_>, b: &ast::FnDecl, c: Span, d_: ast::NodeId);
+            fn check_fn_post(
+                a: syntax::visit::FnKind<'_>,
+                b: &ast::FnDecl,
+                c: Span,
+                d: ast::NodeId
+            );
+            fn check_trait_item(a: &ast::AssocItem);
+            fn check_trait_item_post(a: &ast::AssocItem);
+            fn check_impl_item(a: &ast::AssocItem);
+            fn check_impl_item_post(a: &ast::AssocItem);
+            fn check_struct_def(a: &ast::VariantData);
+            fn check_struct_def_post(a: &ast::VariantData);
+            fn check_struct_field(a: &ast::StructField);
+            fn check_variant(a: &ast::Variant);
+            fn check_variant_post(a: &ast::Variant);
+            fn check_lifetime(a: &ast::Lifetime);
+            fn check_path(a: &ast::Path, b: ast::NodeId);
+            fn check_attribute(a: &ast::Attribute);
+            fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
+            fn check_mac(a: &ast::Mac);
+
+            /// Called when entering a syntax node that can have lint attributes such
+            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
+            fn enter_lint_attrs(a: &[ast::Attribute]);
+
+            /// Counterpart to `enter_lint_attrs`.
+            fn exit_lint_attrs(a: &[ast::Attribute]);
+        ]);
+    )
+}
+
+macro_rules! expand_early_lint_pass_methods {
+    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
+    )
+}
+
+macro_rules! declare_early_lint_pass {
+    ([], [$($methods:tt)*]) => (
+        pub trait EarlyLintPass: LintPass {
+            expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
+        }
+    )
+}
+
+early_lint_methods!(declare_early_lint_pass, []);
+
+#[macro_export]
+macro_rules! expand_combined_early_lint_pass_method {
+    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$passes.$name $params;)*
+    })
+}
+
+#[macro_export]
+macro_rules! expand_combined_early_lint_pass_methods {
+    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
+            expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
+        })*
+    )
+}
+
+#[macro_export]
+macro_rules! declare_combined_early_lint_pass {
+    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
+        #[allow(non_snake_case)]
+        $v struct $name {
+            $($passes: $passes,)*
+        }
+
+        impl $name {
+            $v fn new() -> Self {
+                Self {
+                    $($passes: $constructor,)*
+                }
+            }
+
+            $v fn get_lints() -> LintArray {
+                let mut lints = Vec::new();
+                $(lints.extend_from_slice(&$passes::get_lints());)*
+                lints
+            }
+        }
+
+        impl EarlyLintPass for $name {
+            expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
+        }
+
+        #[allow(rustc::lint_pass_impl_without_macro)]
+        impl LintPass for $name {
+            fn name(&self) -> &'static str {
+                panic!()
+            }
+        }
+    )
+}
+
+/// A lint pass boxed up as a trait object.
+pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
+pub type LateLintPassObject =
+    Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send + sync::Sync + 'static>;
diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs
index 8dbf96a..21b244a 100644
--- a/src/librustc_lint/redundant_semicolon.rs
+++ b/src/librustc_lint/redundant_semicolon.rs
@@ -1,6 +1,6 @@
-use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_errors::Applicability;
 use syntax::ast::{ExprKind, Stmt, StmtKind};
-use syntax::errors::Applicability;
 
 declare_lint! {
     pub REDUNDANT_SEMICOLON,
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 7944c88..674a82b 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -1,22 +1,20 @@
 #![allow(non_snake_case)]
 
-use crate::hir::def_id::DefId;
-use lint::{LateContext, LintArray, LintContext};
-use lint::{LateLintPass, LintPass};
-use rustc::hir;
-use rustc::hir::{is_range_literal, ExprKind, Node};
-use rustc::lint;
+use crate::{LateContext, LateLintPass, LintContext};
 use rustc::mir::interpret::{sign_extend, truncate};
 use rustc::ty::layout::{self, IntegerExt, LayoutOf, SizeSkeleton, VariantIdx};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{is_range_literal, ExprKind, Node};
 use rustc_index::vec::Idx;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
-use syntax::errors::Applicability;
 use syntax::{ast, attr};
 
 use log::debug;
@@ -376,7 +374,7 @@
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr<'tcx>) {
         match e.kind {
-            hir::ExprKind::Unary(hir::UnNeg, ref expr) => {
+            hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => {
                 // propagate negation, if the negation itself isn't negated
                 if self.negated_expr_id != e.hir_id {
                     self.negated_expr_id = expr.hir_id;
@@ -969,7 +967,7 @@
             self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false);
         }
 
-        if let hir::Return(ref ret_hir) = decl.output {
+        if let hir::FunctionRetTy::Return(ref ret_hir) = decl.output {
             let ret_ty = sig.output();
             if !ret_ty.is_unit() {
                 self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false);
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index db2598d..26cbda3 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -1,21 +1,18 @@
-use lint::{EarlyContext, LateContext, LintArray, LintContext};
-use lint::{EarlyLintPass, LateLintPass, LintPass};
-use rustc::hir;
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::DefId;
-use rustc::lint;
-use rustc::lint::builtin::UNUSED_ATTRIBUTES;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::ty::adjustment;
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, Applicability};
 use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
-
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
 use syntax::ast;
 use syntax::attr;
-use syntax::errors::{pluralize, Applicability};
 use syntax::print::pprust;
 use syntax::util::parser;
 
diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml
deleted file mode 100644
index 9a24361..0000000
--- a/src/librustc_lsan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_lsan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_lsan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
deleted file mode 100644
index 6201bc9..0000000
--- a/src/librustc_lsan/build.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("lsan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_lsan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index c8ef9f1..48767c3 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -16,7 +16,8 @@
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 rustc_index = { path = "../librustc_index" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index f95801d..181f872 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -3,35 +3,32 @@
 use crate::locator::{CrateLocator, CratePaths};
 use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
 
-use rustc::hir::def_id::CrateNum;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir::map::Definitions;
 use rustc::middle::cstore::DepKind;
 use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
-use rustc::session::config::{self, Sanitizer};
+use rustc::session::config;
 use rustc::session::search_paths::PathKind;
 use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
-use rustc_index::vec::IndexVec;
-use rustc_target::spec::{PanicStrategy, TargetTriple};
-
-use std::path::Path;
-use std::{cmp, fs};
-
-use log::{debug, info, log_enabled};
-use proc_macro::bridge::client::ProcMacro;
+use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_expand::base::SyntaxExtension;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_index::vec::IndexVec;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::{PanicStrategy, TargetTriple};
 use syntax::ast;
 use syntax::attr;
 use syntax::expand::allocator::{global_allocator_spans, AllocatorKind};
-use syntax::span_fatal;
 
-use rustc_error_codes::*;
+use log::{debug, info, log_enabled};
+use proc_macro::bridge::client::ProcMacro;
+use std::path::Path;
+use std::{cmp, fs};
 
 #[derive(Clone)]
 pub struct CStore {
@@ -261,7 +258,7 @@
         if self.local_crate_name == root.name()
             && self.sess.local_crate_disambiguator() == root.disambiguator()
         {
-            span_fatal!(
+            struct_span_err!(
                 self.sess,
                 span,
                 E0519,
@@ -271,6 +268,7 @@
                          will result in symbol conflicts between the two.",
                 root.name()
             )
+            .emit()
         }
 
         // Check for conflicts with any crate loaded so far
@@ -280,7 +278,7 @@
                other.hash() != root.hash()
             {
                 // but different SVH
-                span_fatal!(
+                struct_span_err!(
                     self.sess,
                     span,
                     E0523,
@@ -289,6 +287,7 @@
                          will result in symbol conflicts between the two.",
                     root.name()
                 )
+                .emit();
             }
         });
     }
@@ -672,108 +671,6 @@
         self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime());
     }
 
-    fn inject_sanitizer_runtime(&mut self) {
-        if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
-            // Sanitizers can only be used on some tested platforms with
-            // executables linked to `std`
-            const ASAN_SUPPORTED_TARGETS: &[&str] =
-                &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-            const TSAN_SUPPORTED_TARGETS: &[&str] =
-                &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-            const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
-            const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
-
-            let supported_targets = match *sanitizer {
-                Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
-                Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
-                Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
-                Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
-            };
-            if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) {
-                self.sess.err(&format!(
-                    "{:?}Sanitizer only works with the `{}` target",
-                    sanitizer,
-                    supported_targets.join("` or `")
-                ));
-                return;
-            }
-
-            // firstyear 2017 - during testing I was unable to access an OSX machine
-            // to make this work on different crate types. As a result, today I have
-            // only been able to test and support linux as a target.
-            if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" {
-                if !self.sess.crate_types.borrow().iter().all(|ct| {
-                    match *ct {
-                        // Link the runtime
-                        config::CrateType::Executable => true,
-                        // This crate will be compiled with the required
-                        // instrumentation pass
-                        config::CrateType::Staticlib
-                        | config::CrateType::Rlib
-                        | config::CrateType::Dylib
-                        | config::CrateType::Cdylib => false,
-                        _ => {
-                            self.sess.err(&format!(
-                                "Only executables, staticlibs, \
-                                cdylibs, dylibs and rlibs can be compiled with \
-                                `-Z sanitizer`"
-                            ));
-                            false
-                        }
-                    }
-                }) {
-                    return;
-                }
-            } else {
-                if !self.sess.crate_types.borrow().iter().all(|ct| {
-                    match *ct {
-                        // Link the runtime
-                        config::CrateType::Executable => true,
-                        // This crate will be compiled with the required
-                        // instrumentation pass
-                        config::CrateType::Rlib => false,
-                        _ => {
-                            self.sess.err(&format!(
-                                "Only executables and rlibs can be \
-                                                    compiled with `-Z sanitizer`"
-                            ));
-                            false
-                        }
-                    }
-                }) {
-                    return;
-                }
-            }
-
-            let mut uses_std = false;
-            self.cstore.iter_crate_data(|_, data| {
-                if data.name() == sym::std {
-                    uses_std = true;
-                }
-            });
-
-            if uses_std {
-                let name = Symbol::intern(match sanitizer {
-                    Sanitizer::Address => "rustc_asan",
-                    Sanitizer::Leak => "rustc_lsan",
-                    Sanitizer::Memory => "rustc_msan",
-                    Sanitizer::Thread => "rustc_tsan",
-                });
-                info!("loading sanitizer: {}", name);
-
-                let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None);
-                let data = self.cstore.get_crate_data(cnum);
-
-                // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
-                if !data.is_sanitizer_runtime() {
-                    self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", name));
-                }
-            } else {
-                self.sess.err("Must link std to be compiled with `-Z sanitizer`");
-            }
-        }
-    }
-
     fn inject_profiler_runtime(&mut self) {
         if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() {
             info!("loading profiler");
@@ -925,7 +822,6 @@
     }
 
     pub fn postprocess(&mut self, krate: &ast::Crate) {
-        self.inject_sanitizer_runtime();
         self.inject_profiler_runtime();
         self.inject_allocator_crate(krate);
         self.inject_panic_runtime(krate);
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index f82579a..3427de1 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -53,13 +53,13 @@
 
 use crate::creader::CStore;
 
-use rustc::hir::def_id::CrateNum;
 use rustc::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
 use rustc::middle::cstore::{self, DepKind};
 use rustc::middle::dependency_format::{Dependencies, DependencyList, Linkage};
 use rustc::session::config;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::CrateNum;
 use rustc_target::spec::PanicStrategy;
 
 crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs
index a48d7f0..fc988ec 100644
--- a/src/librustc_metadata/foreign_modules.rs
+++ b/src/librustc_metadata/foreign_modules.rs
@@ -1,7 +1,7 @@
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::middle::cstore::ForeignModule;
 use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
     let mut collector = Collector { tcx, modules: Vec::new() };
diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs
index 6649cf0..8d018b9 100644
--- a/src/librustc_metadata/link_args.rs
+++ b/src/librustc_metadata/link_args.rs
@@ -1,6 +1,6 @@
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
 
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 59e769c..4745ad0 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -222,13 +222,10 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
-
-use errors::DiagnosticBuilder;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
-use syntax::struct_span_err;
-use syntax::{span_err, span_fatal};
 
 use std::cmp;
 use std::fmt;
@@ -1038,28 +1035,28 @@
     };
 
     if target_only {
-        // Need to abort before syntax expansion.
         let message = format!(
-            "plugin `{}` is not available for triple `{}` \
-                                (only found {})",
+            "plugin `{}` is not available for triple `{}` (only found {})",
             name,
             config::host_triple(),
             sess.opts.target_triple
         );
-        span_fatal!(sess, span, E0456, "{}", &message);
+        struct_span_err!(sess, span, E0456, "{}", &message).emit();
+        return None;
     }
 
     match library.source.dylib {
         Some(dylib) => Some((dylib.0, library.metadata.get_root().disambiguator())),
         None => {
-            span_err!(
+            struct_span_err!(
                 sess,
                 span,
                 E0457,
                 "plugin `{}` only found in rlib format, but must be available \
                         in dylib format",
                 name
-            );
+            )
+            .emit();
             // No need to abort because the loading code will just ignore this
             // empty dylib.
             None
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index bdd9eab..9426d5e 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -1,17 +1,16 @@
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::middle::cstore::{self, NativeLibrary};
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
 use syntax::attr;
-use syntax::feature_gate::feature_err;
-use syntax::{span_err, struct_span_err};
-
-use rustc_error_codes::*;
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
     let mut collector = Collector { tcx, libs: Vec::new() };
@@ -159,7 +158,7 @@
         if lib.kind == cstore::NativeFramework && !is_osx {
             let msg = "native frameworks are only available on macOS targets";
             match span {
-                Some(span) => span_err!(self.tcx.sess, span, E0455, "{}", msg),
+                Some(span) => struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit(),
                 None => self.tcx.sess.err(msg),
             }
         }
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 1ed6b74..eb3dcfa 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -4,9 +4,6 @@
 use crate::rmeta::*;
 
 use rustc::dep_graph::{self, DepNodeIndex};
-use rustc::hir;
-use rustc::hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::exports::Export;
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
@@ -19,12 +16,15 @@
 use rustc::session::Session;
 use rustc::ty::codec::TyDecoder;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::util::captures::Captures;
 use rustc::util::common::record_time;
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 
 use std::io;
@@ -1587,10 +1587,6 @@
         self.root.panic_runtime
     }
 
-    crate fn is_sanitizer_runtime(&self) -> bool {
-        self.root.sanitizer_runtime
-    }
-
     crate fn is_profiler_runtime(&self) -> bool {
         self.root.profiler_runtime
     }
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index 5d5fcf4..fb7e554 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -4,8 +4,6 @@
 use crate::native_libs;
 use crate::rmeta::{self, encoder};
 
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::exports::Export;
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::map::{DefKey, DefPath, DefPathHash};
@@ -17,6 +15,8 @@
 use rustc::ty::query::QueryConfig;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::svh::Svh;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_parse::parser::emit_unclosed_delims;
 use rustc_parse::source_file_to_stream;
 
@@ -161,7 +161,6 @@
     is_compiler_builtins => { cdata.root.compiler_builtins }
     has_global_allocator => { cdata.root.has_global_allocator }
     has_panic_handler => { cdata.root.has_panic_handler }
-    is_sanitizer_runtime => { cdata.root.sanitizer_runtime }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     panic_strategy => { cdata.root.panic_strategy }
     extern_crate => {
@@ -478,6 +477,14 @@
     pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource {
         self.get_crate_data(cnum).source.clone()
     }
+
+    pub fn get_span_untracked(&self, def_id: DefId, sess: &Session) -> Span {
+        self.get_crate_data(def_id.krate).get_span(def_id.index, sess)
+    }
+
+    pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
+        self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes
+    }
 }
 
 impl CrateStore for CStore {
@@ -485,10 +492,6 @@
         self
     }
 
-    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
-        self.get_crate_data(def.krate).get_generics(def.index, sess)
-    }
-
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol {
         self.get_crate_data(cnum).root.name
     }
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index fc7eae1..7f8791d 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -1,10 +1,8 @@
 use crate::rmeta::table::FixedSizeEncoding;
 use crate::rmeta::*;
 
-use rustc::hir::def::CtorKind;
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::map::definitions::DefPathTable;
-use rustc::hir::{AnonConst, GenericParamKind};
+use rustc::hir::map::Map;
 use rustc::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLibrary};
 use rustc::middle::dependency_format::Linkage;
 use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
@@ -15,6 +13,9 @@
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_hir::def::CtorKind;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::{AnonConst, GenericParamKind};
 use rustc_index::vec::Idx;
 
 use rustc::session::config::{self, CrateType};
@@ -35,10 +36,9 @@
 use syntax::attr;
 use syntax::expand::is_proc_macro_attr;
 
-use rustc::hir::intravisit;
-use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::{self, PatKind};
+use rustc_hir as hir;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
 struct EncodeContext<'tcx> {
     opaque: opaque::Encoder,
@@ -514,7 +514,6 @@
             no_builtins: attr::contains_name(&attrs, sym::no_builtins),
             panic_runtime: attr::contains_name(&attrs, sym::panic_runtime),
             profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime),
-            sanitizer_runtime: attr::contains_name(&attrs, sym::sanitizer_runtime),
             symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
 
             crate_deps,
@@ -951,7 +950,7 @@
         self.tcx.dep_graph.with_ignore(|| {
             let body = self.tcx.hir().body(body_id);
             self.lazy(body.params.iter().map(|arg| match arg.pat.kind {
-                PatKind::Binding(_, _, ident, _) => ident.name,
+                hir::PatKind::Binding(_, _, ident, _) => ident.name,
                 _ => kw::Invalid,
             }))
         })
@@ -1520,7 +1519,9 @@
 
 // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
 impl Visitor<'tcx> for EncodeContext<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 4ef978c..426ea62 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -1,10 +1,8 @@
 use decoder::Metadata;
 use table::{Table, TableBuilder};
 
-use rustc::hir;
-use rustc::hir::def::CtorKind;
-use rustc::hir::def_id::{DefId, DefIndex};
 use rustc::hir::exports::Export;
+use rustc::hir::map;
 use rustc::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLibrary};
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::middle::lang_items;
@@ -14,6 +12,9 @@
 use rustc::ty::{self, ReprOptions, Ty};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
+use rustc_hir as hir;
+use rustc_hir::def::CtorKind;
+use rustc_hir::def_id::{DefId, DefIndex};
 use rustc_index::vec::IndexVec;
 use rustc_serialize::opaque::Encoder;
 use rustc_span::edition::Edition;
@@ -192,7 +193,7 @@
     native_libraries: Lazy<[NativeLibrary]>,
     foreign_modules: Lazy<[ForeignModule]>,
     source_map: Lazy<[rustc_span::SourceFile]>,
-    def_path_table: Lazy<hir::map::definitions::DefPathTable>,
+    def_path_table: Lazy<map::definitions::DefPathTable>,
     impls: Lazy<[TraitImpls]>,
     exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
     interpret_alloc_index: Lazy<[u32]>,
@@ -208,7 +209,6 @@
     no_builtins: bool,
     panic_runtime: bool,
     profiler_runtime: bool,
-    sanitizer_runtime: bool,
     symbol_mangling_version: SymbolManglingVersion,
 }
 
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 3f9e2c0..f9b61b9 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -10,7 +10,6 @@
 doctest = false
 
 [dependencies]
-arena = { path = "../libarena" }
 either = "1.5.0"
 dot = { path = "../libgraphviz", package = "graphviz" }
 itertools = "0.8"
@@ -18,13 +17,14 @@
 log_settings = "0.1.1"
 polonius-engine = "0.11.0"
 rustc = { path = "../librustc" }
-rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_index = { path = "../librustc_index" }
 rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_index = { path = "../librustc_index" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
+rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc_apfloat = { path = "../librustc_apfloat" }
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index b66b2e4..f2a4498 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -208,9 +208,7 @@
 
             self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx);
 
-            if let mir::PlaceBase::Local(local) = borrowed_place.base {
-                self.local_map.entry(local).or_default().insert(idx);
-            }
+            self.local_map.entry(borrowed_place.local).or_default().insert(idx);
         }
 
         self.super_assign(assigned_place, rvalue, location)
diff --git a/src/librustc_mir/borrow_check/constraint_generation.rs b/src/librustc_mir/borrow_check/constraint_generation.rs
index 97de201..0f6a360 100644
--- a/src/librustc_mir/borrow_check/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/constraint_generation.rs
@@ -2,8 +2,8 @@
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
 use rustc::mir::{
-    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, PlaceRef, ProjectionElem,
-    Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
+    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue,
+    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
 };
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::SubstsRef;
@@ -16,7 +16,6 @@
 
 pub(super) fn generate_constraints<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     liveness_constraints: &mut LivenessValues<RegionVid>,
     all_facts: &mut Option<AllFacts>,
     location_table: &LocationTable,
@@ -30,7 +29,6 @@
         location_table,
         all_facts,
         body,
-        param_env,
     };
 
     for (bb, data) in body.basic_blocks().iter_enumerated() {
@@ -41,7 +39,6 @@
 /// 'cg = the duration of the constraint generation process itself.
 struct ConstraintGeneration<'cg, 'cx, 'tcx> {
     infcx: &'cg InferCtxt<'cx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     all_facts: &'cg mut Option<AllFacts>,
     location_table: &'cg LocationTable,
     liveness_constraints: &'cg mut LivenessValues<RegionVid>,
@@ -191,11 +188,8 @@
             //   of the borrows are killed: the ones whose `borrowed_place`
             //   conflicts with the `place`.
             match place.as_ref() {
-                PlaceRef { base: &PlaceBase::Local(local), projection: &[] }
-                | PlaceRef {
-                    base: &PlaceBase::Local(local),
-                    projection: &[ProjectionElem::Deref],
-                } => {
+                PlaceRef { local, projection: &[] }
+                | PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
                     debug!(
                         "Recording `killed` facts for borrows of local={:?} at location={:?}",
                         local, location
@@ -205,16 +199,12 @@
                         all_facts,
                         self.borrow_set,
                         self.location_table,
-                        &local,
+                        local,
                         location,
                     );
                 }
 
-                PlaceRef { base: &PlaceBase::Static(_), .. } => {
-                    // Ignore kills of static or static mut variables.
-                }
-
-                PlaceRef { base: &PlaceBase::Local(local), projection: &[.., _] } => {
+                PlaceRef { local, projection: &[.., _] } => {
                     // Kill conflicting borrows of the innermost local.
                     debug!(
                         "Recording `killed` facts for borrows of \
@@ -222,11 +212,10 @@
                         local, location
                     );
 
-                    if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
+                    if let Some(borrow_indices) = self.borrow_set.local_map.get(local) {
                         for &borrow_index in borrow_indices {
                             let places_conflict = places_conflict::places_conflict(
                                 self.infcx.tcx,
-                                self.param_env,
                                 self.body,
                                 &self.borrow_set.borrows[borrow_index].borrowed_place,
                                 place,
diff --git a/src/librustc_mir/borrow_check/constraints/mod.rs b/src/librustc_mir/borrow_check/constraints/mod.rs
index 48defec..ef70b12 100644
--- a/src/librustc_mir/borrow_check/constraints/mod.rs
+++ b/src/librustc_mir/borrow_check/constraints/mod.rs
@@ -1,7 +1,7 @@
 use rustc::mir::ConstraintCategory;
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph::scc::Sccs;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use std::fmt;
 use std::ops::Index;
 
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 61d69f8..08333ae 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -1,15 +1,15 @@
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
-    FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceBase,
-    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
+    FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
+    ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
 };
 use rustc::traits::error_reporting::suggest_constraining_type_param;
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc_index::vec::Idx;
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::Span;
@@ -186,7 +186,7 @@
             }
 
             let ty =
-                Place::ty_from(used_place.base, used_place.projection, *self.body, self.infcx.tcx)
+                Place::ty_from(used_place.local, used_place.projection, *self.body, self.infcx.tcx)
                     .ty;
             let needs_note = match ty.kind {
                 ty::Closure(id, _) => {
@@ -597,15 +597,15 @@
                 // field access to a union. If we find that, then we will keep the place of the
                 // union being accessed and the field that was being accessed so we can check the
                 // second borrowed place for the same union and a access to a different field.
-                let Place { base, projection } = first_borrowed_place;
+                let Place { local, projection } = first_borrowed_place;
 
                 let mut cursor = projection.as_ref();
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
                     match elem {
-                        ProjectionElem::Field(field, _) if union_ty(base, proj_base).is_some() => {
-                            return Some((PlaceRef { base: base, projection: proj_base }, field));
+                        ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => {
+                            return Some((PlaceRef { local, projection: proj_base }, field));
                         }
                         _ => {}
                     }
@@ -615,21 +615,21 @@
             .and_then(|(target_base, target_field)| {
                 // With the place of a union and a field access into it, we traverse the second
                 // borrowed place and look for a access to a different field of the same union.
-                let Place { base, projection } = second_borrowed_place;
+                let Place { local, projection } = second_borrowed_place;
 
                 let mut cursor = projection.as_ref();
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
                     if let ProjectionElem::Field(field, _) = elem {
-                        if let Some(union_ty) = union_ty(base, proj_base) {
+                        if let Some(union_ty) = union_ty(local, proj_base) {
                             if field != target_field
-                                && base == target_base.base
+                                && local == target_base.local
                                 && proj_base == target_base.projection
                             {
                                 // FIXME when we avoid clone reuse describe_place closure
                                 let describe_base_place = self
-                                    .describe_place(PlaceRef { base: base, projection: proj_base })
+                                    .describe_place(PlaceRef { local, projection: proj_base })
                                     .unwrap_or_else(|| "_".to_owned());
 
                                 return Some((
@@ -686,15 +686,12 @@
         let borrow_span = borrow_spans.var_or_use();
 
         assert!(root_place.projection.is_empty());
-        let proper_span = match root_place.base {
-            PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span,
-            _ => drop_span,
-        };
+        let proper_span = self.body.local_decls[*root_place.local].source_info.span;
 
         let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection);
 
         if self.access_place_error_reported.contains(&(
-            Place { base: root_place.base.clone(), projection: root_place_projection },
+            Place { local: root_place.local.clone(), projection: root_place_projection },
             borrow_span,
         )) {
             debug!(
@@ -705,18 +702,17 @@
         }
 
         self.access_place_error_reported.insert((
-            Place { base: root_place.base.clone(), projection: root_place_projection },
+            Place { local: root_place.local.clone(), projection: root_place_projection },
             borrow_span,
         ));
 
-        if let PlaceBase::Local(local) = borrow.borrowed_place.base {
-            if self.body.local_decls[local].is_ref_to_thread_local() {
-                let err = self
-                    .report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
-                err.buffer(&mut self.errors_buffer);
-                return;
-            }
-        };
+        let borrowed_local = borrow.borrowed_place.local;
+        if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
+            let err =
+                self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
+            err.buffer(&mut self.errors_buffer);
+            return;
+        }
 
         if let StorageDeadOrDrop::Destructor(dropped_ty) =
             self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
@@ -1142,12 +1138,7 @@
         } else {
             let root_place =
                 self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
-            let local =
-                if let PlaceRef { base: PlaceBase::Local(local), projection: [] } = root_place {
-                    local
-                } else {
-                    bug!("try_report_cannot_return_reference_to_local: not a local")
-                };
+            let local = root_place.local;
             match self.body.local_kind(*local) {
                 LocalKind::ReturnPointer | LocalKind::Temp => {
                     ("temporary value".to_string(), "temporary value created here".to_string())
@@ -1514,7 +1505,7 @@
             [proj_base @ .., elem] => {
                 // FIXME(spastorino) make this iterate
                 let base_access = self.classify_drop_access_kind(PlaceRef {
-                    base: place.base,
+                    local: place.local,
                     projection: proj_base,
                 });
                 match elem {
@@ -1522,7 +1513,9 @@
                         StorageDeadOrDrop::LocalStorageDead
                         | StorageDeadOrDrop::BoxedStorageDead => {
                             assert!(
-                                Place::ty_from(&place.base, proj_base, *self.body, tcx).ty.is_box(),
+                                Place::ty_from(&place.local, proj_base, *self.body, tcx)
+                                    .ty
+                                    .is_box(),
                                 "Drop of value behind a reference or raw pointer"
                             );
                             StorageDeadOrDrop::BoxedStorageDead
@@ -1530,7 +1523,7 @@
                         StorageDeadOrDrop::Destructor(_) => base_access,
                     },
                     ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
-                        let base_ty = Place::ty_from(&place.base, proj_base, *self.body, tcx).ty;
+                        let base_ty = Place::ty_from(&place.local, proj_base, *self.body, tcx).ty;
                         match base_ty.kind {
                             ty::Adt(def, _) if def.has_dtor(tcx) => {
                                 // Report the outermost adt with a destructor
@@ -1839,7 +1832,7 @@
                     if let ty::Ref(argument_region, _, _) = argument.kind {
                         if argument_region == return_region {
                             // Need to use the `rustc::ty` types to compare against the
-                            // `return_region`. Then use the `rustc::hir` type to get only
+                            // `return_region`. Then use the `rustc_hir` type to get only
                             // the lifetime span.
                             if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind {
                                 // With access to the lifetime, we can get
diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index e006c6dd..3f3bdb9 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -1,18 +1,17 @@
 //! Borrow checker diagnostics.
 
-use rustc::hir;
-use rustc::hir::def::Namespace;
-use rustc::hir::def_id::DefId;
-use rustc::hir::GeneratorKind;
 use rustc::mir::{
     AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
-    PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Static, StaticKind,
-    Terminator, TerminatorKind,
+    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::print::Print;
 use rustc::ty::{self, DefIdTree, Ty, TyCtxt};
 use rustc_errors::DiagnosticBuilder;
+use rustc_hir as hir;
+use rustc_hir::def::Namespace;
+use rustc_hir::def_id::DefId;
+use rustc_hir::GeneratorKind;
 use rustc_span::Span;
 
 use super::borrow_set::BorrowData;
@@ -169,42 +168,30 @@
         including_downcast: &IncludingDowncast,
     ) -> Result<(), ()> {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 self.append_local_to_string(*local, buf)?;
             }
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Promoted(..), .. }),
-                projection: [],
-            } => {
-                buf.push_str("promoted");
-            }
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }),
-                projection: [],
-            } => {
-                buf.push_str(&self.infcx.tcx.item_name(*def_id).to_string());
-            }
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_for_guard() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_for_guard() =>
             {
                 self.append_place_to_string(
-                    PlaceRef { base: &PlaceBase::Local(local), projection: &[] },
+                    PlaceRef { local: local, projection: &[] },
                     buf,
                     autoderef,
                     &including_downcast,
                 )?;
             }
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_to_static() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_to_static() =>
             {
-                let local_info = &self.body.local_decls[local].local_info;
+                let local_info = &self.body.local_decls[*local].local_info;
                 if let LocalInfo::StaticRef { def_id, .. } = *local_info {
                     buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
                 } else {
                     unreachable!();
                 }
             }
-            PlaceRef { base, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local, projection: [proj_base @ .., elem] } => {
                 match elem {
                     ProjectionElem::Deref => {
                         let upvar_field_projection = self.is_upvar_field_projection(place);
@@ -220,29 +207,25 @@
                             if autoderef {
                                 // FIXME turn this recursion into iteration
                                 self.append_place_to_string(
-                                    PlaceRef { base, projection: proj_base },
+                                    PlaceRef { local, projection: proj_base },
                                     buf,
                                     autoderef,
                                     &including_downcast,
                                 )?;
                             } else {
-                                match (proj_base, base) {
-                                    _ => {
-                                        buf.push_str(&"*");
-                                        self.append_place_to_string(
-                                            PlaceRef { base, projection: proj_base },
-                                            buf,
-                                            autoderef,
-                                            &including_downcast,
-                                        )?;
-                                    }
-                                }
+                                buf.push_str(&"*");
+                                self.append_place_to_string(
+                                    PlaceRef { local, projection: proj_base },
+                                    buf,
+                                    autoderef,
+                                    &including_downcast,
+                                )?;
                             }
                         }
                     }
                     ProjectionElem::Downcast(..) => {
                         self.append_place_to_string(
-                            PlaceRef { base, projection: proj_base },
+                            PlaceRef { local, projection: proj_base },
                             buf,
                             autoderef,
                             &including_downcast,
@@ -261,9 +244,9 @@
                             buf.push_str(&name);
                         } else {
                             let field_name = self
-                                .describe_field(PlaceRef { base, projection: proj_base }, *field);
+                                .describe_field(PlaceRef { local, projection: proj_base }, *field);
                             self.append_place_to_string(
-                                PlaceRef { base, projection: proj_base },
+                                PlaceRef { local, projection: proj_base },
                                 buf,
                                 autoderef,
                                 &including_downcast,
@@ -275,7 +258,7 @@
                         autoderef = true;
 
                         self.append_place_to_string(
-                            PlaceRef { base, projection: proj_base },
+                            PlaceRef { local, projection: proj_base },
                             buf,
                             autoderef,
                             &including_downcast,
@@ -292,7 +275,7 @@
                         // then use another while the borrow is held, don't output indices details
                         // to avoid confusing the end-user
                         self.append_place_to_string(
-                            PlaceRef { base, projection: proj_base },
+                            PlaceRef { local, projection: proj_base },
                             buf,
                             autoderef,
                             &including_downcast,
@@ -323,20 +306,18 @@
     fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
         // FIXME Place2 Make this work iteratively
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 let local = &self.body.local_decls[*local];
                 self.describe_field_from_ty(&local.ty, field, None)
             }
-            PlaceRef { base: PlaceBase::Static(static_), projection: [] } => {
-                self.describe_field_from_ty(&static_.ty, field, None)
-            }
-            PlaceRef { base, projection: [proj_base @ .., elem] } => match elem {
+            PlaceRef { local, projection: [proj_base @ .., elem] } => match elem {
                 ProjectionElem::Deref => {
-                    self.describe_field(PlaceRef { base, projection: proj_base }, field)
+                    self.describe_field(PlaceRef { local, projection: proj_base }, field)
                 }
                 ProjectionElem::Downcast(_, variant_index) => {
                     let base_ty =
-                        Place::ty_from(place.base, place.projection, *self.body, self.infcx.tcx).ty;
+                        Place::ty_from(place.local, place.projection, *self.body, self.infcx.tcx)
+                            .ty;
                     self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
                 }
                 ProjectionElem::Field(_, field_type) => {
@@ -345,7 +326,7 @@
                 ProjectionElem::Index(..)
                 | ProjectionElem::ConstantIndex { .. }
                 | ProjectionElem::Subslice { .. } => {
-                    self.describe_field(PlaceRef { base, projection: proj_base }, field)
+                    self.describe_field(PlaceRef { local, projection: proj_base }, field)
                 }
             },
         }
@@ -466,7 +447,7 @@
 
         // If we didn't find an overloaded deref or index, then assume it's a
         // built in deref and check the type of the base.
-        let base_ty = Place::ty_from(deref_base.base, deref_base.projection, *self.body, tcx).ty;
+        let base_ty = Place::ty_from(deref_base.local, deref_base.projection, *self.body, tcx).ty;
         if base_ty.is_unsafe_ptr() {
             BorrowedContentSource::DerefRawPointer
         } else if base_ty.is_mutable_ptr() {
diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index 3f4204b..eb6db7c 100644
--- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -243,9 +243,6 @@
             );
             (
                 match kind {
-                    IllegalMoveOriginKind::Static => {
-                        unreachable!();
-                    }
                     IllegalMoveOriginKind::BorrowedContent { target_place } => self
                         .report_cannot_move_from_borrowed_content(
                             original_path,
@@ -276,7 +273,8 @@
         let description = if place.projection.len() == 1 {
             format!("static item `{}`", self.describe_place(place.as_ref()).unwrap())
         } else {
-            let base_static = PlaceRef { base: &place.base, projection: &[ProjectionElem::Deref] };
+            let base_static =
+                PlaceRef { local: &place.local, projection: &[ProjectionElem::Deref] };
 
             format!(
                 "`{:?}` as `{:?}` is a static item",
@@ -305,12 +303,12 @@
 
         let deref_base = match deref_target_place.projection.as_ref() {
             &[ref proj_base @ .., ProjectionElem::Deref] => {
-                PlaceRef { base: &deref_target_place.base, projection: &proj_base }
+                PlaceRef { local: &deref_target_place.local, projection: &proj_base }
             }
             _ => bug!("deref_target_place is not a deref projection"),
         };
 
-        if let PlaceRef { base: PlaceBase::Local(local), projection: [] } = deref_base {
+        if let PlaceRef { local, projection: [] } = deref_base {
             let decl = &self.body.local_decls[*local];
             if decl.is_ref_for_guard() {
                 let mut err = self.cannot_move_out_of(
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index 99fedc8..ae468e8 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -1,8 +1,8 @@
-use rustc::hir;
-use rustc::hir::Node;
 use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyAndCache};
-use rustc::mir::{Mutability, Place, PlaceBase, PlaceRef, ProjectionElem};
+use rustc::mir::{Mutability, Place, PlaceRef, ProjectionElem};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::Node;
 use rustc_index::vec::Idx;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -42,7 +42,7 @@
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
                 if access_place.as_local().is_some() {
                     reason = ", as it is not declared as mutable".to_string();
@@ -53,11 +53,11 @@
             }
 
             PlaceRef {
-                base: _,
+                local,
                 projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             } => {
                 debug_assert!(is_closure_or_generator(
-                    Place::ty_from(&the_place_err.base, proj_base, *self.body, self.infcx.tcx).ty
+                    Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
@@ -69,21 +69,21 @@
                 }
             }
 
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_for_guard() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_for_guard() =>
             {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
                 reason = ", as it is immutable for the pattern guard".to_string();
             }
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_to_static() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_to_static() =>
             {
                 if access_place.projection.len() == 1 {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
                     reason = String::new();
                 } else {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
-                    let local_info = &self.body.local_decls[local].local_info;
+                    let local_info = &self.body.local_decls[*local].local_info;
                     if let LocalInfo::StaticRef { def_id, .. } = *local_info {
                         let static_name = &self.infcx.tcx.item_name(def_id);
                         reason = format!(", as `{}` is an immutable static item", static_name);
@@ -92,8 +92,8 @@
                     }
                 }
             }
-            PlaceRef { base: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
-                if the_place_err.base == &PlaceBase::Local(Local::new(1))
+            PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
+                if *the_place_err.local == Local::new(1)
                     && proj_base.is_empty()
                     && !self.upvars.is_empty()
                 {
@@ -101,7 +101,7 @@
                     debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr());
                     debug_assert!(is_closure_or_generator(
                         Place::ty_from(
-                            the_place_err.base,
+                            the_place_err.local,
                             the_place_err.projection,
                             *self.body,
                             self.infcx.tcx
@@ -116,7 +116,7 @@
                     }
                 } else {
                     let source = self.borrowed_content_source(PlaceRef {
-                        base: the_place_err.base,
+                        local: the_place_err.local,
                         projection: proj_base,
                     });
                     let pointer_type = source.describe_for_immutable_place();
@@ -136,11 +136,10 @@
                 }
             }
 
-            PlaceRef { base: PlaceBase::Static(_), .. }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::Index(_)] }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::ConstantIndex { .. }] }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::Subslice { .. }] }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::Downcast(..)] } => {
+            PlaceRef { local: _, projection: [.., ProjectionElem::Index(_)] }
+            | PlaceRef { local: _, projection: [.., ProjectionElem::ConstantIndex { .. }] }
+            | PlaceRef { local: _, projection: [.., ProjectionElem::Subslice { .. }] }
+            | PlaceRef { local: _, projection: [.., ProjectionElem::Downcast(..)] } => {
                 bug!("Unexpected immutable place.")
             }
         }
@@ -188,7 +187,7 @@
             // struct we've got a field access of (it must be a reference since there's a deref
             // after the field access).
             PlaceRef {
-                base,
+                local,
                 projection:
                     [proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref],
             } => {
@@ -196,7 +195,7 @@
 
                 if let Some((span, message)) = annotate_struct_field(
                     self.infcx.tcx,
-                    Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty,
+                    Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty,
                     field,
                 ) {
                     err.span_suggestion(
@@ -209,7 +208,7 @@
             }
 
             // Suggest removing a `&mut` from the use of a mutable reference.
-            PlaceRef { base: PlaceBase::Local(local), projection: [] }
+            PlaceRef { local, projection: [] }
                 if {
                     self.body
                         .local_decls
@@ -247,7 +246,7 @@
 
             // We want to suggest users use `let mut` for local (user
             // variable) mutations...
-            PlaceRef { base: PlaceBase::Local(local), projection: [] }
+            PlaceRef { local, projection: [] }
                 if self.body.local_decls[*local].can_be_made_mutable() =>
             {
                 // ... but it doesn't make sense to suggest it on
@@ -268,11 +267,11 @@
 
             // Also suggest adding mut for upvars
             PlaceRef {
-                base,
+                local,
                 projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             } => {
                 debug_assert!(is_closure_or_generator(
-                    Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty
+                    Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty
                 ));
 
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
@@ -299,7 +298,7 @@
             // complete hack to approximate old AST-borrowck
             // diagnostic: if the span starts with a mutable borrow of
             // a local variable, then just suggest the user remove it.
-            PlaceRef { base: PlaceBase::Local(_), projection: [] }
+            PlaceRef { local: _, projection: [] }
                 if {
                     if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         snippet.starts_with("&mut ")
@@ -312,7 +311,7 @@
                 err.span_label(span, "try removing `&mut` here");
             }
 
-            PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
                 if self.body.local_decls[*local].is_ref_for_guard() =>
             {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
@@ -326,7 +325,7 @@
             //
             // FIXME: can this case be generalized to work for an
             // arbitrary base for the projection?
-            PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
                 if self.body.local_decls[*local].is_user_variable() =>
             {
                 let local_decl = &self.body.local_decls[*local];
@@ -409,10 +408,10 @@
             }
 
             PlaceRef {
-                base,
+                local,
                 projection: [ProjectionElem::Deref],
                 // FIXME document what is this 1 magic number about
-            } if *base == PlaceBase::Local(Local::new(1)) && !self.upvars.is_empty() => {
+            } if *local == Local::new(1) && !self.upvars.is_empty() => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
                 err.span_help(
                     self.body.span,
@@ -420,7 +419,7 @@
                 );
             }
 
-            PlaceRef { base: _, projection: [.., ProjectionElem::Deref] } => {
+            PlaceRef { local: _, projection: [.., ProjectionElem::Deref] } => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
 
                 match opt_source {
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 8d534b6..dc63fa8 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -1,18 +1,17 @@
 //! Error reporting machinery for lifetime errors.
 
-use rustc::hir::def_id::DefId;
 use rustc::infer::{
     error_reporting::nice_region_error::NiceRegionError, region_constraints::GenericKind,
     InferCtxt, NLLRegionVariableOrigin,
 };
 use rustc::mir::{Body, ConstraintCategory, Location};
 use rustc::ty::{self, RegionVid, Ty};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
 use std::collections::VecDeque;
-use syntax::errors::Applicability;
 
 use crate::util::borrowck_errors;
 
@@ -800,7 +799,7 @@
                 // If there is a static predicate, then the only sensible suggestion is to replace
                 // fr with `'static`.
                 if has_static_predicate {
-                    diag.help(&format!("consider replacing `{}` with `{}`", fr_name, static_str,));
+                    diag.help(&format!("consider replacing `{}` with `{}`", fr_name, static_str));
                 } else {
                     // Otherwise, we should suggest adding a constraint on the return type.
                     let span = infcx.tcx.def_span(*did);
@@ -810,7 +809,12 @@
                         } else {
                             "'_".to_string()
                         };
-
+                        let suggestion = if snippet.ends_with(";") {
+                            // `type X = impl Trait;`
+                            format!("{} + {};", &snippet[..snippet.len() - 1], suggestable_fr_name)
+                        } else {
+                            format!("{} + {}", snippet, suggestable_fr_name)
+                        };
                         diag.span_suggestion(
                             span,
                             &format!(
@@ -818,7 +822,7 @@
                                  `{}`, add `{}` as a bound",
                                 fr_name, suggestable_fr_name,
                             ),
-                            format!("{} + {}", snippet, suggestable_fr_name),
+                            suggestion,
                             Applicability::MachineApplicable,
                         );
                     }
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
index d66c38e..734e386 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -1,12 +1,12 @@
 use std::fmt::{self, Display};
 
-use rustc::hir;
-use rustc::hir::def::{DefKind, Res};
 use rustc::ty::print::RegionHighlightMode;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::{self, RegionVid, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::DiagnosticBuilder;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
 use rustc_span::symbol::kw;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
 
diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index f9ffa21..bb56c11 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -3,7 +3,7 @@
 use rustc::mir::{BasicBlock, Body, Location, Place, ReadOnlyBodyAndCache, Rvalue};
 use rustc::mir::{BorrowKind, Mutability, Operand};
 use rustc::mir::{Statement, StatementKind};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::TyCtxt;
 use rustc_data_structures::graph::dominators::Dominators;
 
 use crate::dataflow::indexes::BorrowIndex;
@@ -16,7 +16,6 @@
 
 pub(super) fn generate_invalidates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     all_facts: &mut Option<AllFacts>,
     location_table: &LocationTable,
     body: ReadOnlyBodyAndCache<'_, 'tcx>,
@@ -33,7 +32,6 @@
         let mut ig = InvalidationGenerator {
             all_facts,
             borrow_set,
-            param_env,
             tcx,
             location_table,
             body: &body,
@@ -45,7 +43,6 @@
 
 struct InvalidationGenerator<'cx, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     all_facts: &'cx mut AllFacts,
     location_table: &'cx LocationTable,
     body: &'cx Body<'tcx>,
@@ -337,13 +334,11 @@
         );
         let tcx = self.tcx;
         let body = self.body;
-        let param_env = self.param_env;
         let borrow_set = self.borrow_set.clone();
         let indices = self.borrow_set.borrows.indices();
         each_borrow_involving_path(
             self,
             tcx,
-            param_env,
             body,
             location,
             (sd, place),
diff --git a/src/librustc_mir/borrow_check/member_constraints.rs b/src/librustc_mir/borrow_check/member_constraints.rs
index 9f10ddb..c959196 100644
--- a/src/librustc_mir/borrow_check/member_constraints.rs
+++ b/src/librustc_mir/borrow_check/member_constraints.rs
@@ -1,8 +1,8 @@
 use crate::rustc::ty::{self, Ty};
-use rustc::hir::def_id::DefId;
 use rustc::infer::region_constraints::MemberConstraint;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_hir::def_id::DefId;
+use rustc_index::vec::IndexVec;
 use rustc_span::Span;
 use std::hash::Hash;
 use std::ops::Index;
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 2c6aa7e..7b0a103 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1,26 +1,26 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
-use rustc::hir::{self, def_id::DefId, HirId, Node};
 use rustc::infer::{opaque_types, InferCtxt};
 use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT;
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::mir::{
     read_only, Body, BodyAndCache, ClearCrossCrate, Local, Location, Mutability, Operand, Place,
-    PlaceBase, PlaceElem, PlaceRef, ReadOnlyBodyAndCache, Static, StaticKind,
+    PlaceElem, PlaceRef, ReadOnlyBodyAndCache,
 };
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
-
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::{def_id::DefId, HirId, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
-use smallvec::SmallVec;
 
+use smallvec::SmallVec;
 use std::collections::BTreeMap;
 use std::mem;
 use std::rc::Rc;
@@ -239,7 +239,7 @@
         def_id,
         &attributes,
         &dead_unwinds,
-        Borrows::new(tcx, &body, param_env, regioncx.clone(), &borrow_set),
+        Borrows::new(tcx, &body, regioncx.clone(), &borrow_set),
         |rs, i| DebugFormatted::new(&rs.location(i)),
     ));
     let flow_uninits = FlowAtLocation::new(do_dataflow(
@@ -275,7 +275,6 @@
         infcx,
         body,
         mir_def_id: def_id,
-        param_env,
         move_data: &mdpe.move_data,
         location_table,
         movable_generator,
@@ -418,7 +417,6 @@
     crate infcx: &'cx InferCtxt<'cx, 'tcx>,
     body: ReadOnlyBodyAndCache<'cx, 'tcx>,
     mir_def_id: DefId,
-    param_env: ty::ParamEnv<'tcx>,
     move_data: &'cx MoveData<'tcx>,
 
     /// Map from MIR `Location` to `LocationIndex`; created
@@ -817,7 +815,7 @@
 }
 
 struct RootPlace<'d, 'tcx> {
-    place_base: &'d PlaceBase<'tcx>,
+    place_local: &'d Local,
     place_projection: &'d [PlaceElem<'tcx>],
     is_local_mutation_allowed: LocalMutationIsAllowed,
 }
@@ -926,13 +924,11 @@
         let tcx = self.infcx.tcx;
         let body = self.body;
         let body: &Body<'_> = &body;
-        let param_env = self.param_env;
         let location_table = self.location_table.start_index(location);
         let borrow_set = self.borrow_set.clone();
         each_borrow_involving_path(
             self,
             tcx,
-            param_env,
             body,
             location,
             (sd, place_span.0),
@@ -1255,8 +1251,8 @@
                 if let Some(field) = this.is_upvar_field_projection(place.as_ref()) {
                     this.used_mut_upvars.push(field);
                 }
-            } else if let PlaceBase::Local(local) = place.base {
-                this.used_mut.insert(local);
+            } else {
+                this.used_mut.insert(place.local);
             }
         };
 
@@ -1380,7 +1376,7 @@
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
         let deref = [ProjectionElem::Deref];
-        let mut root_place = PlaceRef { base: &place.base, projection: &[] };
+        let mut root_place = PlaceRef { local: &place.local, projection: &[] };
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
         // we just know that all locals are dropped at function exit (otherwise
@@ -1388,20 +1384,16 @@
         //
         // FIXME: allow thread-locals to borrow other thread locals?
 
-        let (might_be_alive, will_be_dropped) = match root_place.base {
-            PlaceBase::Static(_) => (true, false),
-            PlaceBase::Local(local) => {
-                if self.body.local_decls[*local].is_ref_to_thread_local() {
-                    // Thread-locals might be dropped after the function exits
-                    // We have to dereference the outer reference because
-                    // borrows don't conflict behind shared references.
-                    root_place.projection = &deref;
-                    (true, true)
-                } else {
-                    (false, self.locals_are_invalidated_at_exit)
-                }
-            }
-        };
+        let (might_be_alive, will_be_dropped) =
+            if self.body.local_decls[*root_place.local].is_ref_to_thread_local() {
+                // Thread-locals might be dropped after the function exits
+                // We have to dereference the outer reference because
+                // borrows don't conflict behind shared references.
+                root_place.projection = &deref;
+                (true, true)
+            } else {
+                (false, self.locals_are_invalidated_at_exit)
+            };
 
         if !will_be_dropped {
             debug!("place_is_invalidated_at_exit({:?}) - won't be dropped", place);
@@ -1412,7 +1404,6 @@
 
         if places_conflict::borrow_conflicts_with_place(
             self.infcx.tcx,
-            self.param_env,
             &self.body,
             place,
             borrow.kind,
@@ -1654,26 +1645,20 @@
         // This code covers scenarios 1, 2, and 3.
 
         debug!("check_if_full_path_is_moved place: {:?}", place_span.0);
-        match self.move_path_closest_to(place_span.0) {
-            Ok((prefix, mpi)) => {
-                if maybe_uninits.contains(mpi) {
-                    self.report_use_of_moved_or_uninitialized(
-                        location,
-                        desired_action,
-                        (prefix, place_span.0, place_span.1),
-                        mpi,
-                    );
-                }
-            }
-            Err(NoMovePathFound::ReachedStatic) => {
-                // Okay: we do not build MoveData for static variables
-            } // Only query longest prefix with a MovePath, not further
-              // ancestors; dataflow recurs on children when parents
-              // move (to support partial (re)inits).
-              //
-              // (I.e., querying parents breaks scenario 7; but may want
-              // to do such a query based on partial-init feature-gate.)
-        }
+        let (prefix, mpi) = self.move_path_closest_to(place_span.0);
+        if maybe_uninits.contains(mpi) {
+            self.report_use_of_moved_or_uninitialized(
+                location,
+                desired_action,
+                (prefix, place_span.0, place_span.1),
+                mpi,
+            );
+        } // Only query longest prefix with a MovePath, not further
+        // ancestors; dataflow recurs on children when parents
+        // move (to support partial (re)inits).
+        //
+        // (I.e., querying parents breaks scenario 7; but may want
+        // to do such a query based on partial-init feature-gate.)
     }
 
     /// Subslices correspond to multiple move paths, so we iterate through the
@@ -1746,9 +1731,9 @@
             place_span.0.projection
         {
             let place_ty =
-                Place::ty_from(place_span.0.base, base_proj, self.body(), self.infcx.tcx);
+                Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx);
             if let ty::Array(..) = place_ty.ty.kind {
-                let array_place = PlaceRef { base: place_span.0.base, projection: base_proj };
+                let array_place = PlaceRef { local: place_span.0.local, projection: base_proj };
                 self.check_if_subslice_element_is_moved(
                     location,
                     desired_action,
@@ -1797,12 +1782,12 @@
     fn move_path_closest_to(
         &mut self,
         place: PlaceRef<'_, 'tcx>,
-    ) -> Result<(PlaceRef<'cx, 'tcx>, MovePathIndex), NoMovePathFound> {
+    ) -> (PlaceRef<'cx, 'tcx>, MovePathIndex) {
         match self.move_data.rev_lookup.find(place) {
             LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => {
-                Ok((self.move_data.move_paths[mpi].place.as_ref(), mpi))
+                (self.move_data.move_paths[mpi].place.as_ref(), mpi)
             }
-            LookupResult::Parent(None) => Err(NoMovePathFound::ReachedStatic),
+            LookupResult::Parent(None) => panic!("should have move path for every Local"),
         }
     }
 
@@ -1845,7 +1830,7 @@
                     self.check_if_full_path_is_moved(
                         location, InitializationRequiringAction::Use,
                         (PlaceRef {
-                            base: &place.base,
+                            local: &place.local,
                             projection: proj_base,
                         }, span), flow_state);
                     // (base initialized; no need to
@@ -1863,13 +1848,13 @@
                     // assigning to `P.f` requires `P` itself
                     // be already initialized
                     let tcx = self.infcx.tcx;
-                    let base_ty = Place::ty_from(&place.base, proj_base, self.body(), tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, self.body(), tcx).ty;
                     match base_ty.kind {
                         ty::Adt(def, _) if def.has_dtor(tcx) => {
                             self.check_if_path_or_subpath_is_moved(
                                 location, InitializationRequiringAction::Assignment,
                                 (PlaceRef {
-                                    base: &place.base,
+                                    local: &place.local,
                                     projection: proj_base,
                                 }, span), flow_state);
 
@@ -1882,21 +1867,14 @@
                         // is allowed, remove this match arm.
                         ty::Adt(..) | ty::Tuple(..) => {
                             check_parent_of_field(self, location, PlaceRef {
-                                base: &place.base,
+                                local: &place.local,
                                 projection: proj_base,
                             }, span, flow_state);
 
-                            if let PlaceBase::Local(local) = place.base {
-                                // rust-lang/rust#21232,
-                                // #54499, #54986: during
-                                // period where we reject
-                                // partial initialization, do
-                                // not complain about
-                                // unnecessary `mut` on an
-                                // attempt to do a partial
-                                // initialization.
-                                self.used_mut.insert(local);
-                            }
+                            // rust-lang/rust#21232, #54499, #54986: during period where we reject
+                            // partial initialization, do not complain about unnecessary `mut` on
+                            // an attempt to do a partial initialization.
+                            self.used_mut.insert(place.local);
                         }
 
                         _ => {}
@@ -1974,7 +1952,7 @@
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
                 if let ty::Adt(def, _) =
-                    Place::ty_from(base.base, base.projection, this.body(), tcx).ty.kind
+                    Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind
                 {
                     if def.is_union() {
                         if this.move_data.path_map[mpi].iter().any(|moi| {
@@ -2093,11 +2071,8 @@
         // partial initialization, do not complain about mutability
         // errors except for actual mutation (as opposed to an attempt
         // to do a partial initialization).
-        let previously_initialized = if let PlaceBase::Local(local) = place.base {
-            self.is_local_ever_initialized(local, flow_state).is_some()
-        } else {
-            true
-        };
+        let previously_initialized =
+            self.is_local_ever_initialized(place.local, flow_state).is_some();
 
         // at this point, we have set up the error reporting state.
         if previously_initialized {
@@ -2126,11 +2101,7 @@
     /// Adds the place into the used mutable variables set
     fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flows<'cx, 'tcx>) {
         match root_place {
-            RootPlace {
-                place_base: PlaceBase::Local(local),
-                place_projection: [],
-                is_local_mutation_allowed,
-            } => {
+            RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
                 // If the local may have been initialized, and it is now currently being
                 // mutated, then it is justified to be annotated with the `mut`
                 // keyword, since the mutation may be a possible reassignment.
@@ -2141,27 +2112,22 @@
                 }
             }
             RootPlace {
-                place_base: _,
+                place_local: _,
                 place_projection: _,
                 is_local_mutation_allowed: LocalMutationIsAllowed::Yes,
             } => {}
             RootPlace {
-                place_base,
+                place_local,
                 place_projection: place_projection @ [.., _],
                 is_local_mutation_allowed: _,
             } => {
                 if let Some(field) = self.is_upvar_field_projection(PlaceRef {
-                    base: &place_base,
-                    projection: &place_projection,
+                    local: place_local,
+                    projection: place_projection,
                 }) {
                     self.used_mut_upvars.push(field);
                 }
             }
-            RootPlace {
-                place_base: PlaceBase::Static(..),
-                place_projection: [],
-                is_local_mutation_allowed: _,
-            } => {}
         }
     }
 
@@ -2173,58 +2139,34 @@
         is_local_mutation_allowed: LocalMutationIsAllowed,
     ) -> Result<RootPlace<'d, 'tcx>, PlaceRef<'d, 'tcx>> {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 let local = &self.body.local_decls[*local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
                         LocalMutationIsAllowed::Yes => Ok(RootPlace {
-                            place_base: place.base,
+                            place_local: place.local,
                             place_projection: place.projection,
                             is_local_mutation_allowed: LocalMutationIsAllowed::Yes,
                         }),
                         LocalMutationIsAllowed::ExceptUpvars => Ok(RootPlace {
-                            place_base: place.base,
+                            place_local: place.local,
                             place_projection: place.projection,
                             is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars,
                         }),
                         LocalMutationIsAllowed::No => Err(place),
                     },
                     Mutability::Mut => Ok(RootPlace {
-                        place_base: place.base,
+                        place_local: place.local,
                         place_projection: place.projection,
                         is_local_mutation_allowed,
                     }),
                 }
             }
-            // The rules for promotion are made by `qualify_consts`, there wouldn't even be a
-            // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Promoted(..), .. }),
-                projection: [],
-            } => Ok(RootPlace {
-                place_base: place.base,
-                place_projection: place.projection,
-                is_local_mutation_allowed,
-            }),
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }),
-                projection: [],
-            } => {
-                if !self.infcx.tcx.is_mutable_static(*def_id) {
-                    Err(place)
-                } else {
-                    Ok(RootPlace {
-                        place_base: place.base,
-                        place_projection: place.projection,
-                        is_local_mutation_allowed,
-                    })
-                }
-            }
-            PlaceRef { base: _, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
                 match elem {
                     ProjectionElem::Deref => {
                         let base_ty =
-                            Place::ty_from(place.base, proj_base, self.body(), self.infcx.tcx).ty;
+                            Place::ty_from(place.local, proj_base, self.body(), self.infcx.tcx).ty;
 
                         // Check the kind of deref to decide
                         match base_ty.kind {
@@ -2243,7 +2185,7 @@
                                         };
 
                                         self.is_mutable(
-                                            PlaceRef { base: place.base, projection: proj_base },
+                                            PlaceRef { local: place.local, projection: proj_base },
                                             mode,
                                         )
                                     }
@@ -2256,7 +2198,7 @@
                                     // `*mut` raw pointers are always mutable, regardless of
                                     // context. The users have to check by themselves.
                                     hir::Mutability::Mut => Ok(RootPlace {
-                                        place_base: place.base,
+                                        place_local: place.local,
                                         place_projection: place.projection,
                                         is_local_mutation_allowed,
                                     }),
@@ -2264,7 +2206,7 @@
                             }
                             // `Box<T>` owns its content, so mutable if its location is mutable
                             _ if base_ty.is_box() => self.is_mutable(
-                                PlaceRef { base: place.base, projection: proj_base },
+                                PlaceRef { local: place.local, projection: proj_base },
                                 is_local_mutation_allowed,
                             ),
                             // Deref should only be for reference, pointers or boxes
@@ -2320,11 +2262,11 @@
                                     // }
                                     // ```
                                     let _ = self.is_mutable(
-                                        PlaceRef { base: place.base, projection: proj_base },
+                                        PlaceRef { local: place.local, projection: proj_base },
                                         is_local_mutation_allowed,
                                     )?;
                                     Ok(RootPlace {
-                                        place_base: place.base,
+                                        place_local: place.local,
                                         place_projection: place.projection,
                                         is_local_mutation_allowed,
                                     })
@@ -2332,7 +2274,7 @@
                             }
                         } else {
                             self.is_mutable(
-                                PlaceRef { base: place.base, projection: proj_base },
+                                PlaceRef { local: place.local, projection: proj_base },
                                 is_local_mutation_allowed,
                             )
                         }
@@ -2358,7 +2300,7 @@
         match place_projection {
             [base @ .., ProjectionElem::Field(field, _ty)] => {
                 let tcx = self.infcx.tcx;
-                let base_ty = Place::ty_from(place_ref.base, base, self.body(), tcx).ty;
+                let base_ty = Place::ty_from(place_ref.local, base, self.body(), tcx).ty;
 
                 if (base_ty.is_closure() || base_ty.is_generator())
                     && (!by_ref || self.upvars[field.index()].by_ref)
@@ -2374,11 +2316,6 @@
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum NoMovePathFound {
-    ReachedStatic,
-}
-
 /// The degree of overlap between 2 places for borrow-checking.
 enum Overlap {
     /// The places might partially overlap - in this case, we give
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index 6f22378..151a2c4 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -1,6 +1,5 @@
 //! The entry point of the NLL borrow checker.
 
-use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::mir::{
     BasicBlock, Body, BodyAndCache, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind,
@@ -8,6 +7,7 @@
 };
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc_errors::Diagnostic;
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_span::symbol::sym;
 use std::env;
@@ -231,7 +231,6 @@
 
     constraint_generation::generate_constraints(
         infcx,
-        param_env,
         &mut liveness_constraints,
         &mut all_facts,
         location_table,
@@ -253,14 +252,7 @@
     );
 
     // Generate various additional constraints.
-    invalidation::generate_invalidates(
-        infcx.tcx,
-        param_env,
-        &mut all_facts,
-        location_table,
-        body,
-        borrow_set,
-    );
+    invalidation::generate_invalidates(infcx.tcx, &mut all_facts, location_table, body, borrow_set);
 
     // Dump facts if requested.
     let polonius_output = all_facts.and_then(|all_facts| {
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index 23b4799..deec6f3 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -3,8 +3,8 @@
 use crate::borrow_check::AccessDepth;
 use crate::dataflow::indexes::BorrowIndex;
 use rustc::mir::BorrowKind;
-use rustc::mir::{BasicBlock, Body, Location, Place, PlaceBase};
-use rustc::ty::{self, TyCtxt};
+use rustc::mir::{BasicBlock, Body, Location, Place};
+use rustc::ty::TyCtxt;
 use rustc_data_structures::graph::dominators::Dominators;
 
 /// Returns `true` if the borrow represented by `kind` is
@@ -25,7 +25,6 @@
 pub(super) fn each_borrow_involving_path<'tcx, F, I, S>(
     s: &mut S,
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     _location: Location,
     access_place: (AccessDepth, &Place<'tcx>),
@@ -48,7 +47,6 @@
 
         if places_conflict::borrow_conflicts_with_place(
             tcx,
-            param_env,
             body,
             &borrowed.borrowed_place,
             borrowed.kind,
@@ -133,11 +131,7 @@
 /// Determines if a given borrow is borrowing local data
 /// This is called for all Yield expressions on movable generators
 pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
-    match place.base {
-        PlaceBase::Static(_) => false,
-
-        // Reborrow of already borrowed data is ignored
-        // Any errors will be caught on the initial borrow
-        PlaceBase::Local(_) => !place.is_indirect(),
-    }
+    // Reborrow of already borrowed data is ignored
+    // Any errors will be caught on the initial borrow
+    !place.is_indirect()
 }
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index fd59046..ac02da2 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -1,8 +1,8 @@
 use crate::borrow_check::borrow_set::LocalsStateAtExit;
-use rustc::hir;
 use rustc::mir::ProjectionElem;
-use rustc::mir::{Body, Mutability, Place, PlaceBase};
+use rustc::mir::{Body, Mutability, Place};
 use rustc::ty::{self, TyCtxt};
+use rustc_hir as hir;
 
 /// Extension methods for the `Place` type.
 crate trait PlaceExt<'tcx> {
@@ -25,41 +25,35 @@
         body: &Body<'tcx>,
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
-        let local = match self.base {
-            // If a local variable is immutable, then we only need to track borrows to guard
-            // against two kinds of errors:
-            // * The variable being dropped while still borrowed (e.g., because the fn returns
-            //   a reference to a local variable)
-            // * The variable being moved while still borrowed
-            //
-            // In particular, the variable cannot be mutated -- the "access checks" will fail --
-            // so we don't have to worry about mutation while borrowed.
-            PlaceBase::Local(local) => match locals_state_at_exit {
-                LocalsStateAtExit::AllAreInvalidated => local,
-                LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
-                    let ignore = !has_storage_dead_or_moved.contains(local)
-                        && body.local_decls[local].mutability == Mutability::Not;
-                    debug!("ignore_borrow: local {:?} => {:?}", local, ignore);
-                    if ignore {
-                        return true;
-                    } else {
-                        local
-                    }
-                }
-            },
-            PlaceBase::Static(_) => return true,
-        };
+        // If a local variable is immutable, then we only need to track borrows to guard
+        // against two kinds of errors:
+        // * The variable being dropped while still borrowed (e.g., because the fn returns
+        //   a reference to a local variable)
+        // * The variable being moved while still borrowed
+        //
+        // In particular, the variable cannot be mutated -- the "access checks" will fail --
+        // so we don't have to worry about mutation while borrowed.
+        if let LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } =
+            locals_state_at_exit
+        {
+            let ignore = !has_storage_dead_or_moved.contains(self.local)
+                && body.local_decls[self.local].mutability == Mutability::Not;
+            debug!("ignore_borrow: local {:?} => {:?}", self.local, ignore);
+            if ignore {
+                return true;
+            }
+        }
 
         for (i, elem) in self.projection.iter().enumerate() {
             let proj_base = &self.projection[..i];
 
             if *elem == ProjectionElem::Deref {
-                let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty;
+                let ty = Place::ty_from(&self.local, proj_base, body, tcx).ty;
                 match ty.kind {
                     ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
                         // For references to thread-local statics, we do need
                         // to track the borrow.
-                        if body.local_decls[local].is_ref_to_thread_local() {
+                        if body.local_decls[self.local].is_ref_to_thread_local() {
                             continue;
                         }
                         return true;
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index f0d51c9..b95d1af 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -1,11 +1,9 @@
 use crate::borrow_check::ArtificialField;
 use crate::borrow_check::Overlap;
 use crate::borrow_check::{AccessDepth, Deep, Shallow};
-use rustc::hir;
-use rustc::mir::{
-    Body, BorrowKind, Place, PlaceBase, PlaceElem, PlaceRef, ProjectionElem, StaticKind,
-};
+use rustc::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
 use rustc::ty::{self, TyCtxt};
+use rustc_hir as hir;
 use std::cmp::max;
 
 /// When checking if a place conflicts with another place, this enum is used to influence decisions
@@ -25,7 +23,6 @@
 /// dataflow).
 crate fn places_conflict<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     access_place: &Place<'tcx>,
@@ -33,7 +30,6 @@
 ) -> bool {
     borrow_conflicts_with_place(
         tcx,
-        param_env,
         body,
         borrow_place,
         BorrowKind::Mut { allow_two_phase_borrow: true },
@@ -49,7 +45,6 @@
 /// order to make the conservative choice and preserve soundness.
 pub(super) fn borrow_conflicts_with_place<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
@@ -70,21 +65,11 @@
         }
     }
 
-    place_components_conflict(
-        tcx,
-        param_env,
-        body,
-        borrow_place,
-        borrow_kind,
-        access_place,
-        access,
-        bias,
-    )
+    place_components_conflict(tcx, body, borrow_place, borrow_kind, access_place, access, bias)
 }
 
 fn place_components_conflict<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
@@ -134,10 +119,10 @@
     //    and either equal or disjoint.
     //  - If we did run out of access, the borrow can access a part of it.
 
-    let borrow_base = &borrow_place.base;
-    let access_base = access_place.base;
+    let borrow_local = &borrow_place.local;
+    let access_local = access_place.local;
 
-    match place_base_conflict(tcx, param_env, borrow_base, access_base) {
+    match place_base_conflict(borrow_local, access_local) {
         Overlap::Arbitrary => {
             bug!("Two base can't return Arbitrary");
         }
@@ -176,7 +161,7 @@
         match place_projection_conflict(
             tcx,
             body,
-            borrow_base,
+            borrow_local,
             borrow_proj_base,
             borrow_c,
             access_c,
@@ -223,7 +208,7 @@
             // access cares about.
 
             let proj_base = &borrow_place.projection[..access_place.projection.len() + i];
-            let base_ty = Place::ty_from(borrow_base, proj_base, body, tcx).ty;
+            let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty;
 
             match (elem, &base_ty.kind, access) {
                 (_, _, Shallow(Some(ArtificialField::ArrayLength)))
@@ -308,68 +293,15 @@
 // Given that the bases of `elem1` and `elem2` are always either equal
 // or disjoint (and have the same type!), return the overlap situation
 // between `elem1` and `elem2`.
-fn place_base_conflict<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    elem1: &PlaceBase<'tcx>,
-    elem2: &PlaceBase<'tcx>,
-) -> Overlap {
-    match (elem1, elem2) {
-        (PlaceBase::Local(l1), PlaceBase::Local(l2)) => {
-            if l1 == l2 {
-                // the same local - base case, equal
-                debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
-                Overlap::EqualOrDisjoint
-            } else {
-                // different locals - base case, disjoint
-                debug!("place_element_conflict: DISJOINT-LOCAL");
-                Overlap::Disjoint
-            }
-        }
-        (PlaceBase::Static(s1), PlaceBase::Static(s2)) => {
-            match (&s1.kind, &s2.kind) {
-                (StaticKind::Static, StaticKind::Static) => {
-                    if s1.def_id != s2.def_id {
-                        debug!("place_element_conflict: DISJOINT-STATIC");
-                        Overlap::Disjoint
-                    } else if tcx.is_mutable_static(s1.def_id) {
-                        // We ignore mutable statics - they can only be unsafe code.
-                        debug!("place_element_conflict: IGNORE-STATIC-MUT");
-                        Overlap::Disjoint
-                    } else {
-                        debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
-                        Overlap::EqualOrDisjoint
-                    }
-                }
-                (StaticKind::Promoted(promoted_1, _), StaticKind::Promoted(promoted_2, _)) => {
-                    if promoted_1 == promoted_2 {
-                        if let ty::Array(_, len) = s1.ty.kind {
-                            if let Some(0) = len.try_eval_usize(tcx, param_env) {
-                                // Ignore conflicts with promoted [T; 0].
-                                debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
-                                return Overlap::Disjoint;
-                            }
-                        }
-                        // the same promoted - base case, equal
-                        debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
-                        Overlap::EqualOrDisjoint
-                    } else {
-                        // different promoteds - base case, disjoint
-                        debug!("place_element_conflict: DISJOINT-PROMOTED");
-                        Overlap::Disjoint
-                    }
-                }
-                (_, _) => {
-                    debug!("place_element_conflict: DISJOINT-STATIC-PROMOTED");
-                    Overlap::Disjoint
-                }
-            }
-        }
-        (PlaceBase::Local(_), PlaceBase::Static(_))
-        | (PlaceBase::Static(_), PlaceBase::Local(_)) => {
-            debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
-            Overlap::Disjoint
-        }
+fn place_base_conflict(l1: &Local, l2: &Local) -> Overlap {
+    if l1 == l2 {
+        // the same local - base case, equal
+        debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
+        Overlap::EqualOrDisjoint
+    } else {
+        // different locals - base case, disjoint
+        debug!("place_element_conflict: DISJOINT-LOCAL");
+        Overlap::Disjoint
     }
 }
 
@@ -379,7 +311,7 @@
 fn place_projection_conflict<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
-    pi1_base: &PlaceBase<'tcx>,
+    pi1_local: &Local,
     pi1_proj_base: &[PlaceElem<'tcx>],
     pi1_elem: &PlaceElem<'tcx>,
     pi2_elem: &PlaceElem<'tcx>,
@@ -397,7 +329,7 @@
                 debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
                 Overlap::EqualOrDisjoint
             } else {
-                let ty = Place::ty_from(pi1_base, pi1_proj_base, body, tcx).ty;
+                let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
                 match ty.kind {
                     ty::Adt(def, _) if def.is_union() => {
                         // Different fields of a union, we are basically stuck.
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index b994baf..31bee46 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -9,9 +9,9 @@
 
 use super::MirBorrowckCtxt;
 
-use rustc::hir;
-use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
+use rustc::mir::{Place, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
 use rustc::ty::{self, TyCtxt};
+use rustc_hir as hir;
 
 pub trait IsPrefixOf<'cx, 'tcx> {
     fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool;
@@ -19,7 +19,7 @@
 
 impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
     fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
-        self.base == other.base
+        self.local == other.local
             && self.projection.len() <= other.projection.len()
             && self.projection == &other.projection[..self.projection.len()]
     }
@@ -69,39 +69,23 @@
 
         'cursor: loop {
             match &cursor {
-                PlaceRef {
-                    base: PlaceBase::Local(_),
-                    projection: [],
-                }
-                | // search yielded this leaf
-                PlaceRef {
-                    base: PlaceBase::Static(_),
-                    projection: [],
-                } => {
+                PlaceRef { local: _, projection: [] } => {
                     self.next = None;
                     return Some(cursor);
                 }
-                PlaceRef {
-                    base: _,
-                    projection: [proj_base @ .., elem],
-                } => {
+                PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
                     match elem {
                         ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
                             // FIXME: add union handling
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
-                        ProjectionElem::Downcast(..) |
-                        ProjectionElem::Subslice { .. } |
-                        ProjectionElem::ConstantIndex { .. } |
-                        ProjectionElem::Index(_) => {
-                            cursor = PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            };
+                        ProjectionElem::Downcast(..)
+                        | ProjectionElem::Subslice { .. }
+                        | ProjectionElem::ConstantIndex { .. }
+                        | ProjectionElem::Index(_) => {
+                            cursor = PlaceRef { local: cursor.local, projection: proj_base };
                             continue 'cursor;
                         }
                         ProjectionElem::Deref => {
@@ -122,10 +106,8 @@
                         PrefixSet::All => {
                             // All prefixes: just blindly enqueue the base
                             // of the projection.
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
                         PrefixSet::Supporting => {
@@ -138,37 +120,24 @@
                     // derefs, except we stop at the deref of a shared
                     // reference.
 
-                    let ty = Place::ty_from(cursor.base, proj_base, *self.body, self.tcx).ty;
+                    let ty = Place::ty_from(cursor.local, proj_base, *self.body, self.tcx).ty;
                     match ty.kind {
-                        ty::RawPtr(_) |
-                        ty::Ref(
-                            _, /*rgn*/
-                            _, /*ty*/
-                            hir::Mutability::Not
-                            ) => {
+                        ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => {
                             // don't continue traversing over derefs of raw pointers or shared
                             // borrows.
                             self.next = None;
                             return Some(cursor);
                         }
 
-                        ty::Ref(
-                            _, /*rgn*/
-                            _, /*ty*/
-                            hir::Mutability::Mut,
-                            ) => {
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                        ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => {
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
 
                         ty::Adt(..) if ty.is_box() => {
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
 
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 73267b0..7d2384f 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -1,6 +1,5 @@
 use std::rc::Rc;
 
-use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::QueryOutlivesConstraint;
 use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
@@ -14,6 +13,7 @@
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_data_structures::graph::vec_graph::VecGraph;
 use rustc_data_structures::graph::WithSuccessors;
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 use rustc_span::Span;
diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index 0e4801b..f0dc94f 100644
--- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -1,10 +1,10 @@
 use rustc::infer::canonical::QueryRegionConstraints;
-use rustc::infer::outlives::free_region_map::FreeRegionRelations;
 use rustc::infer::region_constraints::GenericKind;
 use rustc::infer::InferCtxt;
 use rustc::mir::ConstraintCategory;
 use rustc::traits::query::outlives_bounds::{self, OutlivesBound};
 use rustc::traits::query::type_op::{self, TypeOp};
+use rustc::ty::free_region_map::FreeRegionRelations;
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_data_structures::transitive_relation::TransitiveRelation;
 use rustc_span::DUMMY_SP;
diff --git a/src/librustc_mir/borrow_check/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/type_check/liveness/local_use_map.rs
index 7bf355d..8155aa0 100644
--- a/src/librustc_mir/borrow_check/type_check/liveness/local_use_map.rs
+++ b/src/librustc_mir/borrow_check/type_check/liveness/local_use_map.rs
@@ -1,7 +1,7 @@
 use rustc::mir::visit::{PlaceContext, Visitor};
 use rustc::mir::{Local, Location, ReadOnlyBodyAndCache};
 use rustc_data_structures::vec_linked_list as vll;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 
 use crate::util::liveness::{categorize, DefUse};
 
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 369bce6..947bbef 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -5,8 +5,6 @@
 
 use either::Either;
 
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -30,6 +28,9 @@
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -309,17 +310,54 @@
                 );
             }
         } else {
-            if let ty::ConstKind::Unevaluated(def_id, substs) = constant.literal.val {
-                if let Err(terr) = self.cx.fully_perform_op(
-                    location.to_locations(),
-                    ConstraintCategory::Boring,
-                    self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
-                        constant.literal.ty,
-                        def_id,
-                        UserSubsts { substs, user_self_ty: None },
-                    )),
-                ) {
-                    span_mirbug!(self, constant, "bad constant type {:?} ({:?})", constant, terr);
+            if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val {
+                if let Some(promoted) = promoted {
+                    let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
+                                     promoted: &ReadOnlyBodyAndCache<'_, 'tcx>,
+                                     ty,
+                                     san_ty| {
+                        if let Err(terr) = verifier.cx.eq_types(
+                            san_ty,
+                            ty,
+                            location.to_locations(),
+                            ConstraintCategory::Boring,
+                        ) {
+                            span_mirbug!(
+                                verifier,
+                                promoted,
+                                "bad promoted type ({:?}: {:?}): {:?}",
+                                ty,
+                                san_ty,
+                                terr
+                            );
+                        };
+                    };
+
+                    if !self.errors_reported {
+                        let promoted_body = self.promoted[promoted];
+                        self.sanitize_promoted(promoted_body, location);
+
+                        let promoted_ty = promoted_body.return_ty();
+                        check_err(self, &promoted_body, ty, promoted_ty);
+                    }
+                } else {
+                    if let Err(terr) = self.cx.fully_perform_op(
+                        location.to_locations(),
+                        ConstraintCategory::Boring,
+                        self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                            constant.literal.ty,
+                            def_id,
+                            UserSubsts { substs, user_self_ty: None },
+                        )),
+                    ) {
+                        span_mirbug!(
+                            self,
+                            constant,
+                            "bad constant type {:?} ({:?})",
+                            constant,
+                            terr
+                        );
+                    }
                 }
             }
             if let ty::FnDef(def_id, substs) = constant.literal.ty.kind {
@@ -427,83 +465,32 @@
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
 
-        let mut place_ty = match &place.base {
-            PlaceBase::Local(index) => PlaceTy::from_ty(self.body.local_decls[*index].ty),
-            PlaceBase::Static(box Static { kind, ty, def_id }) => {
-                let san_ty = self.sanitize_type(place, ty);
-                let check_err =
-                    |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, place: &Place<'tcx>, ty, san_ty| {
-                        if let Err(terr) = verifier.cx.eq_types(
-                            san_ty,
-                            ty,
-                            location.to_locations(),
-                            ConstraintCategory::Boring,
-                        ) {
-                            span_mirbug!(
-                                verifier,
-                                place,
-                                "bad promoted type ({:?}: {:?}): {:?}",
-                                ty,
-                                san_ty,
-                                terr
-                            );
-                        };
-                    };
-                match kind {
-                    StaticKind::Promoted(promoted, _) => {
-                        if !self.errors_reported {
-                            let promoted_body_cache = self.promoted[*promoted];
-                            self.sanitize_promoted(promoted_body_cache, location);
-
-                            let promoted_ty = promoted_body_cache.return_ty();
-                            check_err(self, place, promoted_ty, san_ty);
-                        }
-                    }
-                    StaticKind::Static => {
-                        let ty = self.tcx().type_of(*def_id);
-                        let ty = self.cx.normalize(ty, location);
-
-                        check_err(self, place, ty, san_ty);
-                    }
-                }
-                PlaceTy::from_ty(san_ty)
-            }
-        };
+        let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
 
         if place.projection.is_empty() {
             if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-                let is_promoted = match place.as_ref() {
-                    PlaceRef {
-                        base: &PlaceBase::Static(box Static { kind: StaticKind::Promoted(..), .. }),
-                        projection: &[],
-                    } => true,
-                    _ => false,
+                let tcx = self.tcx();
+                let trait_ref = ty::TraitRef {
+                    def_id: tcx.lang_items().copy_trait().unwrap(),
+                    substs: tcx.mk_substs_trait(place_ty.ty, &[]),
                 };
 
-                if !is_promoted {
-                    let tcx = self.tcx();
-                    let trait_ref = ty::TraitRef {
-                        def_id: tcx.lang_items().copy_trait().unwrap(),
-                        substs: tcx.mk_substs_trait(place_ty.ty, &[]),
-                    };
-
-                    // To have a `Copy` operand, the type `T` of the
-                    // value must be `Copy`. Note that we prove that `T: Copy`,
-                    // rather than using the `is_copy_modulo_regions`
-                    // test. This is important because
-                    // `is_copy_modulo_regions` ignores the resulting region
-                    // obligations and assumes they pass. This can result in
-                    // bounds from `Copy` impls being unsoundly ignored (e.g.,
-                    // #29149). Note that we decide to use `Copy` before knowing
-                    // whether the bounds fully apply: in effect, the rule is
-                    // that if a value of some type could implement `Copy`, then
-                    // it must.
-                    self.cx.prove_trait_ref(
-                        trait_ref,
-                        location.to_locations(),
-                        ConstraintCategory::CopyBound,
-                    );
-                }
+                // To have a `Copy` operand, the type `T` of the
+                // value must be `Copy`. Note that we prove that `T: Copy`,
+                // rather than using the `is_copy_modulo_regions`
+                // test. This is important because
+                // `is_copy_modulo_regions` ignores the resulting region
+                // obligations and assumes they pass. This can result in
+                // bounds from `Copy` impls being unsoundly ignored (e.g.,
+                // #29149). Note that we decide to use `Copy` before knowing
+                // whether the bounds fully apply: in effect, the rule is
+                // that if a value of some type could implement `Copy`, then
+                // it must.
+                self.cx.prove_trait_ref(
+                    trait_ref,
+                    location.to_locations(),
+                    ConstraintCategory::CopyBound,
+                );
             }
         }
 
@@ -2400,7 +2387,7 @@
             match elem {
                 ProjectionElem::Deref => {
                     let tcx = self.infcx.tcx;
-                    let base_ty = Place::ty_from(&borrowed_place.base, proj_base, body, tcx).ty;
+                    let base_ty = Place::ty_from(&borrowed_place.local, proj_base, body, tcx).ty;
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.kind {
diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs
index c7ef017..6e36508 100644
--- a/src/librustc_mir/borrow_check/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/universal_regions.rs
@@ -13,8 +13,6 @@
 //! just returns them for other code to use.
 
 use either::Either;
-use rustc::hir::def_id::DefId;
-use rustc::hir::{self, BodyOwnerKind, HirId};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 use rustc::middle::lang_items;
 use rustc::ty::fold::TypeFoldable;
@@ -22,6 +20,9 @@
 use rustc::ty::{self, RegionVid, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::DiagnosticBuilder;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{BodyOwnerKind, HirId};
 use rustc_index::vec::{Idx, IndexVec};
 use std::iter;
 
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
index 608a243..5e4eebb 100644
--- a/src/librustc_mir/borrow_check/used_muts.rs
+++ b/src/librustc_mir/borrow_check/used_muts.rs
@@ -1,5 +1,5 @@
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind};
+use rustc::mir::{Local, Location, Place, Statement, StatementKind, TerminatorKind};
 
 use rustc_data_structures::fx::FxHashSet;
 
@@ -57,9 +57,7 @@
         // be those that were never initialized - we will consider those as being used as
         // they will either have been removed by unreachable code optimizations; or linted
         // as unused variables.
-        if let PlaceBase::Local(local) = into.base {
-            let _ = self.never_initialized_mut_locals.remove(&local);
-        }
+        self.never_initialized_mut_locals.remove(&into.local);
     }
 }
 
@@ -80,13 +78,11 @@
     fn visit_statement(&mut self, statement: &Statement<'tcx>, _location: Location) {
         match &statement.kind {
             StatementKind::Assign(box (into, _)) => {
-                if let PlaceBase::Local(local) = into.base {
-                    debug!(
-                        "visit_statement: statement={:?} local={:?} \
-                         never_initialized_mut_locals={:?}",
-                        statement, local, self.never_initialized_mut_locals
-                    );
-                }
+                debug!(
+                    "visit_statement: statement={:?} local={:?} \
+                    never_initialized_mut_locals={:?}",
+                    statement, into.local, self.never_initialized_mut_locals
+                );
                 self.remove_never_initialized_mut_locals(into);
             }
             _ => {}
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index ac04ae2..aa7be3d 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -9,10 +9,12 @@
 
 mod error;
 mod eval_queries;
+mod fn_queries;
 mod machine;
 
 pub use error::*;
 pub use eval_queries::*;
+pub use fn_queries::*;
 pub use machine::*;
 
 /// Extracts a field of a (variant of a) const.
@@ -50,7 +52,7 @@
 
     let loc_ty = tcx.caller_location_ty();
     let loc_place = ecx.alloc_caller_location(file, line, col);
-    intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap();
+    intern_const_alloc_recursive(&mut ecx, None, loc_place, false).unwrap();
     let loc_const = ty::Const {
         ty: loc_ty,
         val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),
@@ -59,15 +61,32 @@
     tcx.mk_const(loc_const)
 }
 
-// this function uses `unwrap` copiously, because an already validated constant must have valid
-// fields and can thus never fail outside of compiler bugs
-pub(crate) fn const_variant_index<'tcx>(
+// this function uses `unwrap` copiously, because an already validated constant
+// must have valid fields and can thus never fail outside of compiler bugs
+pub(crate) fn destructure_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     val: &'tcx ty::Const<'tcx>,
-) -> VariantIdx {
-    trace!("const_variant_index: {:?}", val);
+) -> mir::DestructuredConst<'tcx> {
+    trace!("destructure_const: {:?}", val);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
     let op = ecx.eval_const_to_op(val, None).unwrap();
-    ecx.read_discriminant(op).unwrap().1
+
+    let variant = ecx.read_discriminant(op).unwrap().1;
+
+    let field_count = match val.ty.kind {
+        ty::Array(_, len) => len.eval_usize(tcx, param_env),
+        ty::Adt(def, _) => def.variants[variant].fields.len() as u64,
+        ty::Tuple(substs) => substs.len() as u64,
+        _ => bug!("cannot destructure constant {:?}", val),
+    };
+
+    let down = ecx.operand_downcast(op, variant).unwrap();
+    let fields_iter = (0..field_count).map(|i| {
+        let field_op = ecx.operand_field(down, i).unwrap();
+        op_to_const(&ecx, field_op)
+    });
+    let fields = tcx.arena.alloc_from_iter(fields_iter);
+
+    mir::DestructuredConst { variant, fields }
 }
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 46e7651..d260a68 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -5,11 +5,11 @@
     InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar, ScalarMaybeUndef,
     StackPopCleanup,
 };
-use rustc::hir::def::DefKind;
 use rustc::mir;
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
 use rustc::traits::Reveal;
 use rustc::ty::{self, layout, layout::LayoutOf, subst::Subst, TyCtxt};
+use rustc_hir::def::DefKind;
 use rustc_span::source_map::Span;
 use std::convert::TryInto;
 
@@ -56,7 +56,12 @@
     ecx.run()?;
 
     // Intern the result
-    intern_const_alloc_recursive(ecx, tcx.static_mutability(cid.instance.def_id()), ret)?;
+    intern_const_alloc_recursive(
+        ecx,
+        tcx.static_mutability(cid.instance.def_id()),
+        ret,
+        body.ignore_interior_mut_in_const_validation,
+    )?;
 
     debug!("eval_body_using_ecx done: {:?}", *ret);
     Ok(ret)
@@ -115,28 +120,31 @@
         // by-val is if we are in const_field, i.e., if this is (a field of) something that we
         // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
         // structs containing such.
-        op.try_as_mplace()
+        op.try_as_mplace(ecx)
     };
-    let val = match immediate {
-        Ok(mplace) => {
-            let ptr = mplace.ptr.assert_ptr();
+
+    let to_const_value = |mplace: MPlaceTy<'_>| match mplace.ptr {
+        Scalar::Ptr(ptr) => {
             let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
             ConstValue::ByRef { alloc, offset: ptr.offset }
         }
+        Scalar::Raw { data, .. } => {
+            assert!(mplace.layout.is_zst());
+            assert_eq!(
+                data,
+                mplace.layout.align.abi.bytes().into(),
+                "this MPlaceTy must come from `try_as_mplace` being used on a zst, so we know what
+                 value this integer address must have",
+            );
+            ConstValue::Scalar(Scalar::zst())
+        }
+    };
+    let val = match immediate {
+        Ok(mplace) => to_const_value(mplace),
         // see comment on `let try_as_immediate` above
         Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
             ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
-            ScalarMaybeUndef::Undef => {
-                // When coming out of "normal CTFE", we'll always have an `Indirect` operand as
-                // argument and we will not need this. The only way we can already have an
-                // `Immediate` is when we are called from `const_field`, and that `Immediate`
-                // comes from a constant so it can happen have `Undef`, because the indirect
-                // memory that was read had undefined bytes.
-                let mplace = op.assert_mem_place();
-                let ptr = mplace.ptr.assert_ptr();
-                let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
-                ConstValue::ByRef { alloc, offset: ptr.offset }
-            }
+            ScalarMaybeUndef::Undef => to_const_value(op.assert_mem_place(ecx)),
         },
         Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
             let (data, start) = match a.not_undef().unwrap() {
@@ -168,9 +176,14 @@
     let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
     let val = (|| {
         let mplace = ecx.raw_const_to_mplace(constant)?;
-        let mut ref_tracking = RefTracking::new(mplace);
-        while let Some((mplace, path)) = ref_tracking.todo.pop() {
-            ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?;
+
+        // FIXME do not validate promoteds until a decision on
+        // https://github.com/rust-lang/rust/issues/67465 is made
+        if cid.promoted.is_none() {
+            let mut ref_tracking = RefTracking::new(mplace);
+            while let Some((mplace, path)) = ref_tracking.todo.pop() {
+                ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?;
+            }
         }
         // Now that we validated, turn this into a proper constant.
         // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs
new file mode 100644
index 0000000..2443e1e
--- /dev/null
+++ b/src/librustc_mir/const_eval/fn_queries.rs
@@ -0,0 +1,151 @@
+use rustc::hir::map::blocks::FnLikeNode;
+use rustc::ty::query::Providers;
+use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::Symbol;
+use rustc_target::spec::abi::Abi;
+use syntax::attr;
+
+/// Whether the `def_id` counts as const fn in your current crate, considering all active
+/// feature gates
+pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    tcx.is_const_fn_raw(def_id)
+        && match is_unstable_const_fn(tcx, def_id) {
+            Some(feature_name) => {
+                // has a `rustc_const_unstable` attribute, check whether the user enabled the
+                // corresponding feature gate.
+                tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_name)
+            }
+            // functions without const stability are either stable user written
+            // const fn or the user is using feature gates and we thus don't
+            // care what they do
+            None => true,
+        }
+}
+
+/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
+pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
+    if tcx.is_const_fn_raw(def_id) {
+        let const_stab = tcx.lookup_const_stability(def_id)?;
+        if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None }
+    } else {
+        None
+    }
+}
+
+/// Returns `true` if this function must conform to `min_const_fn`
+pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    // Bail out if the signature doesn't contain `const`
+    if !tcx.is_const_fn_raw(def_id) {
+        return false;
+    }
+
+    if tcx.features().staged_api {
+        // In order for a libstd function to be considered min_const_fn
+        // it needs to be stable and have no `rustc_const_unstable` attribute.
+        match tcx.lookup_const_stability(def_id) {
+            // `rustc_const_unstable` functions don't need to conform.
+            Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
+            None => {
+                if let Some(stab) = tcx.lookup_stability(def_id) {
+                    if stab.level.is_stable() {
+                        tcx.sess.span_err(
+                            tcx.def_span(def_id),
+                            "stable const functions must have either `rustc_const_stable` or \
+                             `rustc_const_unstable` attribute",
+                        );
+                        // While we errored above, because we don't know if we need to conform, we
+                        // err on the "safe" side and require min_const_fn.
+                        true
+                    } else {
+                        // Unstable functions need not conform to min_const_fn.
+                        false
+                    }
+                } else {
+                    // Internal functions are forced to conform to min_const_fn.
+                    // Annotate the internal function with a const stability attribute if
+                    // you need to use unstable features.
+                    // Note: this is an arbitrary choice that does not affect stability or const
+                    // safety or anything, it just changes whether we need to annotate some
+                    // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
+                    true
+                }
+            }
+            // Everything else needs to conform, because it would be callable from
+            // other `min_const_fn` functions.
+            _ => true,
+        }
+    } else {
+        // users enabling the `const_fn` feature gate can do what they want
+        !tcx.features().const_fn
+    }
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+    /// Const evaluability whitelist is here to check evaluability at the
+    /// top level beforehand.
+    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
+        match tcx.fn_sig(def_id).abi() {
+            Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
+                Some(tcx.lookup_const_stability(def_id).is_some())
+            }
+            _ => None,
+        }
+    }
+
+    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
+    /// said intrinsic is on the whitelist for being const callable.
+    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+        let hir_id = tcx
+            .hir()
+            .as_local_hir_id(def_id)
+            .expect("Non-local call to local provider is_const_fn");
+
+        let node = tcx.hir().get(hir_id);
+
+        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
+            whitelisted
+        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
+            fn_like.constness() == hir::Constness::Const
+        } else if let hir::Node::Ctor(_) = node {
+            true
+        } else {
+            false
+        }
+    }
+
+    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+        is_const_fn(tcx, def_id)
+            && match tcx.lookup_const_stability(def_id) {
+                Some(stab) => {
+                    if cfg!(debug_assertions) && stab.promotable {
+                        let sig = tcx.fn_sig(def_id);
+                        assert_eq!(
+                            sig.unsafety(),
+                            hir::Unsafety::Normal,
+                            "don't mark const unsafe fns as promotable",
+                            // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
+                        );
+                    }
+                    stab.promotable
+                }
+                None => false,
+            }
+    }
+
+    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+        is_const_fn(tcx, def_id)
+            && tcx
+                .lookup_const_stability(def_id)
+                .map(|stab| stab.allow_const_fn_ptr)
+                .unwrap_or(false)
+    }
+
+    *providers = Providers {
+        is_const_fn_raw,
+        is_promotable_const_fn,
+        const_fn_is_allowed_fn_ptr,
+        ..*providers
+    };
+}
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index b39a61c..1aed91b 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -1,7 +1,7 @@
-use rustc::hir::def_id::DefId;
 use rustc::mir;
 use rustc::ty::layout::HasTyCtxt;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir::def_id::DefId;
 use std::borrow::{Borrow, Cow};
 use std::collections::hash_map::Entry;
 use std::hash::Hash;
diff --git a/src/librustc_mir/dataflow/generic.rs b/src/librustc_mir/dataflow/generic.rs
index da2739f..d2ca4f1 100644
--- a/src/librustc_mir/dataflow/generic.rs
+++ b/src/librustc_mir/dataflow/generic.rs
@@ -22,10 +22,10 @@
 use std::path::{Path, PathBuf};
 use std::{fs, io, ops};
 
-use rustc::hir::def_id::DefId;
 use rustc::mir::{self, traversal, BasicBlock, Location};
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::work_queue::WorkQueue;
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::symbol::sym;
diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs
index 399a839..e843956 100644
--- a/src/librustc_mir/dataflow/generic/graphviz.rs
+++ b/src/librustc_mir/dataflow/generic/graphviz.rs
@@ -2,8 +2,8 @@
 use std::io::{self, Write};
 use std::{ops, str};
 
-use rustc::hir::def_id::DefId;
 use rustc::mir::{self, BasicBlock, Body, Location};
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::{BitSet, HybridBitSet};
 use rustc_index::vec::Idx;
 
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index 89a0a08..45d2b1a 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -1,7 +1,7 @@
 //! Hook into libgraphviz for rendering dataflow graphs for MIR.
 
-use rustc::hir::def_id::DefId;
 use rustc::mir::{BasicBlock, Body};
+use rustc_hir::def_id::DefId;
 
 use std::fs;
 use std::io;
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index 6597690..63834d0 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -86,10 +86,7 @@
 }
 
 fn find_local(place: &Place<'_>) -> Option<Local> {
-    match place.base {
-        PlaceBase::Local(local) if !place.is_indirect() => Some(local),
-        _ => None,
-    }
+    if !place.is_indirect() { Some(place.local) } else { None }
 }
 
 impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> {
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 30ecceb..f94ee67 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -1,10 +1,10 @@
-use rustc::mir::{self, Body, Location, Place, PlaceBase};
+use rustc::mir::{self, Body, Location, Place};
 use rustc::ty::RegionVid;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::TyCtxt;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 
 use crate::borrow_check::{
     places_conflict, BorrowData, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext,
@@ -30,7 +30,6 @@
 pub struct Borrows<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
 
     borrow_set: Rc<BorrowSet<'tcx>>,
     borrows_out_of_scope_at_location: FxHashMap<Location, Vec<BorrowIndex>>,
@@ -134,7 +133,6 @@
     crate fn new(
         tcx: TyCtxt<'tcx>,
         body: &'a Body<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
         nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
         borrow_set: &Rc<BorrowSet<'tcx>>,
     ) -> Self {
@@ -156,7 +154,6 @@
         Borrows {
             tcx,
             body,
-            param_env,
             borrow_set: borrow_set.clone(),
             borrows_out_of_scope_at_location,
             _nonlexical_regioncx: nonlexical_regioncx,
@@ -198,37 +195,34 @@
     fn kill_borrows_on_place(&self, trans: &mut GenKillSet<BorrowIndex>, place: &Place<'tcx>) {
         debug!("kill_borrows_on_place: place={:?}", place);
 
-        if let PlaceBase::Local(local) = place.base {
-            let other_borrows_of_local =
-                self.borrow_set.local_map.get(&local).into_iter().flat_map(|bs| bs.into_iter());
+        let other_borrows_of_local =
+            self.borrow_set.local_map.get(&place.local).into_iter().flat_map(|bs| bs.into_iter());
 
-            // If the borrowed place is a local with no projections, all other borrows of this
-            // local must conflict. This is purely an optimization so we don't have to call
-            // `places_conflict` for every borrow.
-            if place.projection.is_empty() {
-                if !self.body.local_decls[local].is_ref_to_static() {
-                    trans.kill_all(other_borrows_of_local);
-                }
-                return;
+        // If the borrowed place is a local with no projections, all other borrows of this
+        // local must conflict. This is purely an optimization so we don't have to call
+        // `places_conflict` for every borrow.
+        if place.projection.is_empty() {
+            if !self.body.local_decls[place.local].is_ref_to_static() {
+                trans.kill_all(other_borrows_of_local);
             }
-
-            // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
-            // pair of array indices are unequal, so that when `places_conflict` returns true, we
-            // will be assured that two places being compared definitely denotes the same sets of
-            // locations.
-            let definitely_conflicting_borrows = other_borrows_of_local.filter(|&&i| {
-                places_conflict(
-                    self.tcx,
-                    self.param_env,
-                    self.body,
-                    &self.borrow_set.borrows[i].borrowed_place,
-                    place,
-                    PlaceConflictBias::NoOverlap,
-                )
-            });
-
-            trans.kill_all(definitely_conflicting_borrows);
+            return;
         }
+
+        // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
+        // pair of array indices are unequal, so that when `places_conflict` returns true, we
+        // will be assured that two places being compared definitely denotes the same sets of
+        // locations.
+        let definitely_conflicting_borrows = other_borrows_of_local.filter(|&&i| {
+            places_conflict(
+                self.tcx,
+                self.body,
+                &self.borrow_set.borrows[i].borrowed_place,
+                place,
+                PlaceConflictBias::NoOverlap,
+            )
+        });
+
+        trans.kill_all(definitely_conflicting_borrows);
     }
 }
 
diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs
index 38401b4..85bf342 100644
--- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs
+++ b/src/librustc_mir/dataflow/impls/indirect_mutation.rs
@@ -111,12 +111,8 @@
     fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
         if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue {
             if self.borrow_allows_mutation(kind, borrowed_place) {
-                match borrowed_place.base {
-                    mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect() => {
-                        self.trans.gen(borrowed_local)
-                    }
-
-                    _ => (),
+                if !borrowed_place.is_indirect() {
+                    self.trans.gen(borrowed_place.local);
                 }
             }
         }
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index 17f71e8..6a48d1e 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -116,15 +116,11 @@
             StatementKind::StorageDead(l) => sets.kill(l),
             StatementKind::Assign(box (ref place, _))
             | StatementKind::SetDiscriminant { box ref place, .. } => {
-                if let PlaceBase::Local(local) = place.base {
-                    sets.gen(local);
-                }
+                sets.gen(place.local);
             }
             StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => {
-                for p in &**outputs {
-                    if let PlaceBase::Local(local) = p.base {
-                        sets.gen(local);
-                    }
+                for place in &**outputs {
+                    sets.gen(place.local);
                 }
             }
             _ => (),
@@ -140,10 +136,8 @@
     fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
         self.check_for_borrow(sets, loc);
 
-        if let TerminatorKind::Call {
-            destination: Some((Place { base: PlaceBase::Local(local), .. }, _)),
-            ..
-        } = self.body[loc.block].terminator().kind
+        if let TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } =
+            self.body[loc.block].terminator().kind
         {
             sets.gen(local);
         }
@@ -171,9 +165,7 @@
         _dest_bb: mir::BasicBlock,
         dest_place: &mir::Place<'tcx>,
     ) {
-        if let PlaceBase::Local(local) = dest_place.base {
-            in_out.insert(local);
-        }
+        in_out.insert(dest_place.local);
     }
 }
 
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index e94f263..e29730f 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -6,11 +6,11 @@
 use rustc_index::bit_set::{BitSet, HybridBitSet};
 use rustc_index::vec::Idx;
 
-use rustc::hir::def_id::DefId;
 use rustc::mir::traversal;
 use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator};
 use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
+use rustc_hir::def_id::DefId;
 
 use std::borrow::Borrow;
 use std::fmt;
@@ -668,6 +668,26 @@
     const BOTTOM_VALUE: bool;
 
     /// Merges `in_set` into `inout_set`, returning `true` if `inout_set` changed.
+    ///
+    /// It is almost certainly wrong to override this, since it automatically applies
+    /// * `inout_set & in_set` if `BOTTOM_VALUE == true`
+    /// * `inout_set | in_set` if `BOTTOM_VALUE == false`
+    ///
+    /// This means that if a bit is not `BOTTOM_VALUE`, it is propagated into all target blocks.
+    /// For clarity, the above statement again from a different perspective:
+    /// A bit in the block's entry set is `!BOTTOM_VALUE` if *any* predecessor block's bit value is
+    /// `!BOTTOM_VALUE`.
+    ///
+    /// There are situations where you want the opposite behaviour: propagate only if *all*
+    /// predecessor blocks's value is `!BOTTOM_VALUE`.
+    /// E.g. if you want to know whether a bit is *definitely* set at a specific location. This
+    /// means that all code paths leading to the location must have set the bit, instead of any
+    /// code path leading there.
+    ///
+    /// If you want this kind of "definitely set" analysis, you need to
+    /// 1. Invert `BOTTOM_VALUE`
+    /// 2. Reset the `entry_set` in `start_block_effect` to `!BOTTOM_VALUE`
+    /// 3. Override `join` to do the opposite from what it's doing now.
     #[inline]
     fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
         if Self::BOTTOM_VALUE == false {
@@ -685,7 +705,9 @@
 /// for each block individually. The entry set for all other basic blocks is
 /// initialized to `Self::BOTTOM_VALUE`. The dataflow analysis then
 /// iteratively modifies the various entry sets (but leaves the the transfer
-/// function unchanged).
+/// function unchanged). `BottomValue::join` is used to merge the bitsets from
+/// two blocks (e.g. when two blocks' terminator jumps to a single block, that
+/// target block's state is the merged state of both incoming blocks).
 pub trait BitDenotation<'tcx>: BottomValue {
     /// Specifies what index type is used to access the bitvector.
     type Idx: Idx;
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index c05f7f8..271bcce 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -96,12 +96,7 @@
     /// Maybe we should have separate "borrowck" and "moveck" modes.
     fn move_path_for(&mut self, place: &Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
         debug!("lookup({:?})", place);
-        let mut base = match place.base {
-            PlaceBase::Local(local) => self.builder.data.rev_lookup.locals[local],
-            PlaceBase::Static(..) => {
-                return Err(MoveError::cannot_move_out_of(self.loc, Static));
-            }
-        };
+        let mut base = self.builder.data.rev_lookup.locals[place.local];
 
         // The move path index of the first union that we find. Once this is
         // some we stop creating child move paths, since moves from unions
@@ -114,7 +109,7 @@
             let proj_base = &place.projection[..i];
             let body = self.builder.body;
             let tcx = self.builder.tcx;
-            let place_ty = Place::ty_from(&place.base, proj_base, body, tcx).ty;
+            let place_ty = Place::ty_from(&place.local, proj_base, body, tcx).ty;
             match place_ty.kind {
                 ty::Ref(..) | ty::RawPtr(..) => {
                     let proj = &place.projection[..i + 1];
@@ -122,7 +117,7 @@
                         self.loc,
                         BorrowedContent {
                             target_place: Place {
-                                base: place.base.clone(),
+                                local: place.local,
                                 projection: tcx.intern_place_elems(proj),
                             },
                         },
@@ -163,7 +158,7 @@
 
             if union_path.is_none() {
                 base = self.add_move_path(base, elem, |tcx| Place {
-                    base: place.base.clone(),
+                    local: place.local.clone(),
                     projection: tcx.intern_place_elems(&place.projection[..i + 1]),
                 });
             }
@@ -436,7 +431,7 @@
             // `ConstIndex` patterns. This is done to ensure that all move paths
             // are disjoint, which is expected by drop elaboration.
             let base_place = Place {
-                base: place.base.clone(),
+                local: place.local.clone(),
                 projection: self.builder.tcx.intern_place_elems(base),
             };
             let base_path = match self.move_path_for(&base_place) {
@@ -497,10 +492,10 @@
         // of the union so it is marked as initialized again.
         if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection {
             if let ty::Adt(def, _) =
-                Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.kind
+                Place::ty_from(place.local, proj_base, self.builder.body, self.builder.tcx).ty.kind
             {
                 if def.is_union() {
-                    place = PlaceRef { base: place.base, projection: proj_base }
+                    place = PlaceRef { local: place.local, projection: proj_base }
                 }
             }
         }
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 6450762..a46465a 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -2,7 +2,7 @@
 use rustc::mir::*;
 use rustc::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_index::vec::{Enumerated, Idx, IndexVec};
+use rustc_index::vec::{Enumerated, IndexVec};
 use rustc_span::Span;
 use smallvec::SmallVec;
 
@@ -246,10 +246,7 @@
     // unknown place, but will rather return the nearest available
     // parent.
     pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult {
-        let mut result = match place.base {
-            PlaceBase::Local(local) => self.locals[*local],
-            PlaceBase::Static(..) => return LookupResult::Parent(None),
-        };
+        let mut result = self.locals[*place.local];
 
         for elem in place.projection.iter() {
             if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
@@ -281,9 +278,6 @@
 
 #[derive(Debug)]
 pub(crate) enum IllegalMoveOriginKind<'tcx> {
-    /// Illegal move due to attempt to move from `static` variable.
-    Static,
-
     /// Illegal move due to attempt to move from behind a reference.
     BorrowedContent {
         /// The place the reference refers to: if erroneous code was trying to
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 5c51597..206d3d1 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -2,8 +2,6 @@
 use std::fmt::Write;
 use std::mem;
 
-use rustc::hir::def::DefKind;
-use rustc::hir::def_id::DefId;
 use rustc::ich::StableHashingContext;
 use rustc::mir;
 use rustc::mir::interpret::{
@@ -15,12 +13,14 @@
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
 use rustc_span::source_map::{self, Span, DUMMY_SP};
 
 use super::{
-    Immediate, MPlaceTy, Machine, MemPlace, Memory, OpTy, Operand, Place, PlaceTy,
+    Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
     ScalarMaybeUndef, StackPopInfo,
 };
 
@@ -393,7 +393,7 @@
     /// This can fail to provide an answer for extern types.
     pub(super) fn size_and_align_of(
         &self,
-        metadata: Option<Scalar<M::PointerTag>>,
+        metadata: MemPlaceMeta<M::PointerTag>,
         layout: TyLayout<'tcx>,
     ) -> InterpResult<'tcx, Option<(Size, Align)>> {
         if !layout.is_unsized() {
@@ -465,14 +465,13 @@
                 Ok(Some((size, align)))
             }
             ty::Dynamic(..) => {
-                let vtable = metadata.expect("dyn trait fat ptr must have vtable");
+                let vtable = metadata.unwrap_meta();
                 // Read size and align from vtable (already checks size).
                 Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
             }
 
             ty::Slice(_) | ty::Str => {
-                let len =
-                    metadata.expect("slice fat ptr must have length").to_machine_usize(self)?;
+                let len = metadata.unwrap_meta().to_machine_usize(self)?;
                 let elem = layout.field(self, 0)?;
 
                 // Make sure the slice is not too big.
@@ -758,13 +757,22 @@
         &self,
         gid: GlobalId<'tcx>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let val = if self.tcx.is_static(gid.instance.def_id()) {
-            self.tcx.const_eval_poly(gid.instance.def_id())?
-        } else if let Some(promoted) = gid.promoted {
-            self.tcx.const_eval_promoted(gid.instance, promoted)?
+        // For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
+        // and thus don't care about the parameter environment. While we could just use
+        // `self.param_env`, that would mean we invoke the query to evaluate the static
+        // with different parameter environments, thus causing the static to be evaluated
+        // multiple times.
+        let param_env = if self.tcx.is_static(gid.instance.def_id()) {
+            ty::ParamEnv::reveal_all()
         } else {
-            self.tcx.const_eval_instance(self.param_env, gid.instance, Some(self.tcx.span))?
+            self.param_env
         };
+        let val = if let Some(promoted) = gid.promoted {
+            self.tcx.const_eval_promoted(param_env, gid.instance, promoted)?
+        } else {
+            self.tcx.const_eval_instance(param_env, gid.instance, Some(self.tcx.span))?
+        };
+
         // Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a
         // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
         // return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
@@ -818,8 +826,8 @@
                                 " by align({}){} ref:",
                                 mplace.align.bytes(),
                                 match mplace.meta {
-                                    Some(meta) => format!(" meta({:?})", meta),
-                                    None => String::new(),
+                                    MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
+                                    MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
                                 }
                             )
                             .unwrap();
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 9f54d4c..220761c 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -4,10 +4,10 @@
 //! memory, we need to extract all memory allocations to the global memory pool so they stay around.
 
 use super::validity::RefTracking;
-use rustc::hir;
 use rustc::mir::interpret::{ErrorHandled, InterpResult};
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
 
 use syntax::ast::Mutability;
 
@@ -41,6 +41,11 @@
     /// despite the nested mutable reference!
     /// The field gets updated when an `UnsafeCell` is encountered.
     mutability: Mutability,
+
+    /// This flag is to avoid triggering UnsafeCells are not allowed behind references in constants
+    /// for promoteds.
+    /// It's a copy of `mir::Body`'s ignore_interior_mut_in_const_validation field
+    ignore_interior_mut_in_const_validation: bool,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
@@ -164,14 +169,16 @@
                 // References we encounter inside here are interned as pointing to mutable
                 // allocations.
                 let old = std::mem::replace(&mut self.mutability, Mutability::Mut);
-                assert_ne!(
-                    self.mode,
-                    InternMode::Const,
-                    "UnsafeCells are not allowed behind references in constants. This should have \
-                    been prevented statically by const qualification. If this were allowed one \
-                    would be able to change a constant at one use site and other use sites could \
-                    observe that mutation.",
-                );
+                if !self.ignore_interior_mut_in_const_validation {
+                    assert_ne!(
+                        self.mode,
+                        InternMode::Const,
+                        "UnsafeCells are not allowed behind references in constants. This should \
+                        have been prevented statically by const qualification. If this were \
+                        allowed one would be able to change a constant at one use site and other \
+                        use sites could observe that mutation.",
+                    );
+                }
                 let walked = self.walk_aggregate(mplace, fields);
                 self.mutability = old;
                 return walked;
@@ -193,7 +200,7 @@
             {
                 // Validation has already errored on an invalid vtable pointer so we can safely not
                 // do anything if this is not a real pointer.
-                if let Scalar::Ptr(vtable) = mplace.meta.unwrap() {
+                if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() {
                     // Explicitly choose `Immutable` here, since vtables are immutable, even
                     // if the reference of the fat pointer is mutable.
                     self.intern_shallow(vtable.alloc_id, Mutability::Not, None)?;
@@ -226,7 +233,8 @@
                     | (InternMode::Const, hir::Mutability::Mut) => match referenced_ty.kind {
                         ty::Array(_, n)
                             if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
-                        ty::Slice(_) if mplace.meta.unwrap().to_machine_usize(self.ecx)? == 0 => {}
+                        ty::Slice(_)
+                            if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)? == 0 => {}
                         _ => bug!("const qualif failed to prevent mutable references"),
                     },
                 }
@@ -265,6 +273,7 @@
     // The `mutability` of the place, ignoring the type.
     place_mut: Option<hir::Mutability>,
     ret: MPlaceTy<'tcx>,
+    ignore_interior_mut_in_const_validation: bool,
 ) -> InterpResult<'tcx> {
     let tcx = ecx.tcx;
     let (base_mutability, base_intern_mode) = match place_mut {
@@ -301,6 +310,7 @@
             mode,
             leftover_allocations,
             mutability,
+            ignore_interior_mut_in_const_validation,
         }
         .visit_value(mplace);
         if let Err(error) = interned {
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index b075e8e..cd6d943 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -2,7 +2,6 @@
 //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
 //! and miri.
 
-use rustc::hir::def_id::DefId;
 use rustc::mir::{
     self,
     interpret::{ConstValue, GlobalId, InterpResult, Scalar},
@@ -12,6 +11,7 @@
 use rustc::ty::layout::{LayoutOf, Primitive, Size};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::TyCtxt;
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index 659651e..eed47c1 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -1,4 +1,3 @@
-use rustc::hir::def_id::CrateNum;
 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
 use rustc::mir::interpret::Allocation;
 use rustc::ty::{
@@ -7,6 +6,7 @@
     subst::{GenericArg, GenericArgKind},
     Ty, TyCtxt,
 };
+use rustc_hir::def_id::CrateNum;
 use std::fmt::Write;
 
 struct AbsolutePathPrinter<'tcx> {
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 3dc572d..3309e9b 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -5,9 +5,9 @@
 use std::borrow::{Borrow, Cow};
 use std::hash::Hash;
 
-use rustc::hir::def_id::DefId;
 use rustc::mir;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 
 use super::{
@@ -212,7 +212,7 @@
         frame.locals[local].access()
     }
 
-    /// Called before a `StaticKind::Static` value is accessed.
+    /// Called before a `Static` value is accessed.
     fn before_access_static(
         _memory_extra: &Self::MemoryExtra,
         _allocation: &Allocation,
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 0d35eae..2e8fbb9 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -20,7 +20,7 @@
 
 pub use self::eval_context::{Frame, InterpCx, LocalState, LocalValue, StackPopCleanup};
 
-pub use self::place::{MPlaceTy, MemPlace, Place, PlaceTy};
+pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
 
 pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind};
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index def979b..b37eff3 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -153,30 +153,6 @@
     Indirect(MemPlace<Tag, Id>),
 }
 
-impl<Tag> Operand<Tag> {
-    #[inline]
-    pub fn assert_mem_place(self) -> MemPlace<Tag>
-    where
-        Tag: ::std::fmt::Debug,
-    {
-        match self {
-            Operand::Indirect(mplace) => mplace,
-            _ => bug!("assert_mem_place: expected Operand::Indirect, got {:?}", self),
-        }
-    }
-
-    #[inline]
-    pub fn assert_immediate(self) -> Immediate<Tag>
-    where
-        Tag: ::std::fmt::Debug,
-    {
-        match self {
-            Operand::Immediate(imm) => imm,
-            _ => bug!("assert_immediate: expected Operand::Immediate, got {:?}", self),
-        }
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct OpTy<'tcx, Tag = ()> {
     op: Operand<Tag>, // Keep this private; it helps enforce invariants.
@@ -267,7 +243,7 @@
         &self,
         op: OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        match op.try_as_mplace() {
+        match op.try_as_mplace(self) {
             Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()),
             Err(imm) => Ok(imm.into()), // Nothing to cast/force
         }
@@ -335,7 +311,7 @@
         &self,
         src: OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::PointerTag>, MPlaceTy<'tcx, M::PointerTag>>> {
-        Ok(match src.try_as_mplace() {
+        Ok(match src.try_as_mplace(self) {
             Ok(mplace) => {
                 if let Some(val) = self.try_read_immediate_from_mplace(mplace)? {
                     Ok(val)
@@ -383,7 +359,7 @@
         op: OpTy<'tcx, M::PointerTag>,
         field: u64,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let base = match op.try_as_mplace() {
+        let base = match op.try_as_mplace(self) {
             Ok(mplace) => {
                 // The easy case
                 let field = self.mplace_field(mplace, field)?;
@@ -420,7 +396,7 @@
         variant: VariantIdx,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
-        Ok(match op.try_as_mplace() {
+        Ok(match op.try_as_mplace(self) {
             Ok(mplace) => self.mplace_downcast(mplace, variant)?.into(),
             Err(..) => {
                 let layout = op.layout.for_variant(self, variant);
@@ -439,30 +415,10 @@
             Field(field, _) => self.operand_field(base, field.index() as u64)?,
             Downcast(_, variant) => self.operand_downcast(base, variant)?,
             Deref => self.deref_operand(base)?.into(),
-            ConstantIndex { .. } | Index(_) if base.layout.is_zst() => {
-                OpTy {
-                    op: Operand::Immediate(Scalar::zst().into()),
-                    // the actual index doesn't matter, so we just pick a convenient one like 0
-                    layout: base.layout.field(self, 0)?,
-                }
-            }
-            Subslice { from, to, from_end } if base.layout.is_zst() => {
-                let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind {
-                    elem_ty
-                } else {
-                    bug!("slices shouldn't be zero-sized");
-                };
-                assert!(!from_end, "arrays shouldn't be subsliced from the end");
-
-                OpTy {
-                    op: Operand::Immediate(Scalar::zst().into()),
-                    layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?,
-                }
-            }
             Subslice { .. } | ConstantIndex { .. } | Index(_) => {
                 // The rest should only occur as mplace, we do not use Immediates for types
                 // allowing such operations.  This matches place_projection forcing an allocation.
-                let mplace = base.assert_mem_place();
+                let mplace = base.assert_mem_place(self);
                 self.mplace_projection(mplace, proj_elem)?.into()
             }
         })
@@ -506,19 +462,15 @@
         place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        use rustc::mir::PlaceBase;
-
-        let base_op = match &place.base {
-            PlaceBase::Local(mir::RETURN_PLACE) => throw_unsup!(ReadFromReturnPointer),
-            PlaceBase::Local(local) => {
+        let base_op = match place.local {
+            mir::RETURN_PLACE => throw_unsup!(ReadFromReturnPointer),
+            local => {
                 // Do not use the layout passed in as argument if the base we are looking at
                 // here is not the entire place.
-                // FIXME use place_projection.is_empty() when is available
                 let layout = if place.projection.is_empty() { layout } else { None };
 
-                self.access_local(self.frame(), *local, layout)?
+                self.access_local(self.frame(), local, layout)?
             }
-            PlaceBase::Static(place_static) => self.eval_static_to_mplace(&place_static)?.into(),
         };
 
         let op = place
@@ -576,7 +528,7 @@
         // Early-return cases.
         let val_val = match val.val {
             ty::ConstKind::Param(_) => throw_inval!(TooGeneric),
-            ty::ConstKind::Unevaluated(def_id, substs) => {
+            ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
                 let instance = self.resolve(def_id, substs)?;
                 // We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
                 // The reason we use `const_eval_raw` everywhere else is to prevent cycles during
@@ -584,9 +536,7 @@
                 // potentially requiring the current static to be evaluated again. This is not a
                 // problem here, because we are building an operand which means an actual read is
                 // happening.
-                // FIXME(oli-obk): eliminate all the `const_eval_raw` usages when we get rid of
-                // `StaticKind` once and for all.
-                return self.const_eval(GlobalId { instance, promoted: None });
+                return Ok(OpTy::from(self.const_eval(GlobalId { instance, promoted })?));
             }
             ty::ConstKind::Infer(..)
             | ty::ConstKind::Bound(..)
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index f4ac7de..8888e3f 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -10,17 +10,57 @@
 use rustc::ty::layout::{
     self, Align, HasDataLayout, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
 };
-use rustc::ty::TypeFoldable;
 use rustc::ty::{self, Ty};
 use rustc_macros::HashStable;
 
 use super::{
-    AllocId, AllocMap, Allocation, AllocationExtra, GlobalId, ImmTy, Immediate, InterpCx,
-    InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer, PointerArithmetic,
-    RawConst, Scalar, ScalarMaybeUndef,
+    AllocId, AllocMap, Allocation, AllocationExtra, ImmTy, Immediate, InterpCx, InterpResult,
+    LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer, PointerArithmetic, RawConst, Scalar,
+    ScalarMaybeUndef,
 };
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
+/// Information required for the sound usage of a `MemPlace`.
+pub enum MemPlaceMeta<Tag = (), Id = AllocId> {
+    /// The unsized payload (e.g. length for slices or vtable pointer for trait objects).
+    Meta(Scalar<Tag, Id>),
+    /// `Sized` types or unsized `extern type`
+    None,
+    /// The address of this place may not be taken. This protects the `MemPlace` from coming from
+    /// a ZST Operand with a backing allocation and being converted to an integer address. This
+    /// should be impossible, because you can't take the address of an operand, but this is a second
+    /// protection layer ensuring that we don't mess up.
+    Poison,
+}
+
+impl<Tag, Id> MemPlaceMeta<Tag, Id> {
+    pub fn unwrap_meta(self) -> Scalar<Tag, Id> {
+        match self {
+            Self::Meta(s) => s,
+            Self::None | Self::Poison => {
+                bug!("expected wide pointer extra data (e.g. slice length or trait object vtable)")
+            }
+        }
+    }
+    fn has_meta(self) -> bool {
+        match self {
+            Self::Meta(_) => true,
+            Self::None | Self::Poison => false,
+        }
+    }
+}
+
+impl<Tag> MemPlaceMeta<Tag> {
+    pub fn erase_tag(self) -> MemPlaceMeta<()> {
+        match self {
+            Self::Meta(s) => MemPlaceMeta::Meta(s.erase_tag()),
+            Self::None => MemPlaceMeta::None,
+            Self::Poison => MemPlaceMeta::Poison,
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
 pub struct MemPlace<Tag = (), Id = AllocId> {
     /// A place may have an integral pointer for ZSTs, and since it might
     /// be turned back into a reference before ever being dereferenced.
@@ -30,7 +70,7 @@
     /// Metadata for unsized places. Interpretation is up to the type.
     /// Must not be present for sized types, but can be missing for unsized types
     /// (e.g., `extern type`).
-    pub meta: Option<Scalar<Tag, Id>>,
+    pub meta: MemPlaceMeta<Tag, Id>,
 }
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
@@ -88,21 +128,17 @@
 
     #[inline]
     pub fn erase_tag(self) -> MemPlace {
-        MemPlace {
-            ptr: self.ptr.erase_tag(),
-            align: self.align,
-            meta: self.meta.map(Scalar::erase_tag),
-        }
+        MemPlace { ptr: self.ptr.erase_tag(), align: self.align, meta: self.meta.erase_tag() }
     }
 
     #[inline(always)]
-    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
-        MemPlace { ptr, align, meta: None }
+    fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
+        MemPlace { ptr, align, meta: MemPlaceMeta::None }
     }
 
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline(always)]
-    pub fn null(cx: &impl HasDataLayout) -> Self {
+    fn null(cx: &impl HasDataLayout) -> Self {
         Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1).unwrap())
     }
 
@@ -116,15 +152,19 @@
     #[inline(always)]
     pub fn to_ref(self) -> Immediate<Tag> {
         match self.meta {
-            None => Immediate::Scalar(self.ptr.into()),
-            Some(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()),
+            MemPlaceMeta::None => Immediate::Scalar(self.ptr.into()),
+            MemPlaceMeta::Meta(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()),
+            MemPlaceMeta::Poison => bug!(
+                "MPlaceTy::dangling may never be used to produce a \
+                place that will have the address of its pointee taken"
+            ),
         }
     }
 
     pub fn offset(
         self,
         offset: Size,
-        meta: Option<Scalar<Tag>>,
+        meta: MemPlaceMeta<Tag>,
         cx: &impl HasDataLayout,
     ) -> InterpResult<'tcx, Self> {
         Ok(MemPlace {
@@ -139,13 +179,10 @@
     /// Produces a MemPlace that works for ZST but nothing else
     #[inline]
     pub fn dangling(layout: TyLayout<'tcx>, cx: &impl HasDataLayout) -> Self {
-        MPlaceTy {
-            mplace: MemPlace::from_scalar_ptr(
-                Scalar::from_uint(layout.align.abi.bytes(), cx.pointer_size()),
-                layout.align.abi,
-            ),
-            layout,
-        }
+        let align = layout.align.abi;
+        let ptr = Scalar::from_uint(align.bytes(), cx.pointer_size());
+        // `Poison` this to make sure that the pointer value `ptr` is never observable by the program.
+        MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout }
     }
 
     /// Replace ptr tag, maintain vtable tag (if any)
@@ -158,7 +195,7 @@
     pub fn offset(
         self,
         offset: Size,
-        meta: Option<Scalar<Tag>>,
+        meta: MemPlaceMeta<Tag>,
         layout: TyLayout<'tcx>,
         cx: &impl HasDataLayout,
     ) -> InterpResult<'tcx, Self> {
@@ -175,7 +212,9 @@
         if self.layout.is_unsized() {
             // We need to consult `meta` metadata
             match self.layout.ty.kind {
-                ty::Slice(..) | ty::Str => return self.mplace.meta.unwrap().to_machine_usize(cx),
+                ty::Slice(..) | ty::Str => {
+                    return self.mplace.meta.unwrap_meta().to_machine_usize(cx);
+                }
                 _ => bug!("len not supported on unsized type {:?}", self.layout.ty),
             }
         } else {
@@ -191,7 +230,7 @@
     #[inline]
     pub(super) fn vtable(self) -> Scalar<Tag> {
         match self.layout.ty.kind {
-            ty::Dynamic(..) => self.mplace.meta.unwrap(),
+            ty::Dynamic(..) => self.mplace.meta.unwrap_meta(),
             _ => bug!("vtable not supported on type {:?}", self.layout.ty),
         }
     }
@@ -200,36 +239,36 @@
 // These are defined here because they produce a place.
 impl<'tcx, Tag: ::std::fmt::Debug + Copy> OpTy<'tcx, Tag> {
     #[inline(always)]
-    pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
+    /// Note: do not call `as_ref` on the resulting place. This function should only be used to
+    /// read from the resulting mplace, not to get its address back.
+    pub fn try_as_mplace(
+        self,
+        cx: &impl HasDataLayout,
+    ) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
         match *self {
             Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
+            Operand::Immediate(_) if self.layout.is_zst() => {
+                Ok(MPlaceTy::dangling(self.layout, cx))
+            }
             Operand::Immediate(imm) => Err(ImmTy { imm, layout: self.layout }),
         }
     }
 
     #[inline(always)]
-    pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> {
-        self.try_as_mplace().unwrap()
+    /// Note: do not call `as_ref` on the resulting place. This function should only be used to
+    /// read from the resulting mplace, not to get its address back.
+    pub fn assert_mem_place(self, cx: &impl HasDataLayout) -> MPlaceTy<'tcx, Tag> {
+        self.try_as_mplace(cx).unwrap()
     }
 }
 
 impl<Tag: ::std::fmt::Debug> Place<Tag> {
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline(always)]
-    pub fn null(cx: &impl HasDataLayout) -> Self {
+    fn null(cx: &impl HasDataLayout) -> Self {
         Place::Ptr(MemPlace::null(cx))
     }
 
-    #[inline(always)]
-    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
-        Place::Ptr(MemPlace::from_scalar_ptr(ptr, align))
-    }
-
-    #[inline(always)]
-    pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
-        Place::Ptr(MemPlace::from_ptr(ptr, align))
-    }
-
     #[inline]
     pub fn assert_mem_place(self) -> MemPlace<Tag> {
         match self {
@@ -270,8 +309,10 @@
             val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty;
         let layout = self.layout_of(pointee_type)?;
         let (ptr, meta) = match *val {
-            Immediate::Scalar(ptr) => (ptr.not_undef()?, None),
-            Immediate::ScalarPair(ptr, meta) => (ptr.not_undef()?, Some(meta.not_undef()?)),
+            Immediate::Scalar(ptr) => (ptr.not_undef()?, MemPlaceMeta::None),
+            Immediate::ScalarPair(ptr, meta) => {
+                (ptr.not_undef()?, MemPlaceMeta::Meta(meta.not_undef()?))
+            }
         };
 
         let mplace = MemPlace {
@@ -305,14 +346,14 @@
     /// On success, returns `None` for zero-sized accesses (where nothing else is
     /// left to do) and a `Pointer` to use for the actual access otherwise.
     #[inline]
-    pub fn check_mplace_access(
+    pub(super) fn check_mplace_access(
         &self,
         place: MPlaceTy<'tcx, M::PointerTag>,
         size: Option<Size>,
     ) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
         let size = size.unwrap_or_else(|| {
             assert!(!place.layout.is_unsized());
-            assert!(place.meta.is_none());
+            assert!(!place.meta.has_meta());
             place.layout.size
         });
         self.memory.check_ptr_access(place.ptr, size, place.align)
@@ -338,7 +379,7 @@
 
     /// Force `place.ptr` to a `Pointer`.
     /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
-    pub fn force_mplace_ptr(
+    pub(super) fn force_mplace_ptr(
         &self,
         mut place: MPlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
@@ -405,7 +446,7 @@
         } else {
             // base.meta could be present; we might be accessing a sized field of an unsized
             // struct.
-            (None, offset)
+            (MemPlaceMeta::None, offset)
         };
 
         // We do not look at `base.layout.align` nor `field_layout.align`, unlike
@@ -415,7 +456,7 @@
 
     // Iterates over all fields of an array. Much more efficient than doing the
     // same by repeatedly calling `mplace_array`.
-    pub fn mplace_array_fields(
+    pub(super) fn mplace_array_fields(
         &self,
         base: MPlaceTy<'tcx, Tag>,
     ) -> InterpResult<'tcx, impl Iterator<Item = InterpResult<'tcx, MPlaceTy<'tcx, Tag>>> + 'tcx>
@@ -427,10 +468,10 @@
         };
         let layout = base.layout.field(self, 0)?;
         let dl = &self.tcx.data_layout;
-        Ok((0..len).map(move |i| base.offset(i * stride, None, layout, dl)))
+        Ok((0..len).map(move |i| base.offset(i * stride, MemPlaceMeta::None, layout, dl)))
     }
 
-    pub fn mplace_subslice(
+    fn mplace_subslice(
         &self,
         base: MPlaceTy<'tcx, M::PointerTag>,
         from: u64,
@@ -460,10 +501,10 @@
         let (meta, ty) = match base.layout.ty.kind {
             // It is not nice to match on the type, but that seems to be the only way to
             // implement this.
-            ty::Array(inner, _) => (None, self.tcx.mk_array(inner, inner_len)),
+            ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(inner, inner_len)),
             ty::Slice(..) => {
                 let len = Scalar::from_uint(inner_len, self.pointer_size());
-                (Some(len), base.layout.ty)
+                (MemPlaceMeta::Meta(len), base.layout.ty)
             }
             _ => bug!("cannot subslice non-array type: `{:?}`", base.layout.ty),
         };
@@ -471,18 +512,18 @@
         base.offset(from_offset, meta, layout, self)
     }
 
-    pub fn mplace_downcast(
+    pub(super) fn mplace_downcast(
         &self,
         base: MPlaceTy<'tcx, M::PointerTag>,
         variant: VariantIdx,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
-        assert!(base.meta.is_none());
+        assert!(!base.meta.has_meta());
         Ok(MPlaceTy { layout: base.layout.for_variant(self, variant), ..base })
     }
 
     /// Project into an mplace
-    pub fn mplace_projection(
+    pub(super) fn mplace_projection(
         &self,
         base: MPlaceTy<'tcx, M::PointerTag>,
         proj_elem: &mir::PlaceElem<'tcx>,
@@ -577,64 +618,14 @@
         })
     }
 
-    /// Evaluate statics and promoteds to an `MPlace`. Used to share some code between
-    /// `eval_place` and `eval_place_to_op`.
-    pub(super) fn eval_static_to_mplace(
-        &self,
-        place_static: &mir::Static<'tcx>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        use rustc::mir::StaticKind;
-
-        Ok(match place_static.kind {
-            StaticKind::Promoted(promoted, promoted_substs) => {
-                let substs = self.subst_from_frame_and_normalize_erasing_regions(promoted_substs);
-                let instance = ty::Instance::new(place_static.def_id, substs);
-
-                // Even after getting `substs` from the frame, this instance may still be
-                // polymorphic because `ConstProp` will try to promote polymorphic MIR.
-                if instance.needs_subst() {
-                    throw_inval!(TooGeneric);
-                }
-
-                self.const_eval_raw(GlobalId { instance, promoted: Some(promoted) })?
-            }
-
-            StaticKind::Static => {
-                let ty = place_static.ty;
-                assert!(!ty.needs_subst());
-                let layout = self.layout_of(ty)?;
-                // Just create a lazy reference, so we can support recursive statics.
-                // tcx takes care of assigning every static one and only one unique AllocId.
-                // When the data here is ever actually used, memory will notice,
-                // and it knows how to deal with alloc_id that are present in the
-                // global table but not in its local memory: It calls back into tcx through
-                // a query, triggering the CTFE machinery to actually turn this lazy reference
-                // into a bunch of bytes.  IOW, statics are evaluated with CTFE even when
-                // this InterpCx uses another Machine (e.g., in miri).  This is what we
-                // want!  This way, computing statics works consistently between codegen
-                // and miri: They use the same query to eventually obtain a `ty::Const`
-                // and use that for further computation.
-                //
-                // Notice that statics have *two* AllocIds: the lazy one, and the resolved
-                // one.  Here we make sure that the interpreted program never sees the
-                // resolved ID.  Also see the doc comment of `Memory::get_static_alloc`.
-                let alloc_id = self.tcx.alloc_map.lock().create_static_alloc(place_static.def_id);
-                let ptr = self.tag_static_base_pointer(Pointer::from(alloc_id));
-                MPlaceTy::from_aligned_ptr(ptr, layout)
-            }
-        })
-    }
-
     /// Computes a place. You should only use this if you intend to write into this
     /// place; for reading, a more efficient alternative is `eval_place_for_read`.
     pub fn eval_place(
         &mut self,
         place: &mir::Place<'tcx>,
     ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
-        use rustc::mir::PlaceBase;
-
-        let mut place_ty = match &place.base {
-            PlaceBase::Local(mir::RETURN_PLACE) => {
+        let mut place_ty = match place.local {
+            mir::RETURN_PLACE => {
                 // `return_place` has the *caller* layout, but we want to use our
                 // `layout to verify our assumption. The caller will validate
                 // their layout on return.
@@ -655,12 +646,11 @@
                     ))?,
                 }
             }
-            PlaceBase::Local(local) => PlaceTy {
+            local => PlaceTy {
                 // This works even for dead/uninitialized locals; we check further when writing
-                place: Place::Local { frame: self.cur_frame(), local: *local },
-                layout: self.layout_of_local(self.frame(), *local, None)?,
+                place: Place::Local { frame: self.cur_frame(), local: local },
+                layout: self.layout_of_local(self.frame(), local, None)?,
             },
-            PlaceBase::Static(place_static) => self.eval_static_to_mplace(&place_static)?.into(),
         };
 
         for elem in place.projection.iter() {
@@ -971,7 +961,7 @@
     pub fn force_allocation_maybe_sized(
         &mut self,
         place: PlaceTy<'tcx, M::PointerTag>,
-        meta: Option<Scalar<M::PointerTag>>,
+        meta: MemPlaceMeta<M::PointerTag>,
     ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, Option<Size>)> {
         let (mplace, size) = match place.place {
             Place::Local { frame, local } => {
@@ -1016,7 +1006,7 @@
         &mut self,
         place: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        Ok(self.force_allocation_maybe_sized(place, None)?.0)
+        Ok(self.force_allocation_maybe_sized(place, MemPlaceMeta::None)?.0)
     }
 
     pub fn allocate(
@@ -1036,8 +1026,11 @@
     ) -> MPlaceTy<'tcx, M::PointerTag> {
         let ptr = self.memory.allocate_static_bytes(str.as_bytes(), kind);
         let meta = Scalar::from_uint(str.len() as u128, self.pointer_size());
-        let mplace =
-            MemPlace { ptr: ptr.into(), align: Align::from_bytes(1).unwrap(), meta: Some(meta) };
+        let mplace = MemPlace {
+            ptr: ptr.into(),
+            align: Align::from_bytes(1).unwrap(),
+            meta: MemPlaceMeta::Meta(meta),
+        };
 
         let layout = self.layout_of(self.tcx.mk_static_str()).unwrap();
         MPlaceTy { mplace, layout }
@@ -1145,7 +1138,7 @@
             assert_eq!(align, layout.align.abi);
         }
 
-        let mplace = MPlaceTy { mplace: MemPlace { meta: None, ..*mplace }, layout };
+        let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..*mplace }, layout };
         Ok((instance, mplace))
     }
 }
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index 6790baf..a8e67c8 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -23,7 +23,9 @@
 use syntax::ast::Mutability;
 
 use super::eval_context::{LocalState, StackPopCleanup};
-use super::{Frame, Immediate, LocalValue, MemPlace, Memory, Operand, Place, ScalarMaybeUndef};
+use super::{
+    Frame, Immediate, LocalValue, MemPlace, MemPlaceMeta, Memory, Operand, Place, ScalarMaybeUndef,
+};
 use crate::const_eval::CompileTimeInterpreter;
 
 #[derive(Default)]
@@ -205,6 +207,14 @@
     }
 );
 
+impl_snapshot_for!(
+    enum MemPlaceMeta {
+        Meta(s),
+        None,
+        Poison,
+    }
+);
+
 impl_snapshot_for!(struct MemPlace {
     ptr,
     meta,
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index a28bb53..37dcab5 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -378,7 +378,7 @@
                     }
                     None => {
                         // Unsized self.
-                        args[0].assert_mem_place()
+                        args[0].assert_mem_place(self)
                     }
                 };
                 // Find and consult vtable
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index b55f66d..12e8cb607 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -7,16 +7,16 @@
 use std::fmt::Write;
 use std::ops::RangeInclusive;
 
-use rustc::hir;
 use rustc::ty;
 use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
 use rustc_span::symbol::{sym, Symbol};
 
 use std::hash::Hash;
 
 use super::{
-    CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Scalar,
+    CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
     ValueVisitor,
 };
 
@@ -246,13 +246,13 @@
 
     fn check_wide_ptr_meta(
         &mut self,
-        meta: Option<Scalar<M::PointerTag>>,
+        meta: MemPlaceMeta<M::PointerTag>,
         pointee: TyLayout<'tcx>,
     ) -> InterpResult<'tcx> {
         let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
         match tail.kind {
             ty::Dynamic(..) => {
-                let vtable = meta.unwrap();
+                let vtable = meta.unwrap_meta();
                 try_validation!(
                     self.ecx.memory.check_ptr_access(
                         vtable,
@@ -276,7 +276,7 @@
             }
             ty::Slice(..) | ty::Str => {
                 let _len = try_validation!(
-                    meta.unwrap().to_machine_usize(self.ecx),
+                    meta.unwrap_meta().to_machine_usize(self.ecx),
                     "non-integer slice length in wide pointer",
                     self.path
                 );
@@ -571,7 +571,7 @@
     ) -> InterpResult<'tcx> {
         match op.layout.ty.kind {
             ty::Str => {
-                let mplace = op.assert_mem_place(); // strings are never immediate
+                let mplace = op.assert_mem_place(self.ecx); // strings are never immediate
                 try_validation!(
                     self.ecx.read_str(mplace),
                     "uninitialized or non-UTF-8 data in str",
@@ -599,15 +599,11 @@
             {
                 // Optimized handling for arrays of integer/float type.
 
-                // bailing out for zsts is ok, since the array element type can only be int/float
-                if op.layout.is_zst() {
-                    return Ok(());
-                }
-                // non-ZST array cannot be immediate, slices are never immediate
-                let mplace = op.assert_mem_place();
+                // Arrays cannot be immediate, slices are never immediate.
+                let mplace = op.assert_mem_place(self.ecx);
                 // This is the length of the array/slice.
                 let len = mplace.len(self.ecx)?;
-                // zero length slices have nothing to be checked
+                // Zero length slices have nothing to be checked.
                 if len == 0 {
                     return Ok(());
                 }
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index 2cfcf0f..d2594e8 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -223,7 +223,7 @@
                 match v.layout().ty.kind {
                     ty::Dynamic(..) => {
                         // immediate trait objects are not a thing
-                        let dest = v.to_op(self.ecx())?.assert_mem_place();
+                        let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
                         let inner = self.ecx().unpack_dyn_trait(dest)?.1;
                         trace!("walk_value: dyn object layout: {:#?}", inner.layout);
                         // recurse with the inner type
@@ -292,13 +292,7 @@
                     },
                     layout::FieldPlacement::Array { .. } => {
                         // Let's get an mplace first.
-                        let mplace = if v.layout().is_zst() {
-                            // it's a ZST, the memory content cannot matter
-                            MPlaceTy::dangling(v.layout(), self.ecx())
-                        } else {
-                            // non-ZST array/slice/str cannot be immediate
-                            v.to_op(self.ecx())?.assert_mem_place()
-                        };
+                        let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
                         // Now we can go over all the fields.
                         let iter = self.ecx().mplace_array_fields(mplace)?
                             .map(|f| f.and_then(|f| {
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 32b35c4..1ff5291 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -13,7 +13,6 @@
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
 #![feature(core_intrinsics)]
-#![feature(const_fn)]
 #![feature(decl_macro)]
 #![feature(drain_filter)]
 #![feature(exhaustive_patterns)]
@@ -35,16 +34,11 @@
 extern crate log;
 #[macro_use]
 extern crate rustc;
-#[macro_use]
-extern crate syntax;
 
 mod borrow_check;
-mod build;
 pub mod const_eval;
 pub mod dataflow;
-mod hair;
 pub mod interpret;
-mod lints;
 pub mod monomorphize;
 mod shim;
 pub mod transform;
@@ -54,15 +48,19 @@
 
 pub fn provide(providers: &mut Providers<'_>) {
     borrow_check::provide(providers);
+    const_eval::provide(providers);
     shim::provide(providers);
     transform::provide(providers);
     monomorphize::partitioning::provide(providers);
     providers.const_eval_validated = const_eval::const_eval_validated_provider;
     providers.const_eval_raw = const_eval::const_eval_raw_provider;
-    providers.check_match = hair::pattern::check_match;
     providers.const_caller_location = const_eval::const_caller_location;
     providers.const_field = |tcx, param_env_and_value| {
         let (param_env, (value, field)) = param_env_and_value.into_parts();
         const_eval::const_field(tcx, param_env, None, field, value)
     };
+    providers.destructure_const = |tcx, param_env_and_value| {
+        let (param_env, value) = param_env_and_value.into_parts();
+        const_eval::destructure_const(tcx, param_env, value)
+    }
 }
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index dca8504..f5f00c9 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -176,25 +176,25 @@
 
 use crate::monomorphize;
 
-use rustc::hir;
-use rustc::hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::mir::interpret::{AllocId, ConstValue};
 use rustc::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
 use rustc::mir::mono::{InstantiationMode, MonoItem};
 use rustc::mir::visit::Visitor as MirVisitor;
-use rustc::mir::{self, Location, PlaceBase, Static, StaticKind};
+use rustc::mir::{self, Local, Location};
 use rustc::session::config::EntryFnType;
 use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc::ty::print::obsolete::DefPathBasedNames;
-use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_index::bit_set::GrowableBitSet;
-
+use smallvec::SmallVec;
 use std::iter;
 
 #[derive(PartialEq)]
@@ -227,12 +227,7 @@
         }
     }
 
-    fn record_accesses<I>(&mut self, source: MonoItem<'tcx>, new_targets: I)
-    where
-        I: Iterator<Item = (MonoItem<'tcx>, bool)> + ExactSizeIterator,
-    {
-        assert!(!self.index.contains_key(&source));
-
+    fn record_accesses(&mut self, source: MonoItem<'tcx>, new_targets: &[(MonoItem<'tcx>, bool)]) {
         let start_index = self.targets.len();
         let new_items_count = new_targets.len();
         let new_items_count_total = new_items_count + self.targets.len();
@@ -240,15 +235,15 @@
         self.targets.reserve(new_items_count);
         self.inlines.ensure(new_items_count_total);
 
-        for (i, (target, inline)) in new_targets.enumerate() {
-            self.targets.push(target);
-            if inline {
+        for (i, (target, inline)) in new_targets.iter().enumerate() {
+            self.targets.push(*target);
+            if *inline {
                 self.inlines.insert(i + start_index);
             }
         }
 
         let end_index = self.targets.len();
-        self.index.insert(source, (start_index, end_index));
+        assert!(self.index.insert(source, (start_index, end_index)).is_none());
     }
 
     // Internally iterate over all items referenced by `source` which will be
@@ -283,10 +278,8 @@
 ) -> (FxHashSet<MonoItem<'_>>, InliningMap<'_>) {
     let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");
 
-    let roots = tcx.sess.time("collecting roots", || {
-        let _prof_timer = tcx.prof.generic_activity("monomorphization_collector_root_collections");
-        collect_roots(tcx, mode)
-    });
+    let roots =
+        tcx.sess.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode));
 
     debug!("building mono item graph, beginning at roots");
 
@@ -297,7 +290,7 @@
         let visited: MTRef<'_, _> = &mut visited;
         let inlining_map: MTRef<'_, _> = &mut inlining_map;
 
-        tcx.sess.time("collecting mono items", || {
+        tcx.sess.time("monomorphization_collector_graph_walk", || {
             par_iter(roots).for_each(|root| {
                 let mut recursion_depths = DefIdMap::default();
                 collect_items_rec(tcx, root, visited, &mut recursion_depths, inlining_map);
@@ -405,10 +398,15 @@
         mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy
     };
 
-    let accesses =
-        callees.into_iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item)));
+    // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock.
+    // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
+    // instead to avoid creating this `SmallVec`.
+    let accesses: SmallVec<[_; 128]> = callees
+        .into_iter()
+        .map(|mono_item| (*mono_item, is_inlining_candidate(mono_item)))
+        .collect();
 
-    inlining_map.lock_mut().record_accesses(caller, accesses);
+    inlining_map.lock_mut().record_accesses(caller, &accesses);
 }
 
 fn check_recursion_limit<'tcx>(
@@ -644,39 +642,10 @@
 
     fn visit_place_base(
         &mut self,
-        place_base: &mir::PlaceBase<'tcx>,
+        _place_local: &Local,
         _context: mir::visit::PlaceContext,
-        location: Location,
+        _location: Location,
     ) {
-        match place_base {
-            PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => {
-                debug!("visiting static {:?} @ {:?}", def_id, location);
-
-                let tcx = self.tcx;
-                let instance = Instance::mono(tcx, *def_id);
-                if should_monomorphize_locally(tcx, &instance) {
-                    self.output.push(MonoItem::Static(*def_id));
-                }
-            }
-            PlaceBase::Static(box Static {
-                kind: StaticKind::Promoted(promoted, substs),
-                def_id,
-                ..
-            }) => {
-                let instance = Instance::new(*def_id, substs.subst(self.tcx, self.param_substs));
-                match self.tcx.const_eval_promoted(instance, *promoted) {
-                    Ok(val) => collect_const(self.tcx, val, substs, self.output),
-                    Err(ErrorHandled::Reported) => {}
-                    Err(ErrorHandled::TooGeneric) => {
-                        let span = self.tcx.promoted_mir(*def_id)[*promoted].span;
-                        span_bug!(span, "collection encountered polymorphic constant")
-                    }
-                }
-            }
-            PlaceBase::Local(_) => {
-                // Locals have no relevance for collector.
-            }
-        }
     }
 }
 
@@ -1251,8 +1220,8 @@
                 collect_miri(tcx, id, output);
             }
         }
-        ty::ConstKind::Unevaluated(def_id, substs) => {
-            match tcx.const_eval_resolve(param_env, def_id, substs, None) {
+        ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
+            match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
                 Ok(val) => collect_const(tcx, val, param_substs, output),
                 Err(ErrorHandled::Reported) => {}
                 Err(ErrorHandled::TooGeneric) => {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 766d6bb..0def51a 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -96,8 +96,6 @@
 use std::collections::hash_map::Entry;
 use std::sync::Arc;
 
-use rustc::hir::def::DefKind;
-use rustc::hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
@@ -106,6 +104,9 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{self, DefIdTree, InstanceDef, TyCtxt};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::sync;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_span::symbol::Symbol;
 
 use crate::monomorphize::collector::InliningMap;
@@ -796,6 +797,8 @@
     I: Iterator<Item = &'a MonoItem<'tcx>>,
     'tcx: 'a,
 {
+    let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct");
+
     let mut symbols: Vec<_> =
         mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect();
 
@@ -865,25 +868,26 @@
         }
     };
 
-    let (items, inlining_map) = tcx.sess.time("monomorphization collection", || {
-        collector::collect_crate_mono_items(tcx, collection_mode)
-    });
+    let (items, inlining_map) = collector::collect_crate_mono_items(tcx, collection_mode);
 
     tcx.sess.abort_if_errors();
 
-    assert_symbols_are_distinct(tcx, items.iter());
+    let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || {
+        sync::join(
+            || {
+                let strategy = if tcx.sess.opts.incremental.is_some() {
+                    PartitioningStrategy::PerModule
+                } else {
+                    PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
+                };
 
-    let strategy = if tcx.sess.opts.incremental.is_some() {
-        PartitioningStrategy::PerModule
-    } else {
-        PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
-    };
-
-    let codegen_units = tcx.sess.time("codegen unit partitioning", || {
-        partition(tcx, items.iter().cloned(), strategy, &inlining_map)
-            .into_iter()
-            .map(Arc::new)
-            .collect::<Vec<_>>()
+                partition(tcx, items.iter().cloned(), strategy, &inlining_map)
+                    .into_iter()
+                    .map(Arc::new)
+                    .collect::<Vec<_>>()
+            },
+            || assert_symbols_are_distinct(tcx, items.iter()),
+        )
     });
 
     let mono_items: DefIdSet = items
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 5d88f3b..01cecdd 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -1,10 +1,10 @@
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::mir::*;
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 
 use rustc_index::vec::{Idx, IndexVec};
 
diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
index dbbbbef..33eafec 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -1,6 +1,6 @@
-use rustc::hir::def_id::DefId;
 use rustc::mir::*;
 use rustc::ty::TyCtxt;
+use rustc_hir::def_id::DefId;
 
 use crate::transform::{MirPass, MirSource};
 use crate::util;
diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs
index b50ce0a..b738366 100644
--- a/src/librustc_mir/transform/check_consts/mod.rs
+++ b/src/librustc_mir/transform/check_consts/mod.rs
@@ -4,9 +4,10 @@
 //! has interior mutability or needs to be dropped, as well as the visitor that emits errors when
 //! it finds operations that are invalid in a certain context.
 
-use rustc::hir::{self, def_id::DefId};
 use rustc::mir;
 use rustc::ty::{self, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 
 use std::fmt;
 
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index 6052813..edb4eb4 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -1,11 +1,12 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
-use rustc::hir::def_id::DefId;
 use rustc::session::config::nightly_options;
+use rustc::session::parse::feature_err;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use syntax::feature_gate::feature_err;
 
 use super::{ConstKind, Item};
 
@@ -115,12 +116,7 @@
             &format!("`{}` is not yet stable as a const fn", item.tcx.def_path_str(def_id)),
         );
         if nightly_options::is_nightly_build() {
-            help!(
-                &mut err,
-                "add `#![feature({})]` to the \
-                   crate attributes to enable",
-                feature
-            );
+            err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
         }
         err.emit();
     }
@@ -197,13 +193,14 @@
 pub struct CellBorrow;
 impl NonConstOp for CellBorrow {
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        span_err!(
+        struct_span_err!(
             item.tcx.sess,
             span,
             E0492,
             "cannot borrow a constant which may contain \
             interior mutability, create a static instead"
-        );
+        )
+        .emit();
     }
 }
 
@@ -353,16 +350,18 @@
             item.tcx.sess,
             span,
             E0013,
-            "{}s cannot refer to statics, use \
-                                        a constant instead",
+            "{}s cannot refer to statics",
             item.const_kind()
         );
+        err.help(
+            "consider extracting the value of the `static` to a `const`, and referring to that",
+        );
         if item.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
-                "Static and const variables can refer to other const variables. \
-                    But a const variable cannot refer to a static variable.",
+                "`static` and `const` variables can refer to other `const` variables. \
+                    A `const` variable, however, cannot refer to a `static` variable.",
             );
-            err.help("To fix this, the value can be extracted as a const and then used.");
+            err.help("To fix this, the value can be extracted to a `const` and then used.");
         }
         err.emit();
     }
@@ -375,13 +374,14 @@
     const IS_SUPPORTED_IN_MIRI: bool = false;
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        span_err!(
+        struct_span_err!(
             item.tcx.sess,
             span,
             E0625,
             "thread-local statics cannot be \
             accessed at compile-time"
-        );
+        )
+        .emit();
     }
 }
 
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 0799cc2..577736f 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -38,12 +38,15 @@
         place: PlaceRef<'_, 'tcx>,
     ) -> bool {
         if let [proj_base @ .., elem] = place.projection {
-            let base_qualif =
-                Self::in_place(cx, per_local, PlaceRef { base: place.base, projection: proj_base });
+            let base_qualif = Self::in_place(
+                cx,
+                per_local,
+                PlaceRef { local: place.local, projection: proj_base },
+            );
             let qualif = base_qualif
                 && Self::in_any_value_of_ty(
                     cx,
-                    Place::ty_from(place.base, proj_base, *cx.body, cx.tcx)
+                    Place::ty_from(place.local, proj_base, *cx.body, cx.tcx)
                         .projection_ty(cx.tcx, elem)
                         .ty,
                 );
@@ -75,11 +78,8 @@
         place: PlaceRef<'_, 'tcx>,
     ) -> bool {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => per_local(*local),
-            PlaceRef { base: PlaceBase::Static(_), projection: [] } => {
-                bug!("qualifying already promoted MIR")
-            }
-            PlaceRef { base: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
+            PlaceRef { local, projection: [] } => per_local(*local),
+            PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
         }
     }
 
@@ -102,7 +102,9 @@
                     // Note: this uses `constant.literal.ty` which is a reference or pointer to the
                     // type of the actual `static` item.
                     Self::in_any_value_of_ty(cx, constant.literal.ty)
-                } else if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val {
+                } else if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val
+                {
+                    assert!(promoted.is_none());
                     // Don't peek inside trait associated constants.
                     if cx.tcx.trait_of_item(def_id).is_some() {
                         Self::in_any_value_of_ty(cx, constant.literal.ty)
@@ -147,12 +149,12 @@
             Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
                 // Special-case reborrows to be more like a copy of the reference.
                 if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                    let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, *cx.body, cx.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
                         return Self::in_place(
                             cx,
                             per_local,
-                            PlaceRef { base: &place.base, projection: proj_base },
+                            PlaceRef { local: &place.local, projection: proj_base },
                         );
                     }
                 }
diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs
index 2076830..c445568 100644
--- a/src/librustc_mir/transform/check_consts/resolver.rs
+++ b/src/librustc_mir/transform/check_consts/resolver.rs
@@ -47,15 +47,15 @@
         debug_assert!(!place.is_indirect());
 
         match (value, place.as_ref()) {
-            (true, mir::PlaceRef { base: &mir::PlaceBase::Local(local), .. }) => {
-                self.qualifs_per_local.insert(local);
+            (true, mir::PlaceRef { local, .. }) => {
+                self.qualifs_per_local.insert(*local);
             }
 
             // For now, we do not clear the qualif if a local is overwritten in full by
             // an unqualified rvalue (e.g. `y = 5`). This is to be consistent
             // with aggregates where we overwrite all fields with assignments, which would not
             // get this feature.
-            (false, mir::PlaceRef { base: &mir::PlaceBase::Local(_local), projection: &[] }) => {
+            (false, mir::PlaceRef { local: _, projection: &[] }) => {
                 // self.qualifs_per_local.remove(*local);
             }
 
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 94b3b51..10a4b7d 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -1,6 +1,5 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
-use rustc::hir::{def_id::DefId, HirId};
 use rustc::middle::lang_items;
 use rustc::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc::mir::*;
@@ -8,6 +7,8 @@
 use rustc::ty::cast::CastTy;
 use rustc::ty::{self, TyCtxt};
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir::{def_id::DefId, HirId};
 use rustc_index::bit_set::BitSet;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -20,6 +21,7 @@
 use super::qualifs::{self, HasMutInterior, NeedsDrop};
 use super::resolver::FlowSensitiveAnalysis;
 use super::{is_lang_panic_fn, ConstKind, Item, Qualif};
+use crate::const_eval::{is_const_fn, is_unstable_const_fn};
 use crate::dataflow::{self as old_dataflow, generic as dataflow};
 
 pub type IndirectlyMutableResults<'mir, 'tcx> =
@@ -172,7 +174,7 @@
         let Item { tcx, body, def_id, const_kind, .. } = *self.item;
 
         let use_min_const_fn_checks = (const_kind == Some(ConstKind::ConstFn)
-            && tcx.is_min_const_fn(def_id))
+            && crate::const_eval::is_min_const_fn(tcx, def_id))
             && !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
 
         if use_min_const_fn_checks {
@@ -302,8 +304,8 @@
                             PlaceContext::MutatingUse(MutatingUseContext::Borrow)
                         }
                     };
-                    self.visit_place_base(&place.base, ctx, location);
-                    self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+                    self.visit_place_base(&place.local, ctx, location);
+                    self.visit_projection(&place.local, reborrowed_proj, ctx, location);
                     return;
                 }
             }
@@ -315,8 +317,8 @@
                         }
                         Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
                     };
-                    self.visit_place_base(&place.base, ctx, location);
-                    self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+                    self.visit_place_base(&place.local, ctx, location);
+                    self.visit_projection(&place.local, reborrowed_proj, ctx, location);
                     return;
                 }
             }
@@ -367,15 +369,6 @@
 
             Rvalue::AddressOf(Mutability::Mut, _) => self.check_op(ops::MutAddressOf),
 
-            // At the moment, `PlaceBase::Static` is only used for promoted MIR.
-            Rvalue::Ref(_, BorrowKind::Shared, ref place)
-            | Rvalue::Ref(_, BorrowKind::Shallow, ref place)
-            | Rvalue::AddressOf(Mutability::Not, ref place)
-                if matches!(place.base, PlaceBase::Static(_)) =>
-            {
-                bug!("Saw a promoted during const-checking, which must run before promotion")
-            }
-
             Rvalue::Ref(_, BorrowKind::Shared, ref place)
             | Rvalue::Ref(_, BorrowKind::Shallow, ref place) => {
                 self.check_immutable_borrow_like(location, place)
@@ -419,26 +412,14 @@
         }
     }
 
-    fn visit_place_base(
-        &mut self,
-        place_base: &PlaceBase<'tcx>,
-        context: PlaceContext,
-        location: Location,
-    ) {
+    fn visit_place_base(&mut self, place_local: &Local, context: PlaceContext, location: Location) {
         trace!(
-            "visit_place_base: place_base={:?} context={:?} location={:?}",
-            place_base,
+            "visit_place_base: place_local={:?} context={:?} location={:?}",
+            place_local,
             context,
             location,
         );
-        self.super_place_base(place_base, context, location);
-
-        match place_base {
-            PlaceBase::Local(_) => {}
-            PlaceBase::Static(_) => {
-                bug!("Promotion must be run after const validation");
-            }
-        }
+        self.super_place_base(place_local, context, location);
     }
 
     fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
@@ -451,30 +432,30 @@
     }
     fn visit_projection_elem(
         &mut self,
-        place_base: &PlaceBase<'tcx>,
+        place_local: &Local,
         proj_base: &[PlaceElem<'tcx>],
         elem: &PlaceElem<'tcx>,
         context: PlaceContext,
         location: Location,
     ) {
         trace!(
-            "visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
+            "visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \
             context={:?} location={:?}",
-            place_base,
+            place_local,
             proj_base,
             elem,
             context,
             location,
         );
 
-        self.super_projection_elem(place_base, proj_base, elem, context, location);
+        self.super_projection_elem(place_local, proj_base, elem, context, location);
 
         match elem {
             ProjectionElem::Deref => {
-                let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
+                let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
                 if let ty::RawPtr(_) = base_ty.kind {
                     if proj_base.is_empty() {
-                        if let (PlaceBase::Local(local), []) = (place_base, proj_base) {
+                        if let (local, []) = (place_local, proj_base) {
                             let decl = &self.body.local_decls[*local];
                             if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
                                 let span = decl.source_info.span;
@@ -495,7 +476,7 @@
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {
-                let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
+                let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
                 match base_ty.ty_adt_def() {
                     Some(def) if def.is_union() => {
                         self.check_op(ops::UnionAccess);
@@ -559,13 +540,13 @@
                 };
 
                 // At this point, we are calling a function whose `DefId` is known...
-                if self.tcx.is_const_fn(def_id) {
+                if is_const_fn(self.tcx, def_id) {
                     return;
                 }
 
                 if is_lang_panic_fn(self.tcx, def_id) {
                     self.check_op(ops::Panic);
-                } else if let Some(feature) = self.tcx.is_unstable_const_fn(def_id) {
+                } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
                     // Exempt unstable const fns inside of macros with
                     // `#[allow_internal_unstable]`.
                     if !self.span.allows_unstable(feature) {
@@ -679,17 +660,15 @@
 
         // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
         // that points to the allocation for the static. Don't treat these as reborrows.
-        if let PlaceBase::Local(local) = place.base {
-            if body.local_decls[local].is_ref_to_static() {
-                return None;
-            }
+        if body.local_decls[place.local].is_ref_to_static() {
+            return None;
         }
 
         // Ensure the type being derefed is a reference and not a raw pointer.
         //
         // This is sufficient to prevent an access to a `static mut` from being marked as a
         // reborrow, even if the check above were to disappear.
-        let inner_ty = Place::ty_from(&place.base, inner, body, tcx).ty;
+        let inner_ty = Place::ty_from(&place.local, inner, body, tcx).ty;
         match inner_ty.kind {
             ty::Ref(..) => Some(inner),
             _ => None,
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index c637557..072cdf2 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -1,19 +1,21 @@
-use rustc_data_structures::fx::FxHashSet;
-
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::Node;
+use rustc::hir::map::Map;
 use rustc::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
 use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc::mir::*;
 use rustc::ty::cast::CastTy;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
-
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit;
+use rustc_hir::Node;
 use rustc_span::symbol::{sym, Symbol};
 
 use std::ops::Bound;
 
+use crate::const_eval::{is_const_fn, is_min_const_fn};
 use crate::util;
 
 use rustc_error_codes::*;
@@ -188,18 +190,6 @@
     }
 
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
-        match place.base {
-            PlaceBase::Local(..) => {
-                // Locals are safe.
-            }
-            PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => {
-                bug!("unsafety checking should happen before promotion");
-            }
-            PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => {
-                bug!("StaticKind::Static should not exist");
-            }
-        }
-
         for (i, elem) in place.projection.iter().enumerate() {
             let proj_base = &place.projection[..i];
 
@@ -227,7 +217,7 @@
                 }
             }
             let is_borrow_of_interior_mut = context.is_borrow()
-                && !Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty.is_freeze(
+                && !Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty.is_freeze(
                     self.tcx,
                     self.param_env,
                     self.source_info.span,
@@ -242,7 +232,7 @@
                 self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use());
             }
             let old_source_info = self.source_info;
-            if let (PlaceBase::Local(local), []) = (&place.base, proj_base) {
+            if let (local, []) = (&place.local, proj_base) {
                 let decl = &self.body.local_decls[*local];
                 if decl.internal {
                     // Internal locals are used in the `move_val_init` desugaring.
@@ -270,7 +260,7 @@
                     }
                 }
             }
-            let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
+            let base_ty = Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty;
             match base_ty.kind {
                 ty::RawPtr(..) => self.require_unsafe(
                     "dereference of raw pointer",
@@ -424,7 +414,8 @@
             match elem {
                 ProjectionElem::Field(..) => {
                     let ty =
-                        Place::ty_from(&place.base, proj_base, &self.body.local_decls, self.tcx).ty;
+                        Place::ty_from(&place.local, proj_base, &self.body.local_decls, self.tcx)
+                            .ty;
                     match ty.kind {
                         ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
                             (Bound::Unbounded, Bound::Unbounded) => {}
@@ -474,15 +465,17 @@
     unsafe_blocks: &'a mut Vec<(hir::HirId, bool)>,
 }
 
-impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
-    fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> {
-        hir::intravisit::NestedVisitorMap::None
+impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
+        intravisit::NestedVisitorMap::None
     }
 
     fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
-        hir::intravisit::walk_block(self, block);
+        intravisit::walk_block(self, block);
 
-        if let hir::UnsafeBlock(hir::UserProvided) = block.rules {
+        if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules {
             self.unsafe_blocks.push((block.hir_id, self.used_unsafe.contains(&block.hir_id)));
         }
     }
@@ -508,7 +501,7 @@
     debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})", def_id, body, used_unsafe);
 
     let mut visitor = UnusedUnsafeVisitor { used_unsafe, unsafe_blocks };
-    hir::intravisit::Visitor::visit_body(&mut visitor, body);
+    intravisit::Visitor::visit_body(&mut visitor, body);
 }
 
 fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult {
@@ -523,7 +516,7 @@
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
         hir::BodyOwnerKind::Closure => (false, false),
-        hir::BodyOwnerKind::Fn => (tcx.is_const_fn(def_id), tcx.is_min_const_fn(def_id)),
+        hir::BodyOwnerKind::Fn => (is_const_fn(tcx, def_id), is_min_const_fn(tcx, def_id)),
         hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false),
     };
     let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env);
@@ -644,17 +637,17 @@
                 if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) {
                     tcx.unsafe_derive_on_repr_packed(impl_def_id);
                 } else {
-                    tcx.lint_node_note(
+                    tcx.struct_span_lint_hir(
                         SAFE_PACKED_BORROWS,
                         lint_hir_id,
                         source_info.span,
                         &format!(
-                            "{} is unsafe and requires unsafe function or block \
-                                            (error E0133)",
+                            "{} is unsafe and requires unsafe function or block (error E0133)",
                             description
                         ),
-                        &details.as_str(),
-                    );
+                    )
+                    .note(&details.as_str())
+                    .emit();
                 }
             }
         }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 31c3a2c..1d5a643 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -4,25 +4,25 @@
 use std::borrow::Cow;
 use std::cell::Cell;
 
-use rustc::hir::def::DefKind;
-use rustc::hir::def_id::DefId;
-use rustc::hir::HirId;
 use rustc::mir::interpret::{InterpResult, PanicInfo, Scalar};
 use rustc::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
 };
 use rustc::mir::{
     read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant,
-    Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, ReadOnlyBodyAndCache, Rvalue,
+    Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue,
     SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
     UnOp, RETURN_PLACE,
 };
 use rustc::ty::layout::{
     HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout,
 };
-use rustc::ty::subst::InternalSubsts;
-use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
 use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::Mutability;
@@ -33,7 +33,6 @@
     LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer,
     ScalarMaybeUndef, StackPopCleanup,
 };
-use crate::rustc::ty::subst::Subst;
 use crate::transform::{MirPass, MirSource};
 
 /// The maximum number of bytes that we'll allocate space for a return value.
@@ -432,12 +431,25 @@
         source_info: SourceInfo,
     ) -> Option<Const<'tcx>> {
         self.ecx.tcx.span = c.span;
+
+        // FIXME we need to revisit this for #67176
+        if c.needs_subst() {
+            return None;
+        }
+
         match self.ecx.eval_const_to_op(c.literal, None) {
             Ok(op) => Some(op),
             Err(error) => {
                 let err = error_to_const_error(&self.ecx, error);
-                match self.lint_root(source_info) {
-                    Some(lint_root) if c.literal.needs_subst() => {
+                if let Some(lint_root) = self.lint_root(source_info) {
+                    let lint_only = match c.literal.val {
+                        // Promoteds must lint and not error as the user didn't ask for them
+                        ConstKind::Unevaluated(_, _, Some(_)) => true,
+                        // Out of backwards compatibility we cannot report hard errors in unused
+                        // generic functions using associated constants of the generic parameters.
+                        _ => c.literal.needs_subst(),
+                    };
+                    if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
                         // generic functions using associated constants of the generic parameters.
                         err.report_as_lint(
@@ -446,10 +458,11 @@
                             lint_root,
                             Some(c.span),
                         );
-                    }
-                    _ => {
+                    } else {
                         err.report_as_error(self.ecx.tcx, "erroneous constant used");
                     }
+                } else {
+                    err.report_as_error(self.ecx.tcx, "erroneous constant used");
                 }
                 None
             }
@@ -552,6 +565,11 @@
             return None;
         }
 
+        // FIXME we need to revisit this for #67176
+        if rvalue.needs_subst() {
+            return None;
+        }
+
         let overflow_check = self.tcx.sess.overflow_checks();
 
         // Perform any special handling for specific Rvalue types.
@@ -707,7 +725,8 @@
                 ScalarMaybeUndef::Scalar(r),
             )) => l.is_bits() && r.is_bits(),
             interpret::Operand::Indirect(_) if mir_opt_level >= 2 => {
-                intern_const_alloc_recursive(&mut self.ecx, None, op.assert_mem_place())
+                let mplace = op.assert_mem_place(&self.ecx);
+                intern_const_alloc_recursive(&mut self.ecx, None, mplace, false)
                     .expect("failed to intern alloc");
                 true
             }
@@ -865,9 +884,7 @@
                         // doesn't use the invalid value
                         match cond {
                             Operand::Move(ref place) | Operand::Copy(ref place) => {
-                                if let PlaceBase::Local(local) = place.base {
-                                    self.remove_const(local);
-                                }
+                                self.remove_const(place.local);
                             }
                             Operand::Constant(_) => {}
                         }
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 860a014..b9d9ed5 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -9,11 +9,11 @@
 use crate::util::elaborate_drops::{elaborate_drop, DropFlagState, Unwind};
 use crate::util::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle};
 use crate::util::patch::MirPatch;
-use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_span::Span;
 use std::fmt;
@@ -28,7 +28,13 @@
         let param_env = tcx.param_env(src.def_id()).with_reveal_all();
         let move_data = match MoveData::gather_moves(body, tcx, param_env) {
             Ok(move_data) => move_data,
-            Err(_) => bug!("No `move_errors` should be allowed in MIR borrowck"),
+            Err((move_data, _)) => {
+                tcx.sess.delay_span_bug(
+                    body.span,
+                    "No `move_errors` should be allowed in MIR borrowck",
+                );
+                move_data
+            }
         };
         let elaborate_patch = {
             let body = &*body;
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index fc4f803..825ac4a 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -57,8 +57,6 @@
 use crate::transform::{MirPass, MirSource};
 use crate::util::dump_mir;
 use crate::util::liveness;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc::mir::*;
 use rustc::ty::layout::VariantIdx;
@@ -66,6 +64,8 @@
 use rustc::ty::GeneratorSubsts;
 use rustc::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::{BitMatrix, BitSet};
 use rustc_index::vec::{Idx, IndexVec};
 use std::borrow::Cow;
@@ -112,17 +112,17 @@
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.base == PlaceBase::Local(self_arg()) {
+        if place.local == self_arg() {
             replace_base(
                 place,
                 Place {
-                    base: PlaceBase::Local(self_arg()),
+                    local: self_arg(),
                     projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]),
                 },
                 self.tcx,
             );
         } else {
-            self.visit_place_base(&mut place.base, context, location);
+            self.visit_place_base(&mut place.local, context, location);
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
@@ -148,11 +148,11 @@
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.base == PlaceBase::Local(self_arg()) {
+        if place.local == self_arg() {
             replace_base(
                 place,
                 Place {
-                    base: PlaceBase::Local(self_arg()),
+                    local: self_arg(),
                     projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Field(
                         Field::new(0),
                         self.ref_gen_ty,
@@ -161,7 +161,7 @@
                 self.tcx,
             );
         } else {
-            self.visit_place_base(&mut place.base, context, location);
+            self.visit_place_base(&mut place.local, context, location);
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
@@ -173,7 +173,7 @@
 }
 
 fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
-    place.base = new_base.base;
+    place.local = new_base.local;
 
     let mut new_projection = new_base.projection.to_vec();
     new_projection.append(&mut place.projection.to_vec());
@@ -236,7 +236,7 @@
         let mut projection = base.projection.to_vec();
         projection.push(ProjectionElem::Field(Field::new(idx), ty));
 
-        Place { base: base.base, projection: self.tcx.intern_place_elems(&projection) }
+        Place { local: base.local, projection: self.tcx.intern_place_elems(&projection) }
     }
 
     // Create a statement which changes the discriminant
@@ -275,20 +275,15 @@
         assert_eq!(self.remap.get(local), None);
     }
 
-    fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if let PlaceBase::Local(l) = place.base {
-            // Replace an Local in the remap with a generator struct access
-            if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) {
-                replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
-            }
-        } else {
-            self.visit_place_base(&mut place.base, context, location);
-
-            for elem in place.projection.iter() {
-                if let PlaceElem::Index(local) = elem {
-                    assert_ne!(*local, self_arg());
-                }
-            }
+    fn visit_place(
+        &mut self,
+        place: &mut Place<'tcx>,
+        _context: PlaceContext,
+        _location: Location,
+    ) {
+        // Replace an Local in the remap with a generator struct access
+        if let Some(&(ty, variant_index, idx)) = self.remap.get(&place.local) {
+            replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
         }
     }
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 52a1056..2dd00fe 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -1,6 +1,6 @@
 //! Inlining pass for MIR functions
 
-use rustc::hir::def_id::DefId;
+use rustc_hir::def_id::DefId;
 
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
@@ -430,12 +430,7 @@
                         }
                     }
 
-                    match place.base {
-                        // Static variables need a borrow because the callee
-                        // might modify the same static.
-                        PlaceBase::Static(_) => true,
-                        _ => false,
-                    }
+                    false
                 }
 
                 let dest = if dest_needs_borrow(&destination.0) {
@@ -647,10 +642,7 @@
 
     fn make_integrate_local(&self, local: &Local) -> Local {
         if *local == RETURN_PLACE {
-            match self.destination.base {
-                PlaceBase::Local(l) => return l,
-                PlaceBase::Static(ref s) => bug!("Return place is {:?}, not local", s),
-            }
+            return self.destination.local;
         }
 
         let idx = local.index() - 1;
@@ -672,19 +664,14 @@
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        match &mut place.base {
-            PlaceBase::Static(_) => {}
-            PlaceBase::Local(l) => {
-                // If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
-                let dest_proj_len = self.destination.projection.len();
-                if *l == RETURN_PLACE && dest_proj_len > 0 {
-                    let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
-                    projs.extend(self.destination.projection);
-                    projs.extend(place.projection);
+        // If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
+        let dest_proj_len = self.destination.projection.len();
+        if place.local == RETURN_PLACE && dest_proj_len > 0 {
+            let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
+            projs.extend(self.destination.projection);
+            projs.extend(place.projection);
 
-                    place.projection = self.tcx.intern_place_elems(&*projs);
-                }
-            }
+            place.projection = self.tcx.intern_place_elems(&*projs);
         }
         // Handles integrating any locals that occur in the base
         // or projections
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index a2f3fce..69eedb1 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -3,7 +3,7 @@
 use crate::transform::{MirPass, MirSource};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::mir::{
-    read_only, Body, BodyAndCache, Constant, Local, Location, Operand, Place, PlaceBase, PlaceRef,
+    read_only, Body, BodyAndCache, Constant, Local, Location, Operand, Place, PlaceRef,
     ProjectionElem, Rvalue,
 };
 use rustc::ty::{self, TyCtxt};
@@ -55,7 +55,7 @@
 
                         Place {
                             // Replace with dummy
-                            base: mem::replace(&mut place.base, PlaceBase::Local(Local::new(0))),
+                            local: mem::replace(&mut place.local, Local::new(0)),
                             projection: self.tcx().intern_place_elems(proj_l),
                         }
                     } else {
@@ -92,10 +92,10 @@
 impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         if let Rvalue::Ref(_, _, place) = rvalue {
-            if let PlaceRef { base, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
+            if let PlaceRef { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
                 place.as_ref()
             {
-                if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
+                if Place::ty_from(local, proj_base, self.body, self.tcx).ty.is_region_ptr() {
                     self.optimizations.and_stars.insert(location);
                 }
             }
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 7cf94f7..22aed9a 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -1,11 +1,12 @@
-use crate::{build, shim};
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use crate::{shim, util};
+use rustc::hir::map::Map;
 use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted};
 use rustc::ty::query::Providers;
 use rustc::ty::steal::Steal;
 use rustc::ty::{InstanceDef, TyCtxt, TypeFoldable};
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_index::vec::IndexVec;
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -40,7 +41,6 @@
     self::check_unsafety::provide(providers);
     *providers = Providers {
         mir_keys,
-        mir_built,
         mir_const,
         mir_const_qualif,
         mir_validated,
@@ -85,7 +85,8 @@
             }
             intravisit::walk_struct_def(self, v)
         }
-        fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
+        type Map = Map<'tcx>;
+        fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, Self::Map> {
             NestedVisitorMap::None
         }
     }
@@ -96,11 +97,6 @@
     tcx.arena.alloc(set)
 }
 
-fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
-    let mir = build::mir_build(tcx, def_id);
-    tcx.alloc_steal_mir(mir)
-}
-
 /// Where a specific `mir::Body` comes from.
 #[derive(Debug, Copy, Clone)]
 pub struct MirSource<'tcx> {
@@ -220,6 +216,9 @@
     let _ = tcx.unsafety_check_result(def_id);
 
     let mut body = tcx.mir_built(def_id).steal();
+
+    util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
+
     run_passes(
         tcx,
         &mut body,
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 819ed9a..f058ac8 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -12,13 +12,13 @@
 //! initialization and can otherwise silence errors, if
 //! move analysis runs after promotion on broken MIR.
 
-use rustc::hir::def_id::DefId;
 use rustc::mir::traversal::ReversePostorder;
 use rustc::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc::mir::*;
 use rustc::ty::cast::CastTy;
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, List, TyCtxt, TypeFoldable};
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::LitKind;
@@ -27,8 +27,9 @@
 use rustc_target::spec::abi::Abi;
 
 use std::cell::Cell;
-use std::{iter, mem, usize};
+use std::{cmp, iter, mem, usize};
 
+use crate::const_eval::{is_const_fn, is_unstable_const_fn};
 use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstKind, Item};
 use crate::transform::{MirPass, MirSource};
 
@@ -38,7 +39,7 @@
 /// errors when promotion of `#[rustc_args_required_const]` arguments fails.
 ///
 /// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each
-/// newly created `StaticKind::Promoted`.
+/// newly created `Constant`.
 #[derive(Default)]
 pub struct PromoteTemps<'tcx> {
     pub promoted_fragments: Cell<IndexVec<Promoted, BodyAndCache<'tcx>>>,
@@ -307,18 +308,14 @@
 
                         // We can only promote interior borrows of promotable temps (non-temps
                         // don't get promoted anyway).
-                        let base = match place.base {
-                            PlaceBase::Local(local) => local,
-                            _ => return Err(Unpromotable),
-                        };
-                        self.validate_local(base)?;
+                        self.validate_local(place.local)?;
 
                         if place.projection.contains(&ProjectionElem::Deref) {
                             return Err(Unpromotable);
                         }
 
                         let mut has_mut_interior =
-                            self.qualif_local::<qualifs::HasMutInterior>(base);
+                            self.qualif_local::<qualifs::HasMutInterior>(place.local);
                         // HACK(eddyb) this should compute the same thing as
                         // `<HasMutInterior as Qualif>::in_projection` from
                         // `check_consts::qualifs` but without recursion.
@@ -332,7 +329,7 @@
                                 // FIXME(eddyb) this is probably excessive, with
                                 // the exception of `union` member accesses.
                                 let ty =
-                                    Place::ty_from(&place.base, proj_base, *self.body, self.tcx)
+                                    Place::ty_from(&place.local, proj_base, *self.body, self.tcx)
                                         .projection_ty(self.tcx, elem)
                                         .ty;
                                 if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
@@ -348,7 +345,7 @@
                         if has_mut_interior {
                             return Err(Unpromotable);
                         }
-                        if self.qualif_local::<qualifs::NeedsDrop>(base) {
+                        if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
                             return Err(Unpromotable);
                         }
 
@@ -478,13 +475,8 @@
 
     fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
-                self.validate_local(*local)
-            }
-            PlaceRef { base: PlaceBase::Static(_), projection: [] } => {
-                bug!("qualifying already promoted MIR")
-            }
-            PlaceRef { base: _, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local, projection: [] } => self.validate_local(*local),
+            PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
                 match *elem {
                     ProjectionElem::Deref | ProjectionElem::Downcast(..) => {
                         return Err(Unpromotable);
@@ -499,7 +491,7 @@
                     ProjectionElem::Field(..) => {
                         if self.const_kind.is_none() {
                             let base_ty =
-                                Place::ty_from(place.base, proj_base, *self.body, self.tcx).ty;
+                                Place::ty_from(place.local, proj_base, *self.body, self.tcx).ty;
                             if let Some(def) = base_ty.ty_adt_def() {
                                 // No promotion of union field accesses.
                                 if def.is_union() {
@@ -510,7 +502,7 @@
                     }
                 }
 
-                self.validate_place(PlaceRef { base: place.base, projection: proj_base })
+                self.validate_place(PlaceRef { local: place.local, projection: proj_base })
             }
         }
     }
@@ -597,10 +589,12 @@
                 // Raw reborrows can come from reference to pointer coercions,
                 // so are allowed.
                 if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                    let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
-                        return self
-                            .validate_place(PlaceRef { base: &place.base, projection: proj_base });
+                        return self.validate_place(PlaceRef {
+                            local: &place.local,
+                            projection: proj_base,
+                        });
                     }
                 }
                 Err(Unpromotable)
@@ -634,9 +628,9 @@
                 // Special-case reborrows to be more like a copy of the reference.
                 let mut place = place.as_ref();
                 if let [proj_base @ .., ProjectionElem::Deref] = &place.projection {
-                    let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
-                        place = PlaceRef { base: &place.base, projection: proj_base };
+                        place = PlaceRef { local: &place.local, projection: proj_base };
                     }
                 }
 
@@ -645,17 +639,15 @@
                 // HACK(eddyb) this should compute the same thing as
                 // `<HasMutInterior as Qualif>::in_projection` from
                 // `check_consts::qualifs` but without recursion.
-                let mut has_mut_interior = match place.base {
-                    PlaceBase::Local(local) => self.qualif_local::<qualifs::HasMutInterior>(*local),
-                    PlaceBase::Static(_) => false,
-                };
+                let mut has_mut_interior =
+                    self.qualif_local::<qualifs::HasMutInterior>(*place.local);
                 if has_mut_interior {
                     let mut place_projection = place.projection;
                     // FIXME(eddyb) use a forward loop instead of a reverse one.
                     while let [proj_base @ .., elem] = place_projection {
                         // FIXME(eddyb) this is probably excessive, with
                         // the exception of `union` member accesses.
-                        let ty = Place::ty_from(place.base, proj_base, *self.body, self.tcx)
+                        let ty = Place::ty_from(place.local, proj_base, *self.body, self.tcx)
                             .projection_ty(self.tcx, elem)
                             .ty;
                         if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
@@ -702,8 +694,8 @@
 
         let is_const_fn = match fn_ty.kind {
             ty::FnDef(def_id, _) => {
-                self.tcx.is_const_fn(def_id)
-                    || self.tcx.is_unstable_const_fn(def_id).is_some()
+                is_const_fn(self.tcx, def_id)
+                    || is_unstable_const_fn(self.tcx, def_id).is_some()
                     || is_lang_panic_fn(self.tcx, self.def_id)
             }
             _ => false,
@@ -760,6 +752,7 @@
     source: &'a mut BodyAndCache<'tcx>,
     promoted: BodyAndCache<'tcx>,
     temps: &'a mut IndexVec<Local, TempState>,
+    extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>,
 
     /// If true, all nested temps are also kept in the
     /// source MIR, not moved to the promoted MIR.
@@ -902,39 +895,76 @@
         candidate: Candidate,
         next_promoted_id: usize,
     ) -> Option<BodyAndCache<'tcx>> {
-        let mut operand = {
+        let mut rvalue = {
             let promoted = &mut self.promoted;
             let promoted_id = Promoted::new(next_promoted_id);
             let tcx = self.tcx;
-            let mut promoted_place = |ty, span| {
+            let mut promoted_operand = |ty, span| {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span);
-                Place {
-                    base: PlaceBase::Static(box Static {
-                        kind: StaticKind::Promoted(
-                            promoted_id,
-                            InternalSubsts::identity_for_item(tcx, def_id),
-                        ),
+
+                Operand::Constant(Box::new(Constant {
+                    span,
+                    user_ty: None,
+                    literal: tcx.mk_const(ty::Const {
                         ty,
-                        def_id,
+                        val: ty::ConstKind::Unevaluated(
+                            def_id,
+                            InternalSubsts::identity_for_item(tcx, def_id),
+                            Some(promoted_id),
+                        ),
                     }),
-                    projection: List::empty(),
-                }
+                }))
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
             match candidate {
                 Candidate::Ref(loc) => {
                     let ref mut statement = blocks[loc.block].statements[loc.statement_index];
                     match statement.kind {
-                        StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref mut place))) => {
+                        StatementKind::Assign(box (
+                            _,
+                            Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
+                        )) => {
                             // Use the underlying local for this (necessarily interior) borrow.
-                            let ty = place.base.ty(local_decls).ty;
+                            let ty = local_decls.local_decls()[place.local].ty;
                             let span = statement.source_info.span;
 
-                            Operand::Move(Place {
-                                base: mem::replace(&mut place.base, promoted_place(ty, span).base),
-                                projection: List::empty(),
-                            })
+                            let ref_ty = tcx.mk_ref(
+                                tcx.lifetimes.re_erased,
+                                ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() },
+                            );
+
+                            *region = tcx.lifetimes.re_erased;
+
+                            let mut projection = vec![PlaceElem::Deref];
+                            projection.extend(place.projection);
+                            place.projection = tcx.intern_place_elems(&projection);
+
+                            // Create a temp to hold the promoted reference.
+                            // This is because `*r` requires `r` to be a local,
+                            // otherwise we would use the `promoted` directly.
+                            let mut promoted_ref = LocalDecl::new_temp(ref_ty, span);
+                            promoted_ref.source_info = statement.source_info;
+                            let promoted_ref = local_decls.push(promoted_ref);
+                            assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);
+
+                            let promoted_ref_statement = Statement {
+                                source_info: statement.source_info,
+                                kind: StatementKind::Assign(Box::new((
+                                    Place::from(promoted_ref),
+                                    Rvalue::Use(promoted_operand(ref_ty, span)),
+                                ))),
+                            };
+                            self.extra_statements.push((loc, promoted_ref_statement));
+
+                            Rvalue::Ref(
+                                tcx.lifetimes.re_erased,
+                                borrow_kind,
+                                Place {
+                                    local: mem::replace(&mut place.local, promoted_ref),
+                                    projection: List::empty(),
+                                },
+                            )
                         }
                         _ => bug!(),
                     }
@@ -945,7 +975,8 @@
                         StatementKind::Assign(box (_, Rvalue::Repeat(ref mut operand, _))) => {
                             let ty = operand.ty(local_decls, self.tcx);
                             let span = statement.source_info.span;
-                            mem::replace(operand, Operand::Copy(promoted_place(ty, span)))
+
+                            Rvalue::Use(mem::replace(operand, promoted_operand(ty, span)))
                         }
                         _ => bug!(),
                     }
@@ -956,8 +987,8 @@
                         TerminatorKind::Call { ref mut args, .. } => {
                             let ty = args[index].ty(local_decls, self.tcx);
                             let span = terminator.source_info.span;
-                            let operand = Operand::Copy(promoted_place(ty, span));
-                            mem::replace(&mut args[index], operand)
+
+                            Rvalue::Use(mem::replace(&mut args[index], promoted_operand(ty, span)))
                         }
                         // We expected a `TerminatorKind::Call` for which we'd like to promote an
                         // argument. `qualify_consts` saw a `TerminatorKind::Call` here, but
@@ -974,13 +1005,13 @@
         };
 
         assert_eq!(self.new_block(), START_BLOCK);
-        self.visit_operand(
-            &mut operand,
+        self.visit_rvalue(
+            &mut rvalue,
             Location { block: BasicBlock::new(0), statement_index: usize::MAX },
         );
 
         let span = self.promoted.span;
-        self.assign(RETURN_PLACE, Rvalue::Use(operand), span);
+        self.assign(RETURN_PLACE, rvalue, span);
         Some(self.promoted)
     }
 }
@@ -1019,6 +1050,7 @@
 
     let mut promotions = IndexVec::new();
 
+    let mut extra_statements = vec![];
     for candidate in candidates.into_iter().rev() {
         match candidate {
             Candidate::Repeat(Location { block, statement_index })
@@ -1042,23 +1074,27 @@
         let initial_locals =
             iter::once(LocalDecl::new_return_place(tcx.types.never, body.span)).collect();
 
+        let mut promoted = Body::new(
+            IndexVec::new(),
+            // FIXME: maybe try to filter this to avoid blowing up
+            // memory usage?
+            body.source_scopes.clone(),
+            initial_locals,
+            IndexVec::new(),
+            0,
+            vec![],
+            body.span,
+            vec![],
+            body.generator_kind,
+        );
+        promoted.ignore_interior_mut_in_const_validation = true;
+
         let promoter = Promoter {
-            promoted: BodyAndCache::new(Body::new(
-                IndexVec::new(),
-                // FIXME: maybe try to filter this to avoid blowing up
-                // memory usage?
-                body.source_scopes.clone(),
-                initial_locals,
-                IndexVec::new(),
-                0,
-                vec![],
-                body.span,
-                vec![],
-                body.generator_kind,
-            )),
+            promoted: BodyAndCache::new(promoted),
             tcx,
             source: body,
             temps: &mut temps,
+            extra_statements: &mut extra_statements,
             keep_original: false,
         };
 
@@ -1068,6 +1104,13 @@
         }
     }
 
+    // Insert each of `extra_statements` before its indicated location, which
+    // has to be done in reverse location order, to not invalidate the rest.
+    extra_statements.sort_by_key(|&(loc, _)| cmp::Reverse(loc));
+    for (loc, statement) in extra_statements {
+        body[loc.block].statements.insert(loc.statement_index, statement);
+    }
+
     // Eliminate assignments to, and drops of promoted temps.
     let promoted = |index: Local| temps[index] == TempState::PromotedOut;
     for block in body.basic_blocks_mut() {
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 3741ca1..7034556 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -1,7 +1,7 @@
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::mir::*;
 use rustc::ty::{self, adjustment::PointerCast, Predicate, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -261,7 +261,7 @@
             ProjectionElem::Downcast(_symbol, _variant_index) => {}
 
             ProjectionElem::Field(..) => {
-                let base_ty = Place::ty_from(&place.base, &proj_base, body, tcx).ty;
+                let base_ty = Place::ty_from(&place.local, &proj_base, body, tcx).ty;
                 if let Some(def) = base_ty.ty_adt_def() {
                     // No union field accesses in `const fn`
                     if def.is_union() {
@@ -281,8 +281,22 @@
     Ok(())
 }
 
-/// Returns whether `allow_internal_unstable(..., <feature_gate>, ...)` is present.
+/// Returns `true` if the given feature gate is allowed within the function with the given `DefId`.
 fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
+    // All features require that the corresponding gate be enabled,
+    // even if the function has `#[allow_internal_unstable(the_gate)]`.
+    if !tcx.features().enabled(feature_gate) {
+        return false;
+    }
+
+    // If this crate is not using stability attributes, or this function is not claiming to be a
+    // stable `const fn`, that is all that is required.
+    if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
+        return true;
+    }
+
+    // However, we cannot allow stable `const fn`s to use unstable features without an explicit
+    // opt-in via `allow_internal_unstable`.
     attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic())
         .map_or(false, |mut features| features.any(|name| name == feature_gate))
 }
@@ -327,7 +341,7 @@
         TerminatorKind::Call { func, args, from_hir_call: _, destination: _, cleanup: _ } => {
             let fn_ty = func.ty(body, tcx);
             if let ty::FnDef(def_id, _) = fn_ty.kind {
-                if !tcx.is_min_const_fn(def_id) {
+                if !crate::const_eval::is_min_const_fn(tcx, def_id) {
                     return Err((
                         span,
                         format!(
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 394924f..7a90cb0 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -4,9 +4,9 @@
 use syntax::ast;
 
 use crate::transform::{MirPass, MirSource};
-use rustc::hir::def_id::DefId;
 use rustc::mir::{self, Body, BodyAndCache, Local, Location};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
 
 use crate::dataflow::move_paths::{HasMoveData, MoveData};
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index fb7f4fa..ddf8d73 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -388,13 +388,7 @@
         // Remove unnecessary StorageLive and StorageDead annotations.
         data.statements.retain(|stmt| match &stmt.kind {
             StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => self.map[*l].is_some(),
-            StatementKind::Assign(box (place, _)) => {
-                if let PlaceBase::Local(local) = place.base {
-                    self.map[local].is_some()
-                } else {
-                    true
-                }
-            }
+            StatementKind::Assign(box (place, _)) => self.map[place.local].is_some(),
             _ => true,
         });
         self.super_basic_block_data(block, data);
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
index 3b8871f..e733b0a 100644
--- a/src/librustc_mir/transform/simplify_try.rs
+++ b/src/librustc_mir/transform/simplify_try.rs
@@ -137,9 +137,9 @@
 fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarField<'tcx>)> {
     match place.as_ref() {
         PlaceRef {
-            base: &PlaceBase::Local(local),
+            local,
             projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)],
-        } => Some((local, VarField { field, field_ty: ty, var_idx })),
+        } => Some((*local, VarField { field, field_ty: ty, var_idx })),
         _ => None,
     }
 }
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index 70d6aaf..e17c7a8 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -46,7 +46,7 @@
             // encountered a Deref, which is ABI-aligned
             ProjectionElem::Deref => break,
             ProjectionElem::Field(..) => {
-                let ty = Place::ty_from(&place.base, proj_base, local_decls, tcx).ty;
+                let ty = Place::ty_from(&place.local, proj_base, local_decls, tcx).ty;
                 match ty.kind {
                     ty::Adt(def, _) if def.repr.packed() => return true,
                     _ => {}
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 9f67109..c275eec 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -1,8 +1,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_span::{MultiSpan, Span};
-
 use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId};
+use rustc_span::{MultiSpan, Span};
 
 impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
     crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 7fd6738..aacefeb 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -1,5 +1,4 @@
 use crate::util::patch::MirPatch;
-use rustc::hir;
 use rustc::middle::lang_items;
 use rustc::mir::*;
 use rustc::traits::Reveal;
@@ -7,6 +6,7 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
 use rustc_index::vec::Idx;
 use std::fmt;
 
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index fb53888..8291bc9 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -1,6 +1,6 @@
-use rustc::hir::def_id::DefId;
 use rustc::mir::*;
 use rustc::ty::TyCtxt;
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use std::fmt::Debug;
 use std::io::{self, Write};
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index a3f8523..e0919e7 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -1,10 +1,10 @@
 use super::graphviz::write_mir_fn_graphviz;
 use crate::transform::MirSource;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::visit::Visitor;
 use rustc::mir::*;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::Idx;
 use std::fmt::Display;
 use std::fmt::Write as _;
@@ -540,7 +540,7 @@
     body: &Body<'_>,
     w: &mut dyn Write,
 ) -> io::Result<()> {
-    use rustc::hir::def::DefKind;
+    use rustc_hir::def::DefKind;
 
     trace!("write_mir_sig: {:?}", src.instance);
     let kind = tcx.def_kind(src.def_id());
diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml
new file mode 100644
index 0000000..79c7303
--- /dev/null
+++ b/src/librustc_mir_build/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_mir_build"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_mir_build"
+path = "lib.rs"
+doctest = false
+
+[dependencies]
+arena = { path = "../libarena" }
+itertools = "0.8"
+log = "0.4"
+rustc = { path = "../librustc" }
+rustc_apfloat = { path = "../librustc_apfloat" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_index = { path = "../librustc_index" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_macros = { path = "../librustc_macros" }
+rustc_serialize = { path = "../libserialize", package = "serialize" }
+rustc_span = { path = "../librustc_span" }
+rustc_target = { path = "../librustc_target" }
+syntax = { path = "../libsyntax" }
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir_build/build/block.rs
similarity index 99%
rename from src/librustc_mir/build/block.rs
rename to src/librustc_mir_build/build/block.rs
index 4b1a5d0..c517d31 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir_build/build/block.rs
@@ -2,12 +2,12 @@
 use crate::build::ForGuard::OutsideGuard;
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::hair::*;
-use rustc::hir;
 use rustc::mir::*;
+use rustc_hir as hir;
 use rustc_span::Span;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn ast_block(
+    crate fn ast_block(
         &mut self,
         destination: &Place<'tcx>,
         block: BasicBlock,
diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir_build/build/cfg.rs
similarity index 80%
rename from src/librustc_mir/build/cfg.rs
rename to src/librustc_mir_build/build/cfg.rs
index 553701c..e197110 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir_build/build/cfg.rs
@@ -4,33 +4,33 @@
 use rustc::mir::*;
 
 impl<'tcx> CFG<'tcx> {
-    pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
+    crate fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
         &self.basic_blocks[blk]
     }
 
-    pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
+    crate fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
         &mut self.basic_blocks[blk]
     }
 
     // llvm.org/PR32488 makes this function use an excess of stack space. Mark
     // it as #[inline(never)] to keep rustc's stack use in check.
     #[inline(never)]
-    pub fn start_new_block(&mut self) -> BasicBlock {
+    crate fn start_new_block(&mut self) -> BasicBlock {
         self.basic_blocks.push(BasicBlockData::new(None))
     }
 
-    pub fn start_new_cleanup_block(&mut self) -> BasicBlock {
+    crate fn start_new_cleanup_block(&mut self) -> BasicBlock {
         let bb = self.start_new_block();
         self.block_data_mut(bb).is_cleanup = true;
         bb
     }
 
-    pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
+    crate fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
         debug!("push({:?}, {:?})", block, statement);
         self.block_data_mut(block).statements.push(statement);
     }
 
-    pub fn push_assign(
+    crate fn push_assign(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -43,7 +43,7 @@
         );
     }
 
-    pub fn push_assign_constant(
+    crate fn push_assign_constant(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -53,7 +53,7 @@
         self.push_assign(block, source_info, temp, Rvalue::Use(Operand::Constant(box constant)));
     }
 
-    pub fn push_assign_unit(
+    crate fn push_assign_unit(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -67,7 +67,7 @@
         );
     }
 
-    pub fn push_fake_read(
+    crate fn push_fake_read(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -79,7 +79,7 @@
         self.push(block, stmt);
     }
 
-    pub fn terminate(
+    crate fn terminate(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -96,7 +96,7 @@
     }
 
     /// In the `origin` block, push a `goto -> target` terminator.
-    pub fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
+    crate fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
         self.terminate(origin, source_info, TerminatorKind::Goto { target })
     }
 }
diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir_build/build/expr/as_constant.rs
similarity index 95%
rename from src/librustc_mir/build/expr/as_constant.rs
rename to src/librustc_mir_build/build/expr/as_constant.rs
index ceac2a0..e485626 100644
--- a/src/librustc_mir/build/expr/as_constant.rs
+++ b/src/librustc_mir_build/build/expr/as_constant.rs
@@ -8,7 +8,7 @@
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
     /// `expr` is a valid compile-time constant!
-    pub fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
+    crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir_build/build/expr/as_operand.rs
similarity index 94%
rename from src/librustc_mir/build/expr/as_operand.rs
rename to src/librustc_mir_build/build/expr/as_operand.rs
index b969932..efe328d 100644
--- a/src/librustc_mir/build/expr/as_operand.rs
+++ b/src/librustc_mir_build/build/expr/as_operand.rs
@@ -13,7 +13,7 @@
     /// The operand returned from this function will *not be valid* after
     /// an ExprKind::Scope is passed, so please do *not* return it from
     /// functions to avoid bad miscompiles.
-    pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
+    crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -27,7 +27,7 @@
     /// this time.
     ///
     /// The operand is known to be live until the end of `scope`.
-    pub fn as_operand<M>(
+    crate fn as_operand<M>(
         &mut self,
         block: BasicBlock,
         scope: Option<region::Scope>,
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs
similarity index 94%
rename from src/librustc_mir/build/expr/as_place.rs
rename to src/librustc_mir_build/build/expr/as_place.rs
index 29eac5e..fd6882f 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir_build/build/expr/as_place.rs
@@ -20,13 +20,13 @@
 /// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
 #[derive(Clone)]
 struct PlaceBuilder<'tcx> {
-    base: PlaceBase<'tcx>,
+    local: Local,
     projection: Vec<PlaceElem<'tcx>>,
 }
 
-impl PlaceBuilder<'tcx> {
+impl<'tcx> PlaceBuilder<'tcx> {
     fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
-        Place { base: self.base, projection: tcx.intern_place_elems(&self.projection) }
+        Place { local: self.local, projection: tcx.intern_place_elems(&self.projection) }
     }
 
     fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
@@ -47,15 +47,9 @@
     }
 }
 
-impl From<Local> for PlaceBuilder<'tcx> {
+impl<'tcx> From<Local> for PlaceBuilder<'tcx> {
     fn from(local: Local) -> Self {
-        Self { base: local.into(), projection: Vec::new() }
-    }
-}
-
-impl From<PlaceBase<'tcx>> for PlaceBuilder<'tcx> {
-    fn from(base: PlaceBase<'tcx>) -> Self {
-        Self { base, projection: Vec::new() }
+        Self { local, projection: Vec::new() }
     }
 }
 
@@ -72,7 +66,7 @@
     /// Extra care is needed if any user code is allowed to run between calling
     /// this method and using it, as is the case for `match` and index
     /// expressions.
-    pub fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
+    crate fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -95,7 +89,11 @@
     /// place. The place itself may or may not be mutable:
     /// * If this expr is a place expr like a.b, then we will return that place.
     /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
-    pub fn as_read_only_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
+    crate fn as_read_only_place<M>(
+        &mut self,
+        mut block: BasicBlock,
+        expr: M,
+    ) -> BlockAnd<Place<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -370,7 +368,7 @@
     ) {
         let tcx = self.hir.tcx();
         let place_ty =
-            Place::ty_from(&base_place.base, &base_place.projection, &self.local_decls, tcx);
+            Place::ty_from(&base_place.local, &base_place.projection, &self.local_decls, tcx);
         if let ty::Slice(_) = place_ty.ty.kind {
             // We need to create fake borrows to ensure that the bounds
             // check that we just did stays valid. Since we can't assign to
@@ -380,7 +378,7 @@
                 match elem {
                     ProjectionElem::Deref => {
                         let fake_borrow_deref_ty = Place::ty_from(
-                            &base_place.base,
+                            &base_place.local,
                             &base_place.projection[..idx],
                             &self.local_decls,
                             tcx,
@@ -398,14 +396,14 @@
                             Rvalue::Ref(
                                 tcx.lifetimes.re_erased,
                                 BorrowKind::Shallow,
-                                Place { base: base_place.base.clone(), projection },
+                                Place { local: base_place.local.clone(), projection },
                             ),
                         );
                         fake_borrow_temps.push(fake_borrow_temp);
                     }
                     ProjectionElem::Index(_) => {
                         let index_ty = Place::ty_from(
-                            &base_place.base,
+                            &base_place.local,
                             &base_place.projection[..idx],
                             &self.local_decls,
                             tcx,
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs
similarity index 96%
rename from src/librustc_mir/build/expr/as_rvalue.rs
rename to src/librustc_mir_build/build/expr/as_rvalue.rs
index 34b0cbf..5959b85 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir_build/build/expr/as_rvalue.rs
@@ -18,7 +18,7 @@
     /// The operand returned from this function will *not be valid* after
     /// an ExprKind::Scope is passed, so please do *not* return it from
     /// functions to avoid bad miscompiles.
-    pub fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
+    crate fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -276,7 +276,7 @@
         }
     }
 
-    pub fn build_binary_op(
+    crate fn build_binary_op(
         &mut self,
         mut block: BasicBlock,
         op: BinOp,
@@ -393,26 +393,24 @@
         let arg_place = unpack!(block = this.as_place(block, arg));
 
         let mutability = match arg_place.as_ref() {
-            PlaceRef { base: &PlaceBase::Local(local), projection: &[] } => {
-                this.local_decls[local].mutability
-            }
-            PlaceRef { base: &PlaceBase::Local(local), projection: &[ProjectionElem::Deref] } => {
+            PlaceRef { local, projection: &[] } => this.local_decls[*local].mutability,
+            PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
                 debug_assert!(
-                    this.local_decls[local].is_ref_for_guard(),
+                    this.local_decls[*local].is_ref_for_guard(),
                     "Unexpected capture place",
                 );
-                this.local_decls[local].mutability
+                this.local_decls[*local].mutability
             }
             PlaceRef {
-                ref base,
+                ref local,
                 projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             }
             | PlaceRef {
-                ref base,
+                ref local,
                 projection:
                     &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _), ProjectionElem::Deref],
             } => {
-                let place = PlaceRef { base, projection: proj_base };
+                let place = PlaceRef { local, projection: proj_base };
 
                 // Not projected from the implicit `self` in a closure.
                 debug_assert!(
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs
similarity index 98%
rename from src/librustc_mir/build/expr/as_temp.rs
rename to src/librustc_mir_build/build/expr/as_temp.rs
index 9c7b112..f47987c 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir_build/build/expr/as_temp.rs
@@ -3,15 +3,15 @@
 use crate::build::scope::DropKind;
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
-use rustc::hir;
 use rustc::middle::region;
 use rustc::mir::*;
+use rustc_hir as hir;
 use rustc_span::symbol::sym;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr` into a fresh temporary. This is used when building
     /// up rvalues so as to freeze the value that will be consumed.
-    pub fn as_temp<M>(
+    crate fn as_temp<M>(
         &mut self,
         block: BasicBlock,
         temp_lifetime: Option<region::Scope>,
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir_build/build/expr/category.rs
similarity index 96%
rename from src/librustc_mir/build/expr/category.rs
rename to src/librustc_mir_build/build/expr/category.rs
index b35616c..c4d3409 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir_build/build/expr/category.rs
@@ -1,7 +1,7 @@
 use crate::hair::*;
 
 #[derive(Debug, PartialEq)]
-pub enum Category {
+crate enum Category {
     // An assignable memory location like `x`, `x.f`, `foo()[3]`, that
     // sort of thing. Something that could appear on the LHS of an `=`
     // sign.
@@ -19,7 +19,7 @@
 // Rvalues fall into different "styles" that will determine which fn
 // is best suited to generate them.
 #[derive(Debug, PartialEq)]
-pub enum RvalueFunc {
+crate enum RvalueFunc {
     // Best generated by `into`. This is generally exprs that
     // cause branching, like `match`, but also includes calls.
     Into,
@@ -31,7 +31,7 @@
 /// Determines the category for a given expression. Note that scope
 /// and paren expressions have no category.
 impl Category {
-    pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
+    crate fn of(ek: &ExprKind<'_>) -> Option<Category> {
         match *ek {
             ExprKind::Scope { .. } => None,
 
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
similarity index 99%
rename from src/librustc_mir/build/expr/into.rs
rename to src/librustc_mir_build/build/expr/into.rs
index 2a2c818..503dfb6 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -3,10 +3,10 @@
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::hair::*;
-use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
 use rustc_span::symbol::sym;
 
 use rustc_target::spec::abi::Abi;
@@ -14,7 +14,7 @@
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
-    pub fn into_expr(
+    crate fn into_expr(
         &mut self,
         destination: &Place<'tcx>,
         mut block: BasicBlock,
diff --git a/src/librustc_mir/build/expr/mod.rs b/src/librustc_mir_build/build/expr/mod.rs
similarity index 100%
rename from src/librustc_mir/build/expr/mod.rs
rename to src/librustc_mir_build/build/expr/mod.rs
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir_build/build/expr/stmt.rs
similarity index 98%
rename from src/librustc_mir/build/expr/stmt.rs
rename to src/librustc_mir_build/build/expr/stmt.rs
index 9f37e77..fd61cb8 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir_build/build/expr/stmt.rs
@@ -10,7 +10,7 @@
     /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
     /// span of that statement (including its semicolon, if any).
     /// The scope is used if a statement temporary must be dropped.
-    pub fn stmt_expr(
+    crate fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
         expr: Expr<'tcx>,
@@ -149,7 +149,7 @@
                     if let ExprKind::Block { body } = expr.kind {
                         if let Some(tail_expr) = &body.expr {
                             let mut expr = tail_expr;
-                            while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.kind {
+                            while let rustc_hir::ExprKind::Block(subblock, _label) = &expr.kind {
                                 if let Some(subtail_expr) = &subblock.expr {
                                     expr = subtail_expr
                                 } else {
diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir_build/build/into.rs
similarity index 90%
rename from src/librustc_mir/build/into.rs
rename to src/librustc_mir_build/build/into.rs
index 9c3ea5f..1a2a9d2 100644
--- a/src/librustc_mir/build/into.rs
+++ b/src/librustc_mir_build/build/into.rs
@@ -18,7 +18,12 @@
 }
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn into<E>(&mut self, destination: &Place<'tcx>, block: BasicBlock, expr: E) -> BlockAnd<()>
+    crate fn into<E>(
+        &mut self,
+        destination: &Place<'tcx>,
+        block: BasicBlock,
+        expr: E,
+    ) -> BlockAnd<()>
     where
         E: EvalInto<'tcx>,
     {
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs
similarity index 98%
rename from src/librustc_mir/build/matches/mod.rs
rename to src/librustc_mir_build/build/matches/mod.rs
index 468a362..f9f10b5 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir_build/build/matches/mod.rs
@@ -10,12 +10,12 @@
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
 use crate::hair::{self, *};
-use rustc::hir::HirId;
 use rustc::middle::region;
 use rustc::mir::*;
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::HirId;
 use rustc_index::bit_set::BitSet;
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
@@ -81,7 +81,7 @@
     ///
     /// * From each prebinding block to the next prebinding block.
     /// * From each otherwise block to the next prebinding block.
-    pub fn match_expr(
+    crate fn match_expr(
         &mut self,
         destination: &Place<'tcx>,
         span: Span,
@@ -417,7 +417,7 @@
         }
     }
 
-    pub fn place_into_pattern(
+    crate fn place_into_pattern(
         &mut self,
         block: BasicBlock,
         irrefutable_pat: Pat<'tcx>,
@@ -488,7 +488,7 @@
     /// scope for the bindings in these patterns, if such a scope had to be
     /// created. NOTE: Declaring the bindings should always be done in their
     /// drop scope.
-    pub fn declare_bindings(
+    crate fn declare_bindings(
         &mut self,
         mut visibility_scope: Option<SourceScope>,
         scope_span: Span,
@@ -525,7 +525,7 @@
         visibility_scope
     }
 
-    pub fn storage_live_binding(
+    crate fn storage_live_binding(
         &mut self,
         block: BasicBlock,
         var: HirId,
@@ -540,7 +540,7 @@
         Place::from(local_id)
     }
 
-    pub fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
+    crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
         let local_id = self.var_local_id(var, for_guard);
         let region_scope = self.hir.region_scope_tree.var_scope(var.local_id);
         self.schedule_drop(span, region_scope, local_id, DropKind::Value);
@@ -641,7 +641,7 @@
 }
 
 #[derive(Debug)]
-pub struct Candidate<'pat, 'tcx> {
+crate struct Candidate<'pat, 'tcx> {
     // span of the original pattern that gave rise to this candidate
     span: Span,
 
@@ -685,7 +685,7 @@
 }
 
 #[derive(Clone, Debug)]
-pub struct MatchPair<'pat, 'tcx> {
+crate struct MatchPair<'pat, 'tcx> {
     // this place...
     place: Place<'tcx>,
 
@@ -739,7 +739,7 @@
 }
 
 #[derive(Debug)]
-pub struct Test<'tcx> {
+crate struct Test<'tcx> {
     span: Span,
     kind: TestKind<'tcx>,
 }
@@ -747,7 +747,7 @@
 /// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
 /// a match arm has a guard expression attached to it.
 #[derive(Copy, Clone, Debug)]
-pub(crate) struct ArmHasGuard(pub bool);
+crate struct ArmHasGuard(crate bool);
 
 ///////////////////////////////////////////////////////////////////////////
 // Main matching algorithm
@@ -890,7 +890,7 @@
                     let proj_base = &source.projection[..i];
 
                     fake_borrows.insert(Place {
-                        base: source.base.clone(),
+                        local: source.local.clone(),
                         projection: self.hir.tcx().intern_place_elems(proj_base),
                     });
                 }
@@ -1241,7 +1241,7 @@
                     // Insert a shallow borrow after a deref. For other
                     // projections the borrow of prefix_cursor will
                     // conflict with any mutation of base.
-                    all_fake_borrows.push(PlaceRef { base: &place.base, projection: proj_base });
+                    all_fake_borrows.push(PlaceRef { local: &place.local, projection: proj_base });
                 }
             }
 
@@ -1258,7 +1258,7 @@
             .into_iter()
             .map(|matched_place_ref| {
                 let matched_place = Place {
-                    base: matched_place_ref.base.clone(),
+                    local: matched_place_ref.local.clone(),
                     projection: tcx.intern_place_elems(matched_place_ref.projection),
                 };
                 let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs
similarity index 98%
rename from src/librustc_mir/build/matches/simplify.rs
rename to src/librustc_mir_build/build/matches/simplify.rs
index bbb555a..a5f691a 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir_build/build/matches/simplify.rs
@@ -15,16 +15,16 @@
 use crate::build::matches::{Ascription, Binding, Candidate, MatchPair};
 use crate::build::Builder;
 use crate::hair::{self, *};
-use rustc::hir::RangeEnd;
 use rustc::mir::interpret::truncate;
 use rustc::ty;
 use rustc::ty::layout::{Integer, IntegerExt, Size};
+use rustc_hir::RangeEnd;
 use syntax::attr::{SignedInt, UnsignedInt};
 
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
+    crate fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
         // repeatedly simplify match pairs until fixed point is reached
         loop {
             let match_pairs = mem::take(&mut candidate.match_pairs);
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs
similarity index 98%
rename from src/librustc_mir/build/matches/test.rs
rename to src/librustc_mir_build/build/matches/test.rs
index b87cf76..31fc0d1 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir_build/build/matches/test.rs
@@ -9,12 +9,12 @@
 use crate::build::Builder;
 use crate::hair::pattern::compare_const_vals;
 use crate::hair::*;
-use rustc::hir::RangeEnd;
 use rustc::mir::*;
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::{self, adjustment::PointerCast, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::RangeEnd;
 use rustc_index::bit_set::BitSet;
 use rustc_span::symbol::sym;
 
@@ -24,7 +24,7 @@
     /// Identifies what test is needed to decide if `match_pair` is applicable.
     ///
     /// It is a bug to call this with a simplifiable pattern.
-    pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
+    crate fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
         match *match_pair.pattern.kind {
             PatKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
                 span: match_pair.pattern.span,
@@ -85,7 +85,7 @@
         }
     }
 
-    pub fn add_cases_to_switch<'pat>(
+    crate fn add_cases_to_switch<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         candidate: &Candidate<'pat, 'tcx>,
@@ -129,7 +129,7 @@
         }
     }
 
-    pub fn add_variants_to_switch<'pat>(
+    crate fn add_variants_to_switch<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         candidate: &Candidate<'pat, 'tcx>,
@@ -156,7 +156,7 @@
         }
     }
 
-    pub fn perform_test(
+    crate fn perform_test(
         &mut self,
         block: BasicBlock,
         place: &Place<'tcx>,
@@ -507,7 +507,7 @@
     /// that it *doesn't* apply. For now, we return false, indicate that the
     /// test does not apply to this candidate, but it might be we can get
     /// tighter match code if we do something a bit different.
-    pub fn sort_candidate<'pat>(
+    crate fn sort_candidate<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         test: &Test<'tcx>,
@@ -657,7 +657,7 @@
                 }
 
                 let no_overlap = (|| {
-                    use rustc::hir::RangeEnd::*;
+                    use rustc_hir::RangeEnd::*;
                     use std::cmp::Ordering::*;
 
                     let tcx = self.hir.tcx();
diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir_build/build/matches/util.rs
similarity index 94%
rename from src/librustc_mir/build/matches/util.rs
rename to src/librustc_mir_build/build/matches/util.rs
index b6e643a6..def8d1b 100644
--- a/src/librustc_mir/build/matches/util.rs
+++ b/src/librustc_mir_build/build/matches/util.rs
@@ -8,7 +8,7 @@
 use std::u32;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn field_match_pairs<'pat>(
+    crate fn field_match_pairs<'pat>(
         &mut self,
         place: Place<'tcx>,
         subpatterns: &'pat [FieldPat<'tcx>],
@@ -26,7 +26,7 @@
             .collect()
     }
 
-    pub fn prefix_slice_suffix<'pat>(
+    crate fn prefix_slice_suffix<'pat>(
         &mut self,
         match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
         place: &Place<'tcx>,
@@ -77,7 +77,7 @@
     /// Creates a false edge to `imaginary_target` and a real edge to
     /// real_target. If `imaginary_target` is none, or is the same as the real
     /// target, a Goto is generated instead to simplify the generated MIR.
-    pub fn false_edges(
+    crate fn false_edges(
         &mut self,
         from_block: BasicBlock,
         real_target: BasicBlock,
@@ -98,7 +98,7 @@
 }
 
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
-    pub fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
+    crate fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
         MatchPair { place, pattern }
     }
 }
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir_build/build/misc.rs
similarity index 81%
rename from src/librustc_mir/build/misc.rs
rename to src/librustc_mir_build/build/misc.rs
index 7c358fe..3d5145b 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir_build/build/misc.rs
@@ -14,7 +14,7 @@
     ///
     /// N.B., **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
-    pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
+    crate fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
         let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
         let place = Place::from(temp);
         debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty);
@@ -23,24 +23,28 @@
 
     /// Convenience function for creating a literal operand, one
     /// without any user type annotation.
-    pub fn literal_operand(&mut self, span: Span, literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> {
+    crate fn literal_operand(
+        &mut self,
+        span: Span,
+        literal: &'tcx ty::Const<'tcx>,
+    ) -> Operand<'tcx> {
         let constant = box Constant { span, user_ty: None, literal };
         Operand::Constant(constant)
     }
 
-    pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
+    crate fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
         Rvalue::Aggregate(box AggregateKind::Tuple, vec![])
     }
 
     // Returns a zero literal operand for the appropriate type, works for
     // bool, char and integers.
-    pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
+    crate fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty));
 
         self.literal_operand(span, literal)
     }
 
-    pub fn push_usize(
+    crate fn push_usize(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -61,7 +65,7 @@
         temp
     }
 
-    pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
+    crate fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
         let tcx = self.hir.tcx();
         let ty = place.ty(&self.local_decls, tcx).ty;
         if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir_build/build/mod.rs
similarity index 98%
rename from src/librustc_mir/build/mod.rs
rename to src/librustc_mir_build/build/mod.rs
index 39edcc9..6214453 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -2,15 +2,14 @@
 use crate::build::scope::DropKind;
 use crate::hair::cx::Cx;
 use crate::hair::{BindingMode, LintLevel, PatKind};
-use crate::transform::MirSource;
-use crate::util as mir_util;
-use rustc::hir::def_id::DefId;
-use rustc::hir::{self, GeneratorKind, HirIdMap, Node};
 use rustc::middle::lang_items;
 use rustc::middle::region;
 use rustc::mir::*;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{GeneratorKind, HirIdMap, Node};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -21,8 +20,12 @@
 
 use super::lints;
 
+crate fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::steal::Steal<BodyAndCache<'_>> {
+    tcx.alloc_steal_mir(mir_build(tcx, def_id))
+}
+
 /// Construct the MIR for a given `DefId`.
-pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
+fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     // Figure out what primary body this item has.
@@ -171,8 +174,6 @@
             build::construct_const(cx, body_id, return_ty, return_ty_span)
         };
 
-        mir_util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
-
         lints::check(tcx, &body, def_id);
 
         let mut body = BodyAndCache::new(body);
@@ -201,7 +202,7 @@
 }
 
 #[derive(Debug, PartialEq, Eq)]
-pub enum BlockFrame {
+enum BlockFrame {
     /// Evaluation is currently within a statement.
     ///
     /// Examples include:
@@ -460,7 +461,7 @@
 }
 
 rustc_index::newtype_index! {
-    pub struct ScopeId { .. }
+    struct ScopeId { .. }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -833,7 +834,7 @@
                             span: tcx_hir.span(var_id),
                         },
                         place: Place {
-                            base: closure_env_arg.into(),
+                            local: closure_env_arg.into(),
                             projection: tcx.intern_place_elems(&projs),
                         },
                     });
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir_build/build/scope.rs
similarity index 97%
rename from src/librustc_mir/build/scope.rs
rename to src/librustc_mir_build/build/scope.rs
index b05b1d2..d994b87 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir_build/build/scope.rs
@@ -84,11 +84,11 @@
 
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
 use crate::hair::{Expr, ExprRef, LintLevel};
-use rustc::hir;
-use rustc::hir::GeneratorKind;
 use rustc::middle::region;
 use rustc::mir::*;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
+use rustc_hir::GeneratorKind;
 use rustc_span::{Span, DUMMY_SP};
 use std::collections::hash_map::Entry;
 use std::mem;
@@ -123,7 +123,7 @@
 }
 
 #[derive(Debug, Default)]
-pub struct Scopes<'tcx> {
+crate struct Scopes<'tcx> {
     scopes: Vec<Scope>,
     /// The current set of breakable scopes. See module comment for more details.
     breakable_scopes: Vec<BreakableScope<'tcx>>,
@@ -183,7 +183,7 @@
 
 /// The target of an expression that breaks out of a scope
 #[derive(Clone, Copy, Debug)]
-pub enum BreakableTarget {
+crate enum BreakableTarget {
     Continue(region::Scope),
     Break(region::Scope),
     Return,
@@ -371,7 +371,7 @@
     // ==========================
     //  Start a breakable scope, which tracks where `continue`, `break` and
     //  `return` should branch to.
-    pub fn in_breakable_scope<F, R>(
+    crate fn in_breakable_scope<F, R>(
         &mut self,
         loop_block: Option<BasicBlock>,
         break_block: BasicBlock,
@@ -395,7 +395,7 @@
         res
     }
 
-    pub fn in_opt_scope<F, R>(
+    crate fn in_opt_scope<F, R>(
         &mut self,
         opt_scope: Option<(region::Scope, SourceInfo)>,
         f: F,
@@ -418,7 +418,7 @@
 
     /// Convenience wrapper that pushes a scope and then executes `f`
     /// to build its contents, popping the scope afterwards.
-    pub fn in_scope<F, R>(
+    crate fn in_scope<F, R>(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
         lint_level: LintLevel,
@@ -463,14 +463,14 @@
     /// scope and call `pop_scope` afterwards. Note that these two
     /// calls must be paired; using `in_scope` as a convenience
     /// wrapper maybe preferable.
-    pub fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
+    crate fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
         self.scopes.push_scope(region_scope, self.source_scope);
     }
 
     /// Pops a scope, which should have region scope `region_scope`,
     /// adding any drops onto the end of `block` that are needed.
     /// This must match 1-to-1 with `push_scope`.
-    pub fn pop_scope(
+    crate fn pop_scope(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
         mut block: BasicBlock,
@@ -500,7 +500,7 @@
         block.unit()
     }
 
-    pub fn break_scope(
+    crate fn break_scope(
         &mut self,
         mut block: BasicBlock,
         value: Option<ExprRef<'tcx>>,
@@ -535,7 +535,7 @@
     /// Branch out of `block` to `target`, exiting all scopes up to
     /// and including `region_scope`. This will insert whatever drops are
     /// needed. See module comment for details.
-    pub fn exit_scope(
+    crate fn exit_scope(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -604,7 +604,7 @@
     ///
     /// This path terminates in GeneratorDrop. Returns the start of the path.
     /// None indicates there’s no cleanup to do at this point.
-    pub fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
+    crate fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
         // Fill in the cache for unwinds
         self.diverge_cleanup_gen(true);
 
@@ -656,7 +656,7 @@
     }
 
     /// Creates a new source scope, nested in the current one.
-    pub fn new_source_scope(
+    crate fn new_source_scope(
         &mut self,
         span: Span,
         lint_level: LintLevel,
@@ -689,7 +689,7 @@
     }
 
     /// Given a span and the current source scope, make a SourceInfo.
-    pub fn source_info(&self, span: Span) -> SourceInfo {
+    crate fn source_info(&self, span: Span) -> SourceInfo {
         SourceInfo { span, scope: self.source_scope }
     }
 
@@ -717,7 +717,7 @@
     ///
     /// When building statics/constants, returns `None` since
     /// intermediate values do not have to be dropped in that case.
-    pub fn local_scope(&self) -> Option<region::Scope> {
+    crate fn local_scope(&self) -> Option<region::Scope> {
         match self.hir.body_owner_kind {
             hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) =>
             // No need to free storage in this context.
@@ -729,7 +729,7 @@
     }
 
     // Schedule an abort block - this is used for some ABIs that cannot unwind
-    pub fn schedule_abort(&mut self) -> BasicBlock {
+    crate fn schedule_abort(&mut self) -> BasicBlock {
         let source_info = self.scopes.source_info(self.scopes.len(), self.fn_span);
         let abortblk = self.cfg.start_new_cleanup_block();
         self.cfg.terminate(abortblk, source_info, TerminatorKind::Abort);
@@ -739,7 +739,7 @@
 
     // Scheduling drops
     // ================
-    pub fn schedule_drop_storage_and_value(
+    crate fn schedule_drop_storage_and_value(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -754,7 +754,7 @@
     ///
     /// When called with `DropKind::Storage`, `place` should be a local
     /// with an index higher than the current `self.arg_count`.
-    pub fn schedule_drop(
+    crate fn schedule_drop(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -884,7 +884,7 @@
     /// spurious borrow-check errors -- the problem, ironically, is
     /// not the `DROP(_X)` itself, but the (spurious) unwind pathways
     /// that it creates. See #64391 for an example.
-    pub fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
+    crate fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
         let scope = match self.local_scope() {
             None => {
                 // if there is no local scope, operands won't be dropped anyway
@@ -921,7 +921,7 @@
     ///
     /// This is a special case because the temporary for the condition needs to
     /// be dropped on both the true and the false arm.
-    pub fn test_bool(
+    crate fn test_bool(
         &mut self,
         mut block: BasicBlock,
         condition: Expr<'tcx>,
@@ -978,7 +978,7 @@
     ///
     /// This path terminates in Resume. Returns the start of the path.
     /// See module comment for more details.
-    pub fn diverge_cleanup(&mut self) -> BasicBlock {
+    crate fn diverge_cleanup(&mut self) -> BasicBlock {
         self.diverge_cleanup_gen(false)
     }
 
@@ -1033,7 +1033,7 @@
     }
 
     /// Utility function for *non*-scope code to build their own drops
-    pub fn build_drop_and_replace(
+    crate fn build_drop_and_replace(
         &mut self,
         block: BasicBlock,
         span: Span,
@@ -1059,7 +1059,7 @@
     /// Creates an Assert terminator and return the success block.
     /// If the boolean condition operand is not the expected value,
     /// a runtime panic will be caused with the given message.
-    pub fn assert(
+    crate fn assert(
         &mut self,
         block: BasicBlock,
         cond: Operand<'tcx>,
@@ -1293,7 +1293,7 @@
     target
 }
 
-fn push_storage_deads(
+fn push_storage_deads<'tcx>(
     cfg: &mut CFG<'tcx>,
     target: BasicBlock,
     storage_deads: &mut Vec<Statement<'tcx>>,
diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir_build/hair/constant.rs
similarity index 100%
rename from src/librustc_mir/hair/constant.rs
rename to src/librustc_mir_build/hair/constant.rs
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir_build/hair/cx/block.rs
similarity index 98%
rename from src/librustc_mir/hair/cx/block.rs
rename to src/librustc_mir_build/hair/cx/block.rs
index 14f6c39..a883b84 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir_build/hair/cx/block.rs
@@ -2,9 +2,9 @@
 use crate::hair::cx::Cx;
 use crate::hair::{self, *};
 
-use rustc::hir;
 use rustc::middle::region;
 use rustc::ty;
+use rustc_hir as hir;
 
 use rustc_index::vec::Idx;
 
@@ -101,7 +101,7 @@
     return result;
 }
 
-pub fn to_expr_ref<'a, 'tcx>(
+crate fn to_expr_ref<'a, 'tcx>(
     cx: &mut Cx<'a, 'tcx>,
     block: &'tcx hir::Block<'tcx>,
 ) -> ExprRef<'tcx> {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
similarity index 97%
rename from src/librustc_mir/hair/cx/expr.rs
rename to src/librustc_mir_build/hair/cx/expr.rs
index 569ac96..97e7181 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -3,14 +3,14 @@
 use crate::hair::cx::Cx;
 use crate::hair::util::UserAnnotatedTyHelpers;
 use crate::hair::*;
-use rustc::hir;
-use rustc::hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc::hir::def_id::LocalDefId;
 use rustc::mir::interpret::{ErrorHandled, Scalar};
 use rustc::mir::BorrowKind;
 use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast};
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, AdtKind, Ty};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::def_id::LocalDefId;
 use rustc_index::vec::Idx;
 use rustc_span::Span;
 
@@ -411,15 +411,18 @@
             let def_id = cx.tcx.hir().local_def_id(count.hir_id);
             let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
             let span = cx.tcx.def_span(def_id);
-            let count = match cx.tcx.const_eval_resolve(cx.param_env, def_id, substs, Some(span)) {
-                Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env),
-                Err(ErrorHandled::Reported) => 0,
-                Err(ErrorHandled::TooGeneric) => {
-                    let span = cx.tcx.def_span(def_id);
-                    cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters");
-                    0
-                }
-            };
+            let count =
+                match cx.tcx.const_eval_resolve(cx.param_env, def_id, substs, None, Some(span)) {
+                    Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env),
+                    Err(ErrorHandled::Reported) => 0,
+                    Err(ErrorHandled::TooGeneric) => {
+                        let span = cx.tcx.def_span(def_id);
+                        cx.tcx
+                            .sess
+                            .span_err(span, "array lengths can't depend on generic parameters");
+                        0
+                    }
+                };
 
             ExprKind::Repeat { value: v.to_ref(), count }
         }
@@ -523,7 +526,7 @@
                             // and not the beginning of discriminants (which is always `0`)
                             let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
                             let lhs = mk_const(cx.tcx().mk_const(ty::Const {
-                                val: ty::ConstKind::Unevaluated(did, substs),
+                                val: ty::ConstKind::Unevaluated(did, substs, None),
                                 ty: var_ty,
                             }));
                             let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
@@ -574,8 +577,8 @@
     Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
 }
 
-fn user_substs_applied_to_res(
-    cx: &mut Cx<'a, 'tcx>,
+fn user_substs_applied_to_res<'tcx>(
+    cx: &mut Cx<'_, 'tcx>,
     hir_id: hir::HirId,
     res: Res,
 ) -> Option<ty::CanonicalUserType<'tcx>> {
@@ -719,7 +722,7 @@
             debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
             ExprKind::Literal {
                 literal: cx.tcx.mk_const(ty::Const {
-                    val: ty::ConstKind::Unevaluated(def_id, substs),
+                    val: ty::ConstKind::Unevaluated(def_id, substs, None),
                     ty: cx.tables().node_type(expr.hir_id),
                 }),
                 user_ty,
@@ -772,7 +775,7 @@
     }
 }
 
-fn convert_var(
+fn convert_var<'tcx>(
     cx: &mut Cx<'_, 'tcx>,
     expr: &'tcx hir::Expr<'tcx>,
     var_hir_id: hir::HirId,
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs
similarity index 76%
rename from src/librustc_mir/hair/cx/mod.rs
rename to src/librustc_mir_build/hair/cx/mod.rs
index e81dc9b..5fc9a1e 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir_build/hair/cx/mod.rs
@@ -6,33 +6,33 @@
 use crate::hair::*;
 
 use crate::hair::constant::{lit_to_const, LitToConstError};
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::Node;
 use rustc::infer::InferCtxt;
 use rustc::middle::region;
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::Subst;
 use rustc::ty::subst::{GenericArg, InternalSubsts};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::Node;
 use rustc_index::vec::Idx;
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast;
 use syntax::attr;
 
 #[derive(Clone)]
-pub struct Cx<'a, 'tcx> {
+crate struct Cx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'a InferCtxt<'a, 'tcx>,
 
-    pub root_lint_level: hir::HirId,
-    pub param_env: ty::ParamEnv<'tcx>,
+    crate root_lint_level: hir::HirId,
+    crate param_env: ty::ParamEnv<'tcx>,
 
     /// Identity `InternalSubsts` for use with const-evaluation.
-    pub identity_substs: &'tcx InternalSubsts<'tcx>,
+    crate identity_substs: &'tcx InternalSubsts<'tcx>,
 
-    pub region_scope_tree: &'tcx region::ScopeTree,
-    pub tables: &'a ty::TypeckTables<'tcx>,
+    crate region_scope_tree: &'tcx region::ScopeTree,
+    crate tables: &'a ty::TypeckTables<'tcx>,
 
     /// This is `Constness::Const` if we are compiling a `static`,
     /// `const`, or the body of a `const fn`.
@@ -42,7 +42,7 @@
     body_owner: DefId,
 
     /// What kind of body is being compiled.
-    pub body_owner_kind: hir::BodyOwnerKind,
+    crate body_owner_kind: hir::BodyOwnerKind,
 
     /// Whether this constant/function needs overflow checks.
     check_overflow: bool,
@@ -52,7 +52,7 @@
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
+    crate fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
         let tcx = infcx.tcx;
         let src_def_id = tcx.hir().local_def_id(src_id);
         let tables = tcx.typeck_tables_of(src_def_id);
@@ -92,42 +92,42 @@
         }
     }
 
-    pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
+    crate fn control_flow_destroyed(self) -> Vec<(Span, String)> {
         self.control_flow_destroyed
     }
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
     /// Normalizes `ast` into the appropriate "mirror" type.
-    pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
+    crate fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
         ast.make_mirror(self)
     }
 
-    pub fn usize_ty(&mut self) -> Ty<'tcx> {
+    crate fn usize_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.usize
     }
 
-    pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
+    crate fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_usize(self.tcx, value)
     }
 
-    pub fn bool_ty(&mut self) -> Ty<'tcx> {
+    crate fn bool_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.bool
     }
 
-    pub fn unit_ty(&mut self) -> Ty<'tcx> {
+    crate fn unit_ty(&mut self) -> Ty<'tcx> {
         self.tcx.mk_unit()
     }
 
-    pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+    crate fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_bool(self.tcx, true)
     }
 
-    pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+    crate fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_bool(self.tcx, false)
     }
 
-    pub fn const_eval_literal(
+    crate fn const_eval_literal(
         &mut self,
         lit: &'tcx ast::LitKind,
         ty: Ty<'tcx>,
@@ -151,15 +151,15 @@
         }
     }
 
-    pub fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
+    crate fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
         let p = match self.tcx.hir().get(p.hir_id) {
             Node::Pat(p) | Node::Binding(p) => p,
             node => bug!("pattern became {:?}", node),
         };
-        Pat::from_hir(self.tcx, self.param_env.and(self.identity_substs), self.tables(), p)
+        Pat::from_hir(self.tcx, self.param_env, self.tables(), p)
     }
 
-    pub fn trait_method(
+    crate fn trait_method(
         &mut self,
         trait_def_id: DefId,
         method_name: Symbol,
@@ -168,6 +168,8 @@
     ) -> &'tcx ty::Const<'tcx> {
         let substs = self.tcx.mk_substs_trait(self_ty, params);
         for item in self.tcx.associated_items(trait_def_id) {
+            // The unhygienic comparison here is acceptable because this is only
+            // used on known traits.
             if item.kind == ty::AssocKind::Method && item.ident.name == method_name {
                 let method_ty = self.tcx.type_of(item.def_id);
                 let method_ty = method_ty.subst(self.tcx, substs);
@@ -178,32 +180,32 @@
         bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
     }
 
-    pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
+    crate fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
         (0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect()
     }
 
-    pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
+    crate fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
         ty.needs_drop(self.tcx, self.param_env)
     }
 
-    pub fn tcx(&self) -> TyCtxt<'tcx> {
+    crate fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    pub fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
+    crate fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
         self.tables
     }
 
-    pub fn check_overflow(&self) -> bool {
+    crate fn check_overflow(&self) -> bool {
         self.check_overflow
     }
 
-    pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
+    crate fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
         self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span)
     }
 }
 
-impl UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
+impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx()
     }
diff --git a/src/librustc_mir/hair/cx/to_ref.rs b/src/librustc_mir_build/hair/cx/to_ref.rs
similarity index 96%
rename from src/librustc_mir/hair/cx/to_ref.rs
rename to src/librustc_mir_build/hair/cx/to_ref.rs
index e40e21e..6cf8122 100644
--- a/src/librustc_mir/hair/cx/to_ref.rs
+++ b/src/librustc_mir_build/hair/cx/to_ref.rs
@@ -1,8 +1,8 @@
 use crate::hair::*;
 
-use rustc::hir;
+use rustc_hir as hir;
 
-pub trait ToRef {
+crate trait ToRef {
     type Output;
     fn to_ref(self) -> Self::Output;
 }
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs
similarity index 85%
rename from src/librustc_mir/hair/mod.rs
rename to src/librustc_mir_build/hair/mod.rs
index 800507e..3257f28 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir_build/hair/mod.rs
@@ -5,8 +5,6 @@
 //! structures.
 
 use self::cx::Cx;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::Canonical;
 use rustc::middle::region;
 use rustc::mir::{BinOp, BorrowKind, Field, UnOp};
@@ -14,36 +12,38 @@
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{AdtDef, Const, Ty, UpvarSubsts, UserType};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 
 mod constant;
-pub mod cx;
+crate mod cx;
 
-pub mod pattern;
-pub(crate) use self::pattern::PatTyProj;
-pub use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
+crate mod pattern;
+crate use self::pattern::PatTyProj;
+crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
 
 mod util;
 
 #[derive(Copy, Clone, Debug)]
-pub enum LintLevel {
+crate enum LintLevel {
     Inherited,
     Explicit(hir::HirId),
 }
 
 #[derive(Clone, Debug)]
-pub struct Block<'tcx> {
-    pub targeted_by_break: bool,
-    pub region_scope: region::Scope,
-    pub opt_destruction_scope: Option<region::Scope>,
-    pub span: Span,
-    pub stmts: Vec<StmtRef<'tcx>>,
-    pub expr: Option<ExprRef<'tcx>>,
-    pub safety_mode: BlockSafety,
+crate struct Block<'tcx> {
+    crate targeted_by_break: bool,
+    crate region_scope: region::Scope,
+    crate opt_destruction_scope: Option<region::Scope>,
+    crate span: Span,
+    crate stmts: Vec<StmtRef<'tcx>>,
+    crate expr: Option<ExprRef<'tcx>>,
+    crate safety_mode: BlockSafety,
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum BlockSafety {
+crate enum BlockSafety {
     Safe,
     ExplicitUnsafe(hir::HirId),
     PushUnsafe,
@@ -51,18 +51,18 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtRef<'tcx> {
+crate enum StmtRef<'tcx> {
     Mirror(Box<Stmt<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct Stmt<'tcx> {
-    pub kind: StmtKind<'tcx>,
-    pub opt_destruction_scope: Option<region::Scope>,
+crate struct Stmt<'tcx> {
+    crate kind: StmtKind<'tcx>,
+    crate opt_destruction_scope: Option<region::Scope>,
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtKind<'tcx> {
+crate enum StmtKind<'tcx> {
     Expr {
         /// scope for this statement; may be used as lifetime of temporaries
         scope: region::Scope,
@@ -112,23 +112,23 @@
 /// example, method calls and overloaded operators are absent: they are
 /// expected to be converted into `Expr::Call` instances.
 #[derive(Clone, Debug)]
-pub struct Expr<'tcx> {
+crate struct Expr<'tcx> {
     /// type of this expression
-    pub ty: Ty<'tcx>,
+    crate ty: Ty<'tcx>,
 
     /// lifetime of this expression if it should be spilled into a
     /// temporary; should be None only if in a constant context
-    pub temp_lifetime: Option<region::Scope>,
+    crate temp_lifetime: Option<region::Scope>,
 
     /// span of the expression in the source
-    pub span: Span,
+    crate span: Span,
 
     /// kind of expression
-    pub kind: ExprKind<'tcx>,
+    crate kind: ExprKind<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprKind<'tcx> {
+crate enum ExprKind<'tcx> {
     Scope {
         region_scope: region::Scope,
         lint_level: LintLevel,
@@ -288,37 +288,37 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprRef<'tcx> {
+crate enum ExprRef<'tcx> {
     Hair(&'tcx hir::Expr<'tcx>),
     Mirror(Box<Expr<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldExprRef<'tcx> {
-    pub name: Field,
-    pub expr: ExprRef<'tcx>,
+crate struct FieldExprRef<'tcx> {
+    crate name: Field,
+    crate expr: ExprRef<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct FruInfo<'tcx> {
-    pub base: ExprRef<'tcx>,
-    pub field_types: Vec<Ty<'tcx>>,
+crate struct FruInfo<'tcx> {
+    crate base: ExprRef<'tcx>,
+    crate field_types: Vec<Ty<'tcx>>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Arm<'tcx> {
-    pub pattern: Pat<'tcx>,
-    pub guard: Option<Guard<'tcx>>,
-    pub body: ExprRef<'tcx>,
-    pub lint_level: LintLevel,
-    pub scope: region::Scope,
-    pub span: Span,
+crate struct Arm<'tcx> {
+    crate pattern: Pat<'tcx>,
+    crate guard: Option<Guard<'tcx>>,
+    crate body: ExprRef<'tcx>,
+    crate lint_level: LintLevel,
+    crate scope: region::Scope,
+    crate span: Span,
 }
 
-impl Arm<'tcx> {
+impl<'tcx> Arm<'tcx> {
     // HACK(or_patterns; Centril | dlrobertson): Remove this and
     // correctly handle each case in which this method is used.
-    pub fn top_pats_hack(&self) -> &[Pat<'tcx>] {
+    crate fn top_pats_hack(&self) -> &[Pat<'tcx>] {
         match &*self.pattern.kind {
             PatKind::Or { pats } => pats,
             _ => std::slice::from_ref(&self.pattern),
@@ -327,18 +327,18 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum Guard<'tcx> {
+crate enum Guard<'tcx> {
     If(ExprRef<'tcx>),
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum LogicalOp {
+crate enum LogicalOp {
     And,
     Or,
 }
 
 impl<'tcx> ExprRef<'tcx> {
-    pub fn span(&self) -> Span {
+    crate fn span(&self) -> Span {
         match self {
             ExprRef::Hair(expr) => expr.span,
             ExprRef::Mirror(expr) => expr.span,
@@ -361,7 +361,7 @@
 /// mirrored. This allows a single AST node from the compiler to
 /// expand into one or more Hair nodes, which lets the Hair nodes be
 /// simpler.
-pub trait Mirror<'tcx> {
+crate trait Mirror<'tcx> {
     type Output;
 
     fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
@@ -378,7 +378,7 @@
 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
     type Output = Expr<'tcx>;
 
-    fn make_mirror(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
+    fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
         match self {
             ExprRef::Hair(h) => h.make_mirror(hir),
             ExprRef::Mirror(m) => *m,
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
similarity index 98%
rename from src/librustc_mir/hair/pattern/_match.rs
rename to src/librustc_mir_build/hair/pattern/_match.rs
index 61d2ece..8fcaa1e 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -229,21 +229,20 @@
 use self::Usefulness::*;
 use self::WitnessPreference::*;
 
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::captures::Captures;
 use rustc_index::vec::Idx;
 
 use super::{compare_const_vals, PatternFoldable, PatternFolder};
 use super::{FieldPat, Pat, PatKind, PatRange};
 
-use rustc::hir::def_id::DefId;
-use rustc::hir::{HirId, RangeEnd};
 use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
 use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{HirId, RangeEnd};
 
 use rustc::lint;
 use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
 use rustc::mir::Field;
-use rustc::util::captures::Captures;
 use rustc::util::common::ErrorReported;
 
 use rustc_span::{Span, DUMMY_SP};
@@ -260,7 +259,7 @@
 use std::ops::RangeInclusive;
 use std::u128;
 
-pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
+crate fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
     LiteralExpander { tcx: cx.tcx, param_env: cx.param_env }.fold_pattern(&pat)
 }
 
@@ -269,7 +268,7 @@
     param_env: ty::ParamEnv<'tcx>,
 }
 
-impl LiteralExpander<'tcx> {
+impl<'tcx> LiteralExpander<'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
@@ -323,7 +322,7 @@
     }
 }
 
-impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
+impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> {
     fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
         debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind, pat.kind);
         match (&pat.ty.kind, &*pat.kind) {
@@ -381,10 +380,10 @@
 /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
 /// works well.
 #[derive(Debug, Clone)]
-pub struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
+crate struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
 
 impl<'p, 'tcx> PatStack<'p, 'tcx> {
-    pub fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
+    crate fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
         PatStack(smallvec![pat])
     }
 
@@ -472,15 +471,15 @@
 
 /// A 2D matrix.
 #[derive(Clone)]
-pub struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
+crate struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
 
 impl<'p, 'tcx> Matrix<'p, 'tcx> {
-    pub fn empty() -> Self {
+    crate fn empty() -> Self {
         Matrix(vec![])
     }
 
     /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
-    pub fn push(&mut self, row: PatStack<'p, 'tcx>) {
+    crate fn push(&mut self, row: PatStack<'p, 'tcx>) {
         if let Some(rows) = row.expand_or_pat() {
             self.0.extend(rows);
         } else {
@@ -569,22 +568,21 @@
     }
 }
 
-pub struct MatchCheckCtxt<'a, 'tcx> {
-    pub tcx: TyCtxt<'tcx>,
+crate struct MatchCheckCtxt<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
     /// The module in which the match occurs. This is necessary for
     /// checking inhabited-ness of types because whether a type is (visibly)
     /// inhabited can depend on whether it was defined in the current module or
     /// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
     /// outside it's module and should not be matchable with an empty match
     /// statement.
-    pub module: DefId,
+    crate module: DefId,
     param_env: ty::ParamEnv<'tcx>,
-    pub pattern_arena: &'a TypedArena<Pat<'tcx>>,
-    pub byte_array_map: FxHashMap<*const Pat<'tcx>, Vec<&'a Pat<'tcx>>>,
+    crate pattern_arena: &'a TypedArena<Pat<'tcx>>,
 }
 
 impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
-    pub fn create_and_enter<F, R>(
+    crate fn create_and_enter<F, R>(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         module: DefId,
@@ -595,13 +593,7 @@
     {
         let pattern_arena = TypedArena::default();
 
-        f(MatchCheckCtxt {
-            tcx,
-            param_env,
-            module,
-            pattern_arena: &pattern_arena,
-            byte_array_map: FxHashMap::default(),
-        })
+        f(MatchCheckCtxt { tcx, param_env, module, pattern_arena: &pattern_arena })
     }
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
@@ -613,7 +605,7 @@
     }
 
     // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
-    pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
+    crate fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.kind {
             ty::Adt(def, ..) => {
                 def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
@@ -773,13 +765,13 @@
         cx: &MatchCheckCtxt<'a, 'tcx>,
         adt: &'tcx ty::AdtDef,
     ) -> VariantIdx {
-        match self {
-            Variant(id) => adt.variant_index_with_id(*id),
+        match *self {
+            Variant(id) => adt.variant_index_with_id(id),
             Single => {
                 assert!(!adt.is_enum());
                 VariantIdx::new(0)
             }
-            ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
+            ConstantValue(c) => cx.tcx.destructure_const(cx.param_env.and(c)).variant,
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt),
         }
     }
@@ -1058,7 +1050,7 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum Usefulness<'tcx, 'p> {
+crate enum Usefulness<'tcx, 'p> {
     /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
     Useful(Vec<&'p Pat<'tcx>>),
     /// Carries a list of witnesses of non-exhaustiveness.
@@ -1146,7 +1138,7 @@
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum WitnessPreference {
+crate enum WitnessPreference {
     ConstructWitness,
     LeaveOutWitness,
 }
@@ -1190,10 +1182,10 @@
 ///
 /// The final `Pair(Some(_), true)` is then the resulting witness.
 #[derive(Clone, Debug)]
-pub struct Witness<'tcx>(Vec<Pat<'tcx>>);
+crate struct Witness<'tcx>(Vec<Pat<'tcx>>);
 
 impl<'tcx> Witness<'tcx> {
-    pub fn single_pattern(self) -> Pat<'tcx> {
+    crate fn single_pattern(self) -> Pat<'tcx> {
         assert_eq!(self.0.len(), 1);
         self.0.into_iter().next().unwrap()
     }
@@ -1358,9 +1350,9 @@
 /// around the (offset) space: i.e., `range.lo <= range.hi`.
 #[derive(Clone, Debug)]
 struct IntRange<'tcx> {
-    pub range: RangeInclusive<u128>,
-    pub ty: Ty<'tcx>,
-    pub span: Span,
+    range: RangeInclusive<u128>,
+    ty: Ty<'tcx>,
+    span: Span,
 }
 
 impl<'tcx> IntRange<'tcx> {
@@ -1631,7 +1623,7 @@
 /// relation to preceding patterns, it is not reachable) and exhaustiveness
 /// checking (if a wildcard pattern is useful in relation to a matrix, the
 /// matrix isn't exhaustive).
-pub fn is_useful<'p, 'tcx>(
+crate fn is_useful<'p, 'tcx>(
     cx: &mut MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
     v: &PatStack<'p, 'tcx>,
@@ -2238,7 +2230,7 @@
     split_ctors
 }
 
-fn lint_overlapping_patterns(
+fn lint_overlapping_patterns<'tcx>(
     tcx: TyCtxt<'tcx>,
     hir_id: Option<HirId>,
     ctor_range: IntRange<'tcx>,
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs
similarity index 93%
rename from src/librustc_mir/hair/pattern/check_match.rs
rename to src/librustc_mir_build/hair/pattern/check_match.rs
index bbbad36..84d57a8 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/hair/pattern/check_match.rs
@@ -4,21 +4,21 @@
 
 use super::{PatCtxt, PatKind, PatternError};
 
-use rustc::hir::def::*;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::HirId;
-use rustc::hir::{self, Pat};
+use rustc::hir::map::Map;
 use rustc::lint;
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_error_codes::*;
-use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::*;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{HirId, Pat};
 use rustc_span::symbol::sym;
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::Mutability;
-use syntax::feature_gate::feature_err;
 
 use std::slice;
 
@@ -28,12 +28,8 @@
         Some(id) => tcx.hir().body_owned_by(id),
     };
 
-    let mut visitor = MatchVisitor {
-        tcx,
-        tables: tcx.body_tables(body_id),
-        param_env: tcx.param_env(def_id),
-        identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
-    };
+    let mut visitor =
+        MatchVisitor { tcx, tables: tcx.body_tables(body_id), param_env: tcx.param_env(def_id) };
     visitor.visit_body(tcx.hir().body(body_id));
 }
 
@@ -45,11 +41,12 @@
     tcx: TyCtxt<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    identity_substs: SubstsRef<'tcx>,
 }
 
 impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -116,7 +113,7 @@
     }
 
     fn span_e0158(&self, span: Span, text: &str) {
-        span_err!(self.tcx.sess, span, E0158, "{}", text)
+        struct_span_err!(self.tcx.sess, span, E0158, "{}", text).emit();
     }
 }
 
@@ -150,11 +147,7 @@
             let inlined_arms: Vec<_> = arms
                 .iter()
                 .map(|arm| {
-                    let mut patcx = PatCtxt::new(
-                        self.tcx,
-                        self.param_env.and(self.identity_substs),
-                        self.tables,
-                    );
+                    let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.tables);
                     patcx.include_lint_checks();
                     let pattern = patcx.lower_pattern(&arm.pat);
                     let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
@@ -186,8 +179,7 @@
     fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>) {
         let module = self.tcx.hir().get_module_parent(pat.hir_id);
         MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
-            let mut patcx =
-                PatCtxt::new(self.tcx, self.param_env.and(self.identity_substs), self.tables);
+            let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.tables);
             patcx.include_lint_checks();
             let pattern = patcx.lower_pattern(pat);
             let pattern_ty = pattern.ty;
@@ -291,24 +283,26 @@
                             variant.ident == ident && variant.ctor_kind == CtorKind::Const
                         })
                     {
-                        // FIXME(Centril): Should be a lint?
                         let ty_path = cx.tcx.def_path_str(edef.did);
-                        let mut err = struct_span_warn!(
-                            cx.tcx.sess,
-                            p.span,
-                            E0170,
-                            "pattern binding `{}` is named the same as one \
-                             of the variants of the type `{}`",
-                            ident,
-                            ty_path
-                        );
-                        err.span_suggestion(
-                            p.span,
-                            "to match on the variant, qualify the path",
-                            format!("{}::{}", ty_path, ident),
-                            Applicability::MachineApplicable,
-                        );
-                        err.emit();
+                        cx.tcx
+                            .struct_span_lint_hir(
+                                lint::builtin::BINDINGS_WITH_VARIANT_NAME,
+                                p.hir_id,
+                                p.span,
+                                &format!(
+                                    "pattern binding `{}` is named the same as one \
+                                    of the variants of the type `{}`",
+                                    ident, ty_path
+                                ),
+                            )
+                            .code(error_code!(E0170))
+                            .span_suggestion(
+                                p.span,
+                                "to match on the variant, qualify the path",
+                                format!("{}::{}", ty_path, ident),
+                                Applicability::MachineApplicable,
+                            )
+                            .emit();
                     }
                 }
             }
@@ -728,7 +722,9 @@
     }
 
     impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
diff --git a/src/librustc_mir/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
similarity index 82%
rename from src/librustc_mir/hair/pattern/const_to_pat.rs
rename to src/librustc_mir_build/hair/pattern/const_to_pat.rs
index dd97565..a21a0ee 100644
--- a/src/librustc_mir/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -1,11 +1,10 @@
-use crate::const_eval::const_variant_index;
-
-use rustc::hir;
 use rustc::infer::InferCtxt;
 use rustc::lint;
 use rustc::mir::Field;
-use rustc::traits::{ObligationCause, PredicateObligation};
+use rustc::traits::predicate_for_trait_def;
+use rustc::traits::{self, ObligationCause, PredicateObligation};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
 
 use rustc_index::vec::Idx;
 
@@ -75,12 +74,12 @@
     fn search_for_structural_match_violation(
         &self,
         ty: Ty<'tcx>,
-    ) -> Option<ty::NonStructuralMatchTy<'tcx>> {
-        ty::search_for_structural_match_violation(self.id, self.span, self.tcx(), ty)
+    ) -> Option<traits::NonStructuralMatchTy<'tcx>> {
+        traits::search_for_structural_match_violation(self.id, self.span, self.tcx(), ty)
     }
 
     fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
-        ty::type_marked_structural(self.id, self.span, &self.infcx, ty)
+        traits::type_marked_structural(self.id, self.span, &self.infcx, ty)
     }
 
     fn to_pat(&mut self, cv: &'tcx ty::Const<'tcx>) -> Pat<'tcx> {
@@ -104,8 +103,8 @@
             );
             if let Some(non_sm_ty) = structural {
                 let adt_def = match non_sm_ty {
-                    ty::NonStructuralMatchTy::Adt(adt_def) => adt_def,
-                    ty::NonStructuralMatchTy::Param => {
+                    traits::NonStructuralMatchTy::Adt(adt_def) => adt_def,
+                    traits::NonStructuralMatchTy::Param => {
                         bug!("use of constant whose type is a parameter inside a pattern")
                     }
                 };
@@ -129,7 +128,8 @@
                 // not *yet* implement `PartialEq`. So for now we leave this here.
                 let ty_is_partial_eq: bool = {
                     let partial_eq_trait_id = self.tcx().lang_items().eq_trait().unwrap();
-                    let obligation: PredicateObligation<'_> = self.tcx().predicate_for_trait_def(
+                    let obligation: PredicateObligation<'_> = predicate_for_trait_def(
+                        self.tcx(),
                         self.param_env,
                         ObligationCause::misc(self.span, self.id),
                         partial_eq_trait_id,
@@ -165,18 +165,14 @@
         let tcx = self.tcx();
         let param_env = self.param_env;
 
-        let adt_subpattern = |i, variant_opt| {
-            let field = Field::new(i);
-            let val = crate::const_eval::const_field(tcx, param_env, variant_opt, field, cv);
-            self.recur(val)
-        };
-        let adt_subpatterns = |n, variant_opt| {
-            (0..n)
-                .map(|i| {
-                    let field = Field::new(i);
-                    FieldPat { field, pattern: adt_subpattern(i, variant_opt) }
+        let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| {
+            vals.iter()
+                .enumerate()
+                .map(|(idx, val)| {
+                    let field = Field::new(idx);
+                    FieldPat { field, pattern: self.recur(val) }
                 })
-                .collect::<Vec<_>>()
+                .collect()
         };
 
         let kind = match cv.ty.kind {
@@ -233,21 +229,28 @@
                 PatKind::Wild
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
-                let variant_index = const_variant_index(tcx, self.param_env, cv);
-                let subpatterns = adt_subpatterns(
-                    adt_def.variants[variant_index].fields.len(),
-                    Some(variant_index),
-                );
-                PatKind::Variant { adt_def, substs, variant_index, subpatterns }
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Variant {
+                    adt_def,
+                    substs,
+                    variant_index: destructured.variant,
+                    subpatterns: field_pats(destructured.fields),
+                }
             }
-            ty::Adt(adt_def, _) => {
-                let struct_var = adt_def.non_enum_variant();
-                PatKind::Leaf { subpatterns: adt_subpatterns(struct_var.fields.len(), None) }
+            ty::Adt(_, _) => {
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
             }
-            ty::Tuple(fields) => PatKind::Leaf { subpatterns: adt_subpatterns(fields.len(), None) },
-            ty::Array(_, n) => PatKind::Array {
-                prefix: (0..n.eval_usize(tcx, self.param_env))
-                    .map(|i| adt_subpattern(i as usize, None))
+            ty::Tuple(_) => {
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
+            }
+            ty::Array(..) => PatKind::Array {
+                prefix: tcx
+                    .destructure_const(param_env.and(cv))
+                    .fields
+                    .iter()
+                    .map(|val| self.recur(val))
                     .collect(),
                 slice: None,
                 suffix: Vec::new(),
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs
similarity index 85%
rename from src/librustc_mir/hair/pattern/mod.rs
rename to src/librustc_mir_build/hair/pattern/mod.rs
index f5d8ed8..9e00c4e 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/hair/pattern/mod.rs
@@ -9,9 +9,6 @@
 use crate::hair::constant::*;
 use crate::hair::util::UserAnnotatedTyHelpers;
 
-use rustc::hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc::hir::pat_util::EnumerateAndAdjustIterator;
-use rustc::hir::{self, RangeEnd};
 use rustc::mir::interpret::{get_slice_bytes, sign_extend, ConstValue, ErrorHandled};
 use rustc::mir::UserTypeProjection;
 use rustc::mir::{BorrowKind, Field, Mutability};
@@ -19,18 +16,22 @@
 use rustc::ty::subst::{GenericArg, SubstsRef};
 use rustc::ty::{self, AdtDef, DefIdTree, Region, Ty, TyCtxt, UserType};
 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
-
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::pat_util::EnumerateAndAdjustIterator;
+use rustc_hir::RangeEnd;
 use rustc_index::vec::Idx;
-
 use rustc_span::{Span, DUMMY_SP};
+use syntax::ast;
+
 use std::cmp::Ordering;
 use std::fmt;
-use syntax::ast;
 
 use rustc_error_codes::*;
 
 #[derive(Clone, Debug)]
-pub enum PatternError {
+crate enum PatternError {
     AssocConstInPattern(Span),
     StaticInPattern(Span),
     FloatBug,
@@ -38,22 +39,22 @@
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum BindingMode {
+crate enum BindingMode {
     ByValue,
     ByRef(BorrowKind),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldPat<'tcx> {
-    pub field: Field,
-    pub pattern: Pat<'tcx>,
+crate struct FieldPat<'tcx> {
+    crate field: Field,
+    crate pattern: Pat<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Pat<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub span: Span,
-    pub kind: Box<PatKind<'tcx>>,
+crate struct Pat<'tcx> {
+    crate ty: Ty<'tcx>,
+    crate span: Span,
+    crate kind: Box<PatKind<'tcx>>,
 }
 
 impl<'tcx> Pat<'tcx> {
@@ -63,8 +64,8 @@
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct PatTyProj<'tcx> {
-    pub user_ty: CanonicalUserType<'tcx>,
+crate struct PatTyProj<'tcx> {
+    crate user_ty: CanonicalUserType<'tcx>,
 }
 
 impl<'tcx> PatTyProj<'tcx> {
@@ -90,8 +91,8 @@
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct Ascription<'tcx> {
-    pub user_ty: PatTyProj<'tcx>,
+crate struct Ascription<'tcx> {
+    crate user_ty: PatTyProj<'tcx>,
     /// Variance to use when relating the type `user_ty` to the **type of the value being
     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
     /// have a type that is some subtype of the ascribed type.
@@ -110,12 +111,12 @@
     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
     /// of the old type-check for now. See #57280 for details.
-    pub variance: ty::Variance,
-    pub user_ty_span: Span,
+    crate variance: ty::Variance,
+    crate user_ty_span: Span,
 }
 
 #[derive(Clone, Debug)]
-pub enum PatKind<'tcx> {
+crate enum PatKind<'tcx> {
     Wild,
 
     AscribeUserType {
@@ -183,10 +184,10 @@
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct PatRange<'tcx> {
-    pub lo: &'tcx ty::Const<'tcx>,
-    pub hi: &'tcx ty::Const<'tcx>,
-    pub end: RangeEnd,
+crate struct PatRange<'tcx> {
+    crate lo: &'tcx ty::Const<'tcx>,
+    crate hi: &'tcx ty::Const<'tcx>,
+    crate end: RangeEnd,
 }
 
 impl<'tcx> fmt::Display for Pat<'tcx> {
@@ -341,23 +342,22 @@
     }
 }
 
-pub struct PatCtxt<'a, 'tcx> {
-    pub tcx: TyCtxt<'tcx>,
-    pub param_env: ty::ParamEnv<'tcx>,
-    pub tables: &'a ty::TypeckTables<'tcx>,
-    pub substs: SubstsRef<'tcx>,
-    pub errors: Vec<PatternError>,
+crate struct PatCtxt<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
+    crate param_env: ty::ParamEnv<'tcx>,
+    crate tables: &'a ty::TypeckTables<'tcx>,
+    crate errors: Vec<PatternError>,
     include_lint_checks: bool,
 }
 
 impl<'a, 'tcx> Pat<'tcx> {
-    pub fn from_hir(
+    crate fn from_hir(
         tcx: TyCtxt<'tcx>,
-        param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
         tables: &'a ty::TypeckTables<'tcx>,
         pat: &'tcx hir::Pat<'tcx>,
     ) -> Self {
-        let mut pcx = PatCtxt::new(tcx, param_env_and_substs, tables);
+        let mut pcx = PatCtxt::new(tcx, param_env, tables);
         let result = pcx.lower_pattern(pat);
         if !pcx.errors.is_empty() {
             let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
@@ -369,27 +369,20 @@
 }
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
-    pub fn new(
+    crate fn new(
         tcx: TyCtxt<'tcx>,
-        param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
         tables: &'a ty::TypeckTables<'tcx>,
     ) -> Self {
-        PatCtxt {
-            tcx,
-            param_env: param_env_and_substs.param_env,
-            tables,
-            substs: param_env_and_substs.value,
-            errors: vec![],
-            include_lint_checks: false,
-        }
+        PatCtxt { tcx, param_env, tables, errors: vec![], include_lint_checks: false }
     }
 
-    pub fn include_lint_checks(&mut self) -> &mut Self {
+    crate fn include_lint_checks(&mut self) -> &mut Self {
         self.include_lint_checks = true;
         self
     }
 
-    pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+    crate fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
         // pattern has the type that results *after* dereferencing. For example, in this code:
         //
@@ -428,14 +421,87 @@
         expr: &'tcx hir::Expr<'tcx>,
     ) -> (PatKind<'tcx>, Option<Ascription<'tcx>>) {
         match self.lower_lit(expr) {
-            PatKind::AscribeUserType {
-                ascription: lo_ascription,
-                subpattern: Pat { kind: box kind, .. },
-            } => (kind, Some(lo_ascription)),
+            PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => {
+                (kind, Some(ascription))
+            }
             kind => (kind, None),
         }
     }
 
+    fn lower_pattern_range(
+        &mut self,
+        ty: Ty<'tcx>,
+        lo: &'tcx ty::Const<'tcx>,
+        hi: &'tcx ty::Const<'tcx>,
+        end: RangeEnd,
+        span: Span,
+    ) -> PatKind<'tcx> {
+        assert_eq!(lo.ty, ty);
+        assert_eq!(hi.ty, ty);
+        let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
+        match (end, cmp) {
+            // `x..y` where `x < y`.
+            // Non-empty because the range includes at least `x`.
+            (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            // `x..y` where `x >= y`. The range is empty => error.
+            (RangeEnd::Excluded, _) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0579,
+                    "lower range bound must be less than upper"
+                )
+                .emit();
+                PatKind::Wild
+            }
+            // `x..=y` where `x == y`.
+            (RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo },
+            // `x..=y` where `x < y`.
+            (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            // `x..=y` where `x > y` hence the range is empty => error.
+            (RangeEnd::Included, _) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0030,
+                    "lower range bound must be less than or equal to upper"
+                );
+                err.span_label(span, "lower bound larger than upper bound");
+                if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                    err.note(
+                        "When matching against a range, the compiler \
+                              verifies that the range is non-empty. Range \
+                              patterns include both end-points, so this is \
+                              equivalent to requiring the start of the range \
+                              to be less than or equal to the end of the range.",
+                    );
+                }
+                err.emit();
+                PatKind::Wild
+            }
+        }
+    }
+
+    fn normalize_range_pattern_ends(
+        &self,
+        ty: Ty<'tcx>,
+        lo: Option<&PatKind<'tcx>>,
+        hi: Option<&PatKind<'tcx>>,
+    ) -> Option<(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>)> {
+        match (lo, hi) {
+            (Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => {
+                Some((lo, hi))
+            }
+            (Some(PatKind::Constant { value: lo }), None) => {
+                Some((lo, ty.numeric_max_val(self.tcx)?))
+            }
+            (None, Some(PatKind::Constant { value: hi })) => {
+                Some((ty.numeric_min_val(self.tcx)?, hi))
+            }
+            _ => None,
+        }
+    }
+
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         let mut ty = self.tables.node_type(pat.hir_id);
 
@@ -450,64 +516,20 @@
             hir::PatKind::Lit(ref value) => self.lower_lit(value),
 
             hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
-                let (lo, lo_ascription) = self.lower_range_expr(lo_expr);
-                let (hi, hi_ascription) = self.lower_range_expr(hi_expr);
+                let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
+                let lo_span = lo_expr.map_or(pat.span, |e| e.span);
+                let lo = lo_expr.map(|e| self.lower_range_expr(e));
+                let hi = hi_expr.map(|e| self.lower_range_expr(e));
 
-                let mut kind = match (lo, hi) {
-                    (PatKind::Constant { value: lo }, PatKind::Constant { value: hi }) => {
-                        assert_eq!(lo.ty, ty);
-                        assert_eq!(hi.ty, ty);
-                        let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
-                        match (end, cmp) {
-                            (RangeEnd::Excluded, Some(Ordering::Less)) => {
-                                PatKind::Range(PatRange { lo, hi, end })
-                            }
-                            (RangeEnd::Excluded, _) => {
-                                span_err!(
-                                    self.tcx.sess,
-                                    lo_expr.span,
-                                    E0579,
-                                    "lower range bound must be less than upper",
-                                );
-                                PatKind::Wild
-                            }
-                            (RangeEnd::Included, Some(Ordering::Equal)) => {
-                                PatKind::Constant { value: lo }
-                            }
-                            (RangeEnd::Included, Some(Ordering::Less)) => {
-                                PatKind::Range(PatRange { lo, hi, end })
-                            }
-                            (RangeEnd::Included, _) => {
-                                let mut err = struct_span_err!(
-                                    self.tcx.sess,
-                                    lo_expr.span,
-                                    E0030,
-                                    "lower range bound must be less than or equal to upper"
-                                );
-                                err.span_label(lo_expr.span, "lower bound larger than upper bound");
-                                if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                                    err.note(
-                                        "When matching against a range, the compiler \
-                                              verifies that the range is non-empty. Range \
-                                              patterns include both end-points, so this is \
-                                              equivalent to requiring the start of the range \
-                                              to be less than or equal to the end of the range.",
-                                    );
-                                }
-                                err.emit();
-                                PatKind::Wild
-                            }
-                        }
-                    }
-                    ref pats => {
-                        self.tcx.sess.delay_span_bug(
-                            pat.span,
-                            &format!(
-                                "found bad range pattern `{:?}` outside of error recovery",
-                                pats,
-                            ),
+                let (lp, hp) = (lo.as_ref().map(|x| &x.0), hi.as_ref().map(|x| &x.0));
+                let mut kind = match self.normalize_range_pattern_ends(ty, lp, hp) {
+                    Some((lc, hc)) => self.lower_pattern_range(ty, lc, hc, end, lo_span),
+                    None => {
+                        let msg = &format!(
+                            "found bad range pattern `{:?}` outside of error recovery",
+                            (&lo, &hi),
                         );
-
+                        self.tcx.sess.delay_span_bug(pat.span, msg);
                         PatKind::Wild
                     }
                 };
@@ -515,12 +537,10 @@
                 // If we are handling a range with associated constants (e.g.
                 // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
                 // constants somewhere. Have them on the range pattern.
-                for ascription in &[lo_ascription, hi_ascription] {
-                    if let Some(ascription) = ascription {
-                        kind = PatKind::AscribeUserType {
-                            ascription: *ascription,
-                            subpattern: Pat { span: pat.span, ty, kind: Box::new(kind) },
-                        };
+                for end in &[lo, hi] {
+                    if let Some((_, Some(ascription))) = end {
+                        let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
+                        kind = PatKind::AscribeUserType { ascription: *ascription, subpattern };
                     }
                 }
 
@@ -747,6 +767,7 @@
                     self.param_env.with_reveal_all(),
                     def_id,
                     substs,
+                    None,
                     Some(span),
                 ) {
                     Ok(value) => {
@@ -814,7 +835,7 @@
                 }
             }
             hir::ExprKind::Path(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind,
-            hir::ExprKind::Unary(hir::UnNeg, ref expr) => {
+            hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => {
                 let ty = self.tables.expr_ty(expr);
                 let lit = match expr.kind {
                     hir::ExprKind::Lit(ref lit) => lit,
@@ -834,7 +855,7 @@
     }
 }
 
-impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
+impl<'tcx> UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -844,7 +865,7 @@
     }
 }
 
-pub trait PatternFoldable<'tcx>: Sized {
+crate trait PatternFoldable<'tcx>: Sized {
     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.super_fold_with(folder)
     }
@@ -852,7 +873,7 @@
     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
 }
 
-pub trait PatternFolder<'tcx>: Sized {
+crate trait PatternFolder<'tcx>: Sized {
     fn fold_pattern(&mut self, pattern: &Pat<'tcx>) -> Pat<'tcx> {
         pattern.super_fold_with(self)
     }
@@ -980,7 +1001,7 @@
     }
 }
 
-pub fn compare_const_vals<'tcx>(
+crate fn compare_const_vals<'tcx>(
     tcx: TyCtxt<'tcx>,
     a: &'tcx ty::Const<'tcx>,
     b: &'tcx ty::Const<'tcx>,
diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir_build/hair/util.rs
similarity index 97%
rename from src/librustc_mir/hair/util.rs
rename to src/librustc_mir_build/hair/util.rs
index 53880b0..c27844e 100644
--- a/src/librustc_mir/hair/util.rs
+++ b/src/librustc_mir_build/hair/util.rs
@@ -1,5 +1,5 @@
-use rustc::hir;
 use rustc::ty::{self, CanonicalUserType, TyCtxt, UserType};
+use rustc_hir as hir;
 
 crate trait UserAnnotatedTyHelpers<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx>;
diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs
new file mode 100644
index 0000000..96032a7
--- /dev/null
+++ b/src/librustc_mir_build/lib.rs
@@ -0,0 +1,26 @@
+//! Construction of MIR from HIR.
+//!
+//! This crate also contains the match exhaustiveness and usefulness checking.
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
+#![feature(slice_patterns)]
+#![feature(bool_to_option)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate rustc;
+
+mod build;
+mod hair;
+mod lints;
+
+use rustc::ty::query::Providers;
+
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.check_match = hair::pattern::check_match;
+    providers.mir_built = build::mir_built;
+}
diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir_build/lints.rs
similarity index 96%
rename from src/librustc_mir/lints.rs
rename to src/librustc_mir_build/lints.rs
index 910286f..4244e1b 100644
--- a/src/librustc_mir/lints.rs
+++ b/src/librustc_mir_build/lints.rs
@@ -1,13 +1,13 @@
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::FnKind;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc::mir::{self, Body, TerminatorKind};
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt};
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::FnKind;
 use rustc_index::bit_set::BitSet;
 
-pub fn check(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
+crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
@@ -15,7 +15,7 @@
     }
 }
 
-fn check_fn_for_unconditional_recursion(
+fn check_fn_for_unconditional_recursion<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_kind: FnKind<'_>,
     body: &Body<'tcx>,
diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml
deleted file mode 100644
index bda4078..0000000
--- a/src/librustc_msan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_msan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_msan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
deleted file mode 100644
index dc08d51..0000000
--- a/src/librustc_msan/build.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("msan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_msan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml
index d41d899..aa159c5 100644
--- a/src/librustc_parse/Cargo.toml
+++ b/src/librustc_parse/Cargo.toml
@@ -18,6 +18,7 @@
 rustc_errors = { path = "../librustc_errors" }
 rustc_error_codes = { path = "../librustc_error_codes" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 syntax = { path = "../libsyntax" }
 unicode-normalization = "0.1.11"
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index f2ffd94..8467acc 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -9,18 +9,22 @@
 //! [#64197]: https://github.com/rust-lang/rust/issues/64197
 
 use crate::{parse_in, validate_attr};
-use rustc_errors::Applicability;
-use rustc_feature::Features;
-use rustc_span::edition::Edition;
-use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_error_codes::*;
+use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
+use rustc_feature::{Feature, Features, State as FeatureState};
+use rustc_feature::{
+    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
+};
+use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, AttrItem, Attribute, MetaItem};
 use syntax::attr;
 use syntax::attr::HasAttrs;
-use syntax::feature_gate::{feature_err, get_features};
 use syntax::mut_visit::*;
 use syntax::ptr::P;
-use syntax::sess::ParseSess;
+use syntax::sess::{feature_err, ParseSess};
 use syntax::util::map_in_place::MapInPlace;
 
 use smallvec::SmallVec;
@@ -31,6 +35,172 @@
     pub features: Option<&'a Features>,
 }
 
+fn get_features(
+    span_handler: &Handler,
+    krate_attrs: &[ast::Attribute],
+    crate_edition: Edition,
+    allow_features: &Option<Vec<String>>,
+) -> Features {
+    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
+        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
+        err.span_label(span, "feature has been removed");
+        if let Some(reason) = reason {
+            err.note(reason);
+        }
+        err.emit();
+    }
+
+    fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
+        ACTIVE_FEATURES.iter().filter(move |feature| {
+            if let Some(feature_edition) = feature.edition {
+                feature_edition <= edition
+            } else {
+                false
+            }
+        })
+    }
+
+    let mut features = Features::default();
+    let mut edition_enabled_features = FxHashMap::default();
+
+    for &edition in ALL_EDITIONS {
+        if edition <= crate_edition {
+            // The `crate_edition` implies its respective umbrella feature-gate
+            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
+            edition_enabled_features.insert(edition.feature_name(), edition);
+        }
+    }
+
+    for feature in active_features_up_to(crate_edition) {
+        feature.set(&mut features, DUMMY_SP);
+        edition_enabled_features.insert(feature.name, crate_edition);
+    }
+
+    // Process the edition umbrella feature-gates first, to ensure
+    // `edition_enabled_features` is completed before it's queried.
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        for mi in list {
+            if !mi.is_word() {
+                continue;
+            }
+
+            let name = mi.name_or_empty();
+
+            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
+            if let Some(edition) = edition {
+                if edition <= crate_edition {
+                    continue;
+                }
+
+                for feature in active_features_up_to(edition) {
+                    // FIXME(Manishearth) there is currently no way to set
+                    // lib features by edition
+                    feature.set(&mut features, DUMMY_SP);
+                    edition_enabled_features.insert(feature.name, edition);
+                }
+            }
+        }
+    }
+
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        let bad_input = |span| {
+            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
+        };
+
+        for mi in list {
+            let name = match mi.ident() {
+                Some(ident) if mi.is_word() => ident.name,
+                Some(ident) => {
+                    bad_input(mi.span())
+                        .span_suggestion(
+                            mi.span(),
+                            "expected just one word",
+                            format!("{}", ident.name),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    continue;
+                }
+                None => {
+                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
+                    continue;
+                }
+            };
+
+            if let Some(edition) = edition_enabled_features.get(&name) {
+                let msg =
+                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
+                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
+                continue;
+            }
+
+            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
+                // Handled in the separate loop above.
+                continue;
+            }
+
+            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
+            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
+            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
+                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
+                    state
+                {
+                    feature_removed(span_handler, mi.span(), *reason);
+                    continue;
+                }
+            }
+
+            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
+                let since = Some(Symbol::intern(since));
+                features.declared_lang_features.push((name, mi.span(), since));
+                continue;
+            }
+
+            if let Some(allowed) = allow_features.as_ref() {
+                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
+                    struct_span_err!(
+                        span_handler,
+                        mi.span(),
+                        E0725,
+                        "the feature `{}` is not in the list of allowed features",
+                        name
+                    )
+                    .emit();
+                    continue;
+                }
+            }
+
+            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
+                f.set(&mut features, mi.span());
+                features.declared_lang_features.push((name, mi.span(), None));
+                continue;
+            }
+
+            features.declared_lib_features.push((name, mi.span()));
+        }
+    }
+
+    features
+}
+
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
 pub fn features(
     mut krate: ast::Crate,
diff --git a/src/librustc_parse/lexer/unescape_error_reporting.rs b/src/librustc_parse/lexer/unescape_error_reporting.rs
index 151c63a..88762da 100644
--- a/src/librustc_parse/lexer/unescape_error_reporting.rs
+++ b/src/librustc_parse/lexer/unescape_error_reporting.rs
@@ -3,11 +3,10 @@
 use std::iter::once;
 use std::ops::Range;
 
+use rustc_errors::{Applicability, Handler};
 use rustc_lexer::unescape::{EscapeError, Mode};
 use rustc_span::{BytePos, Span};
 
-use syntax::errors::{Applicability, Handler};
-
 pub(crate) fn emit_unescape_error(
     handler: &Handler,
     // interior part of the literal, without quotes
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 94785e9..6a18c63 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -2,7 +2,9 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_error_codes::*;
-use rustc_errors::{self, pluralize, Applicability, DiagnosticBuilder, Handler, PResult};
+use rustc_errors::{pluralize, struct_span_err};
+use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult};
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
 use syntax::ast::{
@@ -11,7 +13,6 @@
 use syntax::ast::{AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token::{self, token_can_begin_expr, TokenKind};
 use syntax::util::parser::AssocOp;
 
@@ -51,7 +52,6 @@
         secondary_path: String,
     },
     UselessDocComment,
-    InclusiveRangeWithNoEnd,
 }
 
 impl Error {
@@ -102,11 +102,6 @@
                 );
                 err
             }
-            Error::InclusiveRangeWithNoEnd => {
-                let mut err = struct_span_err!(handler, sp, E0586, "inclusive range with no end",);
-                err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
-                err
-            }
         }
     }
 }
@@ -265,10 +260,7 @@
             };
             (
                 format!("expected one of {}, found {}", expect, actual),
-                (
-                    self.sess.source_map().next_point(self.prev_span),
-                    format!("expected one of {}", short_expect),
-                ),
+                (self.prev_span.shrink_to_hi(), format!("expected one of {}", short_expect)),
             )
         } else if expected.is_empty() {
             (
@@ -278,7 +270,7 @@
         } else {
             (
                 format!("expected {}, found {}", expect, actual),
-                (self.sess.source_map().next_point(self.prev_span), format!("expected {}", expect)),
+                (self.prev_span.shrink_to_hi(), format!("expected {}", expect)),
             )
         };
         self.last_unexpected_token_span = Some(self.token.span);
@@ -500,6 +492,58 @@
         }
     }
 
+    /// Check to see if a pair of chained operators looks like an attempt at chained comparison,
+    /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
+    /// parenthesising the leftmost comparison.
+    fn attempt_chained_comparison_suggestion(
+        &mut self,
+        err: &mut DiagnosticBuilder<'_>,
+        inner_op: &Expr,
+        outer_op: &Spanned<AssocOp>,
+    ) {
+        if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
+            match (op.node, &outer_op.node) {
+                // `x < y < z` and friends.
+                (BinOpKind::Lt, AssocOp::Less) | (BinOpKind::Lt, AssocOp::LessEqual) |
+                (BinOpKind::Le, AssocOp::LessEqual) | (BinOpKind::Le, AssocOp::Less) |
+                // `x > y > z` and friends.
+                (BinOpKind::Gt, AssocOp::Greater) | (BinOpKind::Gt, AssocOp::GreaterEqual) |
+                (BinOpKind::Ge, AssocOp::GreaterEqual) | (BinOpKind::Ge, AssocOp::Greater) => {
+                    let expr_to_str = |e: &Expr| {
+                        self.span_to_snippet(e.span)
+                            .unwrap_or_else(|_| pprust::expr_to_string(&e))
+                    };
+                    err.span_suggestion(
+                        inner_op.span.to(outer_op.span),
+                        "split the comparison into two...",
+                        format!(
+                            "{} {} {} && {} {}",
+                            expr_to_str(&l1),
+                            op.node.to_string(),
+                            expr_to_str(&r1),
+                            expr_to_str(&r1),
+                            outer_op.node.to_ast_binop().unwrap().to_string(),
+                        ),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.span_suggestion(
+                        inner_op.span.to(outer_op.span),
+                        "...or parenthesize one of the comparisons",
+                        format!(
+                            "({} {} {}) {}",
+                            expr_to_str(&l1),
+                            op.node.to_string(),
+                            expr_to_str(&r1),
+                            outer_op.node.to_ast_binop().unwrap().to_string(),
+                        ),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                _ => {}
+            }
+        }
+    }
+
     /// Produces an error if comparison operators are chained (RFC #558).
     /// We only need to check the LHS, not the RHS, because all comparison ops have same
     /// precedence (see `fn precedence`) and are left-associative (see `fn fixity`).
@@ -515,27 +559,31 @@
     ///           /   \
     ///     inner_op   r2
     ///        /  \
-    ///     l1    r1
+    ///      l1    r1
     pub(super) fn check_no_chained_comparison(
         &mut self,
-        lhs: &Expr,
-        outer_op: &AssocOp,
+        inner_op: &Expr,
+        outer_op: &Spanned<AssocOp>,
     ) -> PResult<'a, Option<P<Expr>>> {
         debug_assert!(
-            outer_op.is_comparison(),
+            outer_op.node.is_comparison(),
             "check_no_chained_comparison: {:?} is not comparison",
-            outer_op,
+            outer_op.node,
         );
 
         let mk_err_expr =
             |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new())));
 
-        match lhs.kind {
+        match inner_op.kind {
             ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
                 // Respan to include both operators.
                 let op_span = op.span.to(self.prev_span);
-                let mut err = self
-                    .struct_span_err(op_span, "chained comparison operators require parentheses");
+                let mut err =
+                    self.struct_span_err(op_span, "comparison operators cannot be chained");
+
+                // If it looks like a genuine attempt to chain operators (as opposed to a
+                // misformatted turbofish, for instance), suggest a correct form.
+                self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
 
                 let suggest = |err: &mut DiagnosticBuilder<'_>| {
                     err.span_suggestion_verbose(
@@ -547,12 +595,12 @@
                 };
 
                 if op.node == BinOpKind::Lt &&
-                    *outer_op == AssocOp::Less ||  // Include `<` to provide this recommendation
-                    *outer_op == AssocOp::Greater
+                    outer_op.node == AssocOp::Less ||  // Include `<` to provide this recommendation
+                    outer_op.node == AssocOp::Greater
                 // even in a case like the following:
                 {
                     //     Foo<Bar<Baz<Qux, ()>>>
-                    if *outer_op == AssocOp::Less {
+                    if outer_op.node == AssocOp::Less {
                         let snapshot = self.clone();
                         self.bump();
                         // So far we have parsed `foo<bar<`, consume the rest of the type args.
@@ -584,7 +632,7 @@
                                 // FIXME: actually check that the two expressions in the binop are
                                 // paths and resynthesize new fn call expression instead of using
                                 // `ExprKind::Err` placeholder.
-                                mk_err_expr(self, lhs.span.to(self.prev_span))
+                                mk_err_expr(self, inner_op.span.to(self.prev_span))
                             }
                             Err(mut expr_err) => {
                                 expr_err.cancel();
@@ -606,7 +654,7 @@
                                 // FIXME: actually check that the two expressions in the binop are
                                 // paths and resynthesize new fn call expression instead of using
                                 // `ExprKind::Err` placeholder.
-                                mk_err_expr(self, lhs.span.to(self.prev_span))
+                                mk_err_expr(self, inner_op.span.to(self.prev_span))
                             }
                         }
                     } else {
@@ -809,7 +857,7 @@
             _ if self.prev_span == DUMMY_SP => (self.token.span, self.token.span),
             // EOF, don't want to point at the following char, but rather the last token.
             (token::Eof, None) => (self.prev_span, self.token.span),
-            _ => (self.sess.source_map().next_point(self.prev_span), self.token.span),
+            _ => (self.prev_span.shrink_to_hi(), self.token.span),
         };
         let msg = format!(
             "expected `{}`, found {}",
@@ -1132,7 +1180,7 @@
                     err.span_label(sp, "unclosed delimiter");
                 }
                 err.span_suggestion_short(
-                    self.sess.source_map().next_point(self.prev_span),
+                    self.prev_span.shrink_to_hi(),
                     &format!("{} may belong here", delim.to_string()),
                     delim.to_string(),
                     Applicability::MaybeIncorrect,
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 90f1537..098c835 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -1,11 +1,10 @@
-use super::diagnostics::Error;
 use super::pat::{GateOr, PARAM_EXPECTED};
 use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
 use rustc_errors::{Applicability, PResult};
-use rustc_span::source_map::{self, Span};
+use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::mem;
 use syntax::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, DUMMY_NODE_ID};
@@ -181,17 +180,17 @@
             };
 
             let cur_op_span = self.token.span;
-            let restrictions = if op.is_assign_like() {
+            let restrictions = if op.node.is_assign_like() {
                 self.restrictions & Restrictions::NO_STRUCT_LITERAL
             } else {
                 self.restrictions
             };
-            let prec = op.precedence();
+            let prec = op.node.precedence();
             if prec < min_prec {
                 break;
             }
             // Check for deprecated `...` syntax
-            if self.token == token::DotDotDot && op == AssocOp::DotDotEq {
+            if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq {
                 self.err_dotdotdot_syntax(self.token.span);
             }
 
@@ -200,11 +199,12 @@
             }
 
             self.bump();
-            if op.is_comparison() {
+            if op.node.is_comparison() {
                 if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? {
                     return Ok(expr);
                 }
             }
+            let op = op.node;
             // Special cases:
             if op == AssocOp::As {
                 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
@@ -298,7 +298,7 @@
     }
 
     fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
-        match (self.expr_is_complete(lhs), self.check_assoc_op()) {
+        match (self.expr_is_complete(lhs), self.check_assoc_op().map(|op| op.node)) {
             // Semi-statement forms are odd:
             // See https://github.com/rust-lang/rust/issues/29071
             (true, None) => false,
@@ -343,19 +343,22 @@
     /// The method does not advance the current token.
     ///
     /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
-    fn check_assoc_op(&self) -> Option<AssocOp> {
-        match (AssocOp::from_token(&self.token), &self.token.kind) {
-            (op @ Some(_), _) => op,
-            (None, token::Ident(sym::and, false)) => {
-                self.error_bad_logical_op("and", "&&", "conjunction");
-                Some(AssocOp::LAnd)
-            }
-            (None, token::Ident(sym::or, false)) => {
-                self.error_bad_logical_op("or", "||", "disjunction");
-                Some(AssocOp::LOr)
-            }
-            _ => None,
-        }
+    fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
+        Some(Spanned {
+            node: match (AssocOp::from_token(&self.token), &self.token.kind) {
+                (Some(op), _) => op,
+                (None, token::Ident(sym::and, false)) => {
+                    self.error_bad_logical_op("and", "&&", "conjunction");
+                    AssocOp::LAnd
+                }
+                (None, token::Ident(sym::or, false)) => {
+                    self.error_bad_logical_op("or", "||", "disjunction");
+                    AssocOp::LOr
+                }
+                _ => return None,
+            },
+            span: self.token.span,
+        })
     }
 
     /// Error on `and` and `or` suggesting `&&` and `||` respectively.
@@ -1646,7 +1649,7 @@
                             //   |      |
                             //   |      parsed until here as `"y" & X`
                             err.span_suggestion_short(
-                                cm.next_point(arm_start_span),
+                                arm_start_span.shrink_to_hi(),
                                 "missing a comma here to end this `match` arm",
                                 ",".to_owned(),
                                 Applicability::MachineApplicable,
@@ -1967,7 +1970,8 @@
         limits: RangeLimits,
     ) -> PResult<'a, ExprKind> {
         if end.is_none() && limits == RangeLimits::Closed {
-            Err(self.span_fatal_err(self.token.span, Error::InclusiveRangeWithNoEnd))
+            self.error_inclusive_range_with_no_end(self.prev_span);
+            Ok(ExprKind::Err)
         } else {
             Ok(ExprKind::Range(start, end, limits))
         }
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index 1b816e2..0755837 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -156,7 +156,7 @@
             self.expect_gt()?;
             (params, span_lo.to(self.prev_span))
         } else {
-            (vec![], self.prev_span.between(self.token.span))
+            (vec![], self.prev_span.shrink_to_hi())
         };
         Ok(ast::Generics {
             params,
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index a05bc48..d4756df 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -4,8 +4,8 @@
 use crate::maybe_whole;
 
 use rustc_error_codes::*;
-use rustc_errors::{Applicability, DiagnosticBuilder, PResult, StashKey};
-use rustc_span::source_map::{self, respan, Span};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey};
+use rustc_span::source_map::{self, respan, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::BytePos;
 use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID};
@@ -16,7 +16,6 @@
 use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token;
 use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree};
 
@@ -141,7 +140,7 @@
                     self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span));
                 }
                 let ext = self.parse_extern()?;
-                self.bump(); // `fn`
+                self.expect_keyword(kw::Fn)?;
 
                 let header = FnHeader {
                     unsafety,
@@ -543,10 +542,11 @@
     ///    impl<'a, T> TYPE { /* impl items */ }
     ///    impl<'a, T> TRAIT for TYPE { /* impl items */ }
     ///    impl<'a, T> !TRAIT for TYPE { /* impl items */ }
+    ///    impl<'a, T> const TRAIT for TYPE { /* impl items */ }
     ///
     /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
-    ///     `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
-    ///     `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
+    ///   `impl` GENERICS `const`? `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
+    ///   `impl` GENERICS `const`? `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
     fn parse_item_impl(
         &mut self,
         unsafety: Unsafety,
@@ -556,7 +556,19 @@
         let mut generics = if self.choose_generics_over_qpath() {
             self.parse_generics()?
         } else {
-            Generics::default()
+            let mut generics = Generics::default();
+            // impl A for B {}
+            //    /\ this is where `generics.span` should point when there are no type params.
+            generics.span = self.prev_span.shrink_to_hi();
+            generics
+        };
+
+        let constness = if self.eat_keyword(kw::Const) {
+            let span = self.prev_span;
+            self.sess.gated_spans.gate(sym::const_trait_impl, span);
+            Some(respan(span, Constness::Const))
+        } else {
+            None
         };
 
         // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
@@ -619,7 +631,8 @@
                         err_path(ty_first.span)
                     }
                 };
-                let trait_ref = TraitRef { path, ref_id: ty_first.id };
+                let constness = constness.map(|c| c.node);
+                let trait_ref = TraitRef { path, constness, ref_id: ty_first.id };
 
                 ItemKind::Impl(
                     unsafety,
@@ -632,6 +645,13 @@
                 )
             }
             None => {
+                // Reject `impl const Type {}` here
+                if let Some(Spanned { node: Constness::Const, span }) = constness {
+                    self.struct_span_err(span, "`const` cannot modify an inherent impl")
+                        .help("only a trait impl can be `const`")
+                        .emit();
+                }
+
                 // impl Type
                 ItemKind::Impl(
                     unsafety,
@@ -1490,7 +1510,7 @@
                 }
             }
             _ => {
-                let sp = self.sess.source_map().next_point(self.prev_span);
+                let sp = self.prev_span.shrink_to_hi();
                 let mut err = self.struct_span_err(
                     sp,
                     &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)),
@@ -1629,7 +1649,7 @@
             // it's safe to peel off one character only when it has the close delim
             self.prev_span.with_lo(self.prev_span.hi() - BytePos(1))
         } else {
-            self.sess.source_map().next_point(self.prev_span)
+            self.prev_span.shrink_to_hi()
         };
 
         self.struct_span_err(
@@ -1645,7 +1665,7 @@
             Applicability::MaybeIncorrect,
         )
         .span_suggestion(
-            self.sess.source_map().next_point(self.prev_span),
+            self.prev_span.shrink_to_hi(),
             "add a semicolon",
             ';'.to_string(),
             Applicability::MaybeIncorrect,
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index a2fa335..1368230 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -2,6 +2,7 @@
 mod expr;
 mod item;
 mod module;
+pub use module::{ModulePath, ModulePathSuccess};
 mod pat;
 mod path;
 mod ty;
@@ -15,7 +16,7 @@
 use crate::{Directory, DirectoryOwnership};
 
 use log::debug;
-use rustc_errors::{Applicability, DiagnosticBuilder, FatalError, PResult};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
@@ -24,7 +25,6 @@
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::sess::ParseSess;
-use syntax::struct_span_err;
 use syntax::token::{self, DelimToken, Token, TokenKind};
 use syntax::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndJoint};
 use syntax::util::comments::{doc_comment_style, strip_doc_comment_decoration};
@@ -118,7 +118,8 @@
     /// Used to determine the path to externally loaded source files.
     pub(super) directory: Directory<'a>,
     /// `true` to parse sub-modules in other files.
-    pub(super) recurse_into_file_modules: bool,
+    // Public for rustfmt usage.
+    pub recurse_into_file_modules: bool,
     /// Name of the root module this parser originated from. If `None`, then the
     /// name is not known. This does not change while the parser is descending
     /// into modules, and sub-parsers have new values for this name.
@@ -127,7 +128,8 @@
     token_cursor: TokenCursor,
     desugar_doc_comments: bool,
     /// `true` we should configure out of line modules as we parse.
-    cfg_mods: bool,
+    // Public for rustfmt usage.
+    pub cfg_mods: bool,
     /// This field is used to keep track of how many left angle brackets we have seen. This is
     /// required in order to detect extra leading left angle brackets (`<` characters) and error
     /// appropriately.
@@ -484,7 +486,8 @@
         }
     }
 
-    fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
+    // Public for rustfmt usage.
+    pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
         self.parse_ident_common(true)
     }
 
@@ -541,7 +544,8 @@
 
     /// If the next token is the given keyword, eats it and returns `true`.
     /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
-    fn eat_keyword(&mut self, kw: Symbol) -> bool {
+    // Public for rustfmt usage.
+    pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
         if self.check_keyword(kw) {
             self.bump();
             true
@@ -766,7 +770,7 @@
                             break;
                         }
                         Err(mut expect_err) => {
-                            let sp = self.sess.source_map().next_point(self.prev_span);
+                            let sp = self.prev_span.shrink_to_hi();
                             let token_str = pprust::token_kind_to_string(t);
 
                             // Attempt to keep parsing if it was a similar separator.
diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs
index 3254ab5..6ce94d3 100644
--- a/src/librustc_parse/parser/module.rs
+++ b/src/librustc_parse/parser/module.rs
@@ -14,13 +14,15 @@
 use std::path::{self, Path, PathBuf};
 
 /// Information about the path to a module.
-pub(super) struct ModulePath {
+// Public for rustfmt usage.
+pub struct ModulePath {
     name: String,
     path_exists: bool,
     pub result: Result<ModulePathSuccess, Error>,
 }
 
-pub(super) struct ModulePathSuccess {
+// Public for rustfmt usage.
+pub struct ModulePathSuccess {
     pub path: PathBuf,
     pub directory_ownership: DirectoryOwnership,
 }
@@ -177,7 +179,8 @@
         }
     }
 
-    pub(super) fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
+    // Public for rustfmt usage.
+    pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
         if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) {
             let s = s.as_str();
 
@@ -194,7 +197,8 @@
     }
 
     /// Returns a path to a module.
-    pub(super) fn default_submod_path(
+    // Public for rustfmt usage.
+    pub fn default_submod_path(
         id: ast::Ident,
         relative: Option<ast::Ident>,
         dir_path: &Path,
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index bf7f573..0c2cfc2 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,6 +1,6 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{respan, Span, Spanned};
 use rustc_span::symbol::{kw, sym};
 use syntax::ast::{self, AttrVec, Attribute, FieldPat, Mac, Pat, PatKind, RangeEnd, RangeSyntax};
@@ -281,91 +281,73 @@
         maybe_whole!(self, NtPat, |x| x);
 
         let lo = self.token.span;
-        let pat = match self.token.kind {
-            token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?,
-            token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?,
-            token::OpenDelim(token::Bracket) => {
-                // Parse `[pat, pat,...]` as a slice pattern.
-                let (pats, _) =
-                    self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?;
-                PatKind::Slice(pats)
+
+        let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd {
+            self.parse_pat_deref(expected)?
+        } else if self.check(&token::OpenDelim(token::Paren)) {
+            self.parse_pat_tuple_or_parens()?
+        } else if self.check(&token::OpenDelim(token::Bracket)) {
+            // Parse `[pat, pat,...]` as a slice pattern.
+            let (pats, _) =
+                self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?;
+            PatKind::Slice(pats)
+        } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
+            // A rest pattern `..`.
+            self.bump(); // `..`
+            PatKind::Rest
+        } else if let Some(form) = self.parse_range_end() {
+            self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
+        } else if self.eat_keyword(kw::Underscore) {
+            // Parse _
+            PatKind::Wild
+        } else if self.eat_keyword(kw::Mut) {
+            self.parse_pat_ident_mut()?
+        } else if self.eat_keyword(kw::Ref) {
+            // Parse ref ident @ pat / ref mut ident @ pat
+            let mutbl = self.parse_mutability();
+            self.parse_pat_ident(BindingMode::ByRef(mutbl))?
+        } else if self.eat_keyword(kw::Box) {
+            // Parse `box pat`
+            let pat = self.parse_pat_with_range_pat(false, None)?;
+            self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
+            PatKind::Box(pat)
+        } else if self.can_be_ident_pat() {
+            // Parse `ident @ pat`
+            // This can give false positives and parse nullary enums,
+            // they are dealt with later in resolve.
+            self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
+        } else if self.is_start_of_pat_with_path() {
+            // Parse pattern starting with a path
+            let (qself, path) = if self.eat_lt() {
+                // Parse a qualified path
+                let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
+                (Some(qself), path)
+            } else {
+                // Parse an unqualified path
+                (None, self.parse_path(PathStyle::Expr)?)
+            };
+            let span = lo.to(self.prev_span);
+
+            if qself.is_none() && self.check(&token::Not) {
+                self.parse_pat_mac_invoc(path)?
+            } else if let Some(form) = self.parse_range_end() {
+                let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new());
+                self.parse_pat_range_begin_with(begin, form)?
+            } else if self.check(&token::OpenDelim(token::Brace)) {
+                self.parse_pat_struct(qself, path)?
+            } else if self.check(&token::OpenDelim(token::Paren)) {
+                self.parse_pat_tuple_struct(qself, path)?
+            } else {
+                PatKind::Path(qself, path)
             }
-            token::DotDot => {
-                self.bump();
-                if self.is_pat_range_end_start() {
-                    // Parse `..42` for recovery.
-                    self.parse_pat_range_to(RangeEnd::Excluded, "..")?
-                } else {
-                    // A rest pattern `..`.
-                    PatKind::Rest
-                }
-            }
-            token::DotDotEq => {
-                // Parse `..=42` for recovery.
-                self.bump();
-                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?
-            }
-            token::DotDotDot => {
-                // Parse `...42` for recovery.
-                self.bump();
-                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?
-            }
-            // At this point, token != `&`, `&&`, `(`, `[`, `..`, `..=`, or `...`.
-            _ => {
-                if self.eat_keyword(kw::Underscore) {
-                    // Parse _
-                    PatKind::Wild
-                } else if self.eat_keyword(kw::Mut) {
-                    self.parse_pat_ident_mut()?
-                } else if self.eat_keyword(kw::Ref) {
-                    // Parse ref ident @ pat / ref mut ident @ pat
-                    let mutbl = self.parse_mutability();
-                    self.parse_pat_ident(BindingMode::ByRef(mutbl))?
-                } else if self.eat_keyword(kw::Box) {
-                    // Parse `box pat`
-                    let pat = self.parse_pat_with_range_pat(false, None)?;
-                    self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
-                    PatKind::Box(pat)
-                } else if self.can_be_ident_pat() {
-                    // Parse `ident @ pat`
-                    // This can give false positives and parse nullary enums,
-                    // they are dealt with later in resolve.
-                    self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
-                } else if self.is_start_of_pat_with_path() {
-                    // Parse pattern starting with a path
-                    let (qself, path) = if self.eat_lt() {
-                        // Parse a qualified path
-                        let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
-                        (Some(qself), path)
-                    } else {
-                        // Parse an unqualified path
-                        (None, self.parse_path(PathStyle::Expr)?)
-                    };
-                    match self.token.kind {
-                        token::Not if qself.is_none() => self.parse_pat_mac_invoc(path)?,
-                        token::DotDotDot | token::DotDotEq | token::DotDot => {
-                            self.parse_pat_range_starting_with_path(lo, qself, path)?
-                        }
-                        token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
-                        token::OpenDelim(token::Paren) => {
-                            self.parse_pat_tuple_struct(qself, path)?
-                        }
-                        _ => PatKind::Path(qself, path),
-                    }
-                } else {
-                    // Try to parse everything else as literal with optional minus
-                    match self.parse_literal_maybe_minus() {
-                        Ok(begin)
-                            if self.check(&token::DotDot)
-                                || self.check(&token::DotDotEq)
-                                || self.check(&token::DotDotDot) =>
-                        {
-                            self.parse_pat_range_starting_with_lit(begin)?
-                        }
-                        Ok(begin) => PatKind::Lit(begin),
-                        Err(err) => return self.fatal_unexpected_non_pat(err, expected),
-                    }
-                }
+        } else {
+            // Try to parse everything else as literal with optional minus
+            match self.parse_literal_maybe_minus() {
+                Ok(begin) => match self.parse_range_end() {
+                    Some(form) => self.parse_pat_range_begin_with(begin, form)?,
+                    None => PatKind::Lit(begin),
+                },
+                Err(err) => return self.fatal_unexpected_non_pat(err, expected),
             }
         };
 
@@ -374,7 +356,7 @@
         let pat = self.recover_intersection_pat(pat)?;
 
         if !allow_range_pat {
-            self.ban_pat_range_if_ambiguous(&pat)?
+            self.ban_pat_range_if_ambiguous(&pat)
         }
 
         Ok(pat)
@@ -441,26 +423,25 @@
     }
 
     /// Ban a range pattern if it has an ambiguous interpretation.
-    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> {
+    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) {
         match pat.kind {
             PatKind::Range(
                 ..,
                 Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. },
-            ) => return Ok(()),
+            ) => return,
             PatKind::Range(..) => {}
-            _ => return Ok(()),
+            _ => return,
         }
 
-        let mut err =
-            self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation");
-        err.span_suggestion(
-            pat.span,
-            "add parentheses to clarify the precedence",
-            format!("({})", pprust::pat_to_string(&pat)),
-            // "ambiguous interpretation" implies that we have to be guessing
-            Applicability::MaybeIncorrect,
-        );
-        Err(err)
+        self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation")
+            .span_suggestion(
+                pat.span,
+                "add parentheses to clarify the precedence",
+                format!("({})", pprust::pat_to_string(&pat)),
+                // "ambiguous interpretation" implies that we have to be guessing
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
     }
 
     /// Parse `&pat` / `&mut pat`.
@@ -618,51 +599,6 @@
         Ok(PatKind::Mac(mac))
     }
 
-    fn excluded_range_end(&self, span: Span) -> RangeEnd {
-        self.sess.gated_spans.gate(sym::exclusive_range_pattern, span);
-        RangeEnd::Excluded
-    }
-
-    /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`.
-    /// The `$path` has already been parsed and the next token is the `$form`.
-    fn parse_pat_range_starting_with_path(
-        &mut self,
-        lo: Span,
-        qself: Option<QSelf>,
-        path: Path,
-    ) -> PResult<'a, PatKind> {
-        let (end_kind, form) = match self.token.kind {
-            token::DotDot => (self.excluded_range_end(self.token.span), ".."),
-            token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
-            token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
-            _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"),
-        };
-        let op_span = self.token.span;
-        // Parse range
-        let span = lo.to(self.prev_span);
-        let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new());
-        self.bump();
-        let end = self.parse_pat_range_end_opt(&begin, form)?;
-        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
-    }
-
-    /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`.
-    /// The `$path` has already been parsed and the next token is the `$form`.
-    fn parse_pat_range_starting_with_lit(&mut self, begin: P<Expr>) -> PResult<'a, PatKind> {
-        let op_span = self.token.span;
-        let (end_kind, form) = if self.eat(&token::DotDotDot) {
-            (RangeEnd::Included(RangeSyntax::DotDotDot), "...")
-        } else if self.eat(&token::DotDotEq) {
-            (RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
-        } else if self.eat(&token::DotDot) {
-            (self.excluded_range_end(op_span), "..")
-        } else {
-            panic!("impossible case: we already matched on a range-operator token")
-        };
-        let end = self.parse_pat_range_end_opt(&begin, form)?;
-        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
-    }
-
     fn fatal_unexpected_non_pat(
         &mut self,
         mut err: DiagnosticBuilder<'a>,
@@ -684,57 +620,86 @@
         Err(err)
     }
 
-    /// Is the current token suitable as the start of a range patterns end?
-    fn is_pat_range_end_start(&self) -> bool {
-        self.token.is_path_start() // e.g. `MY_CONST`;
-            || self.token == token::Dot // e.g. `.5` for recovery;
-            || self.token.can_begin_literal_or_bool() // e.g. `42`.
-            || self.token.is_whole_expr()
+    /// Parses the range pattern end form `".." | "..." | "..=" ;`.
+    fn parse_range_end(&mut self) -> Option<Spanned<RangeEnd>> {
+        let re = if self.eat(&token::DotDotDot) {
+            RangeEnd::Included(RangeSyntax::DotDotDot)
+        } else if self.eat(&token::DotDotEq) {
+            RangeEnd::Included(RangeSyntax::DotDotEq)
+        } else if self.eat(&token::DotDot) {
+            self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_span);
+            RangeEnd::Excluded
+        } else {
+            return None;
+        };
+        Some(respan(self.prev_span, re))
     }
 
-    /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
-    fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> {
-        let lo = self.prev_span;
-        let end = self.parse_pat_range_end()?;
-        let range_span = lo.to(end.span);
-        let begin = self.mk_expr(range_span, ExprKind::Err, AttrVec::new());
-
-        self.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
-            .span_suggestion(
-                range_span,
-                "try using the minimum value for the type",
-                format!("MIN{}{}", form, pprust::expr_to_string(&end)),
-                Applicability::HasPlaceholders,
-            )
-            .emit();
-
-        Ok(PatKind::Range(begin, end, respan(lo, re)))
-    }
-
-    /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern  or recover
-    /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
-    fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P<Expr>> {
-        if self.is_pat_range_end_start() {
+    /// Parse a range pattern `$begin $form $end?` where `$form = ".." | "..." | "..=" ;`.
+    /// `$begin $form` has already been parsed.
+    fn parse_pat_range_begin_with(
+        &mut self,
+        begin: P<Expr>,
+        re: Spanned<RangeEnd>,
+    ) -> PResult<'a, PatKind> {
+        let end = if self.is_pat_range_end_start(0) {
             // Parsing e.g. `X..=Y`.
-            self.parse_pat_range_end()
+            Some(self.parse_pat_range_end()?)
         } else {
             // Parsing e.g. `X..`.
-            let range_span = begin.span.to(self.prev_span);
+            self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span));
+            if let RangeEnd::Included(_) = re.node {
+                // FIXME(Centril): Consider semantic errors instead in `ast_validation`.
+                // Possibly also do this for `X..=` in *expression* contexts.
+                self.error_inclusive_range_with_no_end(re.span);
+            }
+            None
+        };
+        Ok(PatKind::Range(Some(begin), end, re))
+    }
 
-            self.struct_span_err(
-                range_span,
-                &format!("`X{}` range patterns are not supported", form),
+    pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) {
+        use rustc_error_codes::E0586;
+        struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
+            .span_suggestion_short(
+                span,
+                "use `..` instead",
+                "..".to_string(),
+                Applicability::MachineApplicable,
             )
-            .span_suggestion(
-                range_span,
-                "try using the maximum value for the type",
-                format!("{}{}MAX", pprust::expr_to_string(&begin), form),
-                Applicability::HasPlaceholders,
-            )
+            .note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")
             .emit();
+    }
 
-            Ok(self.mk_expr(range_span, ExprKind::Err, AttrVec::new()))
+    /// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed.
+    ///
+    /// The form `...X` is prohibited to reduce confusion with the potential
+    /// expression syntax `...expr` for splatting in expressions.
+    fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
+        let end = self.parse_pat_range_end()?;
+        self.sess.gated_spans.gate(sym::half_open_range_patterns, re.span.to(self.prev_span));
+        if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node {
+            *syn = RangeSyntax::DotDotEq;
+            self.struct_span_err(re.span, "range-to patterns with `...` are not allowed")
+                .span_suggestion_short(
+                    re.span,
+                    "use `..=` instead",
+                    "..=".to_string(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
         }
+        Ok(PatKind::Range(None, Some(end), re))
+    }
+
+    /// Is the token `dist` away from the current suitable as the start of a range patterns end?
+    fn is_pat_range_end_start(&self, dist: usize) -> bool {
+        self.look_ahead(dist, |t| {
+            t.is_path_start() // e.g. `MY_CONST`;
+                || t.kind == token::Dot // e.g. `.5` for recovery;
+                || t.can_begin_literal_or_bool() // e.g. `42`.
+                || t.is_whole_expr()
+        })
     }
 
     fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 4122aa1..ea14aa2 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -4,9 +4,9 @@
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
 use rustc_error_codes::*;
-use rustc_errors::{pluralize, Applicability, PResult};
+use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
 use rustc_span::source_map::Span;
-use rustc_span::symbol::kw;
+use rustc_span::symbol::{kw, sym};
 use syntax::ast::{
     self, BareFnTy, FunctionRetTy, GenericParam, Ident, Lifetime, MutTy, Ty, TyKind,
 };
@@ -15,9 +15,26 @@
 };
 use syntax::ast::{Mac, Mutability};
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token::{self, Token};
 
+/// Any `?` or `?const` modifiers that appear at the start of a bound.
+struct BoundModifiers {
+    /// `?Trait`.
+    maybe: Option<Span>,
+
+    /// `?const Trait`.
+    maybe_const: Option<Span>,
+}
+
+impl BoundModifiers {
+    fn trait_bound_modifier(&self) -> TraitBoundModifier {
+        match self.maybe {
+            Some(_) => TraitBoundModifier::Maybe,
+            None => TraitBoundModifier::None,
+        }
+    }
+}
+
 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
 /// `IDENT<<u8 as Trait>::AssocTy>`.
 ///
@@ -196,7 +213,9 @@
         lo: Span,
         parse_plus: bool,
     ) -> PResult<'a, TyKind> {
-        let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
+        assert_ne!(self.token, token::Question);
+
+        let poly_trait_ref = PolyTraitRef::new(generic_params, path, None, lo.to(self.prev_span));
         let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
         if parse_plus {
             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
@@ -422,12 +441,15 @@
         let has_parens = self.eat(&token::OpenDelim(token::Paren));
         let inner_lo = self.token.span;
         let is_negative = self.eat(&token::Not);
-        let question = self.eat(&token::Question).then_some(self.prev_span);
+
+        let modifiers = self.parse_ty_bound_modifiers();
         let bound = if self.token.is_lifetime() {
-            self.parse_generic_lt_bound(lo, inner_lo, has_parens, question)?
+            self.error_lt_bound_with_modifiers(modifiers);
+            self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
         } else {
-            self.parse_generic_ty_bound(lo, has_parens, question)?
+            self.parse_generic_ty_bound(lo, has_parens, modifiers)?
         };
+
         Ok(if is_negative { Err(anchor_lo.to(self.prev_span)) } else { Ok(bound) })
     }
 
@@ -440,9 +462,7 @@
         lo: Span,
         inner_lo: Span,
         has_parens: bool,
-        question: Option<Span>,
     ) -> PResult<'a, GenericBound> {
-        self.error_opt_out_lifetime(question);
         let bound = GenericBound::Outlives(self.expect_lifetime());
         if has_parens {
             // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
@@ -452,8 +472,17 @@
         Ok(bound)
     }
 
-    fn error_opt_out_lifetime(&self, question: Option<Span>) {
-        if let Some(span) = question {
+    /// Emits an error if any trait bound modifiers were present.
+    fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
+        if let Some(span) = modifiers.maybe_const {
+            self.struct_span_err(
+                span,
+                "`?const` may only modify trait bounds, not lifetime bounds",
+            )
+            .emit();
+        }
+
+        if let Some(span) = modifiers.maybe {
             self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
                 .emit();
         }
@@ -479,25 +508,58 @@
         Ok(())
     }
 
+    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `?const Trait`.
+    ///
+    /// If no modifiers are present, this does not consume any tokens.
+    ///
+    /// ```
+    /// TY_BOUND_MODIFIERS = "?" ["const" ["?"]]
+    /// ```
+    fn parse_ty_bound_modifiers(&mut self) -> BoundModifiers {
+        if !self.eat(&token::Question) {
+            return BoundModifiers { maybe: None, maybe_const: None };
+        }
+
+        // `? ...`
+        let first_question = self.prev_span;
+        if !self.eat_keyword(kw::Const) {
+            return BoundModifiers { maybe: Some(first_question), maybe_const: None };
+        }
+
+        // `?const ...`
+        let maybe_const = first_question.to(self.prev_span);
+        self.sess.gated_spans.gate(sym::const_trait_bound_opt_out, maybe_const);
+        if !self.eat(&token::Question) {
+            return BoundModifiers { maybe: None, maybe_const: Some(maybe_const) };
+        }
+
+        // `?const ? ...`
+        let second_question = self.prev_span;
+        BoundModifiers { maybe: Some(second_question), maybe_const: Some(maybe_const) }
+    }
+
     /// Parses a type bound according to:
     /// ```
     /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
-    /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
+    /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
     /// ```
+    ///
+    /// For example, this grammar accepts `?const ?for<'a: 'b> m::Trait<'a>`.
     fn parse_generic_ty_bound(
         &mut self,
         lo: Span,
         has_parens: bool,
-        question: Option<Span>,
+        modifiers: BoundModifiers,
     ) -> PResult<'a, GenericBound> {
         let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
         let path = self.parse_path(PathStyle::Type)?;
         if has_parens {
             self.expect(&token::CloseDelim(token::Paren))?;
         }
-        let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span));
-        let modifier = question.map_or(TraitBoundModifier::None, |_| TraitBoundModifier::Maybe);
-        Ok(GenericBound::Trait(poly_trait, modifier))
+
+        let constness = modifiers.maybe_const.map(|_| ast::Constness::NotConst);
+        let poly_trait = PolyTraitRef::new(lifetime_defs, path, constness, lo.to(self.prev_span));
+        Ok(GenericBound::Trait(poly_trait, modifiers.trait_bound_modifier()))
     }
 
     /// Optionally parses `for<$generic_params>`.
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index f089361..84562fb 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -4,10 +4,10 @@
 
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
+use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
+use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Symbol};
 use syntax::ast::{self, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
-use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
-use syntax::sess::ParseSess;
 use syntax::tokenstream::DelimSpan;
 
 pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index b33b891..639d863 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -12,11 +12,12 @@
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_index = { path = "../librustc_index" }
-rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs
index c08aab2..39ba2fb 100644
--- a/src/librustc_passes/check_const.rs
+++ b/src/librustc_passes/check_const.rs
@@ -7,18 +7,18 @@
 //! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
 use rustc::session::config::nightly_options;
+use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::{sym, Span, Symbol};
 use syntax::ast::Mutability;
-use syntax::feature_gate::feature_err;
-use syntax::span_err;
 
 use std::fmt;
 
@@ -154,7 +154,7 @@
             required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
 
         match missing_gates.as_slice() {
-            &[] => span_err!(self.tcx.sess, span, E0744, "{}", msg),
+            &[] => struct_span_err!(self.tcx.sess, span, E0744, "{}", msg).emit(),
 
             // If the user enabled `#![feature(const_loop)]` but not `#![feature(const_if_match)]`,
             // explain why their `while` loop is being rejected.
@@ -200,18 +200,20 @@
 }
 
 impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
     fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
         let kind = Some(ConstKind::AnonConst);
-        self.recurse_into(kind, |this| hir::intravisit::walk_anon_const(this, anon));
+        self.recurse_into(kind, |this| intravisit::walk_anon_const(this, anon));
     }
 
     fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
         let kind = ConstKind::for_body(body, self.tcx.hir());
-        self.recurse_into(kind, |this| hir::intravisit::walk_body(this, body));
+        self.recurse_into(kind, |this| intravisit::walk_body(this, body));
     }
 
     fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
@@ -220,7 +222,7 @@
                 self.const_check_violated(NonConstExpr::OrPattern, p.span);
             }
         }
-        hir::intravisit::walk_pat(self, p)
+        intravisit::walk_pat(self, p)
     }
 
     fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
@@ -250,6 +252,6 @@
             _ => {}
         }
 
-        hir::intravisit::walk_expr(self, e);
+        intravisit::walk_expr(self, e);
     }
 }
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index f9db1a2..f2778b2 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -2,18 +2,18 @@
 // closely. The idea is that all reachable symbols are live, codes called
 // from live codes are live, and everything else is dead.
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::Node;
-use rustc::hir::{self, PatKind, TyKind};
-
-use rustc::hir::def::{CtorOf, DefKind, Res};
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::lint;
+use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::privacy;
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind, Res};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::{Node, PatKind, TyKind};
+use rustc_session::lint;
 
 use rustc_span;
 use rustc_span::symbol::sym;
@@ -211,7 +211,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -564,11 +566,13 @@
 }
 
 impl Visitor<'tcx> for DeadVisitor<'tcx> {
+    type Map = Map<'tcx>;
+
     /// Walk nested items in place so that we don't report dead-code
     /// on inner functions when the outer function is already getting
     /// an error. We could do this also by checking the parents, but
     /// this is how the code is setup and it seems harmless enough.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
diff --git a/src/librustc_passes/diagnostic_items.rs b/src/librustc_passes/diagnostic_items.rs
index 6b2c426..c083830 100644
--- a/src/librustc_passes/diagnostic_items.rs
+++ b/src/librustc_passes/diagnostic_items.rs
@@ -9,12 +9,12 @@
 //!
 //! * Compiler internal types like `Ty` and `TyCtxt`
 
-use rustc::hir;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast;
 
@@ -73,7 +73,7 @@
                 )),
             };
             if let Some(span) = tcx.hir().span_if_local(original_def_id) {
-                span_note!(&mut err, span, "first defined here.");
+                err.span_note(span, "first defined here.");
             } else {
                 err.note(&format!(
                     "first defined in crate `{}`.",
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index 910d752..028d7c6 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -1,13 +1,14 @@
-use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::map as hir_map;
-use rustc::hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
 use rustc::session::config::EntryFnType;
 use rustc::session::{config, Session};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
 use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use syntax::attr;
 use syntax::entry::EntryPointType;
 
@@ -108,7 +109,8 @@
             if ctxt.main_fn.is_none() {
                 ctxt.main_fn = Some((item.hir_id, item.span));
             } else {
-                span_err!(ctxt.session, item.span, E0136, "multiple `main` functions");
+                struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions")
+                    .emit();
             }
         }
         EntryPointType::OtherMain => {
@@ -166,8 +168,9 @@
     }
 
     // There is no main function.
-    let mut err = struct_err!(
+    let mut err = struct_span_err!(
         tcx.sess,
+        DUMMY_SP,
         E0601,
         "`main` function not found in crate `{}`",
         tcx.crate_name(LOCAL_CRATE)
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index 4341ebf..b6ca2b3 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -2,10 +2,12 @@
 // pieces of AST and HIR. The resulting numbers are good approximations but not
 // completely accurate (some things might be counted twice, others missed).
 
-use rustc::hir::intravisit as hir_visit;
-use rustc::hir::{self, HirId};
+use rustc::hir::map::Map;
 use rustc::util::common::to_readable_str;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::intravisit as hir_visit;
+use rustc_hir::HirId;
 use rustc_span::Span;
 use syntax::ast::{self, AttrId, NodeId};
 use syntax::visit as ast_visit;
@@ -91,7 +93,9 @@
         hir_visit::walk_param(self, param)
     }
 
-    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<'_, Self::Map> {
         panic!("visit_nested_xxx must be manually implemented in this visitor")
     }
 
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index 95dc31c..2c26707 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -1,11 +1,12 @@
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::DefId;
+use rustc::hir::map::Map;
 use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
-
-use rustc::hir;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_index::vec::Idx;
 use rustc_span::{sym, Span};
 use rustc_target::spec::abi::Abi::RustIntrinsic;
@@ -123,7 +124,9 @@
 }
 
 impl Visitor<'tcx> for ItemVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -138,7 +141,9 @@
 }
 
 impl Visitor<'tcx> for ExprVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index 02eecc2..be3e1f4 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -1,7 +1,3 @@
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::ItemKind;
 use rustc::ty::layout::HasDataLayout;
 use rustc::ty::layout::HasParamEnv;
 use rustc::ty::layout::HasTyCtxt;
@@ -11,6 +7,10 @@
 use rustc::ty::ParamEnv;
 use rustc::ty::Ty;
 use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::ItemKind;
 use rustc_span::symbol::sym;
 use syntax::ast::Attribute;
 
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index a692c45..65eb07b 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -14,12 +14,9 @@
 extern crate rustc;
 #[macro_use]
 extern crate log;
-#[macro_use]
-extern crate syntax;
 
 use rustc::ty::query::Providers;
 
-pub mod ast_validation;
 mod check_const;
 pub mod dead;
 mod diagnostic_items;
diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs
index 0d39ea8..8ae7291 100644
--- a/src/librustc_passes/lib_features.rs
+++ b/src/librustc_passes/lib_features.rs
@@ -4,11 +4,13 @@
 // and `#[unstable (..)]`), but are not declared in one single location
 // (unlike lang features), which means we need to collect them instead.
 
-use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::middle::lib_features::LibFeatures;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::Symbol;
 use rustc_span::{sym, Span};
 use syntax::ast::{Attribute, MetaItem, MetaItemKind};
@@ -112,7 +114,9 @@
 }
 
 impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 6a38524..7718139 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -96,24 +96,26 @@
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
-use rustc::hir::def::*;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
-use rustc::hir::{self, Expr, HirId, HirIdMap, HirIdSet, Node};
+use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
-
-use errors::Applicability;
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def::*;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use syntax::ast;
+
 use std::collections::VecDeque;
 use std::io;
 use std::io::prelude::*;
 use std::rc::Rc;
 use std::{fmt, u32};
-use syntax::ast;
 
 #[derive(Copy, Clone, PartialEq)]
 struct Variable(u32);
@@ -152,7 +154,9 @@
 }
 
 impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -375,7 +379,7 @@
 
     for param in body.params {
         let is_shorthand = match param.pat.kind {
-            rustc::hir::PatKind::Struct(..) => true,
+            rustc_hir::PatKind::Struct(..) => true,
             _ => false,
         };
         param.pat.each_binding(|_bm, hir_id, _x, ident| {
@@ -409,7 +413,7 @@
     let mut pats = VecDeque::new();
     pats.push_back(pat);
     while let Some(pat) = pats.pop_front() {
-        use rustc::hir::PatKind::*;
+        use rustc_hir::PatKind::*;
         match &pat.kind {
             Binding(.., inner_pat) => {
                 pats.extend(inner_pat.iter());
@@ -1060,7 +1064,7 @@
                             .sess
                             .struct_span_err(expr.span, "`break` to unknown label")
                             .emit();
-                        errors::FatalError.raise()
+                        rustc_errors::FatalError.raise()
                     }
                 }
             }
@@ -1347,7 +1351,9 @@
 // Checking for error conditions
 
 impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1507,13 +1513,16 @@
                 if ln == self.s.exit_ln { false } else { self.assigned_on_exit(ln, var).is_some() };
 
             if is_assigned {
-                self.ir.tcx.lint_hir_note(
-                    lint::builtin::UNUSED_VARIABLES,
-                    hir_id,
-                    spans,
-                    &format!("variable `{}` is assigned to, but never used", name),
-                    &format!("consider using `_{}` instead", name),
-                );
+                self.ir
+                    .tcx
+                    .struct_span_lint_hir(
+                        lint::builtin::UNUSED_VARIABLES,
+                        hir_id,
+                        spans,
+                        &format!("variable `{}` is assigned to, but never used", name),
+                    )
+                    .note(&format!("consider using `_{}` instead", name))
+                    .emit();
             } else {
                 let mut err = self.ir.tcx.struct_span_lint_hir(
                     lint::builtin::UNUSED_VARIABLES,
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index f5011ce..5ad5795 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -2,15 +2,15 @@
 
 use rustc::session::Session;
 
-use errors::Applicability;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
-use rustc::hir::{self, Destination, Movability, Node};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::{struct_span_err, Applicability};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Destination, Movability, Node};
 use rustc_span::Span;
-use syntax::struct_span_err;
 
 use rustc_error_codes::*;
 
@@ -44,7 +44,9 @@
 }
 
 impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
+    type Map = Map<'hir>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.hir_map)
     }
 
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index 4bcba96..5ce677f 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -5,14 +5,7 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::hir::def_id::{CrateNum, DefId};
-use rustc::hir::intravisit;
-use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::Node;
-use rustc::hir::{self, HirIdSet};
+use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::middle::privacy;
 use rustc::session::config;
@@ -20,6 +13,14 @@
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::intravisit;
+use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::{HirIdSet, Node};
 use rustc_target::spec::abi::Abi;
 
 // Returns true if the given item must be inlined because it may be
@@ -82,7 +83,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs
index 7652d5a..e79ca5c 100644
--- a/src/librustc_passes/region.rs
+++ b/src/librustc_passes/region.rs
@@ -6,18 +6,19 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::Node;
-use rustc::hir::{Arm, Block, Expr, Local, Pat, PatKind, Stmt};
+use rustc::hir::map::Map;
 use rustc::middle::region::*;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt};
 use rustc_index::vec::Idx;
 use rustc_span::source_map;
 use rustc_span::Span;
+use syntax::walk_list;
 
 use std::mem;
 
@@ -651,7 +652,7 @@
 
             match expr.kind {
                 hir::ExprKind::AddrOf(_, _, ref subexpr)
-                | hir::ExprKind::Unary(hir::UnDeref, ref subexpr)
+                | hir::ExprKind::Unary(hir::UnOp::UnDeref, ref subexpr)
                 | hir::ExprKind::Field(ref subexpr, _)
                 | hir::ExprKind::Index(ref subexpr, _) => {
                     expr = &subexpr;
@@ -695,7 +696,9 @@
 }
 
 impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index 60f2662..af37d21 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -1,22 +1,26 @@
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::{self, Generics, HirId, Item, StructField, Variant};
+use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability::{DeprecationEntry, Index};
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
+use rustc::traits::misc::can_type_implement_copy;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Generics, HirId, Item, StructField, Variant};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use syntax::ast::Attribute;
 use syntax::attr::{self, Stability};
-use syntax::feature_gate::feature_err;
 
 use std::cmp::Ordering;
 use std::mem::replace;
@@ -201,7 +205,9 @@
     /// Because stability levels are scoped lexically, we want to walk
     /// nested items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -290,7 +296,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -426,10 +434,12 @@
 }
 
 impl Visitor<'tcx> for Checker<'tcx> {
+    type Map = Map<'tcx>;
+
     /// Because stability levels are scoped lexically, we want to walk
     /// nested items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -487,7 +497,7 @@
                     .emit();
                 } else {
                     let param_env = self.tcx.param_env(def_id);
-                    if !param_env.can_type_implement_copy(self.tcx, ty).is_ok() {
+                    if !can_type_implement_copy(self.tcx, param_env, ty).is_ok() {
                         feature_err(
                             &self.tcx.sess.parse_sess,
                             sym::untagged_unions,
diff --git a/src/librustc_plugin_impl/Cargo.toml b/src/librustc_plugin_impl/Cargo.toml
index a9bbe42..41e6c69 100644
--- a/src/librustc_plugin_impl/Cargo.toml
+++ b/src/librustc_plugin_impl/Cargo.toml
@@ -12,6 +12,9 @@
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_plugin_impl/build.rs b/src/librustc_plugin_impl/build.rs
index 2424ee5..c4b6440 100644
--- a/src/librustc_plugin_impl/build.rs
+++ b/src/librustc_plugin_impl/build.rs
@@ -1,10 +1,10 @@
 //! Used by `rustc` when compiling a plugin crate.
 
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::attr;
diff --git a/src/librustc_plugin_impl/lib.rs b/src/librustc_plugin_impl/lib.rs
index 682d223..10712eb 100644
--- a/src/librustc_plugin_impl/lib.rs
+++ b/src/librustc_plugin_impl/lib.rs
@@ -9,7 +9,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(nll)]
 
-use rustc::lint::LintStore;
+use rustc_lint::LintStore;
 
 pub mod build;
 pub mod load;
diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs
index 2215e49..65661ec 100644
--- a/src/librustc_plugin_impl/load.rs
+++ b/src/librustc_plugin_impl/load.rs
@@ -3,18 +3,17 @@
 use crate::Registry;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::Session;
+use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_metadata::locator;
-
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use syntax::ast::{Crate, Ident};
+
 use std::borrow::ToOwned;
 use std::env;
 use std::mem;
 use std::path::PathBuf;
-use syntax::ast::{Crate, Ident};
-use syntax::struct_span_err;
-
-use rustc_error_codes::*;
 
 /// Pointer to a registrar function.
 type PluginRegistrarFn = fn(&mut Registry<'_>);
diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml
index e39c0b4..795b6c1 100644
--- a/src/librustc_privacy/Cargo.toml
+++ b/src/librustc_privacy/Cargo.toml
@@ -10,6 +10,8 @@
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 68e5e6d..70d4841 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -3,14 +3,8 @@
 #![feature(nll)]
 #![recursion_limit = "256"]
 
-#[macro_use]
-extern crate syntax;
-
 use rustc::bug;
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
-use rustc::hir::{self, AssocItemKind, HirIdSet, Node, PatKind};
+use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::ty::fold::TypeVisitor;
@@ -18,6 +12,12 @@
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
+use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
 use rustc_span::hygiene::Transparency;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -373,7 +373,9 @@
 }
 
 impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
     fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) {
@@ -650,6 +652,9 @@
             if let Some(item) = module
                 .res
                 .and_then(|res| res.mod_def_id())
+                // If the module is `self`, i.e. the current crate,
+                // there will be no corresponding item.
+                .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
                 .and_then(|def_id| self.tcx.hir().as_local_hir_id(def_id))
                 .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
             {
@@ -671,9 +676,11 @@
 }
 
 impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -1040,9 +1047,11 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -1180,9 +1189,11 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -1438,7 +1449,9 @@
 }
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1464,9 +1477,11 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -1907,7 +1922,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index 593662c..af37e7b 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -14,15 +14,16 @@
 bitflags = "1.2.1"
 log = "0.4"
 syntax = { path = "../libsyntax" }
-rustc_expand = { path = "../librustc_expand" }
 arena = { path = "../libarena" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
-rustc_span = { path = "../librustc_span" }
 rustc = { path = "../librustc" }
 rustc_ast_lowering = { path = "../librustc_ast_lowering" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_expand = { path = "../librustc_expand" }
 rustc_feature = { path = "../librustc_feature" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 613fad6..2913864 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -17,21 +17,17 @@
 use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
 
 use rustc::bug;
-use rustc::hir::def::{self, *};
-use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::exports::Export;
 use rustc::middle::cstore::CrateStore;
 use rustc::ty;
-use rustc_metadata::creader::LoadedMacro;
-
 use rustc_data_structures::sync::Lrc;
-use std::cell::Cell;
-use std::ptr;
-
-use errors::Applicability;
-
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::SyntaxExtension;
 use rustc_expand::expand::AstFragment;
+use rustc_hir::def::{self, *};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_metadata::creader::LoadedMacro;
 use rustc_span::hygiene::{ExpnId, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym};
@@ -40,13 +36,12 @@
 use syntax::ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use syntax::ast::{Ident, Name};
 use syntax::attr;
-use syntax::span_err;
 use syntax::token::{self, Token};
 use syntax::visit::{self, Visitor};
 
 use log::debug;
-
-use rustc_error_codes::*;
+use std::cell::Cell;
+use std::ptr;
 
 type Res = def::Res<NodeId>;
 
@@ -954,22 +949,27 @@
         for attr in &item.attrs {
             if attr.check_name(sym::macro_use) {
                 if self.parent_scope.module.parent.is_some() {
-                    span_err!(
+                    struct_span_err!(
                         self.r.session,
                         item.span,
                         E0468,
                         "an `extern crate` loading macros must be at the crate root"
-                    );
+                    )
+                    .emit();
                 }
                 if let ItemKind::ExternCrate(Some(orig_name)) = item.kind {
                     if orig_name == kw::SelfLower {
-                        self.r.session.span_err(
-                            attr.span,
-                            "`macro_use` is not supported on `extern crate self`",
-                        );
+                        self.r
+                            .session
+                            .struct_span_err(
+                                attr.span,
+                                "`macro_use` is not supported on `extern crate self`",
+                            )
+                            .emit();
                     }
                 }
-                let ill_formed = |span| span_err!(self.r.session, span, E0466, "bad macro import");
+                let ill_formed =
+                    |span| struct_span_err!(self.r.session, span, E0466, "bad macro import").emit();
                 match attr.meta() {
                     Some(meta) => match meta.kind {
                         MetaItemKind::Word => {
@@ -1042,7 +1042,8 @@
                         allow_shadowing,
                     );
                 } else {
-                    span_err!(self.r.session, ident.span, E0469, "imported macro not found");
+                    struct_span_err!(self.r.session, ident.span, E0469, "imported macro not found")
+                        .emit();
                 }
             }
         }
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 6561072..4a6df92 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -26,9 +26,10 @@
 use crate::imports::ImportDirectiveSubclass;
 use crate::Resolver;
 
-use errors::pluralize;
 use rustc::{lint, ty};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::pluralize;
+use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::node_id::NodeMap;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use syntax::ast;
@@ -317,7 +318,7 @@
                 unused.use_tree_id,
                 ms,
                 &msg,
-                lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
+                BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
             );
         }
     }
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index 5aea813..f564ea6 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -1,7 +1,7 @@
 use log::debug;
-use rustc::hir::def_id::DefIndex;
 use rustc::hir::map::definitions::*;
 use rustc_expand::expand::AstFragment;
+use rustc_hir::def_id::DefIndex;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 1d45f1c..9742067 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1,22 +1,21 @@
 use std::cmp::Reverse;
 
-use errors::{Applicability, DiagnosticBuilder};
 use log::debug;
 use rustc::bug;
-use rustc::hir::def::Namespace::{self, *};
-use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc::session::Session;
 use rustc::ty::{self, DefIdTree};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_feature::BUILTIN_ATTRIBUTES;
+use rustc_hir::def::Namespace::{self, *};
+use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span};
 use syntax::ast::{self, Ident, Path};
 use syntax::print::pprust;
-use syntax::struct_span_err;
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
@@ -781,8 +780,14 @@
                 suggestion.candidate.to_string(),
                 Applicability::MaybeIncorrect,
             );
-            let def_span =
-                suggestion.res.opt_def_id().and_then(|def_id| self.definitions.opt_span(def_id));
+            let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate {
+                LOCAL_CRATE => self.definitions.opt_span(def_id),
+                _ => Some(
+                    self.session
+                        .source_map()
+                        .def_span(self.cstore().get_span_untracked(def_id, self.session)),
+                ),
+            });
             if let Some(span) = def_span {
                 err.span_label(
                     span,
diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs
index cc35b77..8fe17e8 100644
--- a/src/librustc_resolve/imports.rs
+++ b/src/librustc_resolve/imports.rs
@@ -11,24 +11,23 @@
 use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak};
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
-use errors::{pluralize, Applicability};
-
-use rustc::hir::def::{self, PartialRes};
-use rustc::hir::def_id::DefId;
 use rustc::hir::exports::Export;
-use rustc::lint::builtin::BuiltinLintDiagnostics;
 use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
-use rustc::session::DiagnosticMessageId;
 use rustc::ty;
 use rustc::{bug, span_bug};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
+use rustc_errors::{pluralize, struct_span_err, Applicability};
+use rustc_hir::def::{self, PartialRes};
+use rustc_hir::def_id::DefId;
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::DiagnosticMessageId;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::{Ident, Name, NodeId};
+use syntax::unwrap_or;
 use syntax::util::lev_distance::find_best_match_for_name;
-use syntax::{struct_span_err, unwrap_or};
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 84cb3f7..defca49 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -11,13 +11,13 @@
 use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
-use log::debug;
-use rustc::hir::def::Namespace::{self, *};
-use rustc::hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
-use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
-use rustc::hir::TraitCandidate;
 use rustc::{bug, lint, span_bug};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::DiagnosticId;
+use rustc_hir::def::Namespace::{self, *};
+use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::TraitCandidate;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
@@ -27,6 +27,7 @@
 use syntax::visit::{self, FnKind, Visitor};
 use syntax::{unwrap_or, walk_list};
 
+use log::debug;
 use std::collections::BTreeSet;
 use std::mem::replace;
 
@@ -304,32 +305,21 @@
         }
     }
 
-    fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
-        syntax::diagnostic_used!(E0404);
-        syntax::diagnostic_used!(E0405);
-        syntax::diagnostic_used!(E0412);
-        syntax::diagnostic_used!(E0422);
-        syntax::diagnostic_used!(E0423);
-        syntax::diagnostic_used!(E0425);
-        syntax::diagnostic_used!(E0531);
-        syntax::diagnostic_used!(E0532);
-        syntax::diagnostic_used!(E0573);
-        syntax::diagnostic_used!(E0574);
-        syntax::diagnostic_used!(E0575);
-        syntax::diagnostic_used!(E0576);
+    fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId {
+        use rustc_errors::error_code;
         match (self, has_unexpected_resolution) {
-            (PathSource::Trait(_), true) => "E0404",
-            (PathSource::Trait(_), false) => "E0405",
-            (PathSource::Type, true) => "E0573",
-            (PathSource::Type, false) => "E0412",
-            (PathSource::Struct, true) => "E0574",
-            (PathSource::Struct, false) => "E0422",
-            (PathSource::Expr(..), true) => "E0423",
-            (PathSource::Expr(..), false) => "E0425",
-            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
-            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
-            (PathSource::TraitItem(..), true) => "E0575",
-            (PathSource::TraitItem(..), false) => "E0576",
+            (PathSource::Trait(_), true) => error_code!(E0404),
+            (PathSource::Trait(_), false) => error_code!(E0405),
+            (PathSource::Type, true) => error_code!(E0573),
+            (PathSource::Type, false) => error_code!(E0412),
+            (PathSource::Struct, true) => error_code!(E0574),
+            (PathSource::Struct, false) => error_code!(E0422),
+            (PathSource::Expr(..), true) => error_code!(E0423),
+            (PathSource::Expr(..), false) => error_code!(E0425),
+            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => error_code!(E0532),
+            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => error_code!(E0531),
+            (PathSource::TraitItem(..), true) => error_code!(E0575),
+            (PathSource::TraitItem(..), false) => error_code!(E0576),
         }
     }
 }
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index cd94229..151f3e8 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -4,21 +4,21 @@
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
-use log::debug;
-use rustc::hir::def::Namespace::{self, *};
-use rustc::hir::def::{self, CtorKind, DefKind};
-use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
-use rustc::hir::PrimTy;
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_error_codes::*;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_hir::def::Namespace::{self, *};
+use rustc_hir::def::{self, CtorKind, DefKind};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::PrimTy;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
 use syntax::ast::{self, Expr, ExprKind, Ident, NodeId, Path, Ty, TyKind};
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
+use log::debug;
 
 type Res = def::Res<ast::NodeId>;
 
@@ -73,7 +73,6 @@
         let expected = source.descr_expected();
         let path_str = Segment::names_to_string(path);
         let item_str = path.last().unwrap().ident;
-        let code = source.error_code(res.is_some());
         let (base_msg, fallback_label, base_span, could_be_expr) = if let Some(res) = res {
             (
                 format!("expected {}, found {} `{}`", expected, res.descr(), path_str),
@@ -123,7 +122,7 @@
             )
         };
 
-        let code = DiagnosticId::Error(code.into());
+        let code = source.error_code(res.is_some());
         let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
 
         // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
@@ -140,8 +139,7 @@
 
         // Emit special messages for unresolved `Self` and `self`.
         if is_self_type(path, ns) {
-            syntax::diagnostic_used!(E0411);
-            err.code(DiagnosticId::Error("E0411".into()));
+            err.code(rustc_errors::error_code!(E0411));
             err.span_label(
                 span,
                 format!("`Self` is only available in impls, traits, and type definitions"),
@@ -151,8 +149,7 @@
         if is_self_value(path, ns) {
             debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
 
-            syntax::diagnostic_used!(E0424);
-            err.code(DiagnosticId::Error("E0424".into()));
+            err.code(rustc_errors::error_code!(E0424));
             err.span_label(span, match source {
                 PathSource::Pat => format!(
                     "`self` value is a keyword and may not be bound to variables or shadowed",
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 72e0dc3..8e4630c 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -16,30 +16,31 @@
 #![feature(nll)]
 #![recursion_limit = "256"]
 
-pub use rustc::hir::def::{Namespace, PerNS};
+pub use rustc_hir::def::{Namespace, PerNS};
 
 use Determinacy::*;
 
-use errors::{Applicability, DiagnosticBuilder};
-use rustc::hir::def::Namespace::*;
-use rustc::hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
-use rustc::hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::exports::ExportMap;
-use rustc::hir::map::Definitions;
-use rustc::hir::{Bool, Char, Float, Int, PrimTy, Str, Uint};
-use rustc::hir::{GlobMap, TraitMap};
+use rustc::hir::map::{DefKey, Definitions};
 use rustc::lint;
 use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
-use rustc::session::Session;
 use rustc::span_bug;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, DefIdTree, ResolverOutputs};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtension;
+use rustc_hir::def::Namespace::*;
+use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
+use rustc_hir::{GlobMap, TraitMap};
 use rustc_metadata::creader::{CStore, CrateLoader};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::node_id::{NodeMap, NodeSet};
+use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym};
@@ -49,8 +50,8 @@
 use syntax::ast::{ItemKind, Path};
 use syntax::attr;
 use syntax::print::pprust;
+use syntax::unwrap_or;
 use syntax::visit::{self, Visitor};
-use syntax::{struct_span_err, unwrap_or};
 
 use log::debug;
 use std::cell::{Cell, RefCell};
@@ -960,7 +961,7 @@
     /// when visiting the correspondent variants.
     variant_vis: DefIdMap<ty::Visibility>,
 
-    lint_buffer: lint::LintBuffer,
+    lint_buffer: LintBuffer,
 
     next_node_id: NodeId,
 }
@@ -1027,8 +1028,12 @@
 /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
 /// the resolver is no longer needed as all the relevant information is inline.
 impl rustc_ast_lowering::Resolver for Resolver<'_> {
-    fn cstore(&self) -> &dyn CrateStore {
-        self.cstore()
+    fn def_key(&mut self, id: DefId) -> DefKey {
+        if id.is_local() { self.definitions().def_key(id.index) } else { self.cstore().def_key(id) }
+    }
+
+    fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
+        self.cstore().item_generics_num_lifetimes(def_id, sess)
     }
 
     fn resolve_str_path(
@@ -1078,7 +1083,7 @@
         &mut self.definitions
     }
 
-    fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
+    fn lint_buffer(&mut self) -> &mut LintBuffer {
         &mut self.lint_buffer
     }
 
@@ -1237,7 +1242,7 @@
                 .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
                 .collect(),
             variant_vis: Default::default(),
-            lint_buffer: lint::LintBuffer::default(),
+            lint_buffer: LintBuffer::default(),
             next_node_id: NodeId::from_u32(1),
         }
     }
@@ -1252,7 +1257,7 @@
         self.next_node_id
     }
 
-    pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
+    pub fn lint_buffer(&mut self) -> &mut LintBuffer {
         &mut self.lint_buffer
     }
 
@@ -1709,10 +1714,10 @@
                     if let Some(node_id) = poisoned {
                         self.lint_buffer.buffer_lint_with_diagnostic(
                             lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-                            node_id, ident.span,
+                            node_id,
+                            ident.span,
                             &format!("cannot find {} `{}` in this scope", ns.descr(), ident),
-                            lint::builtin::BuiltinLintDiagnostics::
-                                ProcMacroDeriveResolutionFallback(ident.span),
+                            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(ident.span),
                         );
                     }
                     return Some(LexicalScopeBinding::Item(binding));
@@ -2263,7 +2268,7 @@
             }
         }
 
-        let diag = lint::builtin::BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
+        let diag = BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
         self.lint_buffer.buffer_lint_with_diagnostic(
             lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
             diag_id,
@@ -2558,9 +2563,10 @@
                        cannot be referred to by absolute paths";
             self.lint_buffer.buffer_lint_with_diagnostic(
                 lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
-                CRATE_NODE_ID, span_use, msg,
-                lint::builtin::BuiltinLintDiagnostics::
-                    MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+                CRATE_NODE_ID,
+                span_use,
+                msg,
+                BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
             );
         }
 
diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs
index 5d82c17..d6143ee 100644
--- a/src/librustc_resolve/lifetimes.rs
+++ b/src/librustc_resolve/lifetimes.rs
@@ -5,19 +5,20 @@
 //! used between functions, and they operate in a purely top-down
 //! way. Therefore, we break lifetime name resolution into a separate pass.
 
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
-use rustc::hir::{self, GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
-use rustc::hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
 use rustc::lint;
 use rustc::middle::resolve_lifetime::*;
 use rustc::session::Session;
 use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
+use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -25,7 +26,7 @@
 use std::mem::{replace, take};
 use syntax::ast;
 use syntax::attr;
-use syntax::{help, span_err, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use log::debug;
 
@@ -360,7 +361,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -590,13 +593,14 @@
                                     || krate.impl_items.contains_key(&parent_impl_id)
                                     || krate.trait_items.contains_key(&parent_trait_id))
                                 {
-                                    span_err!(
+                                    struct_span_err!(
                                         self.tcx.sess,
                                         lifetime.span,
                                         E0657,
                                         "`impl Trait` can only capture lifetimes \
                                          bound at the fn or impl level"
-                                    );
+                                    )
+                                    .emit();
                                     self.uninsert_lifetime_on_error(lifetime, def.unwrap());
                                 }
                             }
@@ -846,8 +850,8 @@
 
     fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
         let output = match fd.output {
-            hir::DefaultReturn(_) => None,
-            hir::Return(ref ty) => Some(&**ty),
+            hir::FunctionRetTy::DefaultReturn(_) => None,
+            hir::FunctionRetTy::Return(ref ty) => Some(&**ty),
         };
         self.visit_fn_like_elision(&fd.inputs, output);
     }
@@ -942,12 +946,13 @@
             })
         {
             if self.trait_ref_hack {
-                span_err!(
+                struct_span_err!(
                     self.tcx.sess,
                     trait_ref.span,
                     E0316,
                     "nested quantification of lifetimes"
-                );
+                )
+                .emit();
             }
             let next_early_index = self.next_early_index();
             let scope = Scope::Binder {
@@ -1083,7 +1088,9 @@
     gather.visit_body(body);
 
     impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -2126,7 +2133,9 @@
             }
 
             impl<'a> Visitor<'a> for SelfVisitor<'a> {
-                fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
+                type Map = Map<'a>;
+
+                fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
                     NestedVisitorMap::None
                 }
 
@@ -2214,7 +2223,9 @@
         }
 
         impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> {
-            fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+            type Map = Map<'v>;
+
+            fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
                 NestedVisitorMap::None
             }
 
@@ -2432,36 +2443,32 @@
         }
 
         if len == 0 {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 there is no value for it to be borrowed from"
+            db.help(
+                "this function's return type contains a borrowed value, \
+                but there is no value for it to be borrowed from",
             );
             self.suggest_lifetime(db, span, "consider giving it a 'static lifetime")
         } else if elided_len == 0 {
-            help!(
-                db,
+            db.help(
                 "this function's return type contains a borrowed value with \
                  an elided lifetime, but the lifetime cannot be derived from \
-                 the arguments"
+                 the arguments",
             );
             let msg = "consider giving it an explicit bounded or 'static lifetime";
             self.suggest_lifetime(db, span, msg)
         } else if elided_len == 1 {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 the signature does not say which {} it is borrowed from",
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                but the signature does not say which {} it is borrowed from",
                 m
-            );
+            ));
             true
         } else {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 the signature does not say whether it is borrowed from {}",
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                but the signature does not say whether it is borrowed from {}",
                 m
-            );
+            ));
             true
         }
     }
@@ -2803,7 +2810,9 @@
     }
 
     impl<'v> Visitor<'v> for ConstrainedCollector {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -2844,7 +2853,9 @@
     }
 
     impl<'v> Visitor<'v> for AllCollector {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index a2ef6ad..85b5d8e 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -6,9 +6,8 @@
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy};
 use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
 use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
-use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc::hir::def_id;
 use rustc::middle::stability;
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::{lint, span_bug, ty};
 use rustc_data_structures::fx::FxHashSet;
@@ -17,13 +16,14 @@
 use rustc_expand::compile_declarative_macro;
 use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
 use rustc_feature::is_builtin_attr_name;
+use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
+use rustc_hir::def_id;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, Ident, NodeId};
 use syntax::attr::{self, StabilityLevel};
-use syntax::feature_gate::feature_err;
 use syntax::print::pprust;
 
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml
index cc31f78..e7a7eef 100644
--- a/src/librustc_save_analysis/Cargo.toml
+++ b/src/librustc_save_analysis/Cargo.toml
@@ -13,6 +13,7 @@
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_parse = { path = "../librustc_parse" }
 serde_json = "1"
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index a61030a..2f2ba56 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -13,12 +13,12 @@
 //! DumpVisitor walks the AST and processes it, and Dumper is used for
 //! recording the output.
 
-use rustc::hir::def::{DefKind as HirDefKind, Res};
-use rustc::hir::def_id::DefId;
 use rustc::session::config::Input;
 use rustc::span_bug;
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def::{DefKind as HirDefKind, Res};
+use rustc_hir::def_id::DefId;
 
 use std::env;
 use std::path::Path;
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 1f72d1d..c3221d9 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -8,16 +8,16 @@
 mod span_utils;
 mod sig;
 
-use rustc::hir;
-use rustc::hir::def::{CtorOf, DefKind as HirDefKind, Res};
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::Node;
 use rustc::middle::cstore::ExternCrate;
 use rustc::middle::privacy::AccessLevels;
 use rustc::session::config::{CrateType, Input, OutputType};
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind as HirDefKind, Res};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::Node;
 
 use std::cell::Cell;
 use std::default::Default;
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 3ae15cd..e7b86cf 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -29,7 +29,7 @@
 
 use rls_data::{SigElement, Signature};
 
-use rustc::hir::def::{DefKind, Res};
+use rustc_hir::def::{DefKind, Res};
 use syntax::ast::{self, Extern, NodeId};
 use syntax::print::pprust;
 
diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml
index 47c23bc..377ea14 100644
--- a/src/librustc_session/Cargo.toml
+++ b/src/librustc_session/Cargo.toml
@@ -10,6 +10,7 @@
 
 [dependencies]
 log = "0.4"
+rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs
index 0cce7e8..2ba3932 100644
--- a/src/librustc_session/lint.rs
+++ b/src/librustc_session/lint.rs
@@ -1,8 +1,10 @@
 pub use self::Level::*;
-use crate::node_id::NodeId;
+use crate::node_id::{NodeId, NodeMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_span::edition::Edition;
-use rustc_span::{sym, MultiSpan, Symbol};
+use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
+
+pub mod builtin;
 
 /// Setting for how to handle a lint.
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
@@ -174,7 +176,25 @@
     }
 }
 
-/// Stores buffered lint info which can later be passed to `librustc`.
+// This could be a closure, but then implementing derive trait
+// becomes hacky (and it gets allocated).
+#[derive(PartialEq)]
+pub enum BuiltinLintDiagnostics {
+    Normal,
+    BareTraitObject(Span, /* is_global */ bool),
+    AbsPathWithModule(Span),
+    ProcMacroDeriveResolutionFallback(Span),
+    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
+    ElidedLifetimesInPaths(usize, Span, bool, Span, String),
+    UnknownCrateTypes(Span, String, String),
+    UnusedImports(String, Vec<(Span, String)>),
+    RedundantImport(Vec<(Span, bool)>, Ident),
+    DeprecatedMacro(Option<Symbol>, Span),
+}
+
+/// Lints that are buffered up early on in the `Session` before the
+/// `LintLevels` is calculated. These are later passed to `librustc`.
+#[derive(PartialEq)]
 pub struct BufferedEarlyLint {
     /// The span of code that we are linting on.
     pub span: MultiSpan,
@@ -183,10 +203,65 @@
     pub msg: String,
 
     /// The `NodeId` of the AST node that generated the lint.
-    pub id: NodeId,
+    pub node_id: NodeId,
 
     /// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
-    pub lint_id: &'static Lint,
+    pub lint_id: LintId,
+
+    /// Customization of the `DiagnosticBuilder<'_>` for the lint.
+    pub diagnostic: BuiltinLintDiagnostics,
+}
+
+#[derive(Default)]
+pub struct LintBuffer {
+    pub map: NodeMap<Vec<BufferedEarlyLint>>,
+}
+
+impl LintBuffer {
+    pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
+        let arr = self.map.entry(early_lint.node_id).or_default();
+        if !arr.contains(&early_lint) {
+            arr.push(early_lint);
+        }
+    }
+
+    pub fn add_lint(
+        &mut self,
+        lint: &'static Lint,
+        node_id: NodeId,
+        span: MultiSpan,
+        msg: &str,
+        diagnostic: BuiltinLintDiagnostics,
+    ) {
+        let lint_id = LintId::of(lint);
+        let msg = msg.to_string();
+        self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic });
+    }
+
+    pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
+        self.map.remove(&id).unwrap_or_default()
+    }
+
+    pub fn buffer_lint(
+        &mut self,
+        lint: &'static Lint,
+        id: NodeId,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+    ) {
+        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
+    }
+
+    pub fn buffer_lint_with_diagnostic(
+        &mut self,
+        lint: &'static Lint,
+        id: NodeId,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+        diagnostic: BuiltinLintDiagnostics,
+    ) {
+        self.add_lint(lint, id, sp.into(), msg, diagnostic)
+    }
 }
 
 /// Declares a static item of type `&'static Lint`.
@@ -253,3 +328,41 @@
         };
     );
 }
+
+/// Declares a static `LintArray` and return it as an expression.
+#[macro_export]
+macro_rules! lint_array {
+    ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
+    ($( $lint:expr ),*) => {{
+        vec![$($lint),*]
+    }}
+}
+
+pub type LintArray = Vec<&'static Lint>;
+
+pub trait LintPass {
+    fn name(&self) -> &'static str;
+}
+
+/// Implements `LintPass for $name` with the given list of `Lint` statics.
+#[macro_export]
+macro_rules! impl_lint_pass {
+    ($name:ident => [$($lint:expr),* $(,)?]) => {
+        impl $crate::lint::LintPass for $name {
+            fn name(&self) -> &'static str { stringify!($name) }
+        }
+        impl $name {
+            pub fn get_lints() -> $crate::lint::LintArray { $crate::lint_array!($($lint),*) }
+        }
+    };
+}
+
+/// Declares a type named `$name` which implements `LintPass`.
+/// To the right of `=>` a comma separated list of `Lint` statics is given.
+#[macro_export]
+macro_rules! declare_lint_pass {
+    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
+        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
+        $crate::impl_lint_pass!($name => [$($lint),*]);
+    };
+}
diff --git a/src/librustc/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
similarity index 66%
rename from src/librustc/lint/builtin.rs
rename to src/librustc_session/lint/builtin.rs
index 847c610..3e8503e 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -4,16 +4,31 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use crate::lint::{FutureIncompatibleInfo, LateLintPass, LintArray, LintPass};
-use crate::middle::stability;
-use crate::session::Session;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc_session::declare_lint;
+use crate::lint::FutureIncompatibleInfo;
+use crate::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
-use rustc_span::source_map::Span;
-use rustc_span::symbol::Symbol;
-use syntax::ast;
-use syntax::early_buffered_lints::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
+
+declare_lint! {
+    pub ILL_FORMED_ATTRIBUTE_INPUT,
+    Deny,
+    "ill-formed attribute inputs that were previously accepted and used in practice",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
+        edition: None,
+    };
+}
+
+declare_lint! {
+    pub META_VARIABLE_MISUSE,
+    Allow,
+    "possible meta-variable misuse at macro definition"
+}
+
+declare_lint! {
+    pub INCOMPLETE_INCLUDE,
+    Deny,
+    "trailing content in included file"
+}
 
 declare_lint! {
     pub EXCEEDING_BITSHIFTS,
@@ -96,6 +111,12 @@
 }
 
 declare_lint! {
+    pub BINDINGS_WITH_VARIANT_NAME,
+    Warn,
+    "detects pattern bindings with the same name as one of the matched variants"
+}
+
+declare_lint! {
     pub UNUSED_MACROS,
     Warn,
     "detects macros that were not used"
@@ -459,6 +480,7 @@
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
         OVERLAPPING_PATTERNS,
+        BINDINGS_WITH_VARIANT_NAME,
         UNUSED_MACROS,
         WARNINGS,
         UNUSED_FEATURES,
@@ -506,145 +528,3 @@
         SOFT_UNSTABLE,
     ]
 }
-
-// this could be a closure, but then implementing derive traits
-// becomes hacky (and it gets allocated)
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
-pub enum BuiltinLintDiagnostics {
-    Normal,
-    BareTraitObject(Span, /* is_global */ bool),
-    AbsPathWithModule(Span),
-    ProcMacroDeriveResolutionFallback(Span),
-    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
-    ElidedLifetimesInPaths(usize, Span, bool, Span, String),
-    UnknownCrateTypes(Span, String, String),
-    UnusedImports(String, Vec<(Span, String)>),
-    RedundantImport(Vec<(Span, bool)>, ast::Ident),
-    DeprecatedMacro(Option<Symbol>, Span),
-}
-
-pub fn add_elided_lifetime_in_path_suggestion(
-    sess: &Session,
-    db: &mut DiagnosticBuilder<'_>,
-    n: usize,
-    path_span: Span,
-    incl_angl_brckt: bool,
-    insertion_span: Span,
-    anon_lts: String,
-) {
-    let (replace_span, suggestion) = if incl_angl_brckt {
-        (insertion_span, anon_lts)
-    } else {
-        // When possible, prefer a suggestion that replaces the whole
-        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
-        // at a point (which makes for an ugly/confusing label)
-        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
-            // But our spans can get out of whack due to macros; if the place we think
-            // we want to insert `'_` isn't even within the path expression's span, we
-            // should bail out of making any suggestion rather than panicking on a
-            // subtract-with-overflow or string-slice-out-out-bounds (!)
-            // FIXME: can we do better?
-            if insertion_span.lo().0 < path_span.lo().0 {
-                return;
-            }
-            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
-            if insertion_index > snippet.len() {
-                return;
-            }
-            let (before, after) = snippet.split_at(insertion_index);
-            (path_span, format!("{}{}{}", before, anon_lts, after))
-        } else {
-            (insertion_span, anon_lts)
-        }
-    };
-    db.span_suggestion(
-        replace_span,
-        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
-        suggestion,
-        Applicability::MachineApplicable,
-    );
-}
-
-impl BuiltinLintDiagnostics {
-    pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
-        match self {
-            BuiltinLintDiagnostics::Normal => (),
-            BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
-                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
-                    Ok(ref s) if is_global => {
-                        (format!("dyn ({})", s), Applicability::MachineApplicable)
-                    }
-                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
-                    Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
-                };
-                db.span_suggestion(span, "use `dyn`", sugg, app);
-            }
-            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
-                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
-                    Ok(ref s) => {
-                        // FIXME(Manishearth) ideally the emitting code
-                        // can tell us whether or not this is global
-                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
-
-                        (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
-                    }
-                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
-                };
-                db.span_suggestion(span, "use `crate`", sugg, app);
-            }
-            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
-                db.span_label(
-                    span,
-                    "names from parent modules are not \
-                                     accessible without an explicit import",
-                );
-            }
-            BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
-                db.span_note(span_def, "the macro is defined here");
-            }
-            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-                n,
-                path_span,
-                incl_angl_brckt,
-                insertion_span,
-                anon_lts,
-            ) => {
-                add_elided_lifetime_in_path_suggestion(
-                    sess,
-                    db,
-                    n,
-                    path_span,
-                    incl_angl_brckt,
-                    insertion_span,
-                    anon_lts,
-                );
-            }
-            BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
-                db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
-            }
-            BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
-                if !replaces.is_empty() {
-                    db.tool_only_multipart_suggestion(
-                        &message,
-                        replaces,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
-                for (span, is_imported) in spans {
-                    let introduced = if is_imported { "imported" } else { "defined" };
-                    db.span_label(
-                        span,
-                        format!("the item `{}` is already {} here", ident, introduced),
-                    );
-                }
-            }
-            BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
-                stability::deprecation_suggestion(db, suggestion, span)
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}
diff --git a/src/librustc_session/node_id.rs b/src/librustc_session/node_id.rs
index 5e51c5a..9fefe90 100644
--- a/src/librustc_session/node_id.rs
+++ b/src/librustc_session/node_id.rs
@@ -1,4 +1,3 @@
-use rustc_index::vec::Idx;
 use rustc_serialize::{Decoder, Encoder};
 use rustc_span::ExpnId;
 use std::fmt;
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 656c1b0..4b5736a 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -772,8 +772,6 @@
         "set the current terminal width"),
     panic_abort_tests: bool = (false, parse_bool, [TRACKED],
         "support compiling tests with panic=abort"),
-    continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
-        "attempt to recover from parse errors (experimental)"),
     dep_tasks: bool = (false, parse_bool, [UNTRACKED],
         "print tasks that execute and the color their dep node gets (requires debug build)"),
     incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 6cc6a1e..a98cf92 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -1,15 +1,15 @@
 //! Contains `ParseSess` which holds state living beyond what one `Parser` might.
 //! It also serves as an input to the parser itself.
 
-use crate::lint::BufferedEarlyLint;
+use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
 use crate::node_id::NodeId;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{Lock, Lrc, Once};
-use rustc_errors::{
-    emitter::SilentEmitter, Applicability, ColorConfig, DiagnosticBuilder, Handler,
-};
-use rustc_feature::UnstableFeatures;
+use rustc_error_codes::E0658;
+use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
+use rustc_errors::{error_code, Applicability, DiagnosticBuilder};
+use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
@@ -62,6 +62,45 @@
     }
 }
 
+/// Construct a diagnostic for a language feature error due to the given `span`.
+/// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`.
+pub fn feature_err<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: impl Into<MultiSpan>,
+    explain: &str,
+) -> DiagnosticBuilder<'a> {
+    feature_err_issue(sess, feature, span, GateIssue::Language, explain)
+}
+
+/// Construct a diagnostic for a feature gate error.
+///
+/// This variant allows you to control whether it is a library or language feature.
+/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
+pub fn feature_err_issue<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: impl Into<MultiSpan>,
+    issue: GateIssue,
+    explain: &str,
+) -> DiagnosticBuilder<'a> {
+    let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658));
+
+    if let Some(n) = find_feature_issue(feature, issue) {
+        err.note(&format!(
+            "for more information, see https://github.com/rust-lang/rust/issues/{}",
+            n,
+        ));
+    }
+
+    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
+    if sess.unstable_features.is_nightly_build() {
+        err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
+    }
+
+    err
+}
+
 /// Info about a parsing session.
 pub struct ParseSess {
     pub span_diagnostic: Handler,
@@ -123,17 +162,18 @@
 
     pub fn buffer_lint(
         &self,
-        lint_id: &'static crate::lint::Lint,
+        lint: &'static Lint,
         span: impl Into<MultiSpan>,
-        id: NodeId,
+        node_id: NodeId,
         msg: &str,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
                 span: span.into(),
-                id,
+                node_id,
                 msg: msg.into(),
-                lint_id,
+                lint_id: LintId::of(lint),
+                diagnostic: BuiltinLintDiagnostics::Normal,
             });
         });
     }
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index dba5b9f..d979247 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -1124,6 +1124,32 @@
                   See https://github.com/rust-lang/rust/issues/61002 for details.",
         );
     }
+
+    // Sanitizers can only be used on some tested platforms.
+    if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer {
+        const ASAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const TSAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const LSAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
+
+        let supported_targets = match *sanitizer {
+            Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
+            Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
+            Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
+            Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
+        };
+
+        if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
+            sess.err(&format!(
+                "{:?}Sanitizer only works with the `{}` target",
+                sanitizer,
+                supported_targets.join("` or `")
+            ));
+        }
+    }
 }
 
 /// Hash value constructed out of all the `-C metadata` arguments passed to the
diff --git a/src/librustc_session/utils.rs b/src/librustc_session/utils.rs
index 7806f5e..fda11b6 100644
--- a/src/librustc_session/utils.rs
+++ b/src/librustc_session/utils.rs
@@ -2,11 +2,11 @@
 use rustc_data_structures::profiling::VerboseTimingGuard;
 
 impl Session {
-    pub fn timer<'a>(&'a self, what: &'a str) -> VerboseTimingGuard<'a> {
-        self.prof.sparse_pass(what)
+    pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> {
+        self.prof.verbose_generic_activity(what)
     }
-    pub fn time<R>(&self, what: &str, f: impl FnOnce() -> R) -> R {
-        self.prof.sparse_pass(what).run(f)
+    pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
+        self.prof.verbose_generic_activity(what).run(f)
     }
 }
 
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index a58c12f..5779d17 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -5,7 +5,6 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![feature(const_fn)]
 #![feature(crate_visibility_modifier)]
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
@@ -309,6 +308,11 @@
         self.ctxt() != SyntaxContext::root()
     }
 
+    /// Returns `true` if `span` originates in a derive-macro's expansion.
+    pub fn in_derive_expansion(self) -> bool {
+        matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
+    }
+
     #[inline]
     pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
         Span::new(lo, hi, SyntaxContext::root())
@@ -1052,7 +1056,7 @@
                 name_was_remapped,
                 unmapped_path: None,
                 // `crate_of_origin` has to be set by the importer.
-                // This value matches up with `rustc::hir::def_id::INVALID_CRATE`.
+                // This value matches up with `rustc_hir::def_id::INVALID_CRATE`.
                 // That constant is not available here, unfortunately.
                 crate_of_origin: std::u32::MAX - 1,
                 start_pos,
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index 0b9b9fe..fb5fcf4 100644
--- a/src/librustc_span/source_map.rs
+++ b/src/librustc_span/source_map.rs
@@ -499,14 +499,15 @@
         // and to the end of the line. Be careful because the line
         // numbers in Loc are 1-based, so we subtract 1 to get 0-based
         // lines.
-        for line_index in lo.line - 1..hi.line - 1 {
+        let hi_line = hi.line.saturating_sub(1);
+        for line_index in lo.line.saturating_sub(1)..hi_line {
             let line_len = lo.file.get_line(line_index).map(|s| s.chars().count()).unwrap_or(0);
             lines.push(LineInfo { line_index, start_col, end_col: CharPos::from_usize(line_len) });
             start_col = CharPos::from_usize(0);
         }
 
         // For the last line, it extends from `start_col` to `hi.col`:
-        lines.push(LineInfo { line_index: hi.line - 1, start_col, end_col: hi.col });
+        lines.push(LineInfo { line_index: hi_line, start_col, end_col: hi.col });
 
         Ok(FileLines { file: lo.file, lines })
     }
@@ -709,7 +710,7 @@
     pub fn next_point(&self, sp: Span) -> Span {
         let start_of_next_point = sp.hi().0;
 
-        let width = self.find_width_of_character_at_span(sp, true);
+        let width = self.find_width_of_character_at_span(sp.shrink_to_hi(), true);
         // If the width is 1, then the next span should point to the same `lo` and `hi`. However,
         // in the case of a multibyte character, where the width != 1, the next span should
         // span multiple bytes to include the whole character.
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index fea7274..a8b2db3 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -5,7 +5,6 @@
 use arena::DroplessArena;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
-use rustc_index::vec::Idx;
 use rustc_macros::{symbols, HashStable_Generic};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
@@ -220,6 +219,8 @@
         const_raw_ptr_deref,
         const_raw_ptr_to_usize_cast,
         const_transmute,
+        const_trait_bound_opt_out,
+        const_trait_impl,
         contents,
         context,
         convert,
@@ -342,6 +343,7 @@
         global_allocator,
         global_asm,
         globs,
+        half_open_range_patterns,
         hash,
         Hash,
         HashSet,
diff --git a/src/librustc_target/spec/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs
index 51eb231..a6c1d24 100644
--- a/src/librustc_target/spec/i386_apple_ios.rs
+++ b/src/librustc_target/spec/i386_apple_ios.rs
@@ -8,7 +8,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(),
+        data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:128-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs
index 7dfb2ba..033b87b 100644
--- a/src/librustc_target/spec/i686_apple_darwin.rs
+++ b/src/librustc_target/spec/i686_apple_darwin.rs
@@ -20,7 +20,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(),
+        data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:128-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "macos".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_linux_android.rs b/src/librustc_target/spec/i686_linux_android.rs
index 3f73d24..79242f2 100644
--- a/src/librustc_target/spec/i686_linux_android.rs
+++ b/src/librustc_target/spec/i686_linux_android.rs
@@ -18,7 +18,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_pc_windows_gnu.rs b/src/librustc_target/spec/i686_pc_windows_gnu.rs
index 9056e07..35fbf87 100644
--- a/src/librustc_target/spec/i686_pc_windows_gnu.rs
+++ b/src/librustc_target/spec/i686_pc_windows_gnu.rs
@@ -18,7 +18,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/i686_pc_windows_msvc.rs b/src/librustc_target/spec/i686_pc_windows_msvc.rs
index b160007..ffb66af 100644
--- a/src/librustc_target/spec/i686_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/i686_pc_windows_msvc.rs
@@ -19,7 +19,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/i686_unknown_cloudabi.rs b/src/librustc_target/spec/i686_unknown_cloudabi.rs
index f3b4063..729b1f6 100644
--- a/src/librustc_target/spec/i686_unknown_cloudabi.rs
+++ b/src/librustc_target/spec/i686_unknown_cloudabi.rs
@@ -13,7 +13,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "cloudabi".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_freebsd.rs b/src/librustc_target/spec/i686_unknown_freebsd.rs
index 71f05a1..88c944a 100644
--- a/src/librustc_target/spec/i686_unknown_freebsd.rs
+++ b/src/librustc_target/spec/i686_unknown_freebsd.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "freebsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_haiku.rs b/src/librustc_target/spec/i686_unknown_haiku.rs
index b807e4e..4dc27af 100644
--- a/src/librustc_target/spec/i686_unknown_haiku.rs
+++ b/src/librustc_target/spec/i686_unknown_haiku.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "haiku".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_linux_gnu.rs b/src/librustc_target/spec/i686_unknown_linux_gnu.rs
index 5875cbf..0d578f2 100644
--- a/src/librustc_target/spec/i686_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/i686_unknown_linux_gnu.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/i686_unknown_linux_musl.rs b/src/librustc_target/spec/i686_unknown_linux_musl.rs
index 7329490..699a0ab 100644
--- a/src/librustc_target/spec/i686_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/i686_unknown_linux_musl.rs
@@ -27,7 +27,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/i686_unknown_netbsd.rs b/src/librustc_target/spec/i686_unknown_netbsd.rs
index 01d2b2d..88b1ae7 100644
--- a/src/librustc_target/spec/i686_unknown_netbsd.rs
+++ b/src/librustc_target/spec/i686_unknown_netbsd.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "netbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_openbsd.rs b/src/librustc_target/spec/i686_unknown_openbsd.rs
index d7c323e..829cd1a 100644
--- a/src/librustc_target/spec/i686_unknown_openbsd.rs
+++ b/src/librustc_target/spec/i686_unknown_openbsd.rs
@@ -13,7 +13,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "openbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_uefi.rs b/src/librustc_target/spec/i686_unknown_uefi.rs
index e4b8b66..345590a 100644
--- a/src/librustc_target/spec/i686_unknown_uefi.rs
+++ b/src/librustc_target/spec/i686_unknown_uefi.rs
@@ -86,7 +86,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         target_os: "uefi".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
diff --git a/src/librustc_target/spec/i686_uwp_windows_gnu.rs b/src/librustc_target/spec/i686_uwp_windows_gnu.rs
index 1986474..93f396d 100644
--- a/src/librustc_target/spec/i686_uwp_windows_gnu.rs
+++ b/src/librustc_target/spec/i686_uwp_windows_gnu.rs
@@ -18,7 +18,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/i686_uwp_windows_msvc.rs b/src/librustc_target/spec/i686_uwp_windows_msvc.rs
index 5e8e8c2..ed2dba5 100644
--- a/src/librustc_target/spec/i686_uwp_windows_msvc.rs
+++ b/src/librustc_target/spec/i686_uwp_windows_msvc.rs
@@ -11,7 +11,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/i686_wrs_vxworks.rs b/src/librustc_target/spec/i686_wrs_vxworks.rs
index c5f9583..f5f66ca 100644
--- a/src/librustc_target/spec/i686_wrs_vxworks.rs
+++ b/src/librustc_target/spec/i686_wrs_vxworks.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "vxworks".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index f08634c..528ffdf 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -805,6 +805,9 @@
 
     /// Whether or not RelaxElfRelocation flag will be passed to the linker
     pub relax_elf_relocations: bool,
+
+    /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
+    pub llvm_args: Vec<String>,
 }
 
 impl Default for TargetOptions {
@@ -893,6 +896,7 @@
             target_mcount: "mcount".to_string(),
             llvm_abiname: "".to_string(),
             relax_elf_relocations: false,
+            llvm_args: vec![],
         }
     }
 }
@@ -1206,6 +1210,7 @@
         key!(target_mcount);
         key!(llvm_abiname);
         key!(relax_elf_relocations, bool);
+        key!(llvm_args, list);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1433,6 +1438,7 @@
         target_option_val!(target_mcount);
         target_option_val!(llvm_abiname);
         target_option_val!(relax_elf_relocations);
+        target_option_val!(llvm_args);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert(
diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs
index 002cee4..e846f42 100644
--- a/src/librustc_target/spec/x86_64_apple_darwin.rs
+++ b/src/librustc_target/spec/x86_64_apple_darwin.rs
@@ -20,7 +20,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: arch.to_string(),
         target_os: "macos".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs
index f8441f9..ca02e2d 100644
--- a/src/librustc_target/spec/x86_64_apple_ios.rs
+++ b/src/librustc_target/spec/x86_64_apple_ios.rs
@@ -8,7 +8,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
index 101d836..5f4f6ad 100644
--- a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
+++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
@@ -8,7 +8,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
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 6105eae..3e9552e 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -81,7 +81,8 @@
         target_os: "unknown".into(),
         target_env: "sgx".into(),
         target_vendor: "fortanix".into(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".into(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .into(),
         arch: "x86_64".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         options: opts,
diff --git a/src/librustc_target/spec/x86_64_fuchsia.rs b/src/librustc_target/spec/x86_64_fuchsia.rs
index 5b315bb..37b6d57 100644
--- a/src/librustc_target/spec/x86_64_fuchsia.rs
+++ b/src/librustc_target/spec/x86_64_fuchsia.rs
@@ -11,7 +11,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "fuchsia".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_linux_android.rs b/src/librustc_target/spec/x86_64_linux_android.rs
index c3c6c7b..74097f5 100644
--- a/src/librustc_target/spec/x86_64_linux_android.rs
+++ b/src/librustc_target/spec/x86_64_linux_android.rs
@@ -14,7 +14,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_linux_kernel.rs b/src/librustc_target/spec/x86_64_linux_kernel.rs
index a80b021..89070c9 100644
--- a/src/librustc_target/spec/x86_64_linux_kernel.rs
+++ b/src/librustc_target/spec/x86_64_linux_kernel.rs
@@ -19,7 +19,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         target_os: "none".to_string(),
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
diff --git a/src/librustc_target/spec/x86_64_pc_windows_gnu.rs b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
index 35e0d55..8f523a3 100644
--- a/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
@@ -11,7 +11,8 @@
         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(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_pc_windows_msvc.rs b/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
index 073d49b..75ff6b9 100644
--- a/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
@@ -11,7 +11,8 @@
         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(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
index d71112b..fbade02 100644
--- a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
@@ -18,7 +18,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "netbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_sun_solaris.rs b/src/librustc_target/spec/x86_64_sun_solaris.rs
index 3bf3f51..53f4df9 100644
--- a/src/librustc_target/spec/x86_64_sun_solaris.rs
+++ b/src/librustc_target/spec/x86_64_sun_solaris.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "solaris".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_cloudabi.rs b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
index d48120c..dbc5f96 100644
--- a/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
+++ b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
@@ -13,7 +13,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "cloudabi".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_dragonfly.rs b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
index f55ee69..fd1871b 100644
--- a/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "dragonfly".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_freebsd.rs b/src/librustc_target/spec/x86_64_unknown_freebsd.rs
index 1d9c5cc..a124f58 100644
--- a/src/librustc_target/spec/x86_64_unknown_freebsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_freebsd.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "freebsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_haiku.rs b/src/librustc_target/spec/x86_64_unknown_haiku.rs
index 4ab15fa..5123769 100644
--- a/src/librustc_target/spec/x86_64_unknown_haiku.rs
+++ b/src/librustc_target/spec/x86_64_unknown_haiku.rs
@@ -14,7 +14,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "haiku".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_hermit.rs b/src/librustc_target/spec/x86_64_unknown_hermit.rs
index c9123aa..4a526f9 100644
--- a/src/librustc_target/spec/x86_64_unknown_hermit.rs
+++ b/src/librustc_target/spec/x86_64_unknown_hermit.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "hermit".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs b/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs
index 0b1c834..c25cd08 100644
--- a/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs
+++ b/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs
@@ -14,7 +14,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "hermit".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs b/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
index e5fdb38..cab19f1 100644
--- a/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
+++ b/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
@@ -10,7 +10,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "l4re".to_string(),
         target_env: "uclibc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
index cb279e8..29cbb77 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
index 0b2d7aa..0a37399 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
@@ -16,7 +16,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_linux_musl.rs b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
index 2e1bc83..34c628e 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_netbsd.rs b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
index b0fad314..adf09c8 100644
--- a/src/librustc_target/spec/x86_64_unknown_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "netbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_openbsd.rs b/src/librustc_target/spec/x86_64_unknown_openbsd.rs
index f2abd10..dbd163d 100644
--- a/src/librustc_target/spec/x86_64_unknown_openbsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_openbsd.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "openbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_redox.rs b/src/librustc_target/spec/x86_64_unknown_redox.rs
index 8a5af27..3d40baf 100644
--- a/src/librustc_target/spec/x86_64_unknown_redox.rs
+++ b/src/librustc_target/spec/x86_64_unknown_redox.rs
@@ -12,7 +12,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "redox".to_string(),
         target_env: "relibc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_uefi.rs b/src/librustc_target/spec/x86_64_unknown_uefi.rs
index 443479f..7660b68 100644
--- a/src/librustc_target/spec/x86_64_unknown_uefi.rs
+++ b/src/librustc_target/spec/x86_64_unknown_uefi.rs
@@ -38,7 +38,8 @@
         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(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-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(),
diff --git a/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs b/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs
index da0c324..48366e2 100644
--- a/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs
+++ b/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs
@@ -11,7 +11,8 @@
         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(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
index 40dd52c..258df01 100644
--- a/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
+++ b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
@@ -11,7 +11,8 @@
         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(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_wrs_vxworks.rs b/src/librustc_target/spec/x86_64_wrs_vxworks.rs
index 1ab2f3a..f1e27f4 100644
--- a/src/librustc_target/spec/x86_64_wrs_vxworks.rs
+++ b/src/librustc_target/spec/x86_64_wrs_vxworks.rs
@@ -13,7 +13,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "vxworks".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml
index 979587f..2cb25e6 100644
--- a/src/librustc_traits/Cargo.toml
+++ b/src/librustc_traits/Cargo.toml
@@ -12,6 +12,7 @@
 log = { version = "0.4" }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
index b3983be..7512cbb 100644
--- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
@@ -1,10 +1,10 @@
 use crate::generic_types;
 use crate::lowering::Lower;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::traits::{Clause, GoalKind, ProgramClause, ProgramClauseCategory};
 use rustc::ty::subst::{GenericArg, InternalSubsts, Subst};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 
 /// Returns a predicate of the form
 /// `Implemented(ty: Trait) :- Implemented(nested: Trait)...`
diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs
index 0504602..38a4a72 100644
--- a/src/librustc_traits/chalk_context/program_clauses/mod.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/mod.rs
@@ -2,11 +2,11 @@
 mod primitive;
 
 use super::ChalkInferenceContext;
-use rustc::hir::def_id::DefId;
 use rustc::traits::{
     Clause, DomainGoal, Environment, FromEnv, ProgramClause, ProgramClauseCategory, WellFormed,
 };
 use rustc::ty::{self, TyCtxt};
+use rustc_hir::def_id::DefId;
 use std::iter;
 
 use self::builtin::*;
diff --git a/src/librustc_traits/chalk_context/program_clauses/primitive.rs b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
index 498a733..ae4afe5 100644
--- a/src/librustc_traits/chalk_context/program_clauses/primitive.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
@@ -1,11 +1,11 @@
 use crate::generic_types;
 use crate::lowering::Lower;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::traits::{
     Clause, Clauses, DomainGoal, GoalKind, ProgramClause, ProgramClauseCategory, WellFormed,
 };
 use rustc::ty::{self, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_target::spec::abi;
 use std::iter;
 
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index a0bbc28..bc4d03c 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -1,4 +1,3 @@
-use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::traits::query::dropck_outlives::trivial_dropck_outlives;
 use rustc::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint};
@@ -8,6 +7,7 @@
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::DefId;
 use rustc_span::source_map::{Span, DUMMY_SP};
 
 crate fn provide(p: &mut Providers<'_>) {
diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs
index a48468a..e1a9ec5 100644
--- a/src/librustc_traits/generic_types.rs
+++ b/src/librustc_traits/generic_types.rs
@@ -1,9 +1,9 @@
 //! Utilities for creating generic types with bound vars in place of parameter values.
 
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_target::spec::abi;
 
 crate fn bound(tcx: TyCtxt<'tcx>, index: u32) -> Ty<'tcx> {
diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs
index a58ec5b..40f821c 100644
--- a/src/librustc_traits/implied_outlives_bounds.rs
+++ b/src/librustc_traits/implied_outlives_bounds.rs
@@ -1,17 +1,17 @@
 //! Provider for the `implied_outlives_bounds` query.
 //! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`].
 
-use rustc::hir;
 use rustc::infer::canonical::{self, Canonical};
 use rustc::infer::InferCtxt;
 use rustc::traits::query::outlives_bounds::OutlivesBound;
 use rustc::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
+use rustc::traits::wf;
 use rustc::traits::FulfillmentContext;
 use rustc::traits::{TraitEngine, TraitEngineExt};
 use rustc::ty::outlives::Component;
 use rustc::ty::query::Providers;
-use rustc::ty::wf;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_hir as hir;
 use rustc_span::source_map::DUMMY_SP;
 use smallvec::{smallvec, SmallVec};
 
diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs
index c7e519a..315efe5 100644
--- a/src/librustc_traits/lowering/environment.rs
+++ b/src/librustc_traits/lowering/environment.rs
@@ -1,9 +1,9 @@
-use rustc::hir::def_id::DefId;
 use rustc::traits::{
     Clause, Clauses, DomainGoal, Environment, FromEnv, ProgramClause, ProgramClauseCategory,
 };
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::DefId;
 
 struct ClauseVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -151,7 +151,7 @@
 
 crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> {
     use super::{IntoFromEnvGoal, Lower};
-    use rustc::hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
+    use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
 
     debug!("environment(def_id = {:?})", def_id);
 
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index d23c701..4b4fa4b 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -1,10 +1,7 @@
 mod environment;
 
-use rustc::hir;
-use rustc::hir::def::DefKind;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::definitions::DefPathData;
+use rustc::hir::map::Map;
 use rustc::traits::{
     Clause, Clauses, DomainGoal, FromEnv, GoalKind, PolyDomainGoal, ProgramClause,
     ProgramClauseCategory, WellFormed, WhereClause,
@@ -12,6 +9,10 @@
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::{self, List, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::sym;
 use syntax::ast;
 
@@ -600,7 +601,9 @@
 }
 
 impl Visitor<'tcx> for ClauseDumper<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs
index 6b539b8..e50ca48 100644
--- a/src/librustc_traits/normalize_projection_ty.rs
+++ b/src/librustc_traits/normalize_projection_ty.rs
@@ -1,9 +1,9 @@
-use rustc::hir;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::traits::query::{normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution};
 use rustc::traits::{self, ObligationCause, SelectionContext, TraitEngineExt};
 use rustc::ty::query::Providers;
 use rustc::ty::{ParamEnvAnd, TyCtxt};
+use rustc_hir as hir;
 use rustc_span::DUMMY_SP;
 use std::sync::atomic::Ordering;
 
diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs
index 6357df6..149c42e 100644
--- a/src/librustc_traits/type_op.rs
+++ b/src/librustc_traits/type_op.rs
@@ -1,5 +1,3 @@
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::infer::at::ToTrace;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::infer::InferCtxt;
@@ -15,6 +13,8 @@
 use rustc::ty::{
     FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance,
 };
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::DUMMY_SP;
 use std::fmt;
 
diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml
deleted file mode 100644
index 82045dd..0000000
--- a/src/librustc_tsan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_tsan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_tsan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
deleted file mode 100644
index 570642a..0000000
--- a/src/librustc_tsan/build.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("tsan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-        native.fixup_sanitizer_lib_name("tsan");
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_tsan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index 167ba84..84e5f56 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -15,7 +15,8 @@
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 601a46a..dae394b 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -3,32 +3,34 @@
 //! instance of `AstConv`.
 
 use crate::collect::PlaceholderHirTyCollector;
-use crate::hir::def::{CtorOf, DefKind, Res};
-use crate::hir::def_id::DefId;
-use crate::hir::intravisit::Visitor;
-use crate::hir::print;
-use crate::hir::{self, ExprKind, GenericArg, GenericArgs};
 use crate::lint;
 use crate::middle::lang_items::SizedTraitLangItem;
 use crate::middle::resolve_lifetime as rl;
 use crate::namespace::Namespace;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::ErrorReported;
-use errors::{Applicability, DiagnosticId};
 use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
+use rustc::session::parse::feature_err;
 use rustc::traits;
+use rustc::traits::astconv_object_safety_violations;
+use rustc::traits::error_reporting::report_object_safety_error;
+use rustc::traits::wf::object_region_bounds;
 use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
-use rustc::ty::wf::object_region_bounds;
 use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::print;
+use rustc_hir::{ExprKind, GenericArg, GenericArgs};
 use rustc_span::symbol::sym;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use smallvec::SmallVec;
 use syntax::ast;
-use syntax::errors::pluralize;
-use syntax::feature_gate::feature_err;
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use std::collections::BTreeSet;
@@ -1116,13 +1118,14 @@
                 if unbound.is_none() {
                     unbound = Some(&ptr.trait_ref);
                 } else {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0203,
                         "type parameter has more than one relaxed default \
                         bound, only one is supported"
-                    );
+                    )
+                    .emit();
                 }
             }
         }
@@ -1442,7 +1445,13 @@
         }
 
         if regular_traits.is_empty() && auto_traits.is_empty() {
-            span_err!(tcx.sess, span, E0224, "at least one trait is required for an object type");
+            struct_span_err!(
+                tcx.sess,
+                span,
+                E0224,
+                "at least one trait is required for an object type"
+            )
+            .emit();
             return tcx.types.err;
         }
 
@@ -1451,9 +1460,10 @@
         // to avoid ICEs.
         for item in &regular_traits {
             let object_safety_violations =
-                tcx.astconv_object_safety_violations(item.trait_ref().def_id());
+                astconv_object_safety_violations(tcx, item.trait_ref().def_id());
             if !object_safety_violations.is_empty() {
-                tcx.report_object_safety_error(
+                report_object_safety_error(
+                    tcx,
                     span,
                     item.trait_ref().def_id(),
                     object_safety_violations,
@@ -1597,13 +1607,14 @@
                     self.ast_region_to_region(lifetime, None)
                 } else {
                     self.re_infer(None, span).unwrap_or_else(|| {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             span,
                             E0228,
                             "the lifetime bound for this object type cannot be deduced \
                              from context; please supply an explicit bound"
-                        );
+                        )
+                        .emit();
                         tcx.lifetimes.re_static
                     })
                 }
@@ -2113,9 +2124,13 @@
                     let msg = format!("expected type, found variant `{}`", assoc_ident);
                     tcx.sess.span_err(span, &msg);
                 } else if qself_ty.is_enum() {
-                    let mut err = tcx.sess.struct_span_err(
+                    let mut err = struct_span_err!(
+                        tcx.sess,
                         assoc_ident.span,
-                        &format!("no variant `{}` in enum `{}`", assoc_ident, qself_ty),
+                        E0599,
+                        "no variant named `{}` found for enum `{}`",
+                        assoc_ident,
+                        qself_ty,
                     );
 
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
@@ -2554,12 +2569,12 @@
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(path.segments);
                 match prim_ty {
-                    hir::Bool => tcx.types.bool,
-                    hir::Char => tcx.types.char,
-                    hir::Int(it) => tcx.mk_mach_int(it),
-                    hir::Uint(uit) => tcx.mk_mach_uint(uit),
-                    hir::Float(ft) => tcx.mk_mach_float(ft),
-                    hir::Str => tcx.mk_str(),
+                    hir::PrimTy::Bool => tcx.types.bool,
+                    hir::PrimTy::Char => tcx.types.char,
+                    hir::PrimTy::Int(it) => tcx.mk_mach_int(it),
+                    hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit),
+                    hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft),
+                    hir::PrimTy::Str => tcx.mk_str(),
                 }
             }
             Res::Err => {
@@ -2685,7 +2700,11 @@
         let def_id = tcx.hir().local_def_id(ast_const.hir_id);
 
         let mut const_ = ty::Const {
-            val: ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id)),
+            val: ty::ConstKind::Unevaluated(
+                def_id,
+                InternalSubsts::identity_for_item(tcx, def_id),
+                None,
+            ),
             ty,
         };
 
@@ -2773,11 +2792,11 @@
         }
         let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
         let output_ty = match decl.output {
-            hir::Return(ref output) => {
+            hir::FunctionRetTy::Return(ref output) => {
                 visitor.visit_ty(output);
                 self.ast_ty_to_ty(output)
             }
-            hir::DefaultReturn(..) => tcx.mk_unit(),
+            hir::FunctionRetTy::DefaultReturn(..) => tcx.mk_unit(),
         };
 
         debug!("ty_of_fn: output_ty={:?}", output_ty);
@@ -2791,7 +2810,7 @@
             // allowed. `allow_ty_infer` gates this behavior.
             crate::collect::placeholder_type_error(
                 tcx,
-                ident_span.unwrap_or(DUMMY_SP),
+                ident_span.map(|sp| sp.shrink_to_hi()).unwrap_or(DUMMY_SP),
                 generic_params,
                 visitor.0,
                 ident_span.is_some(),
@@ -2876,12 +2895,13 @@
         // error.
         let r = derived_region_bounds[0];
         if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
-            span_err!(
+            struct_span_err!(
                 tcx.sess,
                 span,
                 E0227,
                 "ambiguous lifetime bound, explicit lifetime bound required"
-            );
+            )
+            .emit();
         }
         return Some(r);
     }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 1f0bc6a..bd84547 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -1,10 +1,11 @@
 use crate::check::coercion::CoerceMany;
 use crate::check::{Diverges, Expectation, FnCtxt, Needs};
-use rustc::hir::{self, ExprKind};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::ObligationCauseCode;
 use rustc::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
 use rustc::ty::Ty;
+use rustc_hir as hir;
+use rustc_hir::ExprKind;
 use rustc_span::Span;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -219,7 +220,7 @@
         &self,
         span: Span,
         then_expr: &'tcx hir::Expr<'tcx>,
-        coercion: &mut CoerceMany<'tcx, '_, rustc::hir::Arm<'tcx>>,
+        coercion: &mut CoerceMany<'tcx, '_, rustc_hir::Arm<'tcx>>,
     ) -> bool {
         // If this `if` expr is the parent's function return expr,
         // the cause of the type coercion is the return type, point at it. (#25228)
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 45c9922..8d6b74c 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -1,13 +1,14 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs, PlaceOp};
 
-use rustc::hir;
 use rustc::infer::{InferCtxt, InferOk};
 use rustc::session::DiagnosticMessageId;
 use rustc::traits::{self, TraitEngine};
 use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc::ty::{self, TraitRef, Ty, TyCtxt};
 use rustc::ty::{ToPredicate, TypeFoldable};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
 
 use rustc_span::Span;
 use syntax::ast::Ident;
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 4b6bb2e..58f407b 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -1,23 +1,22 @@
 use super::autoderef::Autoderef;
 use super::method::MethodCallee;
 use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
+use crate::type_error_struct;
 
-use errors::{Applicability, DiagnosticBuilder};
-use hir::def::Res;
-use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::{infer, traits};
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use syntax::ast::Ident;
 
-use rustc::hir;
-
-use rustc_error_codes::*;
-
 /// Checks that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called).
@@ -241,7 +240,7 @@
         ) = (parent_node, callee_node)
         {
             let start = sp.shrink_to_lo();
-            let end = self.tcx.sess.source_map().next_point(callee_span);
+            let end = callee_span.shrink_to_hi();
             err.multipart_suggestion(
                 "if you meant to create this closure and immediately call it, surround the \
                 closure with parenthesis",
@@ -318,9 +317,8 @@
                             let call_is_multiline =
                                 self.tcx.sess.source_map().is_multiline(call_expr.span);
                             if call_is_multiline {
-                                let span = self.tcx.sess.source_map().next_point(callee.span);
                                 err.span_suggestion(
-                                    span,
+                                    callee.span.shrink_to_hi(),
                                     "try adding a semicolon",
                                     ";".to_owned(),
                                     Applicability::MaybeIncorrect,
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 445a723..ba5e5fd 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -32,17 +32,20 @@
 
 use crate::hir::def_id::DefId;
 use crate::lint;
+use crate::type_error_struct;
 use crate::util::common::ErrorReported;
-use errors::{Applicability, DiagnosticBuilder};
-use rustc::hir;
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::traits;
+use rustc::traits::error_reporting::report_object_safety_error;
+use rustc::traits::object_safety_violations;
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::cast::{CastKind, CastTy};
 use rustc::ty::error::TypeError;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
 use rustc_span::Span;
 use syntax::ast;
 
@@ -423,17 +426,16 @@
                             );
                         }
                         Err(_) => {
-                            span_help!(err, self.cast_span, "did you mean `&{}{}`?", mtstr, tstr)
+                            let msg = &format!("did you mean `&{}{}`?", mtstr, tstr);
+                            err.span_help(self.cast_span, msg);
                         }
                     }
                 } else {
-                    span_help!(
-                        err,
-                        self.span,
+                    let msg = &format!(
                         "consider using an implicit coercion to `&{}{}` instead",
-                        mtstr,
-                        tstr
+                        mtstr, tstr
                     );
+                    err.span_help(self.span, msg);
                 }
             }
             ty::Adt(def, ..) if def.is_box() => {
@@ -446,11 +448,13 @@
                             Applicability::MachineApplicable,
                         );
                     }
-                    Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
+                    Err(_) => {
+                        err.span_help(self.cast_span, &format!("did you mean `Box<{}>`?", tstr));
+                    }
                 }
             }
             _ => {
-                span_help!(err, self.expr.span, "consider using a box or reference as appropriate");
+                err.span_help(self.expr.span, "consider using a box or reference as appropriate");
             }
         }
         err.emit();
@@ -518,8 +522,8 @@
     }
 
     fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) {
-        let violations = fcx.tcx.object_safety_violations(did);
-        let mut err = fcx.tcx.report_object_safety_error(self.cast_span, did, violations);
+        let violations = object_safety_violations(fcx.tcx, did);
+        let mut err = report_object_safety_error(fcx.tcx, self.cast_span, did, violations);
         err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty)));
         err.emit();
     }
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 8bff95c..6bb7f49 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -4,8 +4,6 @@
 
 use crate::astconv::AstConv;
 use crate::middle::{lang_items, region};
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::LateBoundRegionConversionTime;
 use rustc::infer::{InferOk, InferResult};
@@ -14,6 +12,8 @@
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, GenericParamDefKind, Ty};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span::source_map::Span;
 use rustc_target::spec::abi::Abi;
 use std::cmp;
@@ -548,8 +548,8 @@
         // First, convert the types that the user supplied (if any).
         let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
         let supplied_return = match decl.output {
-            hir::Return(ref output) => astconv.ast_ty_to_ty(&output),
-            hir::DefaultReturn(_) => match body.generator_kind {
+            hir::FunctionRetTy::Return(ref output) => astconv.ast_ty_to_ty(&output),
+            hir::FunctionRetTy::DefaultReturn(_) => match body.generator_kind {
                 // In the case of the async block that we create for a function body,
                 // we expect the return type of the block to match that of the enclosing
                 // function.
@@ -696,7 +696,7 @@
             self.tcx.types.err
         });
 
-        if let hir::Return(ref output) = decl.output {
+        if let hir::FunctionRetTy::Return(ref output) = decl.output {
             astconv.ast_ty_to_ty(&output);
         }
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index f9cc86b..1afb703 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -51,11 +51,9 @@
 //! we may want to adjust precisely when coercions occur.
 
 use crate::check::{FnCtxt, Needs};
-use errors::DiagnosticBuilder;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::{Coercion, InferOk, InferResult};
+use rustc::session::parse::feature_err;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -65,14 +63,15 @@
 use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TypeAndMut};
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_span;
 use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
-use syntax::feature_gate;
-
-use rustc_error_codes::*;
 
 struct Coerce<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -544,7 +543,8 @@
         // and almost never more than 3. By using a SmallVec we avoid an
         // allocation, at the (very small) cost of (occasionally) having to
         // shift subsequent elements down when removing the front element.
-        let mut queue: SmallVec<[_; 4]> = smallvec![self.tcx.predicate_for_trait_def(
+        let mut queue: SmallVec<[_; 4]> = smallvec![traits::predicate_for_trait_def(
+            self.tcx,
             self.fcx.param_env,
             cause,
             coerce_unsized_did,
@@ -626,7 +626,7 @@
         }
 
         if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
-            feature_gate::feature_err(
+            feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::unsized_tuple_coercion,
                 self.cause.span,
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index d6ef388..c35661a 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1,6 +1,4 @@
-use errors::{Applicability, DiagnosticId};
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::{self, GenericParamKind, ImplItemKind, TraitItemKind};
+use rustc::hir::map::Map;
 use rustc::infer::{self, InferOk};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::error::{ExpectedFound, TypeError};
@@ -8,9 +6,12 @@
 use rustc::ty::util::ExplicitSelf;
 use rustc::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc::util::common::ErrorReported;
-
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::intravisit;
+use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_span::Span;
-use syntax::errors::pluralize;
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
 
@@ -877,9 +878,9 @@
                             _ => unreachable!(),
                         };
                         struct Visitor(Option<Span>, hir::def_id::DefId);
-                        impl<'v> hir::intravisit::Visitor<'v> for Visitor {
+                        impl<'v> intravisit::Visitor<'v> for Visitor {
                             fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
-                                hir::intravisit::walk_ty(self, ty);
+                                intravisit::walk_ty(self, ty);
                                 if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) =
                                     ty.kind
                                 {
@@ -890,16 +891,17 @@
                                     }
                                 }
                             }
-                            fn nested_visit_map<'this>(
-                                &'this mut self,
-                            ) -> hir::intravisit::NestedVisitorMap<'this, 'v>
+                            type Map = Map<'v>;
+                            fn nested_visit_map(
+                                &mut self,
+                            ) -> intravisit::NestedVisitorMap<'_, Self::Map>
                             {
-                                hir::intravisit::NestedVisitorMap::None
+                                intravisit::NestedVisitorMap::None
                             }
                         }
                         let mut visitor = Visitor(None, impl_def_id);
                         for ty in input_tys {
-                            hir::intravisit::Visitor::visit_ty(&mut visitor, ty);
+                            intravisit::Visitor::visit_ty(&mut visitor, ty);
                         }
                         let span = visitor.0?;
 
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 104321b..e0f9fcc 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -2,10 +2,11 @@
 use rustc::infer::InferOk;
 use rustc::traits::{self, ObligationCause};
 
-use errors::{Applicability, DiagnosticBuilder};
-use rustc::hir::{self, is_range_literal, print, Node};
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::{self, AssocItem, Ty};
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::{is_range_literal, print, Node};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::util::parser::PREC_POSTFIX;
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 004fce7..88e7a26 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -1,5 +1,4 @@
 use crate::check::regionck::RegionCtxt;
-
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::util::common::ErrorReported;
@@ -11,6 +10,7 @@
 use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc::ty::subst::{Subst, SubstsRef};
 use rustc::ty::{self, Predicate, Ty, TyCtxt};
+use rustc_errors::struct_span_err;
 
 use rustc_span::Span;
 
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 743a2c6..35342de 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -14,13 +14,9 @@
 use crate::check::FnCtxt;
 use crate::check::Needs;
 use crate::check::TupleArgumentsFlag::DontTupleArguments;
+use crate::type_error_struct;
 use crate::util::common::ErrorReported;
 
-use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc::hir;
-use rustc::hir::def::{CtorKind, DefKind, Res};
-use rustc::hir::def_id::DefId;
-use rustc::hir::{ExprKind, QPath};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::middle::lang_items;
@@ -31,6 +27,11 @@
 use rustc::ty::TypeFoldable;
 use rustc::ty::{AdtKind, Visibility};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{ExprKind, QPath};
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -306,11 +307,11 @@
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let expected_inner = match unop {
-            hir::UnNot | hir::UnNeg => expected,
-            hir::UnDeref => NoExpectation,
+            hir::UnOp::UnNot | hir::UnOp::UnNeg => expected,
+            hir::UnOp::UnDeref => NoExpectation,
         };
         let needs = match unop {
-            hir::UnDeref => needs,
+            hir::UnOp::UnDeref => needs,
             _ => Needs::None,
         };
         let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd, expected_inner, needs);
@@ -318,7 +319,7 @@
         if !oprnd_t.references_error() {
             oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
             match unop {
-                hir::UnDeref => {
+                hir::UnOp::UnDeref => {
                     if let Some(mt) = oprnd_t.builtin_deref(true) {
                         oprnd_t = mt.ty;
                     } else if let Some(ok) = self.try_overloaded_deref(expr.span, oprnd_t, needs) {
@@ -362,14 +363,14 @@
                         oprnd_t = tcx.types.err;
                     }
                 }
-                hir::UnNot => {
+                hir::UnOp::UnNot => {
                     let result = self.check_user_unop(expr, oprnd_t, unop);
                     // If it's builtin, we can reuse the type, this helps inference.
                     if !(oprnd_t.is_integral() || oprnd_t.kind == ty::Bool) {
                         oprnd_t = result;
                     }
                 }
-                hir::UnNeg => {
+                hir::UnOp::UnNeg => {
                     let result = self.check_user_unop(expr, oprnd_t, unop);
                     // If it's builtin, we can reuse the type, this helps inference.
                     if !oprnd_t.is_numeric() {
@@ -1108,13 +1109,14 @@
         // Prohibit struct expressions when non-exhaustive flag is set.
         let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
         if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
-            span_err!(
+            struct_span_err!(
                 self.tcx.sess,
                 expr.span,
                 E0639,
                 "cannot create non-exhaustive {} using struct expression",
                 adt.variant_descr()
-            );
+            )
+            .emit();
         }
 
         let error_happened = self.check_expr_struct_fields(
@@ -1152,12 +1154,13 @@
                             .insert(expr.hir_id, fru_field_types);
                     }
                     _ => {
-                        span_err!(
+                        struct_span_err!(
                             self.tcx.sess,
                             base_expr.span,
                             E0436,
                             "functional record update syntax requires a struct"
-                        );
+                        )
+                        .emit();
                     }
                 }
             }
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index 63aadd4..9d8805f 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -4,13 +4,15 @@
 //! types computed here.
 
 use super::FnCtxt;
-use rustc::hir::def::{CtorKind, DefKind, Res};
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::{self, Expr, ExprKind, Pat, PatKind};
+use rustc::hir::map::Map;
 use rustc::middle::region::{self, YieldData};
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Expr, ExprKind, Pat, PatKind};
 use rustc_span::Span;
 
 struct InteriorVisitor<'a, 'tcx> {
@@ -192,7 +194,9 @@
 // librustc/middle/region.rs since `expr_count` is compared against the results
 // there.
 impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index ce8edd7..0441514 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -2,17 +2,16 @@
 //! intrinsics that the compiler exposes.
 
 use crate::require_same_types;
+
 use rustc::traits::{ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
-
+use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::abi::Abi;
 
-use rustc::hir;
-
-use rustc_error_codes::*;
-
 use std::iter;
 
 fn equate_intrinsic_type<'tcx>(
@@ -413,19 +412,20 @@
                 (2, params, param(1))
             }
             Err(_) => {
-                span_err!(
+                struct_span_err!(
                     tcx.sess,
                     it.span,
                     E0439,
                     "invalid `simd_shuffle`, needs length: `{}`",
                     name
-                );
+                )
+                .emit();
                 return;
             }
         },
         _ => {
             let msg = format!("unrecognized platform-specific intrinsic function: `{}`", name);
-            tcx.sess.span_err(it.span, &msg);
+            tcx.sess.struct_span_err(it.span, &msg).emit();
             return;
         }
     };
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 0f4d7e2..636ea5b 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -4,7 +4,6 @@
 use crate::check::{callee, FnCtxt, Needs, PlaceOp};
 use crate::hir::def_id::DefId;
 use crate::hir::GenericArg;
-use rustc::hir;
 use rustc::infer::{self, InferOk};
 use rustc::traits;
 use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast};
@@ -12,6 +11,7 @@
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::{Subst, SubstsRef};
 use rustc::ty::{self, GenericParamDefKind, Ty};
+use rustc_hir as hir;
 use rustc_span::Span;
 
 use std::ops::Deref;
@@ -425,7 +425,7 @@
             match exprs.last().unwrap().kind {
                 hir::ExprKind::Field(ref expr, _)
                 | hir::ExprKind::Index(ref expr, _)
-                | hir::ExprKind::Unary(hir::UnDeref, ref expr) => exprs.push(&expr),
+                | hir::ExprKind::Unary(hir::UnOp::UnDeref, ref expr) => exprs.push(&expr),
                 _ => break,
             }
         }
@@ -471,7 +471,7 @@
                         &[index_expr_ty],
                     );
                 }
-                hir::ExprKind::Unary(hir::UnDeref, ref base_expr) => {
+                hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base_expr) => {
                     self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr, &[]);
                 }
                 _ => {}
@@ -596,7 +596,7 @@
         target_trait_def_id: DefId,
     ) -> ty::PolyTraitRef<'tcx> {
         let upcast_trait_refs =
-            self.tcx.upcast_choices(source_trait_ref.clone(), target_trait_def_id);
+            traits::upcast_choices(self.tcx, source_trait_ref.clone(), target_trait_def_id);
 
         // must be exactly one trait ref or we'd get an ambig error etc
         if upcast_trait_refs.len() != 1 {
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index fe168b7..711c285 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -12,10 +12,6 @@
 
 use crate::check::FnCtxt;
 use crate::namespace::Namespace;
-use errors::{Applicability, DiagnosticBuilder};
-use rustc::hir;
-use rustc::hir::def::{CtorOf, DefKind};
-use rustc::hir::def_id::DefId;
 use rustc::infer::{self, InferOk};
 use rustc::traits;
 use rustc::ty::subst::Subst;
@@ -23,6 +19,10 @@
 use rustc::ty::GenericParamDefKind;
 use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable};
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind};
+use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 use syntax::ast;
 
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 28c84c5..b2542cc 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -9,7 +9,6 @@
 use crate::hir::def_id::DefId;
 use crate::namespace::Namespace;
 
-use rustc::hir;
 use rustc::infer::canonical::OriginalQueryValues;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -29,6 +28,8 @@
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
 use std::cmp::max;
 use std::iter;
@@ -373,13 +374,14 @@
                 // so we do a future-compat lint here for the 2015 edition
                 // (see https://github.com/rust-lang/rust/issues/46906)
                 if self.tcx.sess.rust_2018() {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         span,
                         E0699,
                         "the type of this value must be known \
                                to call a method on a raw pointer on it"
-                    );
+                    )
+                    .emit();
                 } else {
                     self.tcx.lint_hir(
                         lint::builtin::TYVAR_BEHIND_RAW_POINTER,
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index fd92e37..b84e1d3 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -4,16 +4,19 @@
 use crate::check::FnCtxt;
 use crate::middle::lang_items::FnOnceTraitLangItem;
 use crate::namespace::Namespace;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::map as hir_map;
-use rustc::hir::{self, ExprKind, Node, QPath};
+use rustc::hir::map::Map;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Obligation;
 use rustc::ty::print::with_crate_prefix;
 use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit;
+use rustc_hir::{ExprKind, Node, QPath};
 use rustc_span::{source_map, FileName, Span};
 use syntax::ast;
 use syntax::util::lev_distance;
@@ -191,21 +194,19 @@
                         let item_span =
                             self.tcx.sess.source_map().def_span(self.tcx.def_span(item.def_id));
                         let idx = if sources.len() > 1 {
-                            span_note!(
-                                err,
-                                item_span,
+                            let msg = &format!(
                                 "candidate #{} is defined in the trait `{}`",
                                 idx + 1,
                                 self.tcx.def_path_str(trait_did)
                             );
+                            err.span_note(item_span, msg);
                             Some(idx + 1)
                         } else {
-                            span_note!(
-                                err,
-                                item_span,
+                            let msg = &format!(
                                 "the candidate is defined in the trait `{}`",
                                 self.tcx.def_path_str(trait_did)
                             );
+                            err.span_note(item_span, msg);
                             None
                         };
                         let path = self.tcx.def_path_str(trait_did);
@@ -359,10 +360,11 @@
                             tcx.sess,
                             span,
                             E0599,
-                            "no {} named `{}` found for type `{}` in the current scope",
+                            "no {} named `{}` found for {} `{}` in the current scope",
                             item_kind,
                             item_name,
-                            ty_str
+                            actual.prefix_string(),
+                            ty_str,
                         );
                         if let Some(span) =
                             tcx.sess.confused_type_with_std_module.borrow().get(&span)
@@ -1073,18 +1075,18 @@
         target_module: hir::HirId,
     ) -> (Option<Span>, bool) {
         let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
-        hir::intravisit::walk_crate(&mut finder, krate);
+        intravisit::walk_crate(&mut finder, krate);
         (finder.span, finder.found_use)
     }
 }
 
-impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
+impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
     fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
         if self.span.is_some() {
             return;
         }
         if hir_id != self.target_module {
-            hir::intravisit::walk_mod(self, module, hir_id);
+            intravisit::walk_mod(self, module, hir_id);
             return;
         }
         // Find a `use` statement.
@@ -1124,8 +1126,10 @@
         }
     }
 
-    fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> {
-        hir::intravisit::NestedVisitorMap::None
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+        intravisit::NestedVisitorMap::None
     }
 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 3122086..92a7e18 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -90,12 +90,7 @@
 use crate::astconv::{AstConv, PathSeg};
 use crate::middle::lang_items;
 use crate::namespace::Namespace;
-use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc::hir::def::{CtorOf, DefKind, Res};
-use rustc::hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::{self, ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath};
+use rustc::hir::map::Map;
 use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc::infer::opaque_types::OpaqueTypeDecl;
@@ -104,6 +99,8 @@
 use rustc::infer::{self, InferCtxt, InferOk, InferResult};
 use rustc::middle::region;
 use rustc::mir::interpret::ConstValue;
+use rustc::session::parse::feature_err;
+use rustc::traits::error_reporting::recursive_type_with_infinite_size_error;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -117,7 +114,15 @@
     self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef,
     ToPredicate, Ty, TyCtxt, UserType,
 };
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::{ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath};
 use rustc_index::vec::Idx;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{original_sp, DUMMY_SP};
@@ -126,7 +131,6 @@
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
-use syntax::feature_gate::feature_err;
 use syntax::util::parser::ExprPrecedence;
 
 use rustc_error_codes::*;
@@ -143,7 +147,6 @@
 use crate::require_c_abi_if_c_variadic;
 use crate::session::config::EntryFnType;
 use crate::session::Session;
-use crate::util::captures::Captures;
 use crate::util::common::{indenter, ErrorReported};
 use crate::TypeAndSubsts;
 
@@ -155,6 +158,17 @@
 pub use self::Expectation::*;
 use self::TupleArgumentsFlag::*;
 
+#[macro_export]
+macro_rules! type_error_struct {
+    ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
+        if $typ.references_error() {
+            $session.diagnostic().struct_dummy()
+        } else {
+            rustc_errors::struct_span_err!($session, $span, $code, $($message)*)
+        }
+    })
+}
+
 /// The type of a local binding, including the revealed type for anon types.
 #[derive(Copy, Clone, Debug)]
 pub struct LocalTy<'tcx> {
@@ -390,6 +404,7 @@
     }
 
     pub fn recurse(&mut self, blk: &hir::Block<'_>) -> UnsafetyState {
+        use hir::BlockCheckMode;
         match self.unsafety {
             // If this unsafe, then if the outer function was already marked as
             // unsafe we shouldn't attribute the unsafe'ness to the block. This
@@ -399,16 +414,16 @@
 
             unsafety => {
                 let (unsafety, def, count) = match blk.rules {
-                    hir::PushUnsafeBlock(..) => {
+                    BlockCheckMode::PushUnsafeBlock(..) => {
                         (unsafety, blk.hir_id, self.unsafe_push_count.checked_add(1).unwrap())
                     }
-                    hir::PopUnsafeBlock(..) => {
+                    BlockCheckMode::PopUnsafeBlock(..) => {
                         (unsafety, blk.hir_id, self.unsafe_push_count.checked_sub(1).unwrap())
                     }
-                    hir::UnsafeBlock(..) => {
+                    BlockCheckMode::UnsafeBlock(..) => {
                         (hir::Unsafety::Unsafe, blk.hir_id, self.unsafe_push_count)
                     }
-                    hir::DefaultBlock => (unsafety, self.def, self.unsafe_push_count),
+                    BlockCheckMode::DefaultBlock => (unsafety, self.def, self.unsafe_push_count),
                 };
                 UnsafetyState { def, unsafety, unsafe_push_count: count, from_fn: false }
             }
@@ -1156,7 +1171,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1898,7 +1915,7 @@
         match parent_item {
             // Parent impl exists, and contains the parent item we're trying to specialize, but
             // doesn't mark it `default`.
-            Some(parent_item) if tcx.impl_item_is_final(&parent_item) => {
+            Some(parent_item) if traits::impl_item_is_final(tcx, &parent_item) => {
                 Some(Err(parent_impl.def_id()))
             }
 
@@ -1909,7 +1926,7 @@
             // grandparent. In that case, if parent is a `default impl`, inherited items use the
             // "defaultness" from the grandparent, else they are final.
             None => {
-                if tcx.impl_is_default(parent_impl.def_id()) {
+                if traits::impl_is_default(tcx, parent_impl.def_id()) {
                     None
                 } else {
                     Some(Err(parent_impl.def_id()))
@@ -2073,7 +2090,7 @@
             .map(|node_item| !node_item.node.is_from_trait())
             .unwrap_or(false);
 
-        if !is_implemented && !tcx.impl_is_default(impl_id) {
+        if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
             if !trait_item.defaultness.has_value() {
                 missing_items.push(trait_item);
             } else if associated_type_overridden {
@@ -2088,7 +2105,7 @@
 
     if !invalidated_items.is_empty() {
         let invalidator = overridden_associated_type.unwrap();
-        span_err!(
+        struct_span_err!(
             tcx.sess,
             invalidator.span,
             E0399,
@@ -2096,6 +2113,7 @@
             invalidator.ident,
             invalidated_items.iter().map(|name| name.to_string()).collect::<Vec<_>>().join("`, `")
         )
+        .emit();
     }
 }
 
@@ -2220,7 +2238,7 @@
     // caught by case 1.
     match rty.is_representable(tcx, sp) {
         Representability::SelfRecursive(spans) => {
-            let mut err = tcx.recursive_type_with_infinite_size_error(item_def_id);
+            let mut err = recursive_type_with_infinite_size_error(tcx, item_def_id);
             for span in spans {
                 err.span_label(span, "recursive without indirection");
             }
@@ -2238,7 +2256,7 @@
         if def.is_struct() {
             let fields = &def.non_enum_variant().fields;
             if fields.is_empty() {
-                span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
+                struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
                 return;
             }
             let e = fields[0].ty(tcx, substs);
@@ -2252,12 +2270,13 @@
                 ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
                 _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         sp,
                         E0077,
                         "SIMD vector element type should be machine type"
-                    );
+                    )
+                    .emit();
                     return;
                 }
             }
@@ -2542,14 +2561,15 @@
 }
 
 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &QPath<'_>) {
-    span_err!(
+    struct_span_err!(
         tcx.sess,
         span,
         E0533,
         "expected unit struct, unit variant or constant, found {} `{}`",
         res.descr(),
         hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))
-    );
+    )
+    .emit();
 }
 
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
@@ -3759,13 +3779,14 @@
                     arg_types.iter().map(|k| k.expect_ty()).collect()
                 }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         sp,
                         E0059,
                         "cannot use call notation; the first type parameter \
                          for the function trait is neither a tuple nor unit"
-                    );
+                    )
+                    .emit();
                     expected_arg_tys = vec![];
                     self.err_args(args.len())
                 }
@@ -4725,14 +4746,13 @@
                         .join(", ");
                 }
                 Some(Node::Expr(hir::Expr {
-                    kind: ExprKind::Closure(_, _, body_id, closure_span, _),
+                    kind: ExprKind::Closure(_, _, body_id, _, _),
                     span: full_closure_span,
                     ..
                 })) => {
                     if *full_closure_span == expr.span {
                         return false;
                     }
-                    err.span_label(*closure_span, "closure defined here");
                     msg = "call this closure";
                     let body = hir.body(*body_id);
                     sugg_call = body
@@ -4932,9 +4952,8 @@
                 | ExprKind::Loop(..)
                 | ExprKind::Match(..)
                 | ExprKind::Block(..) => {
-                    let sp = self.tcx.sess.source_map().next_point(cause_span);
                     err.span_suggestion(
-                        sp,
+                        cause_span.shrink_to_hi(),
                         "try adding a semicolon",
                         ";".to_string(),
                         Applicability::MachineApplicable,
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index e0035c4..edf9d19 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -2,12 +2,12 @@
 
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs};
-use errors::{self, Applicability};
-use rustc::hir;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, Uint};
 use rustc::ty::{self, Ty, TypeFoldable};
+use rustc_errors::{self, struct_span_err, Applicability};
+use rustc_hir as hir;
 use rustc_span::Span;
 use syntax::ast::Ident;
 
@@ -279,7 +279,7 @@
                                             lhs_expr.span,
                                             msg,
                                             format!("*{}", lstring),
-                                            errors::Applicability::MachineApplicable,
+                                            rustc_errors::Applicability::MachineApplicable,
                                         );
                                         suggested_deref = true;
                                     }
@@ -330,7 +330,7 @@
                                     Some("std::ops::Add"),
                                 ),
                                 hir::BinOpKind::Sub => (
-                                    format!("cannot substract `{}` from `{}`", rhs_ty, lhs_ty),
+                                    format!("cannot subtract `{}` from `{}`", rhs_ty, lhs_ty),
                                     Some("std::ops::Sub"),
                                 ),
                                 hir::BinOpKind::Mul => (
@@ -482,7 +482,7 @@
     /// suggest calling the function. Returns wether a suggestion was given.
     fn add_type_neq_err_label(
         &self,
-        err: &mut errors::DiagnosticBuilder<'_>,
+        err: &mut rustc_errors::DiagnosticBuilder<'_>,
         span: Span,
         ty: Ty<'tcx>,
         other_ty: Ty<'tcx>,
@@ -565,7 +565,7 @@
         rhs_expr: &'tcx hir::Expr<'tcx>,
         lhs_ty: Ty<'tcx>,
         rhs_ty: Ty<'tcx>,
-        err: &mut errors::DiagnosticBuilder<'_>,
+        err: &mut rustc_errors::DiagnosticBuilder<'_>,
         is_assign: bool,
         op: hir::BinOp,
     ) -> bool {
@@ -689,16 +689,16 @@
                         ),
                     );
                     match actual.kind {
-                        Uint(_) if op == hir::UnNeg => {
+                        Uint(_) if op == hir::UnOp::UnNeg => {
                             err.note("unsigned values cannot be negated");
                         }
                         Str | Never | Char | Tuple(_) | Array(_, _) => {}
                         Ref(_, ref lty, _) if lty.kind == Str => {}
                         _ => {
                             let missing_trait = match op {
-                                hir::UnNeg => "std::ops::Neg",
-                                hir::UnNot => "std::ops::Not",
-                                hir::UnDeref => "std::ops::UnDerf",
+                                hir::UnOp::UnNeg => "std::ops::Neg",
+                                hir::UnOp::UnNot => "std::ops::Not",
+                                hir::UnOp::UnDeref => "std::ops::UnDerf",
                             };
                             err.note(&format!(
                                 "an implementation of `{}` might \
@@ -771,9 +771,9 @@
                     span_bug!(span, "&& and || are not overloadable")
                 }
             }
-        } else if let Op::Unary(hir::UnNot, _) = op {
+        } else if let Op::Unary(hir::UnOp::UnNot, _) = op {
             ("not", lang.not_trait())
-        } else if let Op::Unary(hir::UnNeg, _) = op {
+        } else if let Op::Unary(hir::UnOp::UnNeg, _) = op {
             ("neg", lang.neg_trait())
         } else {
             bug!("lookup_op_method: op not supported: {:?}", op)
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 8e5e5c3..1478b35 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1,14 +1,15 @@
 use crate::check::FnCtxt;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc::hir::def::{CtorKind, DefKind, Res};
-use rustc::hir::pat_util::EnumerateAndAdjustIterator;
-use rustc::hir::{self, HirId, Pat, PatKind};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Pattern;
 use rustc::ty::subst::GenericArg;
 use rustc::ty::{self, BindingMode, Ty, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::pat_util::EnumerateAndAdjustIterator;
+use rustc_hir::{HirId, Pat, PatKind};
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::Span;
 use syntax::ast;
@@ -134,12 +135,7 @@
         let ty = match pat.kind {
             PatKind::Wild => expected,
             PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
-            PatKind::Range(begin, end, _) => {
-                match self.check_pat_range(pat.span, begin, end, expected, ti) {
-                    None => return,
-                    Some(ty) => ty,
-                }
-            }
+            PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
             PatKind::Binding(ba, var_id, _, sub) => {
                 self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, ti)
             }
@@ -394,39 +390,49 @@
     fn check_pat_range(
         &self,
         span: Span,
-        lhs: &'tcx hir::Expr<'tcx>,
-        rhs: &'tcx hir::Expr<'tcx>,
+        lhs: Option<&'tcx hir::Expr<'tcx>>,
+        rhs: Option<&'tcx hir::Expr<'tcx>>,
         expected: Ty<'tcx>,
         ti: TopInfo<'tcx>,
-    ) -> Option<Ty<'tcx>> {
-        let lhs_ty = self.check_expr(lhs);
-        let rhs_ty = self.check_expr(rhs);
+    ) -> Ty<'tcx> {
+        let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
+            None => (None, None),
+            Some(expr) => {
+                let ty = self.check_expr(expr);
+                // Check that the end-point is of numeric or char type.
+                let fail = !(ty.is_numeric() || ty.is_char() || ty.references_error());
+                (Some(ty), Some((fail, ty, expr.span)))
+            }
+        };
+        let (lhs_ty, lhs) = calc_side(lhs);
+        let (rhs_ty, rhs) = calc_side(rhs);
 
-        // Check that both end-points are of numeric or char type.
-        let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char() || ty.references_error();
-        let lhs_fail = !numeric_or_char(lhs_ty);
-        let rhs_fail = !numeric_or_char(rhs_ty);
-
-        if lhs_fail || rhs_fail {
-            self.emit_err_pat_range(span, lhs.span, rhs.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
-            return None;
+        if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
+            // There exists a side that didn't meet our criteria that the end-point
+            // be of a numeric or char type, as checked in `calc_side` above.
+            self.emit_err_pat_range(span, lhs, rhs);
+            return self.tcx.types.err;
         }
 
-        // Now that we know the types can be unified we find the unified type and use
-        // it to type the entire expression.
-        let common_type = self.resolve_vars_if_possible(&lhs_ty);
+        // Now that we know the types can be unified we find the unified type
+        // and use it to type the entire expression.
+        let common_type = self.resolve_vars_if_possible(&lhs_ty.or(rhs_ty).unwrap_or(expected));
 
         // Subtyping doesn't matter here, as the value is some kind of scalar.
-        let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
-            self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
-                self.endpoint_has_type(&mut err, y_span, y_ty);
-                err.emit();
-            });
+        let demand_eqtype = |x, y| {
+            if let Some((_, x_ty, x_span)) = x {
+                self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
+                    if let Some((_, y_ty, y_span)) = y {
+                        self.endpoint_has_type(&mut err, y_span, y_ty);
+                    }
+                    err.emit();
+                });
+            }
         };
-        demand_eqtype(lhs.span, rhs.span, lhs_ty, rhs_ty);
-        demand_eqtype(rhs.span, lhs.span, rhs_ty, lhs_ty);
+        demand_eqtype(lhs, rhs);
+        demand_eqtype(rhs, lhs);
 
-        Some(common_type)
+        common_type
     }
 
     fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) {
@@ -438,21 +444,15 @@
     fn emit_err_pat_range(
         &self,
         span: Span,
-        begin_span: Span,
-        end_span: Span,
-        lhs_fail: bool,
-        rhs_fail: bool,
-        lhs_ty: Ty<'tcx>,
-        rhs_ty: Ty<'tcx>,
+        lhs: Option<(bool, Ty<'tcx>, Span)>,
+        rhs: Option<(bool, Ty<'tcx>, Span)>,
     ) {
-        let span = if lhs_fail && rhs_fail {
-            span
-        } else if lhs_fail {
-            begin_span
-        } else {
-            end_span
+        let span = match (lhs, rhs) {
+            (Some((true, ..)), Some((true, ..))) => span,
+            (Some((true, _, sp)), _) => sp,
+            (_, Some((true, _, sp))) => sp,
+            _ => span_bug!(span, "emit_err_pat_range: no side failed or exists but still error?"),
         };
-
         let mut err = struct_span_err!(
             self.tcx.sess,
             span,
@@ -460,17 +460,20 @@
             "only char and numeric types are allowed in range patterns"
         );
         let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
-        let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
+        let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
             err.span_label(first_span, &msg(first_ty));
-            self.endpoint_has_type(&mut err, second_span, second_ty);
+            if let Some((_, ty, sp)) = second {
+                self.endpoint_has_type(&mut err, sp, ty);
+            }
         };
-        if lhs_fail && rhs_fail {
-            err.span_label(begin_span, &msg(lhs_ty));
-            err.span_label(end_span, &msg(rhs_ty));
-        } else if lhs_fail {
-            one_side_err(begin_span, lhs_ty, end_span, rhs_ty);
-        } else {
-            one_side_err(end_span, rhs_ty, begin_span, lhs_ty);
+        match (lhs, rhs) {
+            (Some((true, lhs_ty, lhs_sp)), Some((true, rhs_ty, rhs_sp))) => {
+                err.span_label(lhs_sp, &msg(lhs_ty));
+                err.span_label(rhs_sp, &msg(rhs_ty));
+            }
+            (Some((true, lhs_ty, lhs_sp)), rhs) => one_side_err(lhs_sp, lhs_ty, rhs),
+            (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
+            _ => span_bug!(span, "Impossible, verified above."),
         }
         if self.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
@@ -982,22 +985,25 @@
 
         // Require `..` if struct has non_exhaustive attribute.
         if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
-            span_err!(
+            struct_span_err!(
                 tcx.sess,
                 span,
                 E0638,
                 "`..` required with {} marked as non-exhaustive",
                 kind_name
-            );
+            )
+            .emit();
         }
 
         // Report an error if incorrect number of the fields were specified.
         if kind_name == "union" {
             if fields.len() != 1 {
-                tcx.sess.span_err(span, "union patterns should have exactly one field");
+                tcx.sess
+                    .struct_span_err(span, "union patterns should have exactly one field")
+                    .emit();
             }
             if etc {
-                tcx.sess.span_err(span, "`..` cannot be used in union patterns");
+                tcx.sess.struct_span_err(span, "`..` cannot be used in union patterns").emit();
             }
         } else if !etc && unmentioned_fields.len() > 0 {
             self.error_unmentioned_fields(span, &unmentioned_fields, variant);
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 90d8d06..9677410 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -76,15 +76,16 @@
 use crate::check::FnCtxt;
 use crate::mem_categorization as mc;
 use crate::middle::region;
-use rustc::hir::def_id::DefId;
+use rustc::hir::map::Map;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::{self, RegionObligation, SuppressRegionErrors};
 use rustc::ty::adjustment;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::{self, Ty};
-
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::{self, PatKind};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::PatKind;
 use rustc_span::Span;
 use std::mem;
 use std::ops::Deref;
@@ -414,7 +415,9 @@
     // hierarchy, and in particular the relationships between free
     // regions, until regionck, as described in #3238.
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -492,7 +495,7 @@
         if is_method_call {
             let origin = match expr.kind {
                 hir::ExprKind::MethodCall(..) => infer::ParameterOrigin::MethodCall,
-                hir::ExprKind::Unary(op, _) if op == hir::UnDeref => {
+                hir::ExprKind::Unary(op, _) if op == hir::UnOp::UnDeref => {
                     infer::ParameterOrigin::OverloadedDeref
                 }
                 _ => infer::ParameterOrigin::OverloadedOperator,
@@ -577,7 +580,7 @@
                 intravisit::walk_expr(self, expr);
             }
 
-            hir::ExprKind::Unary(hir::UnDeref, ref base) => {
+            hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base) => {
                 // For *a, the lifetime of a must enclose the deref
                 if is_method_call {
                     self.constrain_call(expr, Some(base), None::<hir::Expr<'_>>.iter());
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 4376f9b..e4502bf 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -35,13 +35,14 @@
 use crate::expr_use_visitor as euv;
 use crate::mem_categorization as mc;
 use crate::mem_categorization::PlaceBase;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::def_id::LocalDefId;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::infer::UpvarRegion;
 use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::Span;
 use syntax::ast;
 
@@ -59,7 +60,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -209,7 +212,7 @@
         }
     }
 
-    // Returns a list of `ClosureUpvar`s for each upvar.
+    // Returns a list of `Ty`s for each upvar.
     fn final_upvar_tys(&self, closure_id: hir::HirId) -> Vec<Ty<'tcx>> {
         // Presently an unboxed closure type cannot "escape" out of a
         // function, so we will only encounter ones that originated in the
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index e9df155..a496a6e 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -1,23 +1,22 @@
 use crate::check::{FnCtxt, Inherited};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
-use rustc::hir::def_id::DefId;
-use rustc::hir::ItemKind;
 use rustc::infer::opaque_types::may_define_opaque_type;
 use rustc::middle::lang_items;
+use rustc::session::parse::feature_err;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-
-use errors::DiagnosticBuilder;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_hir::def_id::DefId;
+use rustc_hir::ItemKind;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast;
-use syntax::feature_gate;
 
-use rustc::hir;
-use rustc::hir::itemlikevisit::ParItemLikeVisitor;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 
 use rustc_error_codes::*;
 
@@ -113,13 +112,14 @@
                 ty::ImplPolarity::Negative => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
                     if trait_ref.is_some() && !is_auto {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             item.span,
                             E0192,
                             "negative impls are only allowed for \
                                    auto traits (e.g., `Send` and `Sync`)"
                         )
+                        .emit()
                     }
                 }
                 ty::ImplPolarity::Reservation => {
@@ -417,7 +417,7 @@
                 let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
                 let trait_ref =
                     fcx.normalize_associated_types_in(ast_trait_ref.path.span, &trait_ref);
-                let obligations = ty::wf::trait_obligations(
+                let obligations = traits::wf::trait_obligations(
                     fcx,
                     fcx.param_env,
                     fcx.body_id,
@@ -596,7 +596,7 @@
     let wf_obligations = predicates
         .predicates
         .iter()
-        .flat_map(|p| ty::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, span));
+        .flat_map(|p| traits::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, span));
 
     for obligation in wf_obligations.chain(default_obligations) {
         debug!("next obligation cause: {:?}", obligation.cause);
@@ -821,7 +821,7 @@
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
             if receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
                 // Report error; would have worked with `arbitrary_self_types`.
-                feature_gate::feature_err(
+                feature_err(
                     &fcx.tcx.sess.parse_sess,
                     sym::arbitrary_self_types,
                     span,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 0fbc14a..b4798fb 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -4,15 +4,16 @@
 
 use crate::check::FnCtxt;
 
-use rustc::hir;
-use rustc::hir::def_id::{DefId, DefIdSet, DefIndex};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc::infer::InferCtxt;
 use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, DefIdSet, DefIndex};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -133,8 +134,8 @@
     // operating on scalars, we clear the overload.
     fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr<'_>) {
         match e.kind {
-            hir::ExprKind::Unary(hir::UnNeg, ref inner)
-            | hir::ExprKind::Unary(hir::UnNot, ref inner) => {
+            hir::ExprKind::Unary(hir::UnOp::UnNeg, ref inner)
+            | hir::ExprKind::Unary(hir::UnOp::UnNot, ref inner) => {
                 let inner_ty = self.fcx.node_ty(inner.hir_id);
                 let inner_ty = self.fcx.resolve_vars_if_possible(&inner_ty);
 
@@ -242,7 +243,9 @@
 // traffic in node-ids or update tables in the type context etc.
 
 impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index b0cbabd..ec098c1 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -1,16 +1,14 @@
 use crate::lint;
 use rustc::ty::TyCtxt;
-
-use errors::Applicability;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::print::visibility_qualified;
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc::hir;
-use rustc::hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::print::visibility_qualified;
-use rustc_data_structures::fx::FxHashMap;
-
 pub fn check_crate(tcx: TyCtxt<'_>) {
     let mut used_trait_imports = DefIdSet::default();
     for &body_id in tcx.hir().krate().bodies.keys() {
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 7e016cf..8b3db15 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -1,22 +1,22 @@
 //! Check properties that are required by built-in traits and set
 //! up data structures required by type-checking/codegen.
 
+use rustc::infer;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::SuppressRegionErrors;
 use rustc::middle::lang_items::UnsizeTraitLangItem;
 use rustc::middle::region;
-
-use rustc::infer;
+use rustc::traits::misc::{can_type_implement_copy, CopyImplementationError};
+use rustc::traits::predicate_for_trait_def;
 use rustc::traits::{self, ObligationCause, TraitEngine};
 use rustc::ty::adjustment::CoerceUnsizedInfo;
-use rustc::ty::util::CopyImplementationError;
 use rustc::ty::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt};
-
-use rustc::hir::def_id::DefId;
-use rustc::hir::{self, ItemKind};
-
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::ItemKind;
 
 pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
@@ -90,7 +90,7 @@
 
     debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
 
-    match param_env.can_type_implement_copy(tcx, self_type) {
+    match can_type_implement_copy(tcx, param_env, self_type) {
         Ok(()) => {}
         Err(CopyImplementationError::InfrigingFields(fields)) => {
             let item = tcx.hir().expect_item(impl_hir_id);
@@ -283,7 +283,8 @@
                         let mut fulfill_cx = TraitEngine::new(infcx.tcx);
 
                         for field in coerced_fields {
-                            let predicate = tcx.predicate_for_trait_def(
+                            let predicate = predicate_for_trait_def(
+                                tcx,
                                 param_env,
                                 cause.clone(),
                                 dispatch_from_dyn_trait,
@@ -390,7 +391,7 @@
                 if def_a != def_b {
                     let source_path = tcx.def_path_str(def_a.did);
                     let target_path = tcx.def_path_str(def_b.did);
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0377,
@@ -399,7 +400,8 @@
                                definition; expected `{}`, found `{}`",
                         source_path,
                         target_path
-                    );
+                    )
+                    .emit();
                     return err_info;
                 }
 
@@ -476,14 +478,15 @@
                     .collect::<Vec<_>>();
 
                 if diff_fields.is_empty() {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0374,
                         "the trait `CoerceUnsized` may only be implemented \
                                for a coercion between structures with one field \
                                being coerced, none found"
-                    );
+                    )
+                    .emit();
                     return err_info;
                 } else if diff_fields.len() > 1 {
                     let item = tcx.hir().expect_item(impl_hir_id);
@@ -493,19 +496,19 @@
                         tcx.hir().span(impl_hir_id)
                     };
 
-                    let mut err = struct_span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0375,
                         "implementing the trait \
                                                     `CoerceUnsized` requires multiple \
                                                     coercions"
-                    );
-                    err.note(
+                    )
+                    .note(
                         "`CoerceUnsized` may only be implemented for \
                               a coercion between structures with one field being coerced",
-                    );
-                    err.note(&format!(
+                    )
+                    .note(&format!(
                         "currently, {} fields need coercions: {}",
                         diff_fields.len(),
                         diff_fields
@@ -515,9 +518,9 @@
                             })
                             .collect::<Vec<_>>()
                             .join(", ")
-                    ));
-                    err.span_label(span, "requires multiple coercions");
-                    err.emit();
+                    ))
+                    .span_label(span, "requires multiple coercions")
+                    .emit();
                     return err_info;
                 }
 
@@ -527,13 +530,14 @@
             }
 
             _ => {
-                span_err!(
+                struct_span_err!(
                     tcx.sess,
                     span,
                     E0376,
                     "the trait `CoerceUnsized` may only be implemented \
                            for a coercion between structures"
-                );
+                )
+                .emit();
                 return err_info;
             }
         };
@@ -542,7 +546,8 @@
 
         // Register an obligation for `A: Trait<B>`.
         let cause = traits::ObligationCause::misc(span, impl_hir_id);
-        let predicate = tcx.predicate_for_trait_def(
+        let predicate = predicate_for_trait_def(
+            tcx,
             param_env,
             cause,
             trait_def_id,
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 4e75134..673c1bd 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -7,10 +7,11 @@
 //! `tcx.inherent_impls(def_id)`). That value, however,
 //! is computed by selecting an idea from this table.
 
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::{self, CrateInherentImpls, TyCtxt};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
 use rustc_span::Span;
 use syntax::ast;
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 76eb8f5..a9228c7 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -1,9 +1,10 @@
 use crate::namespace::Namespace;
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::traits::{self, IntercrateMode};
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 2d19b73..fd685e7 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -5,13 +5,13 @@
 // done by the orphan and overlap modules. Then we build up various
 // mappings. That mapping code resides here.
 
-use crate::hir::def_id::{DefId, LOCAL_CRATE};
-use crate::hir::HirId;
 use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
-
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::HirId;
 
 mod builtin;
 mod inherent_impls;
@@ -145,8 +145,8 @@
         tcx.ensure().coherent_trait(trait_def_id);
     }
 
-    tcx.sess.time("unsafety checking", || unsafety::check(tcx));
-    tcx.sess.time("orphan checking", || orphan::check(tcx));
+    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
+    tcx.sess.time("orphan_checking", || orphan::check(tcx));
 
     // these queries are executed for side-effects (error reporting):
     tcx.ensure().crate_inherent_impls(LOCAL_CRATE);
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index b387a5d..1878f93 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -1,10 +1,11 @@
 //! Orphan checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::traits;
 use rustc::ty::{self, TyCtxt};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index eee292c..3f4035b 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -1,9 +1,11 @@
 //! Unsafety checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::{self, Unsafety};
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::Unsafety;
 
 use rustc_error_codes::*;
 
@@ -32,23 +34,25 @@
             });
             match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
                 (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0199,
                         "implementing the trait `{}` is not unsafe",
                         trait_ref.print_only_trait_path()
-                    );
+                    )
+                    .emit();
                 }
 
                 (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0200,
                         "the trait `{}` requires an `unsafe impl` declaration",
                         trait_ref.print_only_trait_path()
-                    );
+                    )
+                    .emit();
                 }
 
                 (
@@ -57,13 +61,14 @@
                     Unsafety::Normal,
                     hir::ImplPolarity::Positive,
                 ) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0569,
                         "requires an `unsafe impl` declaration due to `#[{}]` attribute",
                         attr_name
-                    );
+                    )
+                    .emit();
                 }
 
                 (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index bc39856..ad750d5 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -20,8 +20,11 @@
 use crate::lint;
 use crate::middle::resolve_lifetime as rl;
 use crate::middle::weak_lang_items;
+use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::mono::Linkage;
+use rustc::session::parse::feature_err;
+use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::GenericArgKind;
 use rustc::ty::subst::{InternalSubsts, Subst};
@@ -29,25 +32,20 @@
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::{ReprOptions, ToPredicate};
-use rustc::util::captures::Captures;
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_target::spec::abi;
-
+use rustc_errors::{struct_span_err, Applicability, StashKey};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{GenericParamKind, Node, Unsafety};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::ast::{Ident, MetaItemKind};
 use syntax::attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
-use syntax::feature_gate;
-
-use rustc::hir::def::{CtorKind, DefKind, Res};
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::hir::GenericParamKind;
-use rustc::hir::Node;
-use rustc::hir::{self, Unsafety};
-
-use errors::{Applicability, StashKey};
 
 use rustc_error_codes::*;
 
@@ -107,14 +105,16 @@
 crate struct PlaceholderHirTyCollector(crate Vec<Span>);
 
 impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
         if let hir::TyKind::Infer = t.kind {
             self.0.push(t.span);
         }
-        hir::intravisit::walk_ty(self, t)
+        intravisit::walk_ty(self, t)
     }
 }
 
@@ -127,7 +127,7 @@
 /// all already existing generic type parameters to avoid suggesting a name that is already in use.
 crate fn placeholder_type_error(
     tcx: TyCtxt<'tcx>,
-    ident_span: Span,
+    span: Span,
     generics: &[hir::GenericParam<'_>],
     placeholder_types: Vec<Span>,
     suggest: bool,
@@ -153,7 +153,14 @@
     let mut sugg: Vec<_> =
         placeholder_types.iter().map(|sp| (*sp, type_name.to_string())).collect();
     if generics.is_empty() {
-        sugg.push((ident_span.shrink_to_hi(), format!("<{}>", type_name)));
+        sugg.push((span, format!("<{}>", type_name)));
+    } else if let Some(arg) = generics.iter().find(|arg| match arg.name {
+        hir::ParamName::Plain(Ident { name: kw::Underscore, .. }) => true,
+        _ => false,
+    }) {
+        // Account for `_` already present in cases like `struct S<_>(_);` and suggest
+        // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
+        sugg.push((arg.span, format!("{}", type_name)));
     } else {
         sugg.push((
             generics.iter().last().unwrap().span.shrink_to_hi(),
@@ -175,8 +182,12 @@
     let (generics, suggest) = match &item.kind {
         hir::ItemKind::Union(_, generics)
         | hir::ItemKind::Enum(_, generics)
-        | hir::ItemKind::Struct(_, generics) => (&generics.params[..], true),
-        hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false),
+        | hir::ItemKind::TraitAlias(generics, _)
+        | hir::ItemKind::Trait(_, _, generics, ..)
+        | hir::ItemKind::Impl(_, _, _, generics, ..)
+        | hir::ItemKind::Struct(_, generics) => (generics, true),
+        hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
+        | hir::ItemKind::TyAlias(_, generics) => (generics, false),
         // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
         _ => return,
     };
@@ -184,11 +195,13 @@
     let mut visitor = PlaceholderHirTyCollector::default();
     visitor.visit_item(item);
 
-    placeholder_type_error(tcx, item.ident.span, generics, visitor.0, suggest);
+    placeholder_type_error(tcx, generics.span, &generics.params[..], visitor.0, suggest);
 }
 
 impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -242,7 +255,7 @@
 fn bad_placeholder_type(
     tcx: TyCtxt<'tcx>,
     mut spans: Vec<Span>,
-) -> errors::DiagnosticBuilder<'tcx> {
+) -> rustc_errors::DiagnosticBuilder<'tcx> {
     spans.sort();
     let mut err = struct_span_err!(
         tcx.sess,
@@ -322,13 +335,14 @@
             self.tcx().mk_projection(item_def_id, item_substs)
         } else {
             // There are no late-bound regions; we can just ignore the binder.
-            span_err!(
+            struct_span_err!(
                 self.tcx().sess,
                 span,
                 E0212,
                 "cannot extract an associated type from a higher-ranked trait bound \
                  in this context"
-            );
+            )
+            .emit();
             self.tcx().types.err
         }
     }
@@ -353,7 +367,7 @@
     tcx: TyCtxt<'_>,
     (item_def_id, def_id): (DefId, DefId),
 ) -> ty::GenericPredicates<'_> {
-    use rustc::hir::*;
+    use rustc_hir::*;
 
     // In the AST, bounds can derive from two places. Either
     // written inline like `<T: Foo>` or in a where-clause like
@@ -712,7 +726,7 @@
 }
 
 fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
-    use rustc::hir::*;
+    use rustc_hir::*;
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let item = match tcx.hir().get(hir_id) {
@@ -863,17 +877,14 @@
 
     let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
     if paren_sugar && !tcx.features().unboxed_closures {
-        let mut err = tcx.sess.struct_span_err(
-            item.span,
-            "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
+        tcx.sess
+            .struct_span_err(
+                item.span,
+                "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
              which traits can use parenthetical notation",
-        );
-        help!(
-            &mut err,
-            "add `#![feature(unboxed_closures)]` to \
-             the crate attributes to use it"
-        );
-        err.emit();
+            )
+            .help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")
+            .emit();
     }
 
     let is_marker = tcx.has_attr(def_id, sym::marker);
@@ -890,7 +901,9 @@
     }
 
     impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        type Map = Map<'tcx>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -992,7 +1005,7 @@
 }
 
 fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
-    use rustc::hir::*;
+    use rustc_hir::*;
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
@@ -1208,12 +1221,13 @@
 }
 
 fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
-    span_err!(
+    struct_span_err!(
         tcx.sess,
         span,
         E0202,
         "associated types are not yet supported in inherent impls (see #8995)"
-    );
+    )
+    .emit();
 }
 
 fn infer_placeholder_type(
@@ -1260,7 +1274,7 @@
 }
 
 fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
-    use rustc::hir::*;
+    use rustc_hir::*;
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
@@ -1512,48 +1526,48 @@
             }
         }
 
-        Node::GenericParam(param) => {
-            match &param.kind {
-                hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
-                hir::GenericParamKind::Const { ty: ref hir_ty, .. } => {
-                    let ty = icx.to_ty(hir_ty);
-                    if !tcx.features().const_compare_raw_pointers {
-                        let err = match ty.peel_refs().kind {
-                            ty::FnPtr(_) => Some("function pointers"),
-                            ty::RawPtr(_) => Some("raw pointers"),
-                            _ => None,
-                        };
-                        if let Some(unsupported_type) = err {
-                            feature_gate::feature_err(
-                                &tcx.sess.parse_sess,
-                                sym::const_compare_raw_pointers,
-                                hir_ty.span,
-                                &format!(
-                                    "using {} as const generic parameters is unstable",
-                                    unsupported_type
-                                ),
-                            )
-                            .emit();
-                        };
-                    }
-                    if ty::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
-                        .is_some()
-                    {
-                        struct_span_err!(
+        Node::GenericParam(param) => match &param.kind {
+            hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
+            hir::GenericParamKind::Const { ty: ref hir_ty, .. } => {
+                let ty = icx.to_ty(hir_ty);
+                if !tcx.features().const_compare_raw_pointers {
+                    let err = match ty.peel_refs().kind {
+                        ty::FnPtr(_) => Some("function pointers"),
+                        ty::RawPtr(_) => Some("raw pointers"),
+                        _ => None,
+                    };
+                    if let Some(unsupported_type) = err {
+                        feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::const_compare_raw_pointers,
+                            hir_ty.span,
+                            &format!(
+                                "using {} as const generic parameters is unstable",
+                                unsupported_type
+                            ),
+                        )
+                        .emit();
+                    };
+                }
+                if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
+                    .is_some()
+                {
+                    struct_span_err!(
                         tcx.sess,
                         hir_ty.span,
                         E0741,
                         "the types of const generic parameters must derive `PartialEq` and `Eq`",
-                    ).span_label(
+                    )
+                    .span_label(
                         hir_ty.span,
                         format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
-                    ).emit();
-                    }
-                    ty
+                    )
+                    .emit();
                 }
-                x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
+                ty
             }
-        }
+            x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
+        },
 
         x => {
             bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
@@ -1562,7 +1576,7 @@
 }
 
 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
-    use rustc::hir::{ImplItem, Item, TraitItem};
+    use rustc_hir::{ImplItem, Item, TraitItem};
 
     debug!("find_opaque_ty_constraints({:?})", def_id);
 
@@ -1719,7 +1733,9 @@
     }
 
     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
-        fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+        type Map = Map<'tcx>;
+
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
             intravisit::NestedVisitorMap::All(&self.tcx.hir())
         }
         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
@@ -1793,10 +1809,19 @@
 /// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to
 /// use inference to provide suggestions for the appropriate type if possible.
 fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
+    use hir::TyKind::*;
     match &ty.kind {
-        hir::TyKind::Infer => true,
-        hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_suggestable_infer_ty(ty),
-        hir::TyKind::Tup(tys) => tys.iter().any(|ty| is_suggestable_infer_ty(ty)),
+        Infer => true,
+        Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty),
+        Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
+        Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
+        Def(_, generic_args) => generic_args
+            .iter()
+            .filter_map(|arg| match arg {
+                hir::GenericArg::Type(ty) => Some(ty),
+                _ => None,
+            })
+            .any(is_suggestable_infer_ty),
         _ => false,
     }
 }
@@ -1811,8 +1836,8 @@
 }
 
 fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
-    use rustc::hir::Node::*;
-    use rustc::hir::*;
+    use rustc_hir::Node::*;
+    use rustc_hir::*;
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
@@ -2029,8 +2054,8 @@
 /// Returns a list of user-specified type predicates for the definition with ID `def_id`.
 /// N.B., this does not include any implied/inferred constraints.
 fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
-    use rustc::hir::*;
     use rustc_data_structures::fx::FxHashSet;
+    use rustc_hir::*;
 
     debug!("explicit_predicates_of(def_id={:?})", def_id);
 
@@ -2499,7 +2524,7 @@
         for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) {
             check(&input, ty)
         }
-        if let hir::Return(ref ty) = decl.output {
+        if let hir::FunctionRetTy::Return(ref ty) = decl.output {
             check(&ty, *fty.output().skip_binder())
         }
     }
@@ -2608,7 +2633,7 @@
                 None => true,
             };
             if !allowed && id.is_local() {
-                feature_gate::feature_err(
+                feature_err(
                     &tcx.sess.parse_sess,
                     feature_gate.unwrap(),
                     item.span(),
@@ -2769,14 +2794,26 @@
                 mark_used(attr);
                 inline_span = Some(attr.span);
                 if items.len() != 1 {
-                    span_err!(tcx.sess.diagnostic(), attr.span, E0534, "expected one argument");
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0534,
+                        "expected one argument"
+                    )
+                    .emit();
                     InlineAttr::None
                 } else if list_contains_name(&items[..], sym::always) {
                     InlineAttr::Always
                 } else if list_contains_name(&items[..], sym::never) {
                     InlineAttr::Never
                 } else {
-                    span_err!(tcx.sess.diagnostic(), items[0].span(), E0535, "invalid argument");
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        items[0].span(),
+                        E0535,
+                        "invalid argument"
+                    )
+                    .emit();
 
                     InlineAttr::None
                 }
@@ -2790,7 +2827,7 @@
         if !attr.has_name(sym::optimize) {
             return ia;
         }
-        let err = |sp, s| span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s);
+        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
         match attr.meta().map(|i| i.kind) {
             Some(MetaItemKind::Word) => {
                 err(attr.span, "expected one argument");
diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs
index 030b8a6..be00c57 100644
--- a/src/librustc_typeck/expr_use_visitor.rs
+++ b/src/librustc_typeck/expr_use_visitor.rs
@@ -8,11 +8,12 @@
 // Export these here so that Clippy can use them.
 pub use mc::{Place, PlaceBase, Projection};
 
-use rustc::hir::def::Res;
-use rustc::hir::def_id::DefId;
-use rustc::hir::{self, PatKind};
 use rustc::infer::InferCtxt;
 use rustc::ty::{self, adjustment, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::def_id::DefId;
+use rustc_hir::PatKind;
 
 use crate::mem_categorization as mc;
 use rustc_span::Span;
@@ -192,7 +193,7 @@
 
             hir::ExprKind::Type(ref subexpr, _) => self.walk_expr(subexpr),
 
-            hir::ExprKind::Unary(hir::UnDeref, ref base) => {
+            hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base) => {
                 // *base
                 self.select_from_expr(base);
             }
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index f8c1af0..fb87b28 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -9,12 +9,13 @@
 //! fixed, but for the moment it's easier to do these checks early.
 
 use crate::constrained_generic_params as cgp;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 
 use rustc_span::Span;
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index dbf4c76..b951883 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -71,8 +71,6 @@
 
 #[macro_use]
 extern crate log;
-#[macro_use]
-extern crate syntax;
 
 #[macro_use]
 extern crate rustc;
@@ -93,8 +91,6 @@
 mod structured_errors;
 mod variance;
 
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::{self, Node};
 use rustc::infer::InferOk;
 use rustc::lint;
 use rustc::middle;
@@ -106,6 +102,10 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util;
 use rustc::util::common::ErrorReported;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::Node;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 
@@ -309,7 +309,7 @@
     // have valid types and not error
     // FIXME(matthewjasper) We shouldn't need to do this.
     tcx.sess.track_errors(|| {
-        tcx.sess.time("type collecting", || {
+        tcx.sess.time("type_collecting", || {
             for &module in tcx.hir().krate().modules.keys() {
                 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
             }
@@ -318,35 +318,35 @@
 
     if tcx.features().rustc_attrs {
         tcx.sess.track_errors(|| {
-            tcx.sess.time("outlives testing", || outlives::test::test_inferred_outlives(tcx));
+            tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
         })?;
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("impl wf inference", || impl_wf_check::impl_wf_check(tcx));
+        tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
     })?;
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("coherence checking", || coherence::check_coherence(tcx));
+        tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
     })?;
 
     if tcx.features().rustc_attrs {
         tcx.sess.track_errors(|| {
-            tcx.sess.time("variance testing", || variance::test::test_variance(tcx));
+            tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
         })?;
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("wf checking", || check::check_wf_new(tcx));
+        tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
     })?;
 
-    tcx.sess.time("item-types checking", || {
+    tcx.sess.time("item_types_checking", || {
         for &module in tcx.hir().krate().modules.keys() {
             tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
         }
     });
 
-    tcx.sess.time("item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
+    tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
 
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs
index 4c5e7c8..d3d0aa2 100644
--- a/src/librustc_typeck/mem_categorization.rs
+++ b/src/librustc_typeck/mem_categorization.rs
@@ -48,18 +48,16 @@
 //! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
 //! tied to `x`. The type of `x'` will be a borrowed pointer.
 
-use rustc::hir;
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::DefId;
-use rustc::hir::PatKind;
 use rustc::infer::InferCtxt;
 use rustc::ty::adjustment;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt};
-
-use rustc_span::Span;
-
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::PatKind;
+use rustc_span::Span;
 
 #[derive(Clone, Debug)]
 pub enum PlaceBase {
@@ -347,7 +345,7 @@
 
         let expr_ty = self.expr_ty(expr)?;
         match expr.kind {
-            hir::ExprKind::Unary(hir::UnDeref, ref e_base) => {
+            hir::ExprKind::Unary(hir::UnOp::UnDeref, ref e_base) => {
                 if self.tables.is_method_call(expr) {
                     self.cat_overloaded_place(expr, e_base)
                 } else {
diff --git a/src/librustc_typeck/namespace.rs b/src/librustc_typeck/namespace.rs
index 0d672f2..2aa97aa 100644
--- a/src/librustc_typeck/namespace.rs
+++ b/src/librustc_typeck/namespace.rs
@@ -1,5 +1,5 @@
-use rustc::hir;
 use rustc::ty;
+use rustc_hir as hir;
 
 // Whether an item exists in the type or value namespace.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs
index a922846..7500c39 100644
--- a/src/librustc_typeck/outlives/explicit.rs
+++ b/src/librustc_typeck/outlives/explicit.rs
@@ -1,6 +1,6 @@
-use rustc::hir::def_id::DefId;
 use rustc::ty::{self, OutlivesPredicate, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::DefId;
 
 use super::utils::*;
 
diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs
index b18f89c..1645f01 100644
--- a/src/librustc_typeck/outlives/implicit_infer.rs
+++ b/src/librustc_typeck/outlives/implicit_infer.rs
@@ -1,9 +1,10 @@
-use rustc::hir::def_id::DefId;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::{self, Node};
 use rustc::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::Node;
 use rustc_span::Span;
 
 use super::explicit::ExplicitPredicatesMap;
diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs
index 992781e..5198739 100644
--- a/src/librustc_typeck/outlives/mod.rs
+++ b/src/librustc_typeck/outlives/mod.rs
@@ -1,9 +1,9 @@
 use hir::Node;
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::GenericArgKind;
 use rustc::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
index f29d2d8..908429c 100644
--- a/src/librustc_typeck/outlives/test.rs
+++ b/src/librustc_typeck/outlives/test.rs
@@ -1,6 +1,7 @@
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 
 use rustc_error_codes::*;
@@ -21,7 +22,7 @@
         // attribute and report an error with various results if found.
         if self.tcx.has_attr(item_def_id, sym::rustc_outlives) {
             let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id);
-            span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of);
+            struct_span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of).emit();
         }
     }
 
diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs
index 251732b..0688147 100644
--- a/src/librustc_typeck/structured_errors.rs
+++ b/src/librustc_typeck/structured_errors.rs
@@ -1,6 +1,6 @@
-use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::session::Session;
 use rustc::ty::{Ty, TypeFoldable};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_span::Span;
 
 use rustc_error_codes::*;
@@ -50,8 +50,7 @@
     }
 
     fn code(&self) -> DiagnosticId {
-        syntax::diagnostic_used!(E0617);
-        DiagnosticId::Error("E0617".to_owned())
+        rustc_errors::error_code!(E0617)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
@@ -112,8 +111,7 @@
     }
 
     fn code(&self) -> DiagnosticId {
-        syntax::diagnostic_used!(E0607);
-        DiagnosticId::Error("E0607".to_owned())
+        rustc_errors::error_code!(E0607)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 8fac3a4..5ca961e 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -4,10 +4,10 @@
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
 use super::terms::VarianceTerm::*;
 use super::terms::*;
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index 7449ff1..27dc03b 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -5,10 +5,10 @@
 
 use arena;
 use hir::Node;
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, CrateVariancesMap, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 
 /// Defines the `TermsContext` basically houses an arena where we can
 /// allocate terms.
diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs
index ce5115f..e285f44 100644
--- a/src/librustc_typeck/variance/solve.rs
+++ b/src/librustc_typeck/variance/solve.rs
@@ -5,9 +5,9 @@
 //! optimal solution to the constraints. The final variance for each
 //! inferred is then written into the `variance_map` in the tcx.
 
-use rustc::hir::def_id::DefId;
 use rustc::ty;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::DefId;
 
 use super::constraints::*;
 use super::terms::VarianceTerm::*;
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index db3e7a2..dd593a6 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -10,9 +10,10 @@
 // a variable.
 
 use arena::TypedArena;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::{self, HirIdMap};
 use rustc::ty::{self, TyCtxt};
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::HirIdMap;
 use std::fmt;
 
 use self::VarianceTerm::*;
diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs
index 69e0577..2f41bee1 100644
--- a/src/librustc_typeck/variance/test.rs
+++ b/src/librustc_typeck/variance/test.rs
@@ -1,6 +1,7 @@
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 
 use rustc_error_codes::*;
@@ -21,7 +22,7 @@
         // attribute and report an error with various results if found.
         if self.tcx.has_attr(item_def_id, sym::rustc_variance) {
             let variances_of = self.tcx.variances_of(item_def_id);
-            span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of);
+            struct_span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of).emit();
         }
     }
 
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index dec0197..c8b63ed 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -1,7 +1,7 @@
-use rustc::hir;
 use rustc::traits::auto_trait::{self, AutoTraitResult};
 use rustc::ty::{self, Region, RegionVid, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
 
 use std::fmt::Debug;
 
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 635713b..525b1b2 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -1,9 +1,9 @@
-use rustc::hir;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::infer::InferOk;
 use rustc::traits;
 use rustc::ty::subst::Subst;
 use rustc::ty::ToPredicate;
+use rustc_hir as hir;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_span::DUMMY_SP;
 
 use super::*;
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 13df189..84e6ff6 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -202,23 +202,34 @@
 
 impl ops::BitAndAssign for Cfg {
     fn bitand_assign(&mut self, other: Cfg) {
-        if *self == other {
-            return;
-        }
         match (self, other) {
             (&mut Cfg::False, _) | (_, Cfg::True) => {}
             (s, Cfg::False) => *s = Cfg::False,
             (s @ &mut Cfg::True, b) => *s = b,
-            (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => a.append(b),
-            (&mut Cfg::All(ref mut a), ref mut b) => a.push(mem::replace(b, Cfg::True)),
+            (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => {
+                for c in b.drain(..) {
+                    if !a.contains(&c) {
+                        a.push(c);
+                    }
+                }
+            }
+            (&mut Cfg::All(ref mut a), ref mut b) => {
+                if !a.contains(b) {
+                    a.push(mem::replace(b, Cfg::True));
+                }
+            }
             (s, Cfg::All(mut a)) => {
                 let b = mem::replace(s, Cfg::True);
-                a.push(b);
+                if !a.contains(&b) {
+                    a.push(b);
+                }
                 *s = Cfg::All(a);
             }
             (s, b) => {
-                let a = mem::replace(s, Cfg::True);
-                *s = Cfg::All(vec![a, b]);
+                if *s != b {
+                    let a = mem::replace(s, Cfg::True);
+                    *s = Cfg::All(vec![a, b]);
+                }
             }
         }
     }
@@ -234,23 +245,34 @@
 
 impl ops::BitOrAssign for Cfg {
     fn bitor_assign(&mut self, other: Cfg) {
-        if *self == other {
-            return;
-        }
         match (self, other) {
             (&mut Cfg::True, _) | (_, Cfg::False) => {}
             (s, Cfg::True) => *s = Cfg::True,
             (s @ &mut Cfg::False, b) => *s = b,
-            (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => a.append(b),
-            (&mut Cfg::Any(ref mut a), ref mut b) => a.push(mem::replace(b, Cfg::True)),
+            (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => {
+                for c in b.drain(..) {
+                    if !a.contains(&c) {
+                        a.push(c);
+                    }
+                }
+            }
+            (&mut Cfg::Any(ref mut a), ref mut b) => {
+                if !a.contains(b) {
+                    a.push(mem::replace(b, Cfg::True));
+                }
+            }
             (s, Cfg::Any(mut a)) => {
                 let b = mem::replace(s, Cfg::True);
-                a.push(b);
+                if !a.contains(&b) {
+                    a.push(b);
+                }
                 *s = Cfg::Any(a);
             }
             (s, b) => {
-                let a = mem::replace(s, Cfg::True);
-                *s = Cfg::Any(vec![a, b]);
+                if *s != b {
+                    let a = mem::replace(s, Cfg::True);
+                    *s = Cfg::Any(vec![a, b]);
+                }
             }
         }
     }
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 309f720..d090bf3 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -87,6 +87,12 @@
         x &= word_cfg("test3");
         assert_eq!(x, word_cfg("test3"));
 
+        x &= word_cfg("test3");
+        assert_eq!(x, word_cfg("test3"));
+
+        x &= word_cfg("test4");
+        assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
+
         x &= word_cfg("test4");
         assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
 
@@ -105,6 +111,18 @@
             ])
         );
 
+        x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]);
+        assert_eq!(
+            x,
+            Cfg::All(vec![
+                word_cfg("test3"),
+                word_cfg("test4"),
+                word_cfg("test5"),
+                word_cfg("test6"),
+                word_cfg("test7"),
+            ])
+        );
+
         let mut y = Cfg::Any(vec![word_cfg("a"), word_cfg("b")]);
         y &= x;
         assert_eq!(
@@ -119,6 +137,14 @@
             ])
         );
 
+        let mut z = word_cfg("test8");
+        z &= Cfg::All(vec![word_cfg("test9"), word_cfg("test10")]);
+        assert_eq!(z, Cfg::All(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
+
+        let mut z = word_cfg("test11");
+        z &= Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]);
+        assert_eq!(z, Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]));
+
         assert_eq!(
             word_cfg("a") & word_cfg("b") & word_cfg("c"),
             Cfg::All(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
@@ -145,6 +171,12 @@
         x |= word_cfg("test3");
         assert_eq!(x, word_cfg("test3"));
 
+        x |= word_cfg("test3");
+        assert_eq!(x, word_cfg("test3"));
+
+        x |= word_cfg("test4");
+        assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
+
         x |= word_cfg("test4");
         assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
 
@@ -163,6 +195,18 @@
             ])
         );
 
+        x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]);
+        assert_eq!(
+            x,
+            Cfg::Any(vec![
+                word_cfg("test3"),
+                word_cfg("test4"),
+                word_cfg("test5"),
+                word_cfg("test6"),
+                word_cfg("test7"),
+            ])
+        );
+
         let mut y = Cfg::All(vec![word_cfg("a"), word_cfg("b")]);
         y |= x;
         assert_eq!(
@@ -177,6 +221,14 @@
             ])
         );
 
+        let mut z = word_cfg("test8");
+        z |= Cfg::Any(vec![word_cfg("test9"), word_cfg("test10")]);
+        assert_eq!(z, Cfg::Any(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
+
+        let mut z = word_cfg("test11");
+        z |= Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]);
+        assert_eq!(z, Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]));
+
         assert_eq!(
             word_cfg("a") | word_cfg("b") | word_cfg("c"),
             Cfg::Any(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 49baff0..c7e0f1e 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -2,18 +2,19 @@
 
 use std::iter::once;
 
+use rustc::ty;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::Mutability;
+use rustc_metadata::creader::LoadedMacro;
+use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc::hir::def::{CtorKind, DefKind, Res};
-use rustc::hir::def_id::DefId;
-use rustc::hir::{self, Mutability};
-use rustc::ty;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_metadata::creader::LoadedMacro;
-
 use crate::clean::{self, GetDefId, ToSource, TypeKind};
 use crate::core::DocContext;
 use crate::doctree;
@@ -212,7 +213,7 @@
     let sig = cx.tcx.fn_sig(did);
 
     let constness =
-        if cx.tcx.is_min_const_fn(did) { hir::Constness::Const } else { hir::Constness::NotConst };
+        if is_min_const_fn(cx.tcx, did) { hir::Constness::Const } else { hir::Constness::NotConst };
     let asyncness = cx.tcx.asyncness(did);
     let predicates = cx.tcx.predicates_of(did);
     let (generics, decl) = clean::enter_impl_trait(cx, || {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fad2bab..be96546 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -9,9 +9,6 @@
 pub mod types;
 pub mod utils;
 
-use rustc::hir;
-use rustc::hir::def::{CtorKind, DefKind, Res};
-use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc::middle::lang_items;
 use rustc::middle::resolve_lifetime as rl;
@@ -20,7 +17,11 @@
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, AdtKind, Lift, Ty, TyCtxt};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{self, Pos};
@@ -895,7 +896,7 @@
             enter_impl_trait(cx, || (self.generics.clean(cx), (self.decl, self.body).clean(cx)));
 
         let did = cx.tcx.hir().local_def_id(self.id);
-        let constness = if cx.tcx.is_min_const_fn(did) {
+        let constness = if is_min_const_fn(cx.tcx, did) {
             hir::Constness::Const
         } else {
             hir::Constness::NotConst
@@ -1003,8 +1004,8 @@
 impl Clean<FunctionRetTy> for hir::FunctionRetTy<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy {
         match *self {
-            hir::Return(ref typ) => Return(typ.clean(cx)),
-            hir::DefaultReturn(..) => DefaultReturn,
+            Self::Return(ref typ) => Return(typ.clean(cx)),
+            Self::DefaultReturn(..) => DefaultReturn,
         }
     }
 }
@@ -1187,7 +1188,7 @@
                 };
                 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
                 if provided {
-                    let constness = if cx.tcx.is_min_const_fn(self.def_id) {
+                    let constness = if is_min_const_fn(cx.tcx, self.def_id) {
                         hir::Constness::Const
                     } else {
                         hir::Constness::NotConst
@@ -1313,7 +1314,7 @@
 
 impl Clean<Type> for hir::Ty<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Type {
-        use rustc::hir::*;
+        use rustc_hir::*;
 
         match self.kind {
             TyKind::Never => Never,
@@ -1808,7 +1809,7 @@
     }
 }
 
-impl Clean<VariantStruct> for ::rustc::hir::VariantData<'_> {
+impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
         VariantStruct {
             struct_type: doctree::struct_type_from_def(self),
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 49c3837..c7b12d3 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -14,8 +14,8 @@
 use std::collections::BTreeMap;
 use std::mem;
 
-use rustc::hir::def_id::DefId;
 use rustc::ty;
+use rustc_hir::def_id::DefId;
 
 use crate::clean;
 use crate::clean::GenericArgs as PP;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 6bb1ef7..5d8e27e 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -8,13 +8,14 @@
 use std::sync::Arc;
 use std::{slice, vec};
 
-use rustc::hir::def::Res;
-use rustc::hir::def_id::{CrateNum, DefId};
-use rustc::hir::{self, Mutability};
 use rustc::middle::lang_items;
 use rustc::middle::stability;
 use rustc::ty::layout::VariantIdx;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::Mutability;
 use rustc_index::vec::IndexVec;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::DUMMY_SP;
@@ -496,7 +497,7 @@
         false
     }
 
-    pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
+    pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
         let mut doc_strings = vec![];
         let mut sp = None;
         let mut cfg = Cfg::True;
@@ -701,7 +702,7 @@
     }
 
     pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
-        use rustc::hir::TraitBoundModifier as TBM;
+        use rustc_hir::TraitBoundModifier as TBM;
         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
             if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
                 return true;
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index d17b3ce..8058536 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -9,13 +9,13 @@
 use crate::core::DocContext;
 
 use itertools::Itertools;
-use rustc::hir;
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::interpret::{sign_extend, ConstValue, Scalar};
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::{self, DefIdTree, Ty};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_span;
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::mem;
@@ -412,7 +412,7 @@
 }
 
 pub fn name_from_pat(p: &hir::Pat) -> String {
-    use rustc::hir::*;
+    use rustc_hir::*;
     debug!("trying to get a name from pattern: {:?}", p);
 
     match p.kind {
@@ -460,12 +460,16 @@
 
 pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
     match n.val {
-        ty::ConstKind::Unevaluated(def_id, _) => {
-            if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
+        ty::ConstKind::Unevaluated(def_id, _, promoted) => {
+            let mut s = if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
                 print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
             } else {
                 inline::print_inlined_const(cx, def_id)
+            };
+            if let Some(promoted) = promoted {
+                s.push_str(&format!("::{:?}", promoted))
             }
+            s
         }
         _ => {
             let mut s = n.to_string();
@@ -567,12 +571,12 @@
 
     let is_generic = match path.res {
         Res::PrimTy(p) => match p {
-            hir::Str => return Primitive(PrimitiveType::Str),
-            hir::Bool => return Primitive(PrimitiveType::Bool),
-            hir::Char => return Primitive(PrimitiveType::Char),
-            hir::Int(int_ty) => return Primitive(int_ty.into()),
-            hir::Uint(uint_ty) => return Primitive(uint_ty.into()),
-            hir::Float(float_ty) => return Primitive(float_ty.into()),
+            hir::PrimTy::Str => return Primitive(PrimitiveType::Str),
+            hir::PrimTy::Bool => return Primitive(PrimitiveType::Bool),
+            hir::PrimTy::Char => return Primitive(PrimitiveType::Char),
+            hir::PrimTy::Int(int_ty) => return Primitive(int_ty.into()),
+            hir::PrimTy::Uint(uint_ty) => return Primitive(uint_ty.into()),
+            hir::PrimTy::Float(float_ty) => return Primitive(float_ty.into()),
         },
         Res::SelfTy(..) if path.segments.len() == 1 => {
             return Generic(kw::SelfUpper.to_string());
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 0af25ef..22f5d0d 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -3,7 +3,6 @@
 use std::fmt;
 use std::path::PathBuf;
 
-use errors;
 use getopts;
 use rustc::lint::Level;
 use rustc::session;
@@ -24,7 +23,7 @@
 use crate::html::markdown::IdMap;
 use crate::html::static_files;
 use crate::opts;
-use crate::passes::{self, DefaultPassOption};
+use crate::passes::{self, Condition, DefaultPassOption};
 use crate::theme;
 
 /// Configuration options for rustdoc.
@@ -98,6 +97,10 @@
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
     pub default_passes: DefaultPassOption,
+    /// Document items that have lower than `pub` visibility.
+    pub document_private: bool,
+    /// Document items that have `doc(hidden)`.
+    pub document_hidden: bool,
     /// Any passes manually selected by the user.
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
@@ -146,6 +149,8 @@
             .field("test_args", &self.test_args)
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
+            .field("document_private", &self.document_private)
+            .field("document_hidden", &self.document_hidden)
             .field("manual_passes", &self.manual_passes)
             .field("display_warnings", &self.display_warnings)
             .field("show_coverage", &self.show_coverage)
@@ -240,22 +245,26 @@
                 println!("{:>20} - {}", pass.name, pass.description);
             }
             println!("\nDefault passes for rustdoc:");
-            for pass in passes::DEFAULT_PASSES {
-                println!("{:>20}", pass.name);
-            }
-            println!("\nPasses run with `--document-private-items`:");
-            for pass in passes::DEFAULT_PRIVATE_PASSES {
-                println!("{:>20}", pass.name);
+            for p in passes::DEFAULT_PASSES {
+                print!("{:>20}", p.pass.name);
+                println_condition(p.condition);
             }
 
             if nightly_options::is_nightly_build() {
                 println!("\nPasses run with `--show-coverage`:");
-                for pass in passes::DEFAULT_COVERAGE_PASSES {
-                    println!("{:>20}", pass.name);
+                for p in passes::COVERAGE_PASSES {
+                    print!("{:>20}", p.pass.name);
+                    println_condition(p.condition);
                 }
-                println!("\nPasses run with `--show-coverage --document-private-items`:");
-                for pass in passes::PRIVATE_COVERAGE_PASSES {
-                    println!("{:>20}", pass.name);
+            }
+
+            fn println_condition(condition: Condition) {
+                use Condition::*;
+                match condition {
+                    Always => println!(),
+                    WhenDocumentPrivate => println!("  (when --document-private-items)"),
+                    WhenNotDocumentPrivate => println!("  (when not --document-private-items)"),
+                    WhenNotDocumentHidden => println!("  (when not --document-hidden-items)"),
                 }
             }
 
@@ -444,16 +453,11 @@
             });
 
         let show_coverage = matches.opt_present("show-coverage");
-        let document_private = matches.opt_present("document-private-items");
 
         let default_passes = if matches.opt_present("no-defaults") {
             passes::DefaultPassOption::None
-        } else if show_coverage && document_private {
-            passes::DefaultPassOption::PrivateCoverage
         } else if show_coverage {
             passes::DefaultPassOption::Coverage
-        } else if document_private {
-            passes::DefaultPassOption::Private
         } else {
             passes::DefaultPassOption::Default
         };
@@ -492,6 +496,8 @@
         let runtool = matches.opt_str("runtool");
         let runtool_args = matches.opt_strs("runtool-arg");
         let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores");
+        let document_private = matches.opt_present("document-private-items");
+        let document_hidden = matches.opt_present("document-hidden-items");
 
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -518,6 +524,8 @@
             should_test,
             test_args,
             default_passes,
+            document_private,
+            document_hidden,
             manual_passes,
             display_warnings,
             show_coverage,
@@ -557,7 +565,7 @@
 }
 
 /// Prints deprecation warnings for deprecated options
-fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) {
+fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Handler) {
     let deprecated_flags = ["input-format", "output-format", "no-defaults", "passes"];
 
     for flag in deprecated_flags.iter() {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 988d351..61a7bc7 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -1,7 +1,3 @@
-use rustc::hir::def::Namespace::TypeNS;
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
-use rustc::hir::HirId;
-use rustc::lint;
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
 use rustc::session::config::ErrorOutputType;
@@ -11,12 +7,16 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_driver::abort_on_err;
 use rustc_feature::UnstableFeatures;
+use rustc_hir::def::Namespace::TypeNS;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
+use rustc_hir::HirId;
 use rustc_interface::interface;
 use rustc_lint;
 use rustc_resolve as resolve;
+use rustc_session::lint;
 
-use errors::emitter::{Emitter, EmitterWriter};
-use errors::json::JsonEmitter;
+use rustc_errors::emitter::{Emitter, EmitterWriter};
+use rustc_errors::json::JsonEmitter;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
@@ -33,7 +33,7 @@
 use crate::config::{Options as RustdocOptions, RenderOptions};
 use crate::html::render::RenderInfo;
 
-use crate::passes;
+use crate::passes::{self, Condition::*, ConditionalPass};
 
 pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options};
 pub use rustc::session::search_paths::SearchPath;
@@ -171,7 +171,7 @@
     error_format: ErrorOutputType,
     source_map: Option<Lrc<source_map::SourceMap>>,
     debugging_opts: &DebuggingOptions,
-) -> errors::Handler {
+) -> rustc_errors::Handler {
     let emitter: Box<dyn Emitter + sync::Send> = match error_format {
         ErrorOutputType::HumanReadable(kind) => {
             let (short, color_config) = kind.unzip();
@@ -198,7 +198,10 @@
         }
     };
 
-    errors::Handler::with_emitter_and_flags(emitter, debugging_opts.diagnostic_handler_flags(true))
+    rustc_errors::Handler::with_emitter_and_flags(
+        emitter,
+        debugging_opts.diagnostic_handler_flags(true),
+    )
 }
 
 pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) {
@@ -221,6 +224,8 @@
         describe_lints,
         lint_cap,
         mut default_passes,
+        mut document_private,
+        document_hidden,
         mut manual_passes,
         display_warnings,
         render_options,
@@ -407,7 +412,7 @@
 
                 let mut krate = clean::krate(&mut ctxt);
 
-                fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
+                fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) {
                     let mut msg = diag.struct_warn(&format!(
                         "the `#![doc({})]` attribute is \
                                                          considered deprecated",
@@ -457,16 +462,14 @@
                     }
 
                     if attr.is_word() && name == sym::document_private_items {
-                        if default_passes == passes::DefaultPassOption::Default {
-                            default_passes = passes::DefaultPassOption::Private;
-                        }
+                        document_private = true;
                     }
                 }
 
-                let passes = passes::defaults(default_passes).iter().chain(
+                let passes = passes::defaults(default_passes).iter().copied().chain(
                     manual_passes.into_iter().flat_map(|name| {
                         if let Some(pass) = passes::find_pass(&name) {
-                            Some(pass)
+                            Some(ConditionalPass::always(pass))
                         } else {
                             error!("unknown pass {}, skipping", name);
                             None
@@ -476,9 +479,17 @@
 
                 info!("Executing passes");
 
-                for pass in passes {
-                    debug!("running pass {}", pass.name);
-                    krate = (pass.pass)(krate, &ctxt);
+                for p in passes {
+                    let run = match p.condition {
+                        Always => true,
+                        WhenDocumentPrivate => document_private,
+                        WhenNotDocumentPrivate => !document_private,
+                        WhenNotDocumentHidden => !document_hidden,
+                    };
+                    if run {
+                        debug!("running pass {}", p.pass.name);
+                        krate = (p.pass.run)(krate, &ctxt);
+                    }
                 }
 
                 ctxt.sess().abort_if_errors();
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index 2a107e8..ecc394a 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -9,8 +9,6 @@
 //! needs to read-after-write from a file, then it would be added to this
 //! abstraction.
 
-use errors;
-
 use std::fs;
 use std::io;
 use std::path::Path;
@@ -42,7 +40,7 @@
     }
 
     /// Prints all stored errors. Returns the number of printed errors.
-    pub fn write_errors(&mut self, diag: &errors::Handler) -> usize {
+    pub fn write_errors(&mut self, diag: &rustc_errors::Handler) -> usize {
         let mut printed = 0;
         // In order to drop the sender part of the channel.
         self.sender = None;
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 81f2db9..178ba69 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -7,8 +7,8 @@
 use syntax::ast;
 use syntax::ast::Name;
 
-use rustc::hir;
-use rustc::hir::def_id::CrateNum;
+use rustc_hir as hir;
+use rustc_hir::def_id::CrateNum;
 
 pub struct Module<'hir> {
     pub name: Option<Name>,
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index e0ed02c..8b5a3a2 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -1,6 +1,5 @@
 use crate::html::markdown::{ErrorCodes, IdMap, Markdown, Playground};
 use crate::rustc_span::edition::Edition;
-use errors;
 use rustc_feature::UnstableFeatures;
 use std::fs;
 use std::path::Path;
@@ -26,7 +25,7 @@
         after_content: &[String],
         md_before_content: &[String],
         md_after_content: &[String],
-        diag: &errors::Handler,
+        diag: &rustc_errors::Handler,
         id_map: &mut IdMap,
         edition: Edition,
         playground: &Option<Playground>,
@@ -58,7 +57,7 @@
 
 pub fn load_string<P: AsRef<Path>>(
     file_path: P,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
 ) -> Result<String, LoadStringError> {
     let file_path = file_path.as_ref();
     let contents = match fs::read(file_path) {
@@ -77,7 +76,7 @@
     }
 }
 
-fn load_external_files(names: &[String], diag: &errors::Handler) -> Option<String> {
+fn load_external_files(names: &[String], diag: &rustc_errors::Handler) -> Option<String> {
     let mut out = String::new();
     for name in names {
         let s = match load_string(name, diag) {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index f84fef2..6434dcc 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -9,12 +9,13 @@
 use std::cell::Cell;
 use std::fmt;
 
-use rustc::hir;
-use rustc::hir::def_id::DefId;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_target::spec::abi::Abi;
 
 use crate::clean::{self, PrimitiveType};
+use crate::html::escape::Escape;
 use crate::html::item_type::ItemType;
 use crate::html::render::{self, cache, CURRENT_DEPTH};
 
@@ -314,8 +315,14 @@
 }
 
 impl clean::Constant {
-    crate fn print(&self) -> &str {
-        &self.expr
+    crate fn print(&self) -> impl fmt::Display + '_ {
+        display_fn(move |f| {
+            if f.alternate() {
+                f.write_str(&self.expr)
+            } else {
+                write!(f, "{}", Escape(&self.expr))
+            }
+        })
     }
 }
 
@@ -689,7 +696,11 @@
         clean::Array(ref t, ref n) => {
             primitive_link(f, PrimitiveType::Array, "[")?;
             fmt::Display::fmt(&t.print(), f)?;
-            primitive_link(f, PrimitiveType::Array, &format!("; {}]", n))
+            if f.alternate() {
+                primitive_link(f, PrimitiveType::Array, &format!("; {}]", n))
+            } else {
+                primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)))
+            }
         }
         clean::Never => primitive_link(f, PrimitiveType::Never, "!"),
         clean::RawPointer(m, ref t) => {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 8566162..2d932eb 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -42,14 +42,14 @@
 use std::str;
 use std::sync::Arc;
 
-use errors;
-use rustc::hir::def_id::DefId;
-use rustc::hir::{self, Mutability};
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_feature::UnstableFeatures;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::Mutability;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::FileName;
@@ -393,7 +393,7 @@
     mut krate: clean::Crate,
     options: RenderOptions,
     renderinfo: RenderInfo,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
     edition: Edition,
 ) -> Result<(), Error> {
     // need to save a copy of the options for rendering the index page
@@ -527,7 +527,7 @@
     krate: &clean::Crate,
     search_index: String,
     options: &RenderOptions,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
 ) -> Result<(), Error> {
     // Write out the shared files. Note that these are shared among all rustdoc
     // docs placed in the output directory, so this needs to be a synchronized
@@ -2279,7 +2279,7 @@
     );
 
     if c.value.is_some() || c.is_literal {
-        write!(w, " = {expr};", expr = c.expr);
+        write!(w, " = {expr};", expr = Escape(&c.expr));
     } else {
         write!(w, ";");
     }
@@ -2292,7 +2292,7 @@
             if value_lowercase != expr_lowercase
                 && value_lowercase.trim_end_matches("i32") != expr_lowercase
             {
-                write!(w, " // {value}", value = value);
+                write!(w, " // {value}", value = Escape(value));
             }
         }
     }
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 6de56ec..2250744 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -1,8 +1,8 @@
 use crate::clean::{self, AttributesExt, GetDefId};
 use crate::fold::DocFolder;
-use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc::middle::privacy::AccessLevels;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_span::source_map::FileName;
 use rustc_span::symbol::sym;
 use std::collections::BTreeMap;
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 62fe230..a91fdb7 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -542,11 +542,11 @@
 }
 
 .content .stability::before {
-	content: '˪';
-	font-size: 30px;
+	content: '⬑';
+	font-size: 25px;
 	position: absolute;
-	top: -9px;
-	left: -13px;
+	top: -6px;
+	left: -19px;
 }
 
 .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant {
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index f46bd6d..9a0e7bb 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -105,6 +105,8 @@
 .content .highlighted.primitive { background-color: #00708a; }
 .content .highlighted.keyword { background-color: #884719; }
 
+.content .stability::before { color: #ccc; }
+
 .content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
 .content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
 .content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index ca67b1c..ca8ea1c 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -105,6 +105,8 @@
 .content .highlighted.primitive { background-color: #9aecff; }
 .content .highlighted.keyword { background-color: #f99650; }
 
+.content .stability::before { color: #ccc; }
+
 .content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
 .content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
 .content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index c8a3230..1da00e3 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -13,7 +13,6 @@
 #![feature(vec_remove_item)]
 #![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
-#![feature(const_fn)]
 #![feature(drain_filter)]
 #![feature(never_type)]
 #![feature(unicode_internals)]
@@ -25,15 +24,19 @@
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_error_codes;
+extern crate rustc_errors;
 extern crate rustc_expand;
 extern crate rustc_feature;
+extern crate rustc_hir;
 extern crate rustc_index;
 extern crate rustc_interface;
 extern crate rustc_lexer;
 extern crate rustc_lint;
 extern crate rustc_metadata;
+extern crate rustc_mir;
 extern crate rustc_parse;
 extern crate rustc_resolve;
+extern crate rustc_session;
 extern crate rustc_span as rustc_span;
 extern crate rustc_target;
 extern crate rustc_typeck;
@@ -41,7 +44,6 @@
 extern crate test as testing;
 #[macro_use]
 extern crate log;
-extern crate rustc_errors as errors;
 
 use std::default::Default;
 use std::env;
@@ -173,6 +175,9 @@
         stable("document-private-items", |o| {
             o.optflag("", "document-private-items", "document private items")
         }),
+        unstable("document-hidden-items", |o| {
+            o.optflag("", "document-hidden-items", "document items that have doc(hidden)")
+        }),
         stable("test", |o| o.optflag("", "test", "run code examples as tests")),
         stable("test-args", |o| {
             o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS")
@@ -514,6 +519,6 @@
 
     match result {
         Ok(output) => output,
-        Err(_) => panic::resume_unwind(Box::new(errors::FatalErrorMarker)),
+        Err(_) => panic::resume_unwind(Box::new(rustc_errors::FatalErrorMarker)),
     }
 }
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 69aa248..912a407 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -2,7 +2,6 @@
 use std::io::prelude::*;
 use std::path::PathBuf;
 
-use errors;
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::DUMMY_SP;
@@ -39,7 +38,7 @@
 pub fn render(
     input: PathBuf,
     options: RenderOptions,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
     edition: Edition,
 ) -> i32 {
     let mut output = options.output;
@@ -128,7 +127,7 @@
 }
 
 /// Runs any tests/code examples in the markdown file `input`.
-pub fn test(mut options: Options, diag: &errors::Handler) -> i32 {
+pub fn test(mut options: Options, diag: &rustc_errors::Handler) -> i32 {
     let input_str = match load_string(&options.input, diag) {
         Ok(s) => s,
         Err(LoadStringError::ReadFail) => return 1,
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 803bcc2..7ed531c 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -12,7 +12,7 @@
 
 pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
     name: "calculate-doc-coverage",
-    pass: calculate_doc_coverage,
+    run: calculate_doc_coverage,
     description: "counts the number of items with and without documentation",
 };
 
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index a4ca901..0bab442 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -1,5 +1,5 @@
-use errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
 use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
 use rustc_parse::lexer::StringReader as Lexer;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::{FileName, InnerSpan};
@@ -14,7 +14,7 @@
 
 pub const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
     name: "check-code-block-syntax",
-    pass: check_code_block_syntax,
+    run: check_code_block_syntax,
     description: "validates syntax inside Rust code blocks",
 };
 
diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
index c6b2288..c218559 100644
--- a/src/librustdoc/passes/collapse_docs.rs
+++ b/src/librustdoc/passes/collapse_docs.rs
@@ -8,7 +8,7 @@
 
 pub const COLLAPSE_DOCS: Pass = Pass {
     name: "collapse-docs",
-    pass: collapse_docs,
+    run: collapse_docs,
     description: "concatenates all document attributes into one document attribute",
 };
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index a8bb40a..50d5f70 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1,15 +1,15 @@
-use errors::Applicability;
-use rustc::hir;
-use rustc::hir::def::{
+use rustc::lint;
+use rustc::ty;
+use rustc_errors::Applicability;
+use rustc_expand::base::SyntaxExtensionKind;
+use rustc_feature::UnstableFeatures;
+use rustc_hir as hir;
+use rustc_hir::def::{
     DefKind,
     Namespace::{self, *},
     PerNS, Res,
 };
-use rustc::hir::def_id::DefId;
-use rustc::lint;
-use rustc::ty;
-use rustc_expand::base::SyntaxExtensionKind;
-use rustc_feature::UnstableFeatures;
+use rustc_hir::def_id::DefId;
 use rustc_resolve::ParentScope;
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
@@ -28,7 +28,7 @@
 
 pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
     name: "collect-intra-doc-links",
-    pass: collect_intra_doc_links,
+    run: collect_intra_doc_links,
     description: "reads a crate's documentation to resolve intra-doc-links",
 };
 
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index d9360f2..da0e97f 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -3,13 +3,13 @@
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::symbol::sym;
 
 pub const COLLECT_TRAIT_IMPLS: Pass = Pass {
     name: "collect-trait-impls",
-    pass: collect_trait_impls,
+    run: collect_trait_impls,
     description: "retrieves trait impls for items in the crate",
 };
 
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 784d967..355ea15 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -1,13 +1,14 @@
 //! Contains information about "passes", used to modify crate information during the documentation
 //! process.
 
-use rustc::hir::def_id::{DefId, DefIdSet};
 use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
+use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_span::{InnerSpan, Span, DUMMY_SP};
 use std::mem;
 use std::ops::Range;
 
+use self::Condition::*;
 use crate::clean::{self, GetDefId, Item};
 use crate::core::DocContext;
 use crate::fold::{DocFolder, StripItem};
@@ -52,10 +53,29 @@
 #[derive(Copy, Clone)]
 pub struct Pass {
     pub name: &'static str,
-    pub pass: fn(clean::Crate, &DocContext<'_>) -> clean::Crate,
+    pub run: fn(clean::Crate, &DocContext<'_>) -> clean::Crate,
     pub description: &'static str,
 }
 
+/// In a list of passes, a pass that may or may not need to be run depending on options.
+#[derive(Copy, Clone)]
+pub struct ConditionalPass {
+    pub pass: Pass,
+    pub condition: Condition,
+}
+
+/// How to decide whether to run a conditional pass.
+#[derive(Copy, Clone)]
+pub enum Condition {
+    Always,
+    /// When `--document-private-items` is passed.
+    WhenDocumentPrivate,
+    /// When `--document-private-items` is not passed.
+    WhenNotDocumentPrivate,
+    /// When `--document-hidden-items` is not passed.
+    WhenNotDocumentHidden,
+}
+
 /// The full list of passes.
 pub const PASSES: &[Pass] = &[
     CHECK_PRIVATE_ITEMS_DOC_TESTS,
@@ -72,63 +92,58 @@
 ];
 
 /// The list of passes run by default.
-pub const DEFAULT_PASSES: &[Pass] = &[
-    COLLECT_TRAIT_IMPLS,
-    COLLAPSE_DOCS,
-    UNINDENT_COMMENTS,
-    CHECK_PRIVATE_ITEMS_DOC_TESTS,
-    STRIP_HIDDEN,
-    STRIP_PRIVATE,
-    COLLECT_INTRA_DOC_LINKS,
-    CHECK_CODE_BLOCK_SYNTAX,
-    PROPAGATE_DOC_CFG,
-];
-
-/// The list of default passes run with `--document-private-items` is passed to rustdoc.
-pub const DEFAULT_PRIVATE_PASSES: &[Pass] = &[
-    COLLECT_TRAIT_IMPLS,
-    COLLAPSE_DOCS,
-    UNINDENT_COMMENTS,
-    CHECK_PRIVATE_ITEMS_DOC_TESTS,
-    STRIP_PRIV_IMPORTS,
-    COLLECT_INTRA_DOC_LINKS,
-    CHECK_CODE_BLOCK_SYNTAX,
-    PROPAGATE_DOC_CFG,
+pub const DEFAULT_PASSES: &[ConditionalPass] = &[
+    ConditionalPass::always(COLLECT_TRAIT_IMPLS),
+    ConditionalPass::always(COLLAPSE_DOCS),
+    ConditionalPass::always(UNINDENT_COMMENTS),
+    ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS),
+    ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
+    ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
+    ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate),
+    ConditionalPass::always(COLLECT_INTRA_DOC_LINKS),
+    ConditionalPass::always(CHECK_CODE_BLOCK_SYNTAX),
+    ConditionalPass::always(PROPAGATE_DOC_CFG),
 ];
 
 /// The list of default passes run when `--doc-coverage` is passed to rustdoc.
-pub const DEFAULT_COVERAGE_PASSES: &[Pass] =
-    &[COLLECT_TRAIT_IMPLS, STRIP_HIDDEN, STRIP_PRIVATE, CALCULATE_DOC_COVERAGE];
+pub const COVERAGE_PASSES: &[ConditionalPass] = &[
+    ConditionalPass::always(COLLECT_TRAIT_IMPLS),
+    ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
+    ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
+    ConditionalPass::always(CALCULATE_DOC_COVERAGE),
+];
 
-/// The list of default passes run when `--doc-coverage --document-private-items` is passed to
-/// rustdoc.
-pub const PRIVATE_COVERAGE_PASSES: &[Pass] = &[COLLECT_TRAIT_IMPLS, CALCULATE_DOC_COVERAGE];
+impl ConditionalPass {
+    pub const fn always(pass: Pass) -> Self {
+        Self::new(pass, Always)
+    }
+
+    pub const fn new(pass: Pass, condition: Condition) -> Self {
+        ConditionalPass { pass, condition }
+    }
+}
 
 /// A shorthand way to refer to which set of passes to use, based on the presence of
-/// `--no-defaults` or `--document-private-items`.
+/// `--no-defaults` and `--show-coverage`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum DefaultPassOption {
     Default,
-    Private,
     Coverage,
-    PrivateCoverage,
     None,
 }
 
 /// Returns the given default set of passes.
-pub fn defaults(default_set: DefaultPassOption) -> &'static [Pass] {
+pub fn defaults(default_set: DefaultPassOption) -> &'static [ConditionalPass] {
     match default_set {
         DefaultPassOption::Default => DEFAULT_PASSES,
-        DefaultPassOption::Private => DEFAULT_PRIVATE_PASSES,
-        DefaultPassOption::Coverage => DEFAULT_COVERAGE_PASSES,
-        DefaultPassOption::PrivateCoverage => PRIVATE_COVERAGE_PASSES,
+        DefaultPassOption::Coverage => COVERAGE_PASSES,
         DefaultPassOption::None => &[],
     }
 }
 
 /// If the given name matches a known pass, returns its information.
-pub fn find_pass(pass_name: &str) -> Option<&'static Pass> {
-    PASSES.iter().find(|p| p.name == pass_name)
+pub fn find_pass(pass_name: &str) -> Option<Pass> {
+    PASSES.iter().find(|p| p.name == pass_name).copied()
 }
 
 struct Stripper<'a> {
diff --git a/src/librustdoc/passes/private_items_doc_tests.rs b/src/librustdoc/passes/private_items_doc_tests.rs
index 23e2727..aec5a6b 100644
--- a/src/librustdoc/passes/private_items_doc_tests.rs
+++ b/src/librustdoc/passes/private_items_doc_tests.rs
@@ -5,7 +5,7 @@
 
 pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
     name: "check-private-items-doc-tests",
-    pass: check_private_items_doc_tests,
+    run: check_private_items_doc_tests,
     description: "check private items doc tests",
 };
 
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index a296e73..64b0c45 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -8,7 +8,7 @@
 
 pub const PROPAGATE_DOC_CFG: Pass = Pass {
     name: "propagate-doc-cfg",
-    pass: propagate_doc_cfg,
+    run: propagate_doc_cfg,
     description: "propagates `#[doc(cfg(...))]` to child items",
 };
 
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 5fd97d1..f82e72b 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -1,4 +1,4 @@
-use rustc::hir::def_id::DefIdSet;
+use rustc_hir::def_id::DefIdSet;
 use rustc_span::symbol::sym;
 use std::mem;
 
@@ -10,7 +10,7 @@
 
 pub const STRIP_HIDDEN: Pass = Pass {
     name: "strip-hidden",
-    pass: strip_hidden,
+    run: strip_hidden,
     description: "strips all doc(hidden) items from the output",
 };
 
diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs
index af34842..35b26fb 100644
--- a/src/librustdoc/passes/strip_priv_imports.rs
+++ b/src/librustdoc/passes/strip_priv_imports.rs
@@ -5,7 +5,7 @@
 
 pub const STRIP_PRIV_IMPORTS: Pass = Pass {
     name: "strip-priv-imports",
-    pass: strip_priv_imports,
+    run: strip_priv_imports,
     description: "strips all private import statements (`use`, `extern crate`) from a crate",
 };
 
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index 167aa2c..f244956 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -1,4 +1,4 @@
-use rustc::hir::def_id::DefIdSet;
+use rustc_hir::def_id::DefIdSet;
 
 use crate::clean;
 use crate::core::DocContext;
@@ -7,7 +7,7 @@
 
 pub const STRIP_PRIVATE: Pass = Pass {
     name: "strip-private",
-    pass: strip_private,
+    run: strip_private,
     description: "strips all private items from a crate which cannot be seen externally, \
         implies strip-priv-imports",
 };
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs
index 3212af0..d4e09ce 100644
--- a/src/librustdoc/passes/unindent_comments.rs
+++ b/src/librustdoc/passes/unindent_comments.rs
@@ -12,7 +12,7 @@
 
 pub const UNINDENT_COMMENTS: Pass = Pass {
     name: "unindent-comments",
-    pass: unindent_comments,
+    run: unindent_comments,
     description: "removes excess indentation on comments in order for markdown to like it",
 };
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index ca5c09e..b5731ff 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -1,9 +1,10 @@
-use rustc::hir;
-use rustc::hir::intravisit;
+use rustc::hir::map::Map;
 use rustc::session::{self, config, DiagnosticOutput};
 use rustc::util::common::ErrorReported;
 use rustc_data_structures::sync::Lrc;
 use rustc_feature::UnstableFeatures;
+use rustc_hir as hir;
+use rustc_hir::intravisit;
 use rustc_interface::interface;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
@@ -135,7 +136,7 @@
 }
 
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
-fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
+fn scrape_test_config(krate: &::rustc_hir::Crate) -> TestOptions {
     use syntax::print::pprust;
 
     let mut opts =
@@ -387,8 +388,8 @@
     // crate already is included.
     let result = rustc_driver::catch_fatal_errors(|| {
         with_globals(edition, || {
-            use errors::emitter::EmitterWriter;
-            use errors::Handler;
+            use rustc_errors::emitter::EmitterWriter;
+            use rustc_errors::Handler;
             use rustc_parse::maybe_new_parser_from_source_str;
             use rustc_span::source_map::FilePathMapping;
             use syntax::sess::ParseSess;
@@ -851,7 +852,7 @@
 struct HirCollector<'a, 'hir> {
     sess: &'a session::Session,
     collector: &'a mut Collector,
-    map: &'a hir::map::Map<'hir>,
+    map: &'a Map<'hir>,
     codes: ErrorCodes,
 }
 
@@ -897,7 +898,9 @@
 }
 
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'hir> {
+    type Map = Map<'hir>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
         intravisit::NestedVisitorMap::All(&self.map)
     }
 
diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs
index b45531d..af1c50a 100644
--- a/src/librustdoc/theme.rs
+++ b/src/librustdoc/theme.rs
@@ -3,7 +3,7 @@
 use std::hash::{Hash, Hasher};
 use std::path::Path;
 
-use errors::Handler;
+use rustc_errors::Handler;
 
 #[cfg(test)]
 mod tests;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 707d9a9..5fa9270 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -1,15 +1,16 @@
 //! The Rust AST Visitor. Extracts useful information and massages it into a form
 //! usable for `clean`.
 
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::{self, Node};
 use rustc::middle::privacy::AccessLevel;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::Node;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{kw, sym};
 use rustc_span::{self, Span};
 use syntax::ast;
 
@@ -513,16 +514,20 @@
                 om.statics.push(s);
             }
             hir::ItemKind::Const(type_, expr) => {
-                let s = Constant {
-                    type_,
-                    expr,
-                    id: item.hir_id,
-                    name: ident.name,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                    vis: &item.vis,
-                };
-                om.constants.push(s);
+                // Underscore constants do not correspond to a nameable item and
+                // so are never useful in documentation.
+                if ident.name != kw::Underscore {
+                    let s = Constant {
+                        type_,
+                        expr,
+                        id: item.hir_id,
+                        name: ident.name,
+                        attrs: &item.attrs,
+                        whence: item.span,
+                        vis: &item.vis,
+                    };
+                    om.constants.push(s);
+                }
             }
             hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
                 let items = item_ids.iter().map(|ti| self.cx.tcx.hir().trait_item(ti.id)).collect();
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index d157a0c..12ffd6c 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -1,8 +1,8 @@
-use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::ty::{TyCtxt, Visibility};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_span::symbol::sym;
 
 use crate::clean::{AttributesExt, NestedAttributesExt};
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index a22e162..c9ff93e 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -34,16 +34,6 @@
 [dev-dependencies]
 rand = "0.7"
 
-[target.x86_64-apple-darwin.dependencies]
-rustc_asan = { path = "../librustc_asan" }
-rustc_tsan = { path = "../librustc_tsan" }
-
-[target.x86_64-unknown-linux-gnu.dependencies]
-rustc_asan = { path = "../librustc_asan" }
-rustc_lsan = { path = "../librustc_lsan" }
-rustc_msan = { path = "../librustc_msan" }
-rustc_tsan = { path = "../librustc_tsan" }
-
 [target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
 
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 566e514..b48700f 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -631,6 +631,38 @@
         self.map.raw_entry_mut().from_key(&value).or_insert(value, ()).0
     }
 
+    /// Inserts an owned copy of the given `value` into the set if it is not
+    /// present, then returns a reference to the value in the set.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(hash_set_entry)]
+    ///
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
+    ///     .iter().map(|&pet| pet.to_owned()).collect();
+    ///
+    /// assert_eq!(set.len(), 3);
+    /// for &pet in &["cat", "dog", "fish"] {
+    ///     let value = set.get_or_insert_owned(pet);
+    ///     assert_eq!(value, pet);
+    /// }
+    /// assert_eq!(set.len(), 4); // a new "fish" was inserted
+    /// ```
+    #[inline]
+    #[unstable(feature = "hash_set_entry", issue = "60896")]
+    pub fn get_or_insert_owned<Q: ?Sized>(&mut self, value: &Q) -> &T
+    where
+        T: Borrow<Q>,
+        Q: Hash + Eq + ToOwned<Owned = T>,
+    {
+        // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
+        // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
+        self.map.raw_entry_mut().from_key(value).or_insert_with(|| (value.to_owned(), ())).0
+    }
+
     /// Inserts a value computed from `f` into the set if the given `value` is
     /// not present, then returns a reference to the value in the set.
     ///
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 13fe3bd..af35a5d 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -878,6 +878,7 @@
     /// - mips64
     /// - powerpc
     /// - powerpc64
+    /// - riscv64
     /// - s390x
     /// - sparc64
     #[stable(feature = "env", since = "1.0.0")]
@@ -1035,6 +1036,11 @@
     pub const ARCH: &'static str = "hexagon";
 }
 
+#[cfg(target_arch = "riscv64")]
+mod arch {
+    pub const ARCH: &'static str = "riscv64";
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 1407fe2..b480581 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -250,6 +250,7 @@
     /// assert!(
     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
     /// ```
+    #[inline]
     fn from(err: String) -> Box<dyn Error + Send + Sync> {
         struct StringError(String);
 
@@ -317,6 +318,7 @@
     /// assert!(
     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
     /// ```
+    #[inline]
     fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index d2ee65f..700e015 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -1187,11 +1187,6 @@
     /// function will return the corresponding [`&str`] slice. Otherwise,
     /// it will return an error with details of where UTF-8 validation failed.
     ///
-    /// > **Note**: This method is currently implemented to check for validity
-    /// > after a constant-time cast, but it is planned to alter its definition
-    /// > in the future to perform the length calculation in addition to the
-    /// > UTF-8 check whenever this method is called.
-    ///
     /// [`&str`]: ../primitive.str.html
     ///
     /// # Examples
@@ -1220,11 +1215,6 @@
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
     /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
     ///
-    /// > **Note**: This method is currently implemented to check for validity
-    /// > after a constant-time cast, but it is planned to alter its definition
-    /// > in the future to perform the length calculation in addition to the
-    /// > UTF-8 check whenever this method is called.
-    ///
     /// [`Cow`]: ../borrow/enum.Cow.html
     /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
     /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 4c30832..77da972 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -615,6 +615,7 @@
     /// assert!(!os_str.is_empty());
     /// ```
     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+    #[inline]
     pub fn is_empty(&self) -> bool {
         self.inner.inner.is_empty()
     }
@@ -965,6 +966,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for OsString {
+    #[inline]
     fn as_ref(&self) -> &OsStr {
         self
     }
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index a9d8837..a59d7f0 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -227,10 +227,7 @@
     /// ```
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
     pub fn is_ipv4(&self) -> bool {
-        match *self {
-            SocketAddr::V4(_) => true,
-            SocketAddr::V6(_) => false,
-        }
+        matches!(*self, SocketAddr::V4(_))
     }
 
     /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
@@ -252,10 +249,7 @@
     /// ```
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
     pub fn is_ipv6(&self) -> bool {
-        match *self {
-            SocketAddr::V4(_) => false,
-            SocketAddr::V6(_) => true,
-        }
+        matches!(*self, SocketAddr::V6(_))
     }
 }
 
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index 15d2361..6410a4f 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -281,10 +281,7 @@
     /// ```
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     pub fn is_ipv4(&self) -> bool {
-        match self {
-            IpAddr::V4(_) => true,
-            IpAddr::V6(_) => false,
-        }
+        matches!(self, IpAddr::V4(_))
     }
 
     /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
@@ -303,10 +300,7 @@
     /// ```
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     pub fn is_ipv6(&self) -> bool {
-        match self {
-            IpAddr::V4(_) => false,
-            IpAddr::V6(_) => true,
-        }
+        matches!(self, IpAddr::V6(_))
     }
 }
 
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index c33f98b..5023d69 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -63,14 +63,13 @@
 /// # Examples
 ///
 /// ```no_run
-/// # use std::io;
 /// use std::net::{TcpListener, TcpStream};
 ///
 /// fn handle_client(stream: TcpStream) {
 ///     // ...
 /// }
 ///
-/// fn main() -> io::Result<()> {
+/// fn main() -> std::io::Result<()> {
 ///     let listener = TcpListener::bind("127.0.0.1:80")?;
 ///
 ///     // accept connections and process them serially
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index d9b2236..0caec97 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -230,7 +230,12 @@
     }
 }
 
-#[cfg(any(target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64"))]
+#[cfg(any(
+    target_arch = "mips64",
+    target_arch = "s390x",
+    target_arch = "sparc64",
+    target_arch = "riscv64"
+))]
 mod arch {
     pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
 }
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index e090120..47daf0c 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -18,7 +18,8 @@
             target_arch = "hexagon",
             target_arch = "powerpc",
             target_arch = "powerpc64",
-            target_arch = "s390x"
+            target_arch = "s390x",
+            target_arch = "riscv64"
         )
     ),
     all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
@@ -60,7 +61,8 @@
             target_arch = "hexagon",
             target_arch = "powerpc",
             target_arch = "powerpc64",
-            target_arch = "s390x"
+            target_arch = "s390x",
+            target_arch = "riscv64"
         )
     ),
     all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index f308d51..a703cb7 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -224,18 +224,12 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_verbatim(&self) -> bool {
         use self::Prefix::*;
-        match *self {
-            Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..) => true,
-            _ => false,
-        }
+        matches!(*self, Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..))
     }
 
     #[inline]
     fn is_drive(&self) -> bool {
-        match *self {
-            Prefix::Disk(_) => true,
-            _ => false,
-        }
+        matches!(*self, Prefix::Disk(_))
     }
 
     #[inline]
@@ -1481,6 +1475,7 @@
     /// Converts a `OsString` into a `PathBuf`
     ///
     /// This conversion does not allocate or copy memory.
+    #[inline]
     fn from(s: OsString) -> PathBuf {
         PathBuf { inner: s }
     }
@@ -1541,7 +1536,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Deref for PathBuf {
     type Target = Path;
-
+    #[inline]
     fn deref(&self) -> &Path {
         Path::new(&self.inner)
     }
@@ -2661,6 +2656,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<Path> for str {
+    #[inline]
     fn as_ref(&self) -> &Path {
         Path::new(self)
     }
@@ -2675,6 +2671,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<Path> for PathBuf {
+    #[inline]
     fn as_ref(&self) -> &Path {
         self
     }
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index eddbdff..0131437 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -199,10 +199,7 @@
 
         // At this point, all spawned threads should be blocked,
         // so we shouldn't get anything from the port
-        assert!(match rx.try_recv() {
-            Err(TryRecvError::Empty) => true,
-            _ => false,
-        });
+        assert!(matches!(rx.try_recv(), Err(TryRecvError::Empty)));
 
         let mut leader_found = barrier.wait().is_leader();
 
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index bbe77e7..5b41525 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -118,12 +118,7 @@
     // Just tests whether this channel has been sent on or not, this is only
     // safe to use from the sender.
     pub fn sent(&self) -> bool {
-        unsafe {
-            match *self.upgrade.get() {
-                NothingSent => false,
-                _ => true,
-            }
-        }
+        unsafe { !matches!(*self.upgrade.get(), NothingSent) }
     }
 
     pub fn recv(&self, deadline: Option<Instant>) -> Result<T, Failure<T>> {
diff --git a/src/libstd/sys/hermit/os.rs b/src/libstd/sys/hermit/os.rs
index 5999fdd..78eabf8 100644
--- a/src/libstd/sys/hermit/os.rs
+++ b/src/libstd/sys/hermit/os.rs
@@ -6,7 +6,6 @@
 use crate::marker::PhantomData;
 use crate::memchr;
 use crate::path::{self, PathBuf};
-use crate::ptr;
 use crate::str;
 use crate::sync::Mutex;
 use crate::sys::hermit::abi;
@@ -77,13 +76,17 @@
     unsafe {
         ENV = Some(Mutex::new(HashMap::new()));
 
+        if env.is_null() {
+            return;
+        }
+
         let mut guard = ENV.as_ref().unwrap().lock().unwrap();
         let mut environ = env;
-        while environ != ptr::null() && *environ != ptr::null() {
+        while !(*environ).is_null() {
             if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
                 guard.insert(key, value);
             }
-            environ = environ.offset(1);
+            environ = environ.add(1);
         }
     }
 
diff --git a/src/libstd/sys/hermit/thread_local.rs b/src/libstd/sys/hermit/thread_local.rs
index ba967c7..c6f8adb 100644
--- a/src/libstd/sys/hermit/thread_local.rs
+++ b/src/libstd/sys/hermit/thread_local.rs
@@ -18,14 +18,14 @@
 static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
 
 unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
-    if KEYS == ptr::null_mut() {
+    if KEYS.is_null() {
         KEYS = Box::into_raw(Box::new(BTreeMap::new()));
     }
     &mut *KEYS
 }
 
 unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
-    if LOCALS == ptr::null_mut() {
+    if LOCALS.is_null() {
         LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
     }
     &mut *LOCALS
diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs
index 81a766e..2b0485c 100644
--- a/src/libstd/sys/sgx/abi/tls.rs
+++ b/src/libstd/sys/sgx/abi/tls.rs
@@ -70,7 +70,7 @@
             any_non_null_dtor = false;
             for (value, dtor) in TLS_KEY_IN_USE.iter().filter_map(&value_with_destructor) {
                 let value = value.replace(ptr::null_mut());
-                if value != ptr::null_mut() {
+                if !value.is_null() {
                     any_non_null_dtor = true;
                     unsafe { dtor(value) }
                 }
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 2a05194..ab2a871 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -51,23 +51,14 @@
 
 pub struct File(FileDesc);
 
-// FIXME: This should be available on Linux with all `target_arch` and `target_env`.
-// https://github.com/rust-lang/libc/issues/1545
+// FIXME: This should be available on Linux with all `target_env`.
+// But currently only glibc exposes `statx` fn and structs.
+// We don't want to import unverified raw C structs here directly.
+// https://github.com/rust-lang/rust/pull/67774
 macro_rules! cfg_has_statx {
     ({ $($then_tt:tt)* } else { $($else_tt:tt)* }) => {
         cfg_if::cfg_if! {
-            if #[cfg(all(target_os = "linux", target_env = "gnu", any(
-                target_arch = "x86",
-                target_arch = "arm",
-                // target_arch = "mips",
-                target_arch = "powerpc",
-                target_arch = "x86_64",
-                // target_arch = "aarch64",
-                target_arch = "powerpc64",
-                // target_arch = "mips64",
-                // target_arch = "s390x",
-                target_arch = "sparc64",
-            )))] {
+            if #[cfg(all(target_os = "linux", target_env = "gnu"))] {
                 $($then_tt)*
             } else {
                 $($else_tt)*
@@ -75,18 +66,7 @@
         }
     };
     ($($block_inner:tt)*) => {
-        #[cfg(all(target_os = "linux", target_env = "gnu", any(
-            target_arch = "x86",
-            target_arch = "arm",
-            // target_arch = "mips",
-            target_arch = "powerpc",
-            target_arch = "x86_64",
-            // target_arch = "aarch64",
-            target_arch = "powerpc64",
-            // target_arch = "mips64",
-            // target_arch = "s390x",
-            target_arch = "sparc64",
-        )))]
+        #[cfg(all(target_os = "linux", target_env = "gnu"))]
         {
             $($block_inner)*
         }
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index b277b3d..91f7d15 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -480,11 +480,13 @@
         let _guard = env_lock();
         let mut environ = *environ();
         let mut result = Vec::new();
-        while environ != ptr::null() && *environ != ptr::null() {
-            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                result.push(key_value);
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
             }
-            environ = environ.offset(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/vxworks/mod.rs b/src/libstd/sys/vxworks/mod.rs
index f102e4d..12bbfa1 100644
--- a/src/libstd/sys/vxworks/mod.rs
+++ b/src/libstd/sys/vxworks/mod.rs
@@ -36,18 +36,10 @@
 
 #[cfg(not(test))]
 pub fn init() {
-    // By default, some platforms will send a *signal* when an EPIPE error
-    // would otherwise be delivered. This runtime doesn't install a SIGPIPE
-    // handler, causing it to kill the program, which isn't exactly what we
-    // want!
-    //
-    // Hence, we set SIGPIPE to ignore when the program starts up in order
-    // to prevent this problem.
+    // ignore SIGPIPE
     unsafe {
-        reset_sigpipe();
+        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
     }
-
-    unsafe fn reset_sigpipe() {}
 }
 
 pub use libc::signal;
diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs
index d421915..1fadf71 100644
--- a/src/libstd/sys/vxworks/os.rs
+++ b/src/libstd/sys/vxworks/os.rs
@@ -7,7 +7,6 @@
 use crate::mem;
 use crate::memchr;
 use crate::path::{self, Path, PathBuf};
-use crate::ptr;
 use crate::slice;
 use crate::str;
 use crate::sys::cvt;
@@ -226,15 +225,15 @@
     unsafe {
         let _guard = env_lock();
         let mut environ = *environ();
-        if environ == ptr::null() {
+        if environ.is_null() {
             panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error());
         }
         let mut result = Vec::new();
-        while *environ != ptr::null() {
+        while !(*environ).is_null() {
             if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
                 result.push(key_value);
             }
-            environ = environ.offset(1);
+            environ = environ.add(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/vxworks/weak.rs b/src/libstd/sys/vxworks/weak.rs
deleted file mode 100644
index 4c6fdde..0000000
--- a/src/libstd/sys/vxworks/weak.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-//! Support for "weak linkage" to symbols on Unix
-//!
-//! Some I/O operations we do in libstd require newer versions of OSes but we
-//! need to maintain binary compatibility with older releases for now. In order
-//! to use the new functionality when available we use this module for
-//! detection.
-//!
-//! One option to use here is weak linkage, but that is unfortunately only
-//! really workable on Linux. Hence, use dlsym to get the symbol value at
-//! runtime. This is also done for compatibility with older versions of glibc,
-//! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
-//! we've been dynamically linked to the library the symbol comes from, but that
-//! is currently always the case for things like libpthread/libc.
-//!
-//! A long time ago this used weak linkage for the __pthread_get_minstack
-//! symbol, but that caused Debian to detect an unnecessarily strict versioned
-//! dependency on libc6 (#23628).
-
-use crate::ffi::CStr;
-use crate::marker;
-use crate::mem;
-use crate::sync::atomic::{AtomicUsize, Ordering};
-
-pub struct Weak<F> {
-    name: &'static str,
-    addr: AtomicUsize,
-    _marker: marker::PhantomData<F>,
-}
-
-impl<F> Weak<F> {
-    pub const fn new(name: &'static str) -> Weak<F> {
-        Weak { name, addr: AtomicUsize::new(1), _marker: marker::PhantomData }
-    }
-
-    pub fn get(&self) -> Option<F> {
-        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
-        unsafe {
-            if self.addr.load(Ordering::SeqCst) == 1 {
-                self.addr.store(fetch(self.name), Ordering::SeqCst);
-            }
-            match self.addr.load(Ordering::SeqCst) {
-                0 => None,
-                addr => Some(mem::transmute_copy::<usize, F>(&addr)),
-            }
-        }
-    }
-}
-
-unsafe fn fetch(name: &str) -> usize {
-    let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
-        Ok(cstr) => cstr,
-        Err(..) => return 0,
-    };
-    assert!(false, "FIXME: fetch");
-    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
-}
diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs
index 3baec6b..8052c0a 100644
--- a/src/libstd/sys/wasi/os.rs
+++ b/src/libstd/sys/wasi/os.rs
@@ -6,7 +6,6 @@
 use crate::marker::PhantomData;
 use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::ptr;
 use crate::str;
 use crate::sys::memchr;
 use crate::sys::{unsupported, Void};
@@ -107,11 +106,13 @@
         let _guard = env_lock();
         let mut environ = libc::environ;
         let mut result = Vec::new();
-        while environ != ptr::null_mut() && *environ != ptr::null_mut() {
-            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                result.push(key_value);
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
             }
-            environ = environ.offset(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index c535467..cc4ae40 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -43,7 +43,7 @@
             ];
             module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
 
-            if module != ptr::null_mut() {
+            if !module.is_null() {
                 errnum ^= c::FACILITY_NT_BIT as i32;
                 flags = c::FORMAT_MESSAGE_FROM_HMODULE;
             }
diff --git a/src/libstd/sys_common/alloc.rs b/src/libstd/sys_common/alloc.rs
index 713b994..c669410 100644
--- a/src/libstd/sys_common/alloc.rs
+++ b/src/libstd/sys_common/alloc.rs
@@ -22,7 +22,8 @@
     target_arch = "aarch64",
     target_arch = "mips64",
     target_arch = "s390x",
-    target_arch = "sparc64"
+    target_arch = "sparc64",
+    target_arch = "riscv64"
 )))]
 pub const MIN_ALIGN: usize = 16;
 
diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs
index eb8a881..e965ea7 100644
--- a/src/libstd/sys_common/os_str_bytes.rs
+++ b/src/libstd/sys_common/os_str_bytes.rs
@@ -104,6 +104,7 @@
         self.inner.shrink_to(min_capacity)
     }
 
+    #[inline]
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index b174189..0dc43c7 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -1072,6 +1072,19 @@
             ThreadId(NonZeroU64::new(id).unwrap())
         }
     }
+
+    /// This returns a numeric identifier for the thread identified by this
+    /// `ThreadId`.
+    ///
+    /// As noted in the documentation for the type itself, it is essentially an
+    /// opaque ID, but is guaranteed to be unique for each thread. The returned
+    /// value is entirely opaque -- only equality testing is stable. Note that
+    /// it is not guaranteed which values new threads will return, and this may
+    /// change across Rust versions.
+    #[unstable(feature = "thread_id_value", issue = "67939")]
+    pub fn as_u64(&self) -> u64 {
+        self.0.get()
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 0dce8f8..0b6e728 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -67,7 +67,7 @@
 /// |:---------:|:--------------------------------------------------------------------:|
 /// | Cloud ABI | [clock_time_get (Monotonic Clock)]                                   |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
-/// | UNIX      | [clock_time_get (Monotonic Clock)]                                   |
+/// | UNIX      | [clock_gettime (Monotonic Clock)]                                    |
 /// | Darwin    | [mach_absolute_time]                                                 |
 /// | VXWorks   | [clock_gettime (Monotonic Clock)]                                    |
 /// | WASI      | [__wasi_clock_time_get (Monotonic Clock)]                            |
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 2098656..7d9f715 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -10,13 +10,11 @@
 doctest = false
 
 [dependencies]
-bitflags = "1.2.1"
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 log = "0.4"
 scoped-tls = "1.0"
-lazy_static = "1.0.0"
+rustc_errors = { path = "../librustc_errors" }
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_index = { path = "../librustc_index" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 4707026..33acba8 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -649,7 +649,7 @@
     Lit(P<Expr>),
 
     /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
-    Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
+    Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
 
     /// A slice pattern `[a, b, c]`.
     Slice(Vec<P<Pat>>),
@@ -1033,7 +1033,7 @@
     pub fn to_bound(&self) -> Option<GenericBound> {
         match &self.kind {
             ExprKind::Path(None, path) => Some(GenericBound::Trait(
-                PolyTraitRef::new(Vec::new(), path.clone(), self.span),
+                PolyTraitRef::new(Vec::new(), path.clone(), None, self.span),
                 TraitBoundModifier::None,
             )),
             _ => None,
@@ -2376,6 +2376,15 @@
 pub struct TraitRef {
     pub path: Path,
     pub ref_id: NodeId,
+
+    /// The `const` modifier, if any, that appears before this trait.
+    ///
+    /// |                | `constness`                 |
+    /// |----------------|-----------------------------|
+    /// | `Trait`        | `None`                      |
+    /// | `const Trait`  | `Some(Constness::Const)`    |
+    /// | `?const Trait` | `Some(Constness::NotConst)` |
+    pub constness: Option<Constness>,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -2390,10 +2399,15 @@
 }
 
 impl PolyTraitRef {
-    pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self {
+    pub fn new(
+        generic_params: Vec<GenericParam>,
+        path: Path,
+        constness: Option<Constness>,
+        span: Span,
+    ) -> Self {
         PolyTraitRef {
             bound_generic_params: generic_params,
-            trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID },
+            trait_ref: TraitRef { path, constness, ref_id: DUMMY_NODE_ID },
             span,
         }
     }
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index 04c28dd..70f4f47 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -2,11 +2,10 @@
 
 use super::{mark_used, MetaItemKind};
 use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
-use crate::feature_gate::feature_err;
 use crate::print::pprust;
-use crate::sess::ParseSess;
+use crate::sess::{feature_err, ParseSess};
 
-use errors::{Applicability, Handler};
+use rustc_errors::{struct_span_err, Applicability, Handler};
 use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
 use rustc_macros::HashStable_Generic;
 use rustc_span::hygiene::Transparency;
@@ -31,17 +30,21 @@
 fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
     let diag = &sess.span_diagnostic;
     match error {
-        AttrError::MultipleItem(item) => span_err!(diag, span, E0538, "multiple '{}' items", item),
+        AttrError::MultipleItem(item) => {
+            struct_span_err!(diag, span, E0538, "multiple '{}' items", item).emit();
+        }
         AttrError::UnknownMetaItem(item, expected) => {
             let expected = expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
             struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item)
                 .span_label(span, format!("expected one of {}", expected.join(", ")))
                 .emit();
         }
-        AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"),
-        AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"),
+        AttrError::MissingSince => struct_span_err!(diag, span, E0542, "missing 'since'").emit(),
+        AttrError::MissingFeature => {
+            struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
+        }
         AttrError::MultipleStabilityLevels => {
-            span_err!(diag, span, E0544, "multiple stability levels")
+            struct_span_err!(diag, span, E0544, "multiple stability levels").emit();
         }
         AttrError::UnsupportedLiteral(msg, is_bytestr) => {
             let mut err = struct_span_err!(diag, span, E0565, "{}", msg);
@@ -283,7 +286,7 @@
                     *item = Some(v);
                     true
                 } else {
-                    span_err!(diagnostic, meta.span, E0539, "incorrect meta item");
+                    struct_span_err!(diagnostic, meta.span, E0539, "incorrect meta item").emit();
                     false
                 }
             };
@@ -331,12 +334,13 @@
             match meta_name {
                 sym::rustc_deprecated => {
                     if rustc_depr.is_some() {
-                        span_err!(
+                        struct_span_err!(
                             diagnostic,
                             item_sp,
                             E0540,
                             "multiple rustc_deprecated attributes"
-                        );
+                        )
+                        .emit();
                         continue 'outer;
                     }
 
@@ -351,7 +355,8 @@
                             continue;
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span, E0543, "missing 'reason'");
+                            struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'")
+                                .emit();
                             continue;
                         }
                     }
@@ -426,12 +431,13 @@
                                         // Disallowing this requires updates to some submodules
                                         NonZeroU32::new(num)
                                     } else {
-                                        span_err!(
+                                        struct_span_err!(
                                             diagnostic,
                                             attr.span,
                                             E0545,
                                             "incorrect 'issue'"
-                                        );
+                                        )
+                                        .emit();
                                         continue;
                                     }
                                 }
@@ -453,7 +459,8 @@
                             continue;
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span, E0547, "missing 'issue'");
+                            struct_span_err!(diagnostic, attr.span, E0547, "missing 'issue'")
+                                .emit();
                             continue;
                         }
                     }
@@ -539,13 +546,14 @@
         if let Some(ref mut stab) = stab {
             stab.rustc_depr = Some(rustc_depr);
         } else {
-            span_err!(
+            struct_span_err!(
                 diagnostic,
                 item_sp,
                 E0549,
                 "rustc_deprecated attribute must be paired with \
                        either stable or unstable attribute"
-            );
+            )
+            .emit();
         }
     }
 
@@ -555,14 +563,15 @@
             stab.promotable = promotable;
             stab.allow_const_fn_ptr = allow_const_fn_ptr;
         } else {
-            span_err!(
+            struct_span_err!(
                 diagnostic,
                 item_sp,
                 E0717,
                 "rustc_promotable and rustc_allow_const_fn_ptr attributes \
                       must be paired with either a rustc_const_unstable or a rustc_const_stable \
                       attribute"
-            );
+            )
+            .emit();
         }
     }
 
@@ -649,20 +658,27 @@
                 }
                 sym::not => {
                     if mis.len() != 1 {
-                        span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
+                        struct_span_err!(
+                            sess.span_diagnostic,
+                            cfg.span,
+                            E0536,
+                            "expected 1 cfg-pattern"
+                        )
+                        .emit();
                         return false;
                     }
 
                     !eval_condition(mis[0].meta_item().unwrap(), sess, eval)
                 }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         sess.span_diagnostic,
                         cfg.span,
                         E0537,
                         "invalid predicate `{}`",
                         pprust::path_to_string(&cfg.path)
-                    );
+                    )
+                    .emit();
                     false
                 }
             }
@@ -703,7 +719,7 @@
         }
 
         if depr.is_some() {
-            span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes");
+            struct_span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes").emit();
             break;
         }
 
@@ -741,7 +757,8 @@
                                 ),
                             );
                         } else {
-                            span_err!(diagnostic, meta.span, E0551, "incorrect meta item");
+                            struct_span_err!(diagnostic, meta.span, E0551, "incorrect meta item")
+                                .emit();
                         }
 
                         false
@@ -900,13 +917,14 @@
                         };
                     }
                     if let Some(literal_error) = literal_error {
-                        span_err!(
+                        struct_span_err!(
                             diagnostic,
                             item.span(),
                             E0589,
                             "invalid `repr(align)` attribute: {}",
                             literal_error
-                        );
+                        )
+                        .emit();
                     }
                 } else {
                     if let Some(meta_item) = item.meta_item() {
@@ -945,7 +963,13 @@
                 }
                 if !recognised {
                     // Not a word we recognize
-                    span_err!(diagnostic, item.span(), E0552, "unrecognized representation hint");
+                    struct_span_err!(
+                        diagnostic,
+                        item.span(),
+                        E0552,
+                        "unrecognized representation hint"
+                    )
+                    .emit();
                 }
             }
         }
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 8449b61..ec05dab 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -384,7 +384,7 @@
 
 pub fn allow_internal_unstable<'a>(
     attrs: &[Attribute],
-    span_diagnostic: &'a errors::Handler,
+    span_diagnostic: &'a rustc_errors::Handler,
 ) -> Option<impl Iterator<Item = Symbol> + 'a> {
     find_by_name(attrs, sym::allow_internal_unstable).and_then(|attr| {
         attr.meta_item_list()
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
deleted file mode 100644
index 4ed1741..0000000
--- a/src/libsyntax/diagnostics/macros.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-#[macro_export]
-macro_rules! diagnostic_used {
-    ($code:ident) => {
-        let _ = $code;
-    };
-}
-
-#[macro_export]
-macro_rules! span_fatal {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_fatal_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_err {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_err_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_warn {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_warn_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_err {
-    ($session:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_err_with_code(
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_err_or_warn {
-    ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        if $is_warning {
-            $session.span_warn_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        } else {
-            $session.span_err_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_fatal {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_fatal_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_err {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_err_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! stringify_error_code {
-    ($code:ident) => {{
-        $crate::diagnostic_used!($code);
-        $crate::errors::DiagnosticId::Error(stringify!($code).to_owned())
-    }};
-}
-
-#[macro_export]
-macro_rules! type_error_struct {
-    ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
-        if $typ.references_error() {
-            $session.diagnostic().struct_dummy()
-        } else {
-            struct_span_err!($session, $span, $code, $($message)*)
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_warn {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_warn_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_err_or_warn {
-    ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        if $is_warning {
-            $session.struct_span_warn_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        } else {
-            $session.struct_span_err_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! span_note {
-    ($err:expr, $span:expr, $($message:tt)*) => ({
-        ($err).span_note($span, &format!($($message)*));
-    })
-}
-
-#[macro_export]
-macro_rules! span_help {
-    ($err:expr, $span:expr, $($message:tt)*) => ({
-        ($err).span_help($span, &format!($($message)*));
-    })
-}
-
-#[macro_export]
-macro_rules! help {
-    ($err:expr, $($message:tt)*) => ({
-        ($err).help(&format!($($message)*));
-    })
-}
diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs
deleted file mode 100644
index 7724107..0000000
--- a/src/libsyntax/early_buffered_lints.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! Allows the buffering of lints for later.
-//!
-//! Since we cannot have a dependency on `librustc`, we implement some types here that are somewhat
-//! redundant. Later, these types can be converted to types for use by the rest of the compiler.
-
-use rustc_session::declare_lint;
-pub use rustc_session::lint::BufferedEarlyLint;
-use rustc_session::lint::FutureIncompatibleInfo;
-
-declare_lint! {
-    pub ILL_FORMED_ATTRIBUTE_INPUT,
-    Deny,
-    "ill-formed attribute inputs that were previously accepted and used in practice",
-    @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
-        edition: None,
-    };
-}
-
-declare_lint! {
-    pub META_VARIABLE_MISUSE,
-    Allow,
-    "possible meta-variable misuse at macro definition"
-}
-
-declare_lint! {
-    pub INCOMPLETE_INCLUDE,
-    Deny,
-    "trailing content in included file"
-}
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 72beddf..0184a32 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -7,7 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
 #![feature(bool_to_option)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![feature(const_fn)] // For the `transmute` in `P::new`
 #![feature(const_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
@@ -18,7 +18,6 @@
 #![recursion_limit = "256"]
 
 use ast::AttrId;
-pub use errors;
 use rustc_data_structures::sync::Lock;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
@@ -62,12 +61,6 @@
 
 scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
 
-#[macro_use]
-pub mod diagnostics {
-    #[macro_use]
-    pub mod macros;
-}
-
 pub mod util {
     pub mod classify;
     pub mod comments;
@@ -82,13 +75,8 @@
 pub mod attr;
 pub mod entry;
 pub mod expand;
-pub mod feature_gate {
-    mod check;
-    pub use check::{check_attribute, check_crate, feature_err, feature_err_issue, get_features};
-}
 pub mod mut_visit;
 pub mod ptr;
-pub mod show_span;
 pub use rustc_session::parse as sess;
 pub mod token;
 pub mod tokenstream;
@@ -100,8 +88,6 @@
     pub mod pprust;
 }
 
-pub mod early_buffered_lints;
-
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 1413f15..58d4e46 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -838,7 +838,8 @@
     }
 }
 
-pub fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
+pub fn noop_visit_trait_ref<T: MutVisitor>(tr: &mut TraitRef, vis: &mut T) {
+    let TraitRef { path, ref_id, constness: _ } = tr;
     vis.visit_path(path);
     vis.visit_id(ref_id);
 }
@@ -1074,8 +1075,8 @@
         PatKind::Box(inner) => vis.visit_pat(inner),
         PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
         PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
-            vis.visit_expr(e1);
-            vis.visit_expr(e2);
+            visit_opt(e1, |e| vis.visit_expr(e));
+            visit_opt(e2, |e| vis.visit_expr(e));
             vis.visit_span(span);
         }
         PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index dd99765..11c8cb8 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2329,14 +2329,18 @@
             }
             PatKind::Lit(ref e) => self.print_expr(&**e),
             PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
-                self.print_expr(begin);
-                self.s.space();
+                if let Some(e) = begin {
+                    self.print_expr(e);
+                    self.s.space();
+                }
                 match *end_kind {
                     RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."),
                     RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="),
                     RangeEnd::Excluded => self.s.word(".."),
                 }
-                self.print_expr(end);
+                if let Some(e) = end {
+                    self.print_expr(e);
+                }
             }
             PatKind::Slice(ref elts) => {
                 self.s.word("[");
diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs
index fc69702..cce86fe 100644
--- a/src/libsyntax/util/lev_distance.rs
+++ b/src/libsyntax/util/lev_distance.rs
@@ -54,14 +54,16 @@
     T: Iterator<Item = &'a Symbol>,
 {
     let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);
+    let name_vec: Vec<&Symbol> = iter_names.collect();
 
-    let (case_insensitive_match, levenstein_match) = iter_names
+    let (case_insensitive_match, levenshtein_match) = name_vec
+        .iter()
         .filter_map(|&name| {
             let dist = lev_distance(lookup, &name.as_str());
             if dist <= max_dist { Some((name, dist)) } else { None }
         })
         // Here we are collecting the next structure:
-        // (case_insensitive_match, (levenstein_match, levenstein_distance))
+        // (case_insensitive_match, (levenshtein_match, levenshtein_distance))
         .fold((None, None), |result, (candidate, dist)| {
             (
                 if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
@@ -75,10 +77,31 @@
                 },
             )
         });
-
+    // Priority of matches:
+    // 1. Exact case insensitive match
+    // 2. Levenshtein distance match
+    // 3. Sorted word match
     if let Some(candidate) = case_insensitive_match {
-        Some(candidate) // exact case insensitive match has a higher priority
+        Some(*candidate)
+    } else if levenshtein_match.is_some() {
+        levenshtein_match.map(|(candidate, _)| *candidate)
     } else {
-        levenstein_match.map(|(candidate, _)| candidate)
+        find_match_by_sorted_words(name_vec, lookup)
     }
 }
+
+fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) -> Option<Symbol> {
+    iter_names.iter().fold(None, |result, candidate| {
+        if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) {
+            Some(**candidate)
+        } else {
+            result
+        }
+    })
+}
+
+fn sort_by_words(name: &str) -> String {
+    let mut split_words: Vec<&str> = name.split('_').collect();
+    split_words.sort();
+    split_words.join("_")
+}
diff --git a/src/libsyntax/util/lev_distance/tests.rs b/src/libsyntax/util/lev_distance/tests.rs
index f65f927..2226616 100644
--- a/src/libsyntax/util/lev_distance/tests.rs
+++ b/src/libsyntax/util/lev_distance/tests.rs
@@ -46,5 +46,11 @@
             find_best_match_for_name(input.iter(), "aaaa", Some(4)),
             Some(Symbol::intern("AAAA"))
         );
+
+        let input = vec![Symbol::intern("a_longer_variable_name")];
+        assert_eq!(
+            find_best_match_for_name(input.iter(), "a_variable_longer_name", None),
+            Some(Symbol::intern("a_longer_variable_name"))
+        );
     })
 }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ebb49ab..3c2ebac 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -492,8 +492,8 @@
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visitor.visit_expr(lower_bound);
-            visitor.visit_expr(upper_bound);
+            walk_list!(visitor, visit_expr, lower_bound);
+            walk_list!(visitor, visit_expr, upper_bound);
         }
         PatKind::Wild | PatKind::Rest => {}
         PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => {
diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs
index ea6d632..edff8be 100644
--- a/src/libtest/cli.rs
+++ b/src/libtest/cli.rs
@@ -125,6 +125,8 @@
             `RUST_TEST_TIME_DOCTEST` environment variables.
 
             Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+            Durations must be specified in milliseconds, e.g. `500,2000` means that the warn time
+            is 0.5 seconds, and the critical time is 2 seconds.
 
             Not available for --format=terse",
             "plain|colored",
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index 087bbb4..0c57861 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -54,6 +54,9 @@
 #[cfg(target_arch = "sparc64")]
 pub const unwinder_private_data_size: usize = 2;
 
+#[cfg(target_arch = "riscv64")]
+pub const unwinder_private_data_size: usize = 2;
+
 #[cfg(target_os = "emscripten")]
 pub const unwinder_private_data_size: usize = 20;
 
diff --git a/src/llvm-project b/src/llvm-project
index 2cb4100..9330ec5 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 2cb41005ed5c4747b10d2bf01d8779d3bb4ae32d
+Subproject commit 9330ec5a4c1df5fc1fa62f993ed6a04da68cb040
diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml
index 86a93d7..5e0f167 100644
--- a/src/rustc/Cargo.toml
+++ b/src/rustc/Cargo.toml
@@ -9,7 +9,6 @@
 path = "rustc.rs"
 
 [dependencies]
-rustc_target = { path = "../librustc_target" }
 rustc_driver = { path = "../librustc_driver" }
 
 # Make sure rustc_codegen_ssa ends up in the sysroot, because this
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index dd0111d..678d787 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -89,7 +89,11 @@
 extern "C" LLVMRustArchiveIteratorRef
 LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) {
   Archive *Archive = RustArchive->getBinary();
+#if LLVM_VERSION_GE(10, 0)
+  std::unique_ptr<Error> Err = std::make_unique<Error>(Error::success());
+#else
   std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success());
+#endif
   auto Cur = Archive->child_begin(*Err);
   if (*Err) {
     LLVMRustSetLastError(toString(std::move(*Err)).c_str());
diff --git a/src/rustllvm/Linker.cpp b/src/rustllvm/Linker.cpp
index 7916721..69176f9 100644
--- a/src/rustllvm/Linker.cpp
+++ b/src/rustllvm/Linker.cpp
@@ -18,8 +18,7 @@
 LLVMRustLinkerNew(LLVMModuleRef DstRef) {
   Module *Dst = unwrap(DstRef);
 
-  auto Ret = llvm::make_unique<RustLinker>(*Dst);
-  return Ret.release();
+  return new RustLinker(*Dst);
 }
 
 extern "C" void
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 6698e5d..eaa845a 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -8,6 +8,7 @@
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/InitializePasses.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -532,6 +533,18 @@
   ObjectFile,
 };
 
+#if LLVM_VERSION_GE(10, 0)
+static CodeGenFileType fromRust(LLVMRustFileType Type) {
+  switch (Type) {
+  case LLVMRustFileType::AssemblyFile:
+    return CGFT_AssemblyFile;
+  case LLVMRustFileType::ObjectFile:
+    return CGFT_ObjectFile;
+  default:
+    report_fatal_error("Bad FileType.");
+  }
+}
+#else
 static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) {
   switch (Type) {
   case LLVMRustFileType::AssemblyFile:
@@ -542,6 +555,7 @@
     report_fatal_error("Bad FileType.");
   }
 }
+#endif
 
 extern "C" LLVMRustResult
 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
@@ -849,7 +863,11 @@
                           int num_modules,
                           const char **preserved_symbols,
                           int num_symbols) {
+#if LLVM_VERSION_GE(10, 0)
+  auto Ret = std::make_unique<LLVMRustThinLTOData>();
+#else
   auto Ret = llvm::make_unique<LLVMRustThinLTOData>();
+#endif
 
   // Load each module's summary and merge it into one combined index
   for (int i = 0; i < num_modules; i++) {
@@ -944,6 +962,15 @@
         ExportedGUIDs.insert(GUID);
     }
   }
+#if LLVM_VERSION_GE(10, 0)
+  auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
+    const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
+    return (ExportList != Ret->ExportLists.end() &&
+      ExportList->second.count(VI)) ||
+      ExportedGUIDs.count(VI.getGUID());
+  };
+  thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
+#else
   auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
     const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
     return (ExportList != Ret->ExportLists.end() &&
@@ -951,6 +978,7 @@
       ExportedGUIDs.count(GUID);
   };
   thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported);
+#endif
 
   return Ret.release();
 }
@@ -1081,7 +1109,11 @@
 
 extern "C" LLVMRustThinLTOBuffer*
 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
+#if LLVM_VERSION_GE(10, 0)
+  auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
+#else
   auto Ret = llvm::make_unique<LLVMRustThinLTOBuffer>();
+#endif
   {
     raw_string_ostream OS(Ret->data);
     {
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 720928e..46e4670 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -496,9 +496,11 @@
   if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
     Result |= DINode::DIFlags::FlagAppleBlock;
   }
+#if LLVM_VERSION_LT(10, 0)
   if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) {
     Result |= DINode::DIFlags::FlagBlockByrefStruct;
   }
+#endif
   if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
     Result |= DINode::DIFlags::FlagVirtual;
   }
@@ -825,6 +827,9 @@
   llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
       unwrapDI<DIDescriptor>(Context), Name, LinkageName,
       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
+#if LLVM_VERSION_GE(10, 0)
+      /* isDefined */ true,
+#endif
       InitExpr, unwrapDIPtr<MDNode>(Decl),
 #if LLVM_VERSION_GE(8, 0)
       /* templateParams */ nullptr,
@@ -998,11 +1003,19 @@
 
 extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
                                          const char **Ptr) {
+#if LLVM_VERSION_GE(10, 0)
+  auto NameOrErr = (*unwrap(SI))->getName();
+  if (!NameOrErr)
+    report_fatal_error(NameOrErr.takeError());
+  *Ptr = NameOrErr->data();
+  return NameOrErr->size();
+#else
   StringRef Ret;
   if (std::error_code EC = (*unwrap(SI))->getName(Ret))
     report_fatal_error(EC.message());
   *Ptr = Ret.data();
   return Ret.size();
+#endif
 }
 
 // LLVMArrayType function does not support 64-bit ElementCount
@@ -1253,20 +1266,34 @@
                                             LLVMValueRef Dst, unsigned DstAlign,
                                             LLVMValueRef Src, unsigned SrcAlign,
                                             LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(10, 0)
+  return wrap(unwrap(B)->CreateMemCpy(
+      unwrap(Dst), MaybeAlign(DstAlign),
+      unwrap(Src), MaybeAlign(SrcAlign),
+      unwrap(Size), IsVolatile));
+#else
   return wrap(unwrap(B)->CreateMemCpy(
       unwrap(Dst), DstAlign,
       unwrap(Src), SrcAlign,
       unwrap(Size), IsVolatile));
+#endif
 }
 
 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
                                              LLVMValueRef Dst, unsigned DstAlign,
                                              LLVMValueRef Src, unsigned SrcAlign,
                                              LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(10, 0)
+  return wrap(unwrap(B)->CreateMemMove(
+      unwrap(Dst), MaybeAlign(DstAlign),
+      unwrap(Src), MaybeAlign(SrcAlign),
+      unwrap(Size), IsVolatile));
+#else
   return wrap(unwrap(B)->CreateMemMove(
       unwrap(Dst), DstAlign,
       unwrap(Src), SrcAlign,
       unwrap(Size), IsVolatile));
+#endif
 }
 
 extern "C" LLVMValueRef
@@ -1450,7 +1477,11 @@
 
 extern "C" LLVMRustModuleBuffer*
 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
+#if LLVM_VERSION_GE(10, 0)
+  auto Ret = std::make_unique<LLVMRustModuleBuffer>();
+#else
   auto Ret = llvm::make_unique<LLVMRustModuleBuffer>();
+#endif
   {
     raw_string_ostream OS(Ret->data);
     {
diff --git a/src/test/codegen/abi-main-signature-32bit-c-int.rs b/src/test/codegen/abi-main-signature-32bit-c-int.rs
index c7aab09..a7a4520 100644
--- a/src/test/codegen/abi-main-signature-32bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-32bit-c-int.rs
@@ -7,4 +7,4 @@
 fn main() {
 }
 
-// CHECK: define i32 @main(i32, i8**)
+// CHECK: define i32 @main(i32{{( %0)?}}, i8**{{( %1)?}})
diff --git a/src/test/codegen/bool-cmp.rs b/src/test/codegen/bool-cmp.rs
index 8769a4c..5090f7c 100644
--- a/src/test/codegen/bool-cmp.rs
+++ b/src/test/codegen/bool-cmp.rs
@@ -10,8 +10,9 @@
 // CHECK-LABEL: @cmp_bool
 #[no_mangle]
 pub fn cmp_bool(a: bool, b: bool) -> Ordering {
+// LLVM 10 produces (zext a) + (sext b), but the final lowering is (zext a) - (zext b).
 // CHECK: zext i1
-// CHECK: zext i1
-// CHECK: sub nsw
+// CHECK: {{z|s}}ext i1
+// CHECK: {{sub|add}} nsw
     a.cmp(&b)
 }
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index 7d65ad1..a89ecdf 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -14,10 +14,9 @@
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}}, align 4
+// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @2, i32 0, i32 0, i32 0), {{.*}},
 
 #[derive(Copy, Clone)]
-
 // repr(i16) is required for the {low,high}_align_const test
 #[repr(i16)]
 pub enum E<A, B> {
@@ -31,7 +30,7 @@
 // CHECK-LABEL: @static_enum_const
 #[no_mangle]
 pub fn static_enum_const() -> E<i16, i32> {
-   STATIC
+    STATIC
 }
 
 // CHECK-LABEL: @inline_enum_const
@@ -43,15 +42,15 @@
 // CHECK-LABEL: @low_align_const
 #[no_mangle]
 pub fn low_align_const() -> E<i16, [i16; 3]> {
-// Check that low_align_const and high_align_const use the same constant
-// CHECK: i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
+    // Check that low_align_const and high_align_const use the same constant
+    // CHECK: load %"E<i16, [i16; 3]>"*, %"E<i16, [i16; 3]>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, [i16; 3]>"**),
     *&E::A(0)
 }
 
 // CHECK-LABEL: @high_align_const
 #[no_mangle]
 pub fn high_align_const() -> E<i16, i32> {
-// Check that low_align_const and high_align_const use the same constant
-// CHECK: i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
+    // Check that low_align_const and high_align_const use the same constant
+    // CHECK: load %"E<i16, i32>"*, %"E<i16, i32>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, i32>"**),
     *&E::A(0)
 }
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index 5c9aa48..3511c7c 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -73,7 +73,7 @@
   x
 }
 
-// CHECK: @struct_return(%S* noalias nocapture sret dereferenceable(32))
+// CHECK: @struct_return(%S* noalias nocapture sret dereferenceable(32){{( %0)?}})
 #[no_mangle]
 pub fn struct_return() -> S {
   S {
@@ -117,7 +117,7 @@
 pub fn trait_borrow(_: &Drop) {
 }
 
-// CHECK: @trait_box({}* noalias nonnull align 1, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}))
+// CHECK: @trait_box({}* noalias nonnull align 1{{( %0)?}}, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
 #[no_mangle]
 pub fn trait_box(_: Box<Drop>) {
 }
diff --git a/src/test/codegen/intrinsics/prefetch.rs b/src/test/codegen/intrinsics/prefetch.rs
index 4cd38e1..2386fc4 100644
--- a/src/test/codegen/intrinsics/prefetch.rs
+++ b/src/test/codegen/intrinsics/prefetch.rs
@@ -9,13 +9,13 @@
 #[no_mangle]
 pub fn check_prefetch_read_data(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 0, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 0, i32 1)
         prefetch_read_data(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 1, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 1, i32 1)
         prefetch_read_data(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 2, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 2, i32 1)
         prefetch_read_data(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 3, i32 1)
         prefetch_read_data(data.as_ptr(), 3);
     }
 }
@@ -23,13 +23,13 @@
 #[no_mangle]
 pub fn check_prefetch_write_data(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 0, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 0, i32 1)
         prefetch_write_data(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 1, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 1, i32 1)
         prefetch_write_data(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 2, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 2, i32 1)
         prefetch_write_data(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 3, i32 1)
         prefetch_write_data(data.as_ptr(), 3);
     }
 }
@@ -37,13 +37,13 @@
 #[no_mangle]
 pub fn check_prefetch_read_instruction(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 0, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 0, i32 0)
         prefetch_read_instruction(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 1, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 1, i32 0)
         prefetch_read_instruction(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 2, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 2, i32 0)
         prefetch_read_instruction(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 3, i32 0)
         prefetch_read_instruction(data.as_ptr(), 3);
     }
 }
@@ -51,13 +51,13 @@
 #[no_mangle]
 pub fn check_prefetch_write_instruction(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 0, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 0, i32 0)
         prefetch_write_instruction(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 1, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 1, i32 0)
         prefetch_write_instruction(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 2, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 2, i32 0)
         prefetch_write_instruction(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 3, i32 0)
         prefetch_write_instruction(data.as_ptr(), 3);
     }
 }
diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs
index 2050193..5050ed1 100644
--- a/src/test/codegen/naked-functions.rs
+++ b/src/test/codegen/naked-functions.rs
@@ -17,7 +17,7 @@
 // CHECK: Function Attrs: naked
 #[no_mangle]
 #[naked]
-// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+}})
+// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}})
 pub fn naked_with_args(a: isize) {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: %a = alloca i{{[0-9]+}}
@@ -36,7 +36,7 @@
 }
 
 // CHECK: Function Attrs: naked
-// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
+// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %0)?}})
 #[no_mangle]
 #[naked]
 pub fn naked_with_args_and_return(a: isize) -> isize {
diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs
index 99f3464..8fbe712 100644
--- a/src/test/codegen/repeat-trusted-len.rs
+++ b/src/test/codegen/repeat-trusted-len.rs
@@ -13,6 +13,6 @@
 // CHECK-LABEL: @repeat_take_collect
 #[no_mangle]
 pub fn repeat_take_collect() -> Vec<u8> {
-// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
+// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
     iter::repeat(42).take(100000).collect()
 }
diff --git a/src/test/codegen/repr-transparent-sysv64.rs b/src/test/codegen/repr-transparent-sysv64.rs
index b71cb14..886b0dd 100644
--- a/src/test/codegen/repr-transparent-sysv64.rs
+++ b/src/test/codegen/repr-transparent-sysv64.rs
@@ -10,7 +10,7 @@
 #[repr(transparent)]
 pub struct Rgb8Wrap(Rgb8);
 
-// CHECK: i24 @test_Rgb8Wrap(i24)
+// CHECK: i24 @test_Rgb8Wrap(i24{{( %0)?}})
 #[no_mangle]
 pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} }
 
@@ -23,6 +23,6 @@
 #[repr(transparent)]
 pub struct SmallUnion(FloatBits);
 
-// CHECK: i32 @test_SmallUnion(i32)
+// CHECK: i32 @test_SmallUnion(i32{{( %0)?}})
 #[no_mangle]
 pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} }
diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs
index 98a9ff9..afea01e 100644
--- a/src/test/codegen/union-abi.rs
+++ b/src/test/codegen/union-abi.rs
@@ -54,7 +54,7 @@
 
 pub union UnionF32U32{a:f32, b:u32}
 
-// CHECK: define i32 @test_UnionF32U32(i32)
+// CHECK: define i32 @test_UnionF32U32(i32{{( %0)?}})
 #[no_mangle]
 pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
 
diff --git a/src/test/compile-fail/consts/const-fn-error.rs b/src/test/compile-fail/consts/const-fn-error.rs
index 5d26059..9db595a 100644
--- a/src/test/compile-fail/consts/const-fn-error.rs
+++ b/src/test/compile-fail/consts/const-fn-error.rs
@@ -6,6 +6,7 @@
     let mut sum = 0;
     for i in 0..x {
         //~^ ERROR E0015
+        //~| ERROR E0015
         //~| ERROR E0658
         //~| ERROR E0080
         //~| ERROR E0744
diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs
index ee37aaa..597fbbf 100644
--- a/src/test/compile-fail/issue-52443.rs
+++ b/src/test/compile-fail/issue-52443.rs
@@ -8,6 +8,7 @@
     //~| WARN denote infinite loops with
     [(); { for _ in 0usize.. {}; 0}];
     //~^ ERROR calls in constants are limited to constant functions
+    //~| ERROR calls in constants are limited to constant functions
     //~| ERROR `for` is not allowed in a `const`
     //~| ERROR references in constants may only refer to immutable values
     //~| ERROR evaluation of constant value failed
diff --git a/src/test/debuginfo/borrowed-enum-legacy.rs b/src/test/debuginfo/borrowed-enum-legacy.rs
deleted file mode 100644
index 9a973ed..0000000
--- a/src/test/debuginfo/borrowed-enum-legacy.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:run
-
-// gdb-command:print *the_a_ref
-// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, [...]}}
-// gdbr-check:$1 = borrowed_enum_legacy::ABC::TheA{x: 0, y: 8970181431921507452}
-
-// gdb-command:print *the_b_ref
-// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, [...]}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}}
-// gdbr-check:$2 = borrowed_enum_legacy::ABC::TheB(0, 286331153, 286331153)
-
-// gdb-command:print *univariant_ref
-// gdbg-check:$3 = {{__0 = 4820353753753434}}
-// gdbr-check:$3 = borrowed_enum_legacy::Univariant::TheOnlyCase(4820353753753434)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print *the_a_ref
-// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
-// lldbr-check:(borrowed_enum_legacy::ABC::TheA) *the_a_ref = TheA { borrowed_enum_legacy::ABC::TheA: 0, borrowed_enum_legacy::ABC::TheB: 8970181431921507452 }
-// lldb-command:print *the_b_ref
-// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
-// lldbr-check:(borrowed_enum_legacy::ABC::TheB) *the_b_ref = { = 0 = 286331153 = 286331153 }
-// lldb-command:print *univariant_ref
-// lldbg-check:[...]$2 = TheOnlyCase(4820353753753434)
-// lldbr-check:(borrowed_enum_legacy::Univariant) *univariant_ref = { borrowed_enum_legacy::TheOnlyCase = { = 4820353753753434 } }
-
-#![allow(unused_variables)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum ABC {
-    TheA { x: i64, y: i64 },
-    TheB (i64, i32, i32),
-}
-
-// This is a special case since it does not have the implicit discriminant field.
-enum Univariant {
-    TheOnlyCase(i64)
-}
-
-fn main() {
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let the_a = ABC::TheA { x: 0, y: 8970181431921507452 };
-    let the_a_ref: &ABC = &the_a;
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let the_b = ABC::TheB (0, 286331153, 286331153);
-    let the_b_ref: &ABC = &the_b;
-
-    let univariant = Univariant::TheOnlyCase(4820353753753434);
-    let univariant_ref: &Univariant = &univariant;
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes-legacy.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes-legacy.rs
deleted file mode 100644
index 4f17e48..0000000
--- a/src/test/debuginfo/generic-enum-with-different-disr-sizes-legacy.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// ignore-tidy-linelength
-// ignore-lldb: FIXME(#27089)
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-// gdb-command:run
-
-// gdb-command:print eight_bytes1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}}
-// gdbr-check:$1 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(100)
-
-// gdb-command:print four_bytes1
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}}
-// gdbr-check:$2 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(101)
-
-// gdb-command:print two_bytes1
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}}
-// gdbr-check:$3 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(102)
-
-// gdb-command:print one_byte1
-// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}}
-// gdbr-check:$4 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(65)
-
-
-// gdb-command:print eight_bytes2
-// gdbg-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}}
-// gdbr-check:$5 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(100)
-
-// gdb-command:print four_bytes2
-// gdbg-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}}
-// gdbr-check:$6 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(101)
-
-// gdb-command:print two_bytes2
-// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}}
-// gdbr-check:$7 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(102)
-
-// gdb-command:print one_byte2
-// gdbg-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}}
-// gdbr-check:$8 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(65)
-
-// gdb-command:continue
-
-// === LLDB TESTS ==================================================================================
-// lldb-command:run
-
-// lldb-command:print eight_bytes1
-// lldb-check:[...]$0 = Variant1(100)
-// lldb-command:print four_bytes1
-// lldb-check:[...]$1 = Variant1(101)
-// lldb-command:print two_bytes1
-// lldb-check:[...]$2 = Variant1(102)
-// lldb-command:print one_byte1
-// lldb-check:[...]$3 = Variant1('A')
-
-// lldb-command:print eight_bytes2
-// lldb-check:[...]$4 = Variant2(100)
-// lldb-command:print four_bytes2
-// lldb-check:[...]$5 = Variant2(101)
-// lldb-command:print two_bytes2
-// lldb-check:[...]$6 = Variant2(102)
-// lldb-command:print one_byte2
-// lldb-check:[...]$7 = Variant2('A')
-
-// lldb-command:continue
-
-#![allow(unused_variables)]
-#![allow(dead_code)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-// This test case makes sure that we get correct type descriptions for the enum
-// discriminant of different instantiations of the same generic enum type where,
-// dependending on the generic type parameter(s), the discriminant has a
-// different size in memory.
-
-enum Enum<T> {
-    Variant1(T),
-    Variant2(T)
-}
-
-fn main() {
-    // These are ordered for descending size on purpose
-    let eight_bytes1 = Enum::Variant1(100.0f64);
-    let four_bytes1 = Enum::Variant1(101i32);
-    let two_bytes1 = Enum::Variant1(102i16);
-    let one_byte1 = Enum::Variant1(65u8);
-
-    let eight_bytes2 = Enum::Variant2(100.0f64);
-    let four_bytes2 = Enum::Variant2(101i32);
-    let two_bytes2 = Enum::Variant2(102i16);
-    let one_byte2 = Enum::Variant2(65u8);
-
-    zzz(); // #break
-}
-
-fn zzz() { () }
diff --git a/src/test/debuginfo/generic-struct-style-enum-legacy.rs b/src/test/debuginfo/generic-struct-style-enum-legacy.rs
deleted file mode 100644
index 37a875a..0000000
--- a/src/test/debuginfo/generic-struct-style-enum-legacy.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12.9
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = generic_struct_style_enum_legacy::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868}
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = generic_struct_style_enum_legacy::Regular::Case2{a: 0, b: 286331153, c: 286331153}
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}}
-// gdbr-check:$3 = generic_struct_style_enum_legacy::Regular::Case3{a: 0, b: 6438275382588823897}
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{a = -1}}
-// gdbr-check:$4 = generic_struct_style_enum_legacy::Univariant<i32>::TheOnlyCase{a: -1}
-
-
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
-// substituted with something of size `xx` bits and the same alignment as an integer type of the
-// same size.
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular<T16, T32, T64> {
-    Case1 { a: T64, b: T16, c: T16, d: T16, e: T16},
-    Case2 { a: T64, b: T32, c: T32},
-    Case3 { a: T64, b: T64 }
-}
-
-enum Univariant<T> {
-    TheOnlyCase { a: T }
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1: Regular<u16, u32, i64> = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2: Regular<i16, u32, i64>  = Case2 { a: 0, b: 286331153, c: 286331153 };
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3: Regular<u16, i32, u64>  = Case3 { a: 0, b: 6438275382588823897 };
-
-    let univariant = TheOnlyCase { a: -1 };
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/generic-tuple-style-enum-legacy.rs b/src/test/debuginfo/generic-tuple-style-enum-legacy.rs
deleted file mode 100644
index 452e900..0000000
--- a/src/test/debuginfo/generic-tuple-style-enum-legacy.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12.9
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = generic_tuple_style_enum_legacy::Regular::Case1(0, 31868, 31868, 31868, 31868)
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = generic_tuple_style_enum_legacy::Regular::Case2(0, 286331153, 286331153)
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}}
-// gdbr-check:$3 = generic_tuple_style_enum_legacy::Regular::Case3(0, 6438275382588823897)
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{__0 = -1}}
-// gdbr-check:$4 = generic_tuple_style_enum_legacy::Univariant<i64>::TheOnlyCase(-1)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print case1
-// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
-// lldbr-check:(generic_tuple_style_enum_legacy::Regular<u16, u32, u64>::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
-
-// lldb-command:print case2
-// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
-// lldbr-check:(generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case2) case2 = Regular<i16, i32, i64>::Case2 { generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case2: 286331153, generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case3: 286331153 }
-
-// lldb-command:print case3
-// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
-// lldbr-check:(generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case3) case3 = Regular<i16, i32, i64>::Case3 { generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case2: 6438275382588823897 }
-
-// lldb-command:print univariant
-// lldbg-check:[...]$3 = TheOnlyCase(-1)
-// lldbr-check:(generic_tuple_style_enum_legacy::Univariant<i64>) univariant = { generic_tuple_style_enum_legacy::TheOnlyCase = { = -1 } }
-
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
-// substituted with something of size `xx` bits and the same alignment as an integer type of the
-// same size.
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular<T16, T32, T64> {
-    Case1(T64, T16, T16, T16, T16),
-    Case2(T64, T32, T32),
-    Case3(T64, T64)
-}
-
-enum Univariant<T64> {
-    TheOnlyCase(T64)
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1: Regular<u16, u32, u64> = Case1(0_u64, 31868_u16, 31868_u16, 31868_u16, 31868_u16);
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2: Regular<i16, i32, i64> = Case2(0_i64, 286331153_i32, 286331153_i32);
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3: Regular<i16, i32, i64> = Case3(0_i64, 6438275382588823897_i64);
-
-    let univariant = TheOnlyCase(-1_i64);
-
-    zzz(); // #break
-}
-
-fn zzz() { () }
diff --git a/src/test/debuginfo/recursive-struct-legacy.rs b/src/test/debuginfo/recursive-struct-legacy.rs
deleted file mode 100644
index 9928670..0000000
--- a/src/test/debuginfo/recursive-struct-legacy.rs
+++ /dev/null
@@ -1,235 +0,0 @@
-// ignore-tidy-linelength
-// ignore-lldb
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// gdb-command:run
-
-// gdb-command:print stack_unique.value
-// gdb-check:$1 = 0
-// gdbg-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print stack_unique.next.val.value
-// gdb-check:$2 = 1
-
-// gdbg-command:print unique_unique->value
-// gdbr-command:print unique_unique.value
-// gdb-check:$3 = 2
-// gdbg-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print unique_unique.next.val.value
-// gdb-check:$4 = 3
-
-// gdb-command:print vec_unique[0].value
-// gdb-check:$5 = 6.5
-// gdbg-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print vec_unique[0].next.val.value
-// gdb-check:$6 = 7.5
-
-// gdbg-command:print borrowed_unique->value
-// gdbr-command:print borrowed_unique.value
-// gdb-check:$7 = 8.5
-// gdbg-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print borrowed_unique.next.val.value
-// gdb-check:$8 = 9.5
-
-// LONG CYCLE
-// gdb-command:print long_cycle1.value
-// gdb-check:$9 = 20
-// gdbg-command:print long_cycle1.next->value
-// gdbr-command:print long_cycle1.next.value
-// gdb-check:$10 = 21
-// gdbg-command:print long_cycle1.next->next->value
-// gdbr-command:print long_cycle1.next.next.value
-// gdb-check:$11 = 22
-// gdbg-command:print long_cycle1.next->next->next->value
-// gdbr-command:print long_cycle1.next.next.next.value
-// gdb-check:$12 = 23
-
-// gdb-command:print long_cycle2.value
-// gdb-check:$13 = 24
-// gdbg-command:print long_cycle2.next->value
-// gdbr-command:print long_cycle2.next.value
-// gdb-check:$14 = 25
-// gdbg-command:print long_cycle2.next->next->value
-// gdbr-command:print long_cycle2.next.next.value
-// gdb-check:$15 = 26
-
-// gdb-command:print long_cycle3.value
-// gdb-check:$16 = 27
-// gdbg-command:print long_cycle3.next->value
-// gdbr-command:print long_cycle3.next.value
-// gdb-check:$17 = 28
-
-// gdb-command:print long_cycle4.value
-// gdb-check:$18 = 29.5
-
-// gdbg-command:print (*****long_cycle_w_anonymous_types).value
-// gdbr-command:print long_cycle_w_anonymous_types.value
-// gdb-check:$19 = 30
-
-// gdbg-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value
-// gdbr-command:print long_cycle_w_anonymous_types.next.val.value
-// gdb-check:$20 = 31
-
-// gdb-command:continue
-
-#![allow(unused_variables)]
-#![feature(box_syntax)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Opt::{Empty, Val};
-
-enum Opt<T> {
-    Empty,
-    Val { val: T }
-}
-
-struct UniqueNode<T> {
-    next: Opt<Box<UniqueNode<T>>>,
-    value: T
-}
-
-struct LongCycle1<T> {
-    next: Box<LongCycle2<T>>,
-    value: T,
-}
-
-struct LongCycle2<T> {
-    next: Box<LongCycle3<T>>,
-    value: T,
-}
-
-struct LongCycle3<T> {
-    next: Box<LongCycle4<T>>,
-    value: T,
-}
-
-struct LongCycle4<T> {
-    next: Option<Box<LongCycle1<T>>>,
-    value: T,
-}
-
-struct LongCycleWithAnonymousTypes {
-    next: Opt<Box<Box<Box<Box<Box<LongCycleWithAnonymousTypes>>>>>>,
-    value: usize,
-}
-
-// This test case makes sure that recursive structs are properly described. The Node structs are
-// generic so that we can have a new type (that newly needs to be described) for the different
-// cases. The potential problem with recursive types is that the DI generation algorithm gets
-// trapped in an endless loop. To make sure, we actually test this in the different cases, we have
-// to operate on a new type each time, otherwise we would just hit the DI cache for all but the
-// first case.
-
-// The different cases below (stack_*, unique_*, box_*, etc) are set up so that the type description
-// algorithm will enter the type reference cycle that is created by a recursive definition from a
-// different context each time.
-
-// The "long cycle" cases are constructed to span a longer, indirect recursion cycle between types.
-// The different locals will cause the DI algorithm to enter the type reference cycle at different
-// points.
-
-fn main() {
-    let stack_unique: UniqueNode<u16> = UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 1,
-            }
-        },
-        value: 0,
-    };
-
-    let unique_unique: Box<UniqueNode<u32>> = box UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 3,
-            }
-        },
-        value: 2,
-    };
-
-    let vec_unique: [UniqueNode<f32>; 1] = [UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 7.5,
-            }
-        },
-        value: 6.5,
-    }];
-
-    let borrowed_unique: &UniqueNode<f64> = &UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 9.5,
-            }
-        },
-        value: 8.5,
-    };
-
-    // LONG CYCLE
-    let long_cycle1: LongCycle1<u16> = LongCycle1 {
-        next: box LongCycle2 {
-            next: box LongCycle3 {
-                next: box LongCycle4 {
-                    next: None,
-                    value: 23,
-                },
-                value: 22,
-            },
-            value: 21
-        },
-        value: 20
-    };
-
-    let long_cycle2: LongCycle2<u32> = LongCycle2 {
-        next: box LongCycle3 {
-            next: box LongCycle4 {
-                next: None,
-                value: 26,
-            },
-            value: 25,
-        },
-        value: 24
-    };
-
-    let long_cycle3: LongCycle3<u64> = LongCycle3 {
-        next: box LongCycle4 {
-            next: None,
-            value: 28,
-        },
-        value: 27,
-    };
-
-    let long_cycle4: LongCycle4<f32> = LongCycle4 {
-        next: None,
-        value: 29.5,
-    };
-
-    // It's important that LongCycleWithAnonymousTypes is encountered only at the end of the
-    // `box` chain.
-    let long_cycle_w_anonymous_types = box box box box box LongCycleWithAnonymousTypes {
-        next: Val {
-            val: box box box box box LongCycleWithAnonymousTypes {
-                next: Empty,
-                value: 31,
-            }
-        },
-        value: 30
-    };
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/struct-style-enum-legacy.rs b/src/test/debuginfo/struct-style-enum-legacy.rs
deleted file mode 100644
index 1433493..0000000
--- a/src/test/debuginfo/struct-style-enum-legacy.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = struct_style_enum_legacy::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868}
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = struct_style_enum_legacy::Regular::Case2{a: 0, b: 286331153, c: 286331153}
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}}
-// gdbr-check:$3 = struct_style_enum_legacy::Regular::Case3{a: 0, b: 6438275382588823897}
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{a = -1}}
-// gdbr-check:$4 = struct_style_enum_legacy::Univariant::TheOnlyCase{a: -1}
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print case1
-// lldbg-check:[...]$0 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 }
-// lldbr-check:(struct_style_enum_legacy::Regular::Case1) case1 = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 }
-
-// lldb-command:print case2
-// lldbg-check:[...]$1 = Case2 { a: 0, b: 286331153, c: 286331153 }
-// lldbr-check:(struct_style_enum_legacy::Regular::Case2) case2 = Case2 { struct_style_enum_legacy::Regular::Case1: 0, struct_style_enum_legacy::Regular::Case2: 286331153, struct_style_enum_legacy::Regular::Case3: 286331153 }
-
-// lldb-command:print case3
-// lldbg-check:[...]$2 = Case3 { a: 0, b: 6438275382588823897 }
-// lldbr-check:(struct_style_enum_legacy::Regular::Case3) case3 = Case3 { struct_style_enum_legacy::Regular::Case1: 0, struct_style_enum_legacy::Regular::Case2: 6438275382588823897 }
-
-// lldb-command:print univariant
-// lldbg-check:[...]$3 = TheOnlyCase { a: -1 }
-// lldbr-check:(struct_style_enum_legacy::Univariant) univariant = Univariant { struct_style_enum_legacy::TheOnlyCase: TheOnlyCase { a: -1 } }
-
-#![allow(unused_variables)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular {
-    Case1 { a: u64, b: u16, c: u16, d: u16, e: u16},
-    Case2 { a: u64, b: u32, c: u32},
-    Case3 { a: u64, b: u64 }
-}
-
-enum Univariant {
-    TheOnlyCase { a: i64 }
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2 = Case2 { a: 0, b: 286331153, c: 286331153 };
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3 = Case3 { a: 0, b: 6438275382588823897 };
-
-    let univariant = TheOnlyCase { a: -1 };
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/tuple-style-enum-legacy.rs b/src/test/debuginfo/tuple-style-enum-legacy.rs
deleted file mode 100644
index ebc8e03..0000000
--- a/src/test/debuginfo/tuple-style-enum-legacy.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = tuple_style_enum_legacy::Regular::Case1(0, 31868, 31868, 31868, 31868)
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = tuple_style_enum_legacy::Regular::Case2(0, 286331153, 286331153)
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}}
-// gdbr-check:$3 = tuple_style_enum_legacy::Regular::Case3(0, 6438275382588823897)
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{__0 = -1}}
-// gdbr-check:$4 = tuple_style_enum_legacy::Univariant::TheOnlyCase(-1)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print case1
-// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
-// lldbr-check:(tuple_style_enum_legacy::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
-
-// lldb-command:print case2
-// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
-// lldbr-check:(tuple_style_enum_legacy::Regular::Case2) case2 = Case2 { tuple_style_enum_legacy::Regular::Case1: 0, tuple_style_enum_legacy::Regular::Case2: 286331153, tuple_style_enum_legacy::Regular::Case3: 286331153 }
-
-// lldb-command:print case3
-// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
-// lldbr-check:(tuple_style_enum_legacy::Regular::Case3) case3 = Case3 { tuple_style_enum_legacy::Regular::Case1: 0, tuple_style_enum_legacy::Regular::Case2: 6438275382588823897 }
-
-// lldb-command:print univariant
-// lldbg-check:[...]$3 = TheOnlyCase(-1)
-// lldbr-check:(tuple_style_enum_legacy::Univariant) univariant = { tuple_style_enum_legacy::TheOnlyCase = { = -1 } }
-
-#![allow(unused_variables)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular {
-    Case1(u64, u16, u16, u16, u16),
-    Case2(u64, u32, u32),
-    Case3(u64, u64)
-}
-
-enum Univariant {
-    TheOnlyCase(i64)
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1 = Case1(0, 31868, 31868, 31868, 31868);
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2 = Case2(0, 286331153, 286331153);
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3 = Case3(0, 6438275382588823897);
-
-    let univariant = TheOnlyCase(-1);
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/unique-enum-legacy.rs b/src/test/debuginfo/unique-enum-legacy.rs
deleted file mode 100644
index e7c9357..0000000
--- a/src/test/debuginfo/unique-enum-legacy.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:run
-
-// gdb-command:print *the_a
-// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, [...]}}
-// gdbr-check:$1 = unique_enum_legacy::ABC::TheA{x: 0, y: 8970181431921507452}
-
-// gdb-command:print *the_b
-// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, [...]}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}}
-// gdbr-check:$2 = unique_enum_legacy::ABC::TheB(0, 286331153, 286331153)
-
-// gdb-command:print *univariant
-// gdbg-check:$3 = {{__0 = 123234}}
-// gdbr-check:$3 = unique_enum_legacy::Univariant::TheOnlyCase(123234)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print *the_a
-// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
-// lldbr-check:(unique_enum_legacy::ABC::TheA) *the_a = TheA { unique_enum_legacy::ABC::TheA: 0, unique_enum_legacy::ABC::TheB: 8970181431921507452 }
-
-// lldb-command:print *the_b
-// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
-// lldbr-check:(unique_enum_legacy::ABC::TheB) *the_b = { = 0 = 286331153 = 286331153 }
-
-// lldb-command:print *univariant
-// lldbg-check:[...]$2 = TheOnlyCase(123234)
-// lldbr-check:(unique_enum_legacy::Univariant) *univariant = { unique_enum_legacy::TheOnlyCase = { = 123234 } }
-
-#![allow(unused_variables)]
-#![feature(box_syntax)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum ABC {
-    TheA { x: i64, y: i64 },
-    TheB (i64, i32, i32),
-}
-
-// This is a special case since it does not have the implicit discriminant field.
-enum Univariant {
-    TheOnlyCase(i64)
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let the_a: Box<_> = box ABC::TheA { x: 0, y: 8970181431921507452 };
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let the_b: Box<_> = box ABC::TheB (0, 286331153, 286331153);
-
-    let univariant: Box<_> = box Univariant::TheOnlyCase(123234);
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs
new file mode 100644
index 0000000..3abc90e
--- /dev/null
+++ b/src/test/mir-opt/const-promotion-extern-static.rs
@@ -0,0 +1,73 @@
+extern "C" {
+    static X: i32;
+}
+
+static Y: i32 = 42;
+
+static mut BAR: *const &'static i32 = [&Y].as_ptr();
+
+static mut FOO: *const &'static i32 = [unsafe { &X }].as_ptr();
+
+fn main() {}
+
+// END RUST SOURCE
+// START rustc.FOO.PromoteTemps.before.mir
+// bb0: {
+// ...
+//     _5 = const Scalar(AllocId(1).0x0) : &i32;
+//     _4 = &(*_5);
+//     _3 = [move _4];
+//     _2 = &_3;
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     StorageDead(_5);
+//     StorageDead(_3);
+//     return;
+// }
+// END rustc.FOO.PromoteTemps.before.mir
+// START rustc.BAR.PromoteTemps.before.mir
+// bb0: {
+// ...
+//     _5 = const Scalar(AllocId(0).0x0) : &i32;
+//     _4 = &(*_5);
+//     _3 = [move _4];
+//     _2 = &_3;
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     StorageDead(_5);
+//     StorageDead(_3);
+//     return;
+// }
+// END rustc.BAR.PromoteTemps.before.mir
+// START rustc.BAR.PromoteTemps.after.mir
+// bb0: {
+// ...
+//     _6 = const BAR::promoted[0];
+//     _2 = &(*_6);
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     return;
+// }
+// END rustc.BAR.PromoteTemps.after.mir
+// START rustc.FOO.PromoteTemps.after.mir
+// bb0: {
+// ...
+//     _6 = const FOO::promoted[0];
+//     _2 = &(*_6);
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     return;
+// }
+// END rustc.FOO.PromoteTemps.after.mir
diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs
index d45ffdc..8b48296 100644
--- a/src/test/mir-opt/const_prop/ref_deref.rs
+++ b/src/test/mir-opt/const_prop/ref_deref.rs
@@ -3,10 +3,29 @@
 }
 
 // END RUST SOURCE
+// START rustc.main.PromoteTemps.before.mir
+// bb0: {
+//     ...
+//     _3 = const 4i32;
+//     _2 = &_3;
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.before.mir
+// START rustc.main.PromoteTemps.after.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &(*_4);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.after.mir
 // START rustc.main.ConstProp.before.mir
 // bb0: {
 //     ...
-//     _2 = &(promoted[0]: i32);
+//     _4 = const main::promoted[0];
+//     _2 = _4;
 //     _1 = (*_2);
 //     ...
 //}
@@ -14,7 +33,8 @@
 // START rustc.main.ConstProp.after.mir
 // bb0: {
 //     ...
-//     _2 = &(promoted[0]: i32);
+//     _4 = const main::promoted[0];
+//     _2 = _4;
 //     _1 = const 4i32;
 //     ...
 // }
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs
new file mode 100644
index 0000000..5808a8b
--- /dev/null
+++ b/src/test/mir-opt/const_prop/ref_deref_project.rs
@@ -0,0 +1,41 @@
+fn main() {
+    *(&(4, 5).1);
+}
+
+// END RUST SOURCE
+// START rustc.main.PromoteTemps.before.mir
+// bb0: {
+//     ...
+//     _3 = (const 4i32, const 5i32);
+//     _2 = &(_3.1: i32);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.before.mir
+// START rustc.main.PromoteTemps.after.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &((*_4).1: i32);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.after.mir
+// START rustc.main.ConstProp.before.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &((*_4).1: i32);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &((*_4).1: i32);
+//     _1 = const 5i32;
+//     ...
+// }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index d6ff76b..43813e4 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -6,7 +6,8 @@
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _4 = &(promoted[0]: [u32; 3]);
+//      _9 = const main::promoted[0];
+//      _4 = _9;
 //      _3 = _4;
 //      _2 = move _3 as &[u32] (Pointer(Unsize));
 //      ...
@@ -24,7 +25,8 @@
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _4 = &(promoted[0]: [u32; 3]);
+//      _9 = const main::promoted[0];
+//      _4 = _9;
 //      _3 = _4;
 //      _2 = move _3 as &[u32] (Pointer(Unsize));
 //      ...
diff --git a/src/test/mir-opt/inline/inline-retag.rs b/src/test/mir-opt/inline/inline-retag.rs
index 6cdbcfd..7b78fc3 100644
--- a/src/test/mir-opt/inline/inline-retag.rs
+++ b/src/test/mir-opt/inline/inline-retag.rs
@@ -25,11 +25,11 @@
 //         ...
 //         Retag(_3);
 //         Retag(_6);
-//         StorageLive(_9);
-//         _9 = (*_3);
-//         StorageLive(_10);
-//         _10 = (*_6);
-//         _0 = Eq(move _9, move _10);
+//         StorageLive(_11);
+//         _11 = (*_3);
+//         StorageLive(_12);
+//         _12 = (*_6);
+//         _0 = Eq(move _11, move _12);
 //         ...
 //         return;
 //     }
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
index 648856b..2c20c35 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -65,7 +65,8 @@
 //  }
 //  bb6: { // binding1 and guard
 //      StorageLive(_6);
-//      _6 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
+//      _11 = const full_tested_match::promoted[0];
+//      _6 = &(((*_11) as Some).0: i32);
 //      _4 = &shallow _2;
 //      StorageLive(_7);
 //      _7 = const guard() -> [return: bb7, unwind: bb1];
diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 84b8c7c..84bcd22 100644
--- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -4,6 +4,7 @@
 extern crate rustc_codegen_utils;
 #[macro_use]
 extern crate rustc_data_structures;
+extern crate rustc_hir;
 extern crate rustc_target;
 extern crate rustc_driver;
 extern crate rustc_span;
@@ -65,7 +66,7 @@
         _metadata: EncodedMetadata,
         _need_metadata_module: bool,
     ) -> Box<dyn Any> {
-        use rustc::hir::def_id::LOCAL_CRATE;
+        use rustc_hir::def_id::LOCAL_CRATE;
 
         Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol)
     }
diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile
index 3a377c3..7f5e904 100644
--- a/src/test/run-make-fulldeps/sanitizer-address/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-address/Makefile
@@ -23,7 +23,7 @@
 endif
 
 all:
-	$(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan
+	$(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) rustc_rt.asan
 	# Verify that stack buffer overflow is detected:
 	$(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow
 	# Verify that variable name is included in address sanitizer report:
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile
deleted file mode 100644
index 9581ac5..0000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# needs-sanitizer-support
-
--include ../tools.mk
-
-# NOTE the address sanitizer only supports x86_64 linux and macOS
-
-ifeq ($(TARGET),x86_64-apple-darwin)
-EXTRA_RUSTFLAG=-C rpath
-else
-ifeq ($(TARGET),x86_64-unknown-linux-gnu)
-EXTRA_RUSTFLAG=
-endif
-endif
-
-all:
-	$(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | $(CGREP) '-Z sanitizer'
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs
deleted file mode 100644
index e7a11a9..0000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    println!("Hello, world!");
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
index df8afee..2a23f0f 100644
--- a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
@@ -2,4 +2,4 @@
 
 all:
 	$(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | \
-		$(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` target'
+		$(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target'
diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile
index 101e827..d8598b8 100644
--- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-leak/Makefile
@@ -7,5 +7,5 @@
 # FIXME(#46126) ThinLTO for libstd broke this test
 
 all:
-	$(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_lsan
+	$(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) rustc_rt.lsan
 	$(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks'
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile
index f578790..8bc9df1 100644
--- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-memory/Makefile
@@ -5,7 +5,7 @@
 # only-x86_64
 
 all:
-	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan
+	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) rustc_rt.msan
 	$(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value
-	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) librustc_msan
+	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) rustc_rt.msan
 	$(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value
diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs
index 75d95a4..c63fe4d 100644
--- a/src/test/run-make-fulldeps/simd-ffi/simd.rs
+++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs
@@ -4,35 +4,28 @@
 // cross-compiled standard libraries.
 #![feature(no_core, optin_builtin_traits)]
 #![no_core]
-
 #![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)]
 
-
-#[repr(C)]
 #[derive(Copy)]
 #[repr(simd)]
 pub struct f32x4(f32, f32, f32, f32);
 
-
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.v4f32"]
     fn vsqrt(x: f32x4) -> f32x4;
 }
 
 pub fn foo(x: f32x4) -> f32x4 {
-    unsafe {vsqrt(x)}
+    unsafe { vsqrt(x) }
 }
 
-#[repr(C)]
 #[derive(Copy)]
 #[repr(simd)]
 pub struct i32x4(i32, i32, i32, i32);
 
-
-extern {
+extern "C" {
     // _mm_sll_epi32
-    #[cfg(any(target_arch = "x86",
-              target_arch = "x86-64"))]
+    #[cfg(any(target_arch = "x86", target_arch = "x86-64"))]
     #[link_name = "llvm.x86.sse2.psll.d"]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 
@@ -48,22 +41,24 @@
     // just some substitute foreign symbol, not an LLVM intrinsic; so
     // we still get type checking, but not as detailed as (ab)using
     // LLVM.
-    #[cfg(not(any(target_arch = "x86",
-                  target_arch = "x86-64",
-                  target_arch = "arm",
-                  target_arch = "aarch64")))]
+    #[cfg(not(any(
+        target_arch = "x86",
+        target_arch = "x86-64",
+        target_arch = "arm",
+        target_arch = "aarch64"
+    )))]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 }
 
 pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
-    unsafe {integer(a, b)}
+    unsafe { integer(a, b) }
 }
 
 #[lang = "sized"]
-pub trait Sized { }
+pub trait Sized {}
 
 #[lang = "copy"]
-pub trait Copy { }
+pub trait Copy {}
 
 impl Copy for f32 {}
 impl Copy for i32 {}
@@ -77,4 +72,6 @@
 
 #[macro_export]
 #[rustc_builtin_macro]
-macro_rules! Copy { () => () }
+macro_rules! Copy {
+    () => {};
+}
diff --git a/src/test/run-make/wasm-export-all-symbols/bar.rs b/src/test/run-make/wasm-export-all-symbols/bar.rs
index c5de87e..ac9c20a 100644
--- a/src/test/run-make/wasm-export-all-symbols/bar.rs
+++ b/src/test/run-make/wasm-export-all-symbols/bar.rs
@@ -2,3 +2,6 @@
 
 #[no_mangle]
 pub extern fn foo() {}
+
+#[no_mangle]
+pub static FOO: u64 = 42;
diff --git a/src/test/run-make/wasm-export-all-symbols/verify.js b/src/test/run-make/wasm-export-all-symbols/verify.js
index 7b6fc7a..72db335 100644
--- a/src/test/run-make/wasm-export-all-symbols/verify.js
+++ b/src/test/run-make/wasm-export-all-symbols/verify.js
@@ -9,16 +9,20 @@
 
 const my_exports = {};
 let nexports = 0;
+
 for (const entry of list) {
-  if (entry.kind !== 'function')
-    continue;
-  my_exports[entry.name] = true;
-  nexports += 1;
+  if (entry.kind == 'function'){
+    nexports += 1;
+  }
+  my_exports[entry.name] = entry.kind;
 }
 
-if (my_exports.foo === undefined)
+if (my_exports.foo != "function")
   throw new Error("`foo` wasn't defined");
 
+if (my_exports.FOO != "global")
+  throw new Error("`FOO` wasn't defined");
+
 if (my_exports.main === undefined) {
   if (nexports != 1)
     throw new Error("should only have one function export");
diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs
index 819adfe..7361b22b7 100644
--- a/src/test/rustdoc/const-generics/const-impl.rs
+++ b/src/test/rustdoc/const-generics/const-impl.rs
@@ -30,3 +30,10 @@
         Self { inner: Vec::new() }
     }
 }
+
+pub struct Escape<const S: &'static str>;
+
+// @has foo/struct.Escape.html '//h3[@id="impl"]/code' 'impl Escape<{ r#"<script>alert("Escape");</script>"# }>'
+impl Escape<{ r#"<script>alert("Escape");</script>"# }> {
+    pub fn f() {}
+}
diff --git a/src/test/rustdoc/const-underscore.rs b/src/test/rustdoc/const-underscore.rs
new file mode 100644
index 0000000..0d4809409
--- /dev/null
+++ b/src/test/rustdoc/const-underscore.rs
@@ -0,0 +1,7 @@
+// compile-flags: --document-private-items
+
+// @!has const_underscore/constant._.html
+const _: () = {
+    #[no_mangle]
+    extern "C" fn implementation_detail() {}
+};
diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs
index 505d6ee..9ccc5d7 100644
--- a/src/test/rustdoc/duplicate-cfg.rs
+++ b/src/test/rustdoc/duplicate-cfg.rs
@@ -1,15 +1,42 @@
+// ignore-tidy-linelength
+
 #![crate_name = "foo"]
 #![feature(doc_cfg)]
 
-// @has 'foo/index.html'
-// @!has '-' '//*[@class="stab portability"]' 'feature="sync" and'
-// @has '-' '//*[@class="stab portability"]' 'feature="sync"'
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.'
 #[doc(cfg(feature = "sync"))]
 #[doc(cfg(feature = "sync"))]
 pub struct Foo;
 
+// @has 'foo/bar/struct.Bar.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.'
 #[doc(cfg(feature = "sync"))]
 pub mod bar {
     #[doc(cfg(feature = "sync"))]
     pub struct Bar;
 }
+
+// @has 'foo/baz/struct.Baz.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.'
+#[doc(cfg(all(feature = "sync", feature = "send")))]
+pub mod baz {
+    #[doc(cfg(feature = "sync"))]
+    pub struct Baz;
+}
+
+// @has 'foo/qux/struct.Qux.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.'
+#[doc(cfg(feature = "sync"))]
+pub mod qux {
+    #[doc(cfg(all(feature = "sync", feature = "send")))]
+    pub struct Qux;
+}
+
+// @has 'foo/quux/struct.Quux.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" and foo and bar only.'
+#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
+pub mod quux {
+    #[doc(cfg(all(feature = "send", feature = "sync", bar)))]
+    pub struct Quux;
+}
diff --git a/src/test/rustdoc/issue-46380.rs b/src/test/rustdoc/issue-46380.rs
deleted file mode 100644
index 8837a6b..0000000
--- a/src/test/rustdoc/issue-46380.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// compile-flags: --document-private-items
-
-// @has issue_46380/struct.Hidden.html
-#[doc(hidden)]
-pub struct Hidden;
diff --git a/src/test/rustdoc/issue-67851-both.rs b/src/test/rustdoc/issue-67851-both.rs
new file mode 100644
index 0000000..d69b943
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-both.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Zunstable-options --document-private-items --document-hidden-items
+
+// @has issue_67851_both/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @has issue_67851_both/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/issue-67851-hidden.rs b/src/test/rustdoc/issue-67851-hidden.rs
new file mode 100644
index 0000000..8a3cafe
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-hidden.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Zunstable-options --document-hidden-items
+
+// @has issue_67851_hidden/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has issue_67851_hidden/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/issue-67851-neither.rs b/src/test/rustdoc/issue-67851-neither.rs
new file mode 100644
index 0000000..4e3cd83
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-neither.rs
@@ -0,0 +1,6 @@
+// @!has issue_67851_neither/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has issue_67851_neither/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/issue-67851-private.rs b/src/test/rustdoc/issue-67851-private.rs
new file mode 100644
index 0000000..8addc7f
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-private.rs
@@ -0,0 +1,8 @@
+// compile-flags: --document-private-items
+
+// @!has issue_67851_private/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @has issue_67851_private/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/show-const-contents.rs b/src/test/rustdoc/show-const-contents.rs
index 6d95f78..e84f6e5 100644
--- a/src/test/rustdoc/show-const-contents.rs
+++ b/src/test/rustdoc/show-const-contents.rs
@@ -62,3 +62,6 @@
 
 // @has show_const_contents/constant.MIN.html '= i16::min_value(); // -32_768i16'
 int_module!(i16);
+
+// @has show_const_contents/constant.ESCAPE.html //pre '= r#"<script>alert("ESCAPE");</script>"#;'
+pub const ESCAPE: &str = r#"<script>alert("ESCAPE");</script>"#;
diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
index 6163f27..725c350 100644
--- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -1,14 +1,17 @@
 #![feature(box_syntax, plugin, plugin_registrar, rustc_private)]
 #![crate_type = "dylib"]
 
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+extern crate rustc_hir;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 extern crate rustc_span;
 extern crate syntax;
 
-use rustc::hir::{self, intravisit, Node};
-use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
+use rustc_hir::intravisit;
+use rustc_hir as hir;
+use rustc_hir::Node;
+use rustc_lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
 use rustc_driver::plugin::Registry;
 use rustc_span::source_map;
 use syntax::print::pprust;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
index 47751f4..98963a1 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
@@ -2,14 +2,14 @@
 
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+extern crate rustc_hir;
 extern crate rustc_span;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 extern crate syntax;
 
-use rustc::hir;
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass};
+use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass};
 use rustc_driver::plugin::Registry;
 use rustc_span::symbol::Symbol;
 use syntax::attr;
@@ -25,7 +25,7 @@
         }
 
         impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct {
-            fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
+            fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
                 $(
                     if !attr::contains_name(&krate.attrs, $attr) {
                         cx.span_lint(CRATE_NOT_OKAY, krate.span,
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 4821c9b..589477d 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -3,14 +3,14 @@
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
 
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+extern crate rustc_hir;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 extern crate rustc_span;
 extern crate syntax;
 
-use rustc::hir;
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray};
+use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray};
 use rustc_driver::plugin::Registry;
 use rustc_span::symbol::Symbol;
 use syntax::attr;
@@ -24,7 +24,7 @@
 declare_lint_pass!(Pass => [CRATE_NOT_OKAY]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
-    fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
+    fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
         if !attr::contains_name(&krate.attrs, Symbol::intern("crate_okay")) {
             cx.span_lint(CRATE_NOT_OKAY, krate.span,
                          "crate is not marked with #![crate_okay]");
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index 839c65a..2cc288c 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -4,12 +4,12 @@
 #![feature(box_syntax, rustc_private)]
 
 // Load rustc as a plugin to get macros.
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+extern crate rustc_hir;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 
-use rustc::hir;
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId};
+use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId};
 use rustc_driver::plugin::Registry;
 
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
@@ -19,7 +19,7 @@
 declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) {
         match &*it.ident.as_str() {
             "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"),
             "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"),
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index bb96dba..c704701 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -6,11 +6,11 @@
 extern crate syntax;
 
 // Load rustc as a plugin to get macros
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 
-use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray};
+use rustc_lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray};
 use rustc_driver::plugin::Registry;
 use syntax::ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index 1704909..fa545dd 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -4,11 +4,11 @@
 extern crate syntax;
 
 // Load rustc as a plugin to get macros
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 
-use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId};
 use rustc_driver::plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
index 7ce2a1d..8d9cbe4 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
@@ -6,9 +6,8 @@
 extern crate rustc;
 extern crate rustc_session;
 
-use rustc::lint::{LintArray, LintPass};
-use rustc::{declare_lint_pass, impl_lint_pass};
-use rustc_session::declare_lint;
+use rustc_session::lint::{LintArray, LintPass};
+use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 
 declare_lint! {
     pub TEST_LINT,
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
index ad8670c..39ac001 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
@@ -1,5 +1,5 @@
 error: implementing `LintPass` by hand
-  --> $DIR/lint_pass_impl_without_macro.rs:21:6
+  --> $DIR/lint_pass_impl_without_macro.rs:20:6
    |
 LL | impl LintPass for Foo {
    |      ^^^^^^^^
@@ -12,7 +12,7 @@
    = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
 error: implementing `LintPass` by hand
-  --> $DIR/lint_pass_impl_without_macro.rs:31:14
+  --> $DIR/lint_pass_impl_without_macro.rs:30:14
    |
 LL |         impl LintPass for Custom {
    |              ^^^^^^^^
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs
index 569f04d..35ddab9 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs
@@ -10,6 +10,8 @@
 
 #[allow(test_lint)]
 //~^ ERROR allow(test_lint) overruled by outer forbid(test_lint)
+//~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
+//~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
 pub fn main() {
     lintme();
 }
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr
index c0de1fe..f93a0a0 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr
@@ -7,6 +7,15 @@
 LL | #[allow(test_lint)]
    |         ^^^^^^^^^ overruled by previous forbid
 
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-attrs.rs:11:9
+   |
+LL | #![forbid(test_lint)]
+   |           --------- `forbid` level set here
+...
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-plugin-forbid-attrs.rs:5:1
    |
@@ -27,6 +36,15 @@
 LL | #![forbid(test_lint)]
    |           ^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-attrs.rs:11:9
+   |
+LL | #![forbid(test_lint)]
+   |           --------- `forbid` level set here
+...
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs
index 82313f6..695d3ae 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs
@@ -8,6 +8,8 @@
 fn lintme() { } //~ ERROR item is named 'lintme'
 
 #[allow(test_lint)] //~ ERROR allow(test_lint) overruled by outer forbid(test_lint)
+                    //~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
+                    //~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
 pub fn main() {
     lintme();
 }
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr
index f189efb..0302ec8 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr
@@ -6,6 +6,14 @@
    |
    = note: `forbid` lint level was set on command line
 
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-cmdline.rs:10:9
+   |
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-plugin-forbid-cmdline.rs:6:1
    |
@@ -22,6 +30,14 @@
    |
    = note: requested on the command line with `-F test-lint`
 
-error: aborting due to 2 previous errors
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-cmdline.rs:10:9
+   |
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr
index 825a341..2f1c29e 100644
--- a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr
+++ b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr
@@ -2,6 +2,10 @@
    |
    = note: requested on the command line with `-A test_lint`
 
+warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint
+   |
+   = note: requested on the command line with `-A test_lint`
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-tool-cmdline-allow.rs:7:1
    |
@@ -10,6 +14,10 @@
    |
    = note: `#[warn(deprecated)]` on by default
 
+warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint
+   |
+   = note: requested on the command line with `-A test_lint`
+
 warning: item is named 'lintme'
   --> $DIR/lint-tool-cmdline-allow.rs:9:1
    |
@@ -18,3 +26,7 @@
    |
    = note: `#[warn(clippy::test_lint)]` on by default
 
+warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint
+   |
+   = note: requested on the command line with `-A test_lint`
+
diff --git a/src/test/ui-fulldeps/lint-tool-test.rs b/src/test/ui-fulldeps/lint-tool-test.rs
index 216a8cb..f92bcd2 100644
--- a/src/test/ui-fulldeps/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/lint-tool-test.rs
@@ -8,9 +8,12 @@
 #![allow(dead_code)]
 #![cfg_attr(foo, warn(test_lint))]
 //~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
-//~^^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 #![deny(clippy_group)]
 //~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
@@ -25,6 +28,8 @@
 
 #[allow(test_group)]
 //~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
 fn hello() {
     fn lintmetoo() { }
diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr
index d4031a7..809b9ac 100644
--- a/src/test/ui-fulldeps/lint-tool-test.stderr
+++ b/src/test/ui-fulldeps/lint-tool-test.stderr
@@ -7,19 +7,19 @@
    = note: `#[warn(renamed_and_removed_lints)]` on by default
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
-  --> $DIR/lint-tool-test.rs:12:9
+  --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
-  --> $DIR/lint-tool-test.rs:26:9
+  --> $DIR/lint-tool-test.rs:29:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
 warning: unknown lint: `this_lint_does_not_exist`
-  --> $DIR/lint-tool-test.rs:28:8
+  --> $DIR/lint-tool-test.rs:33:8
    |
 LL | #[deny(this_lint_does_not_exist)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,6 +32,18 @@
 LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:13:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
+warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:29:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-tool-test.rs:6:1
    |
@@ -40,31 +52,49 @@
    |
    = note: `#[warn(deprecated)]` on by default
 
+warning: lint name `test_lint` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:9:23
+   |
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:13:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
 error: item is named 'lintme'
-  --> $DIR/lint-tool-test.rs:15:1
+  --> $DIR/lint-tool-test.rs:18:1
    |
 LL | fn lintme() { }
    | ^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-tool-test.rs:12:9
+  --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_lint)]` implied by `#[deny(clippy::group)]`
 
 error: item is named 'lintmetoo'
-  --> $DIR/lint-tool-test.rs:23:5
+  --> $DIR/lint-tool-test.rs:26:5
    |
 LL |     fn lintmetoo() { }
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-tool-test.rs:12:9
+  --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]`
 
+warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:29:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui-fulldeps/newtype_index.rs b/src/test/ui-fulldeps/newtype_index.rs
deleted file mode 100644
index fe68b39..0000000
--- a/src/test/ui-fulldeps/newtype_index.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-
-#![feature(rustc_private)]
-
-extern crate rustc_index;
-extern crate serialize as rustc_serialize;
-
-use rustc_index::{newtype_index, vec::Idx};
-
-newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA });
-
-use std::mem::size_of;
-
-fn main() {
-    assert_eq!(size_of::<MyIdx>(), 4);
-    assert_eq!(size_of::<Option<MyIdx>>(), 4);
-    assert_eq!(size_of::<Option<Option<MyIdx>>>(), 4);
-    assert_eq!(size_of::<Option<Option<Option<MyIdx>>>>(), 4);
-    assert_eq!(size_of::<Option<Option<Option<Option<MyIdx>>>>>(), 4);
-    assert_eq!(size_of::<Option<Option<Option<Option<Option<MyIdx>>>>>>(), 4);
-    assert_eq!(size_of::<Option<Option<Option<Option<Option<Option<MyIdx>>>>>>>(), 8);
-}
diff --git a/src/test/ui/associated-const/associated-const-no-item.rs b/src/test/ui/associated-const/associated-const-no-item.rs
index 35fb662f..024d14e 100644
--- a/src/test/ui/associated-const/associated-const-no-item.rs
+++ b/src/test/ui/associated-const/associated-const-no-item.rs
@@ -3,7 +3,7 @@
 }
 
 const X: i32 = <i32>::ID;
-//~^ ERROR no associated item named `ID` found for type `i32`
+//~^ ERROR no associated item named `ID` found
 
 fn main() {
     assert_eq!(1, X);
diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr
index 23916a3..3a70e7d 100644
--- a/src/test/ui/associated-const/issue-63496.stderr
+++ b/src/test/ui/associated-const/issue-63496.stderr
@@ -5,9 +5,13 @@
    |     --------------- required by `A::C`
 LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                     ^^^^ cannot infer type
+   |                     ^^^^
+   |                     |
+   |                     cannot infer type
+   |                     help: use the fully qualified path to an implementation: `<Type as A>::C`
    |
    = note: cannot resolve `_: A`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error[E0283]: type annotations needed
   --> $DIR/issue-63496.rs:4:33
@@ -16,9 +20,13 @@
    |     --------------- required by `A::C`
 LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                                 ^^^^ cannot infer type
+   |                                 ^^^^
+   |                                 |
+   |                                 cannot infer type
+   |                                 help: use the fully qualified path to an implementation: `<Type as A>::C`
    |
    = note: cannot resolve `_: A`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr
index 5a62b97..6f89530 100644
--- a/src/test/ui/associated-item/associated-item-enum.stderr
+++ b/src/test/ui/associated-item/associated-item-enum.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `mispellable` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `mispellable` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:17:11
    |
 LL | enum Enum { Variant }
@@ -10,7 +10,7 @@
    |           variant or associated item not found in `Enum`
    |           help: there is a method with a similar name: `misspellable`
 
-error[E0599]: no variant or associated item named `mispellable_trait` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:18:11
    |
 LL | enum Enum { Variant }
@@ -19,7 +19,7 @@
 LL |     Enum::mispellable_trait();
    |           ^^^^^^^^^^^^^^^^^ variant or associated item not found in `Enum`
 
-error[E0599]: no variant or associated item named `MISPELLABLE` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:19:11
    |
 LL | enum Enum { Variant }
diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr
index 9c825d5..ddabd55 100644
--- a/src/test/ui/associated-item/issue-48027.stderr
+++ b/src/test/ui/associated-item/issue-48027.stderr
@@ -13,9 +13,13 @@
 LL |     const X: usize;
    |     --------------- required by `Bar::X`
 LL |     fn return_n(&self) -> [u8; Bar::X];
-   |                                ^^^^^^ cannot infer type
+   |                                ^^^^^^
+   |                                |
+   |                                cannot infer type
+   |                                help: use the fully qualified path to an implementation: `<Type as Bar>::X`
    |
    = note: cannot resolve `_: Bar`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs
index 64bc9ee..65ca017 100644
--- a/src/test/ui/associated-type-bounds/duplicate.rs
+++ b/src/test/ui/associated-type-bounds/duplicate.rs
@@ -157,10 +157,13 @@
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
+//~| ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
+//~| ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
+//~| ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr
index caecc5e..defa629 100644
--- a/src/test/ui/associated-type-bounds/duplicate.stderr
+++ b/src/test/ui/associated-type-bounds/duplicate.stderr
@@ -531,7 +531,15 @@
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:160:46
+  --> $DIR/duplicate.rs:158:46
+   |
+LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
+   |                                  ----------  ^^^^^^^^^^ re-bound here
+   |                                  |
+   |                                  `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:161:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -539,7 +547,15 @@
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:162:49
+  --> $DIR/duplicate.rs:161:46
+   |
+LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
+   |                                  ----------  ^^^^^^^^^^ re-bound here
+   |                                  |
+   |                                  `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:164:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -547,7 +563,15 @@
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:164:43
+  --> $DIR/duplicate.rs:164:49
+   |
+LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
+   |                                  -------------  ^^^^^^^^^^^^^ re-bound here
+   |                                  |
+   |                                  `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:167:43
    |
 LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -555,7 +579,7 @@
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:166:43
+  --> $DIR/duplicate.rs:169:43
    |
 LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -563,7 +587,7 @@
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:168:46
+  --> $DIR/duplicate.rs:171:46
    |
 LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -571,7 +595,7 @@
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:171:40
+  --> $DIR/duplicate.rs:174:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -579,7 +603,7 @@
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:175:44
+  --> $DIR/duplicate.rs:178:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -587,7 +611,7 @@
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:179:43
+  --> $DIR/duplicate.rs:182:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -667,40 +691,40 @@
    |                                           ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:171:28
+  --> $DIR/duplicate.rs:174:28
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:171:40
+  --> $DIR/duplicate.rs:174:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:175:32
+  --> $DIR/duplicate.rs:178:32
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:175:44
+  --> $DIR/duplicate.rs:178:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:179:28
+  --> $DIR/duplicate.rs:182:28
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:179:43
+  --> $DIR/duplicate.rs:182:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                                           ^^^^^^^^^^^^^
 
-error: aborting due to 93 previous errors
+error: aborting due to 96 previous errors
 
diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr
index 239f801..dc3a475 100644
--- a/src/test/ui/async-await/dont-suggest-missing-await.stderr
+++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/dont-suggest-missing-await.rs:14:18
    |
+LL | async fn make_u32() -> u32 {
+   |                        --- the `Output` of this `async fn`'s found opaque type
+...
 LL |         take_u32(x)
    |                  ^ expected `u32`, found opaque type
    |
diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr
index 155c5cc..d682817 100644
--- a/src/test/ui/async-await/issue-64130-3-other.stderr
+++ b/src/test/ui/async-await/issue-64130-3-other.stderr
@@ -3,6 +3,9 @@
    |
 LL | fn is_qux<T: Qux>(t: T) { }
    |    ------    --- required by this bound in `is_qux`
+LL | 
+LL | async fn bar() {
+   |                - within this `impl std::future::Future`
 ...
 LL |     is_qux(bar());
    |     ^^^^^^ within `impl std::future::Future`, the trait `Qux` is not implemented for `Foo`
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
index 2c7a5cd..b12d7bc 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
@@ -8,6 +8,7 @@
 
 async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
     //~^ ERROR ambiguous lifetime bound
+    //~| ERROR ambiguous lifetime bound
     (a, b)
 }
 
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
index 59d7728..f9a1b4b 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
@@ -6,5 +6,13 @@
    |
    = help: add #![feature(member_constraints)] to the crate attributes to enable
 
-error: aborting due to previous error
+error: ambiguous lifetime bound in `impl Trait`
+  --> $DIR/ret-impl-trait-no-fg.rs:9:64
+   |
+LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+   |                                                                ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
+   |
+   = help: add #![feature(member_constraints)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr
index 1efc200..2703cec 100644
--- a/src/test/ui/async-await/suggest-missing-await-closure.stderr
+++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await-closure.rs:16:18
    |
+LL | async fn make_u32() -> u32 {
+   |                        --- the `Output` of this `async fn`'s found opaque type
+...
 LL |         take_u32(x)
    |                  ^
    |                  |
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 7ab0244..6ac05a8 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:13:14
    |
+LL | async fn make_u32() -> u32 {
+   |                        --- the `Output` of this `async fn`'s found opaque type
+...
 LL |     take_u32(x)
    |              ^
    |              |
@@ -13,6 +16,9 @@
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:23:5
    |
+LL | async fn dummy() {}
+   |                  - the `Output` of this `async fn`'s found opaque type
+...
 LL |     dummy()
    |     ^^^^^^^ expected `()`, found opaque type
    |
diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs
index 79c043b..d313691 100644
--- a/src/test/ui/async-await/unresolved_type_param.rs
+++ b/src/test/ui/async-await/unresolved_type_param.rs
@@ -8,8 +8,16 @@
 async fn foo() {
     bar().await;
     //~^ ERROR type inside `async fn` body must be known in this context
+    //~| ERROR type inside `async fn` body must be known in this context
+    //~| ERROR type inside `async fn` body must be known in this context
+    //~| NOTE cannot infer type for type parameter `T`
+    //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE in this expansion of desugaring of `await`
+    //~| NOTE in this expansion of desugaring of `await`
     //~| NOTE in this expansion of desugaring of `await`
 }
 fn main() {}
diff --git a/src/test/ui/async-await/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr
index 3ffdb8c..6b9e960 100644
--- a/src/test/ui/async-await/unresolved_type_param.stderr
+++ b/src/test/ui/async-await/unresolved_type_param.stderr
@@ -10,6 +10,30 @@
 LL |     bar().await;
    |     ^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^^^^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0698`.
diff --git a/src/test/ui/attributes/register-attr-tool-import.rs b/src/test/ui/attributes/register-attr-tool-import.rs
index 3d0cf91..e01dc4d 100644
--- a/src/test/ui/attributes/register-attr-tool-import.rs
+++ b/src/test/ui/attributes/register-attr-tool-import.rs
@@ -11,4 +11,5 @@
 
 #[renamed_attr] //~ ERROR cannot use an explicitly registered attribute through an import
 #[renamed_tool::attr] //~ ERROR cannot use a tool module through an import
+                      //~| ERROR cannot use a tool module through an import
 fn main() {}
diff --git a/src/test/ui/attributes/register-attr-tool-import.stderr b/src/test/ui/attributes/register-attr-tool-import.stderr
index 6f280c8..59f5a86 100644
--- a/src/test/ui/attributes/register-attr-tool-import.stderr
+++ b/src/test/ui/attributes/register-attr-tool-import.stderr
@@ -22,5 +22,17 @@
 LL | use tool as renamed_tool; // OK
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: cannot use a tool module through an import
+  --> $DIR/register-attr-tool-import.rs:13:3
+   |
+LL | #[renamed_tool::attr]
+   |   ^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/register-attr-tool-import.rs:10:5
+   |
+LL | use tool as renamed_tool; // OK
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
index 3e36f24..a0739a7 100644
--- a/src/test/ui/auto-ref-slice-plus-ref.stderr
+++ b/src/test/ui/auto-ref-slice-plus-ref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}>` in the current scope
+error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut();
@@ -8,7 +8,7 @@
    = note: the following trait defines an item `test_mut`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` in the current scope
+error[E0599]: no method named `test` found for struct `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:8:7
    |
 LL |     a.test();
@@ -18,7 +18,7 @@
    = note: the following trait defines an item `test`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `[{integer}; 1]` in the current scope
+error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:10:11
    |
 LL |     ([1]).test();
@@ -28,7 +28,7 @@
    = note: the following trait defines an item `test`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `&[{integer}; 1]` in the current scope
+error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:11:12
    |
 LL |     (&[1]).test();
diff --git a/src/test/ui/block-result/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs
index 9b313d3..0b652a1 100644
--- a/src/test/ui/block-result/issue-3563.rs
+++ b/src/test/ui/block-result/issue-3563.rs
@@ -1,7 +1,7 @@
 trait A {
     fn a(&self) {
         || self.b()
-        //~^ ERROR no method named `b` found for type `&Self` in the current scope
+        //~^ ERROR no method named `b` found
     }
 }
 fn main() {}
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
index 237b8c5..be551f6 100644
--- a/src/test/ui/block-result/issue-3563.stderr
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `b` found for type `&Self` in the current scope
+error[E0599]: no method named `b` found for reference `&Self` in the current scope
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr
index 890f680..cb3199e 100644
--- a/src/test/ui/bogus-tag.stderr
+++ b/src/test/ui/bogus-tag.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Hsl` found for type `Color` in the current scope
+error[E0599]: no variant or associated item named `Hsl` found for enum `Color` in the current scope
   --> $DIR/bogus-tag.rs:7:16
    |
 LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
new file mode 100644
index 0000000..232d436
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
@@ -0,0 +1,118 @@
+#![feature(slice_patterns)]
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        [.., _y] => {} //~ ERROR use of moved value
+    }
+}
+
+fn move_out_from_begin_field_and_end() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., _y] => {} //~ ERROR use of moved value
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., (_y, _)] => {} //~ ERROR use of moved value
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_subslice_and_const_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _, _] => {}
+    }
+    match a {
+        [(_x, _), _, _] => {} //~ ERROR use of moved value
+    }
+}
+
+fn move_out_by_subslice_and_const_index_end_field() {
+    let a = array();
+    match a {
+        [_, _, _y @ ..] => {}
+    }
+    match a {
+        [.., (_x, _)] => {} //~ ERROR use of moved value
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
new file mode 100644
index 0000000..e46a58a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
@@ -0,0 +1,113 @@
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-match.rs:15:14
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+...
+LL |         [.., _y] => {}
+   |              ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-match.rs:25:14
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., _y] => {}
+   |              ^^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-match.rs:35:15
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., (_y, _)] => {}
+   |               ^^ value used here after move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:46:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:57:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:68:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:79:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-match.rs:91:11
+   |
+LL |         [_y @ .., _, _] => {}
+   |          ------- value moved here
+...
+LL |         [(_x, _), _, _] => {}
+   |           ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-match.rs:101:15
+   |
+LL |         [_, _, _y @ ..] => {}
+   |                ------- value moved here
+...
+LL |         [.., (_x, _)] => {}
+   |               ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:112:11
+   |
+LL |         [x @ .., _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
new file mode 100644
index 0000000..e5e6169
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
@@ -0,0 +1,117 @@
+// Due to #53114, which causes a "read" of the `_` patterns,
+// the borrow-checker refuses this code, while it should probably be allowed.
+// Once the bug is fixed, the test, which is derived from a
+// passing test for `let` statements, should become check-pass.
+
+#![feature(slice_patterns)]
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_one_from_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., _y, _] => {}
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (_, _y)] => {}
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_index_field() {
+    let a = array();
+    match a {
+        [_, _y @ ..] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [(_x, _), _, _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_end_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (_x, _)] => {}
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
new file mode 100644
index 0000000..72cd420
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
@@ -0,0 +1,102 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:19:11
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:30:11
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:43:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:54:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:65:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:76:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:87:11
+   |
+LL |         [_, _y @ ..] => {}
+   |             ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:98:11
+   |
+LL |         [_y @ .., _] => {}
+   |          ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:111:11
+   |
+LL |         [x @ .., _, _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
new file mode 100644
index 0000000..1ca3df5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
@@ -0,0 +1,152 @@
+#![feature(slice_patterns)]
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        [.., ref _y] => {} //~ ERROR [E0382]
+    }
+}
+
+fn move_out_from_begin_field_and_end() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., ref _y] => {} //~ ERROR [E0382]
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., (ref _y, _)] => {} //~ ERROR [E0382]
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [ref _y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [_, _, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [ref _y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [_, _, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_subslice_and_const_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _, _] => {}
+    }
+    match a {
+        [(ref _x, _), _, _] => {} //~ ERROR [E0382]
+    }
+}
+
+fn move_out_by_subslice_and_const_index_end_field() {
+    let a = array();
+    match a {
+        [_, _, _y @ ..] => {}
+    }
+    match a {
+        [.., (ref _x, _)] => {} //~ ERROR [E0382]
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [_, ref _y @ ..] => {}
+    }
+}
+
+// Move + Assign
+
+fn move_out_and_assign_end() {
+    let mut a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    a[2] = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_and_assign_end_field() {
+    let mut a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    a[2].1 = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_slice_and_assign_end() {
+    let mut a = array();
+    match a {
+        [_, _, _x @ ..] => {}
+    }
+    a[0] = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_slice_and_assign_end_field() {
+    let mut a = array();
+    match a {
+        [_, _, _x @ ..] => {}
+    }
+    a[0].1 = Default::default(); //~ ERROR [E0382]
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
new file mode 100644
index 0000000..028442a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
@@ -0,0 +1,157 @@
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:15:14
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+...
+LL |         [.., ref _y] => {}
+   |              ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:25:14
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., ref _y] => {}
+   |              ^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:35:15
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., (ref _y, _)] => {}
+   |               ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:46:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:57:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:68:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:79:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:91:11
+   |
+LL |         [_y @ .., _, _] => {}
+   |          ------- value moved here
+...
+LL |         [(ref _x, _), _, _] => {}
+   |           ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:101:15
+   |
+LL |         [_, _, _y @ ..] => {}
+   |                ------- value moved here
+...
+LL |         [.., (ref _x, _)] => {}
+   |               ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:112:11
+   |
+LL |         [x @ .., _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:125:5
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+LL |     }
+LL |     a[2] = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:133:5
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+LL |     }
+LL |     a[2].1 = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:141:5
+   |
+LL |         [_, _, _x @ ..] => {}
+   |                ------- value moved here
+LL |     }
+LL |     a[0] = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:149:5
+   |
+LL |         [_, _, _x @ ..] => {}
+   |                ------- value moved here
+LL |     }
+LL |     a[0].1 = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
new file mode 100644
index 0000000..79fe593
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
@@ -0,0 +1,117 @@
+// Due to #53114, which causes a "read" of the `_` patterns,
+// the borrow-checker refuses this code, while it should probably be allowed.
+// Once the bug is fixed, the test, which is derived from a
+// passing test for `let` statements, should become check-pass.
+
+#![feature(slice_patterns)]
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_one_from_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., ref _y, _] => {}
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (_, ref _y)] => {}
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [ref _y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [ref _y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_index_field() {
+    let a = array();
+    match a {
+        [_, _y @ ..] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [(ref _x, _), _, _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_end_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (ref _x, _)] => {}
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, ref _y @ ..] => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
new file mode 100644
index 0000000..43ba2b6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
@@ -0,0 +1,102 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:19:11
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:30:11
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:43:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:54:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:65:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:76:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:87:11
+   |
+LL |         [_, _y @ ..] => {}
+   |             ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:98:11
+   |
+LL |         [_y @ .., _] => {}
+   |          ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:111:11
+   |
+LL |         [x @ .., _, _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
index da918ba..141ad5b 100644
--- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
@@ -26,6 +26,7 @@
 
     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
         //~^ ERROR method not compatible with trait
+        //~| ERROR method not compatible with trait
         //
         // Note: This is a terrible error message. It is caused
         // because, in the trait, 'b is early bound, and in the impl,
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
index 4f86ffb..ad39b36 100644
--- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -35,8 +35,27 @@
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |                        ^^
 
+error[E0308]: method not compatible with trait
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:5
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
+              found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
+note: the lifetime `'c` as defined on the method body at 27:24...
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |                        ^^
+note: ...does not necessarily outlive the lifetime `'c` as defined on the method body at 27:24
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |                        ^^
+
 error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:41:20
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20
    |
 LL |     fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
    |                    ---------------- lifetimes in impl do not match this method in trait
@@ -45,7 +64,7 @@
    |                    ^ lifetimes do not match method in trait
 
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:48:5
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:49:5
    |
 LL |     fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
    |     ------------------------------------------------------- definition of `another_bound` from trait
@@ -53,7 +72,7 @@
 LL |     fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0195, E0276, E0308.
 For more information about an error, try `rustc --explain E0195`.
diff --git a/src/test/ui/class-cast-to-trait.stderr b/src/test/ui/class-cast-to-trait.stderr
index 4cab52e..0f932cd 100644
--- a/src/test/ui/class-cast-to-trait.stderr
+++ b/src/test/ui/class-cast-to-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `eat` found for type `std::boxed::Box<dyn Noisy>` in the current scope
+error[E0599]: no method named `eat` found for struct `std::boxed::Box<dyn Noisy>` in the current scope
   --> $DIR/class-cast-to-trait.rs:53:8
    |
 LL |   nyan.eat();
diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr
index 63236cf..3c4ae45 100644
--- a/src/test/ui/closures/closure-reform-bad.stderr
+++ b/src/test/ui/closures/closure-reform-bad.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/closure-reform-bad.rs:11:15
    |
+LL |     let f = |s: &str| println!("{}{}", s, string);
+   |             ------------------------------------- the found closure
 LL |     call_bare(f)
    |               ^ expected fn pointer, found closure
    |
diff --git a/src/test/ui/coherence/coherence_inherent.stderr b/src/test/ui/coherence/coherence_inherent.stderr
index e719d52..3d37d8a 100644
--- a/src/test/ui/coherence/coherence_inherent.stderr
+++ b/src/test/ui/coherence/coherence_inherent.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `the_fn` found for type `&Lib::TheStruct` in the current scope
+error[E0599]: no method named `the_fn` found for reference `&Lib::TheStruct` in the current scope
   --> $DIR/coherence_inherent.rs:31:11
    |
 LL |         s.the_fn();
diff --git a/src/test/ui/coherence/coherence_inherent_cc.stderr b/src/test/ui/coherence/coherence_inherent_cc.stderr
index c666c1a..d968c8b 100644
--- a/src/test/ui/coherence/coherence_inherent_cc.stderr
+++ b/src/test/ui/coherence/coherence_inherent_cc.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `the_fn` found for type `&coherence_inherent_cc_lib::TheStruct` in the current scope
+error[E0599]: no method named `the_fn` found for reference `&coherence_inherent_cc_lib::TheStruct` in the current scope
   --> $DIR/coherence_inherent_cc.rs:23:11
    |
 LL |         s.the_fn();
diff --git a/src/test/ui/conflicting-repr-hints.rs b/src/test/ui/conflicting-repr-hints.rs
index cc986b2..8e9c116 100644
--- a/src/test/ui/conflicting-repr-hints.rs
+++ b/src/test/ui/conflicting-repr-hints.rs
@@ -1,16 +1,24 @@
 #![allow(dead_code)]
 
 #[repr(C)]
-enum A { A }
+enum A {
+    A,
+}
 
 #[repr(u64)]
-enum B { B }
+enum B {
+    B,
+}
 
-#[repr(C, u64)] //~ WARNING conflicting representation hints
-enum C { C }
+#[repr(C, u64)] //~ ERROR conflicting representation hints
+enum C {
+    C,
+}
 
-#[repr(u32, u64)] //~ WARNING conflicting representation hints
-enum D { D }
+#[repr(u32, u64)] //~ ERROR conflicting representation hints
+enum D {
+    D,
+}
 
 #[repr(C, packed)]
 struct E(i32);
@@ -37,20 +45,23 @@
 struct K(i32);
 
 #[repr(packed, align(8))]
-union X { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union X {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 #[repr(packed)]
 #[repr(align(8))]
-union Y { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union Y {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 #[repr(align(8))]
 #[repr(packed)]
-union Z { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union Z {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 fn main() {}
diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr
index 414c15f..0dfe360 100644
--- a/src/test/ui/conflicting-repr-hints.stderr
+++ b/src/test/ui/conflicting-repr-hints.stderr
@@ -1,70 +1,73 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/conflicting-repr-hints.rs:9:8
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:13:8
    |
 LL | #[repr(C, u64)]
    |        ^  ^^^
 
-warning[E0566]: conflicting representation hints
-  --> $DIR/conflicting-repr-hints.rs:12:8
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:18:8
    |
 LL | #[repr(u32, u64)]
    |        ^^^  ^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:19:1
+  --> $DIR/conflicting-repr-hints.rs:27:1
    |
 LL | struct F(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:23:1
+  --> $DIR/conflicting-repr-hints.rs:31:1
    |
 LL | struct G(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:27:1
+  --> $DIR/conflicting-repr-hints.rs:35:1
    |
 LL | struct H(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0634]: type has conflicting packed representation hints
-  --> $DIR/conflicting-repr-hints.rs:30:1
+  --> $DIR/conflicting-repr-hints.rs:38:1
    |
 LL | struct I(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0634]: type has conflicting packed representation hints
-  --> $DIR/conflicting-repr-hints.rs:34:1
+  --> $DIR/conflicting-repr-hints.rs:42:1
    |
 LL | struct J(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:40:1
+  --> $DIR/conflicting-repr-hints.rs:48:1
    |
 LL | / union X {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:46:1
+  --> $DIR/conflicting-repr-hints.rs:55:1
    |
 LL | / union Y {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:52:1
+  --> $DIR/conflicting-repr-hints.rs:62:1
    |
 LL | / union Z {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0566, E0587.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/confuse-field-and-method/issue-18343.stderr b/src/test/ui/confuse-field-and-method/issue-18343.stderr
index 79ba931..d6b399a 100644
--- a/src/test/ui/confuse-field-and-method/issue-18343.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-18343.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
   --> $DIR/issue-18343.rs:7:7
    |
 LL | struct Obj<F> where F: FnMut() -> u32 {
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr
index a44b971..f9dfddd 100644
--- a/src/test/ui/confuse-field-and-method/issue-2392.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
   --> $DIR/issue-2392.rs:36:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -12,7 +12,7 @@
 LL |     (o_closure.closure)();
    |     ^                 ^
 
-error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
   --> $DIR/issue-2392.rs:38:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -23,7 +23,7 @@
    |               |
    |               field, not a method
 
-error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:42:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -37,7 +37,7 @@
 LL |     (o_func.closure)();
    |     ^              ^
 
-error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope
   --> $DIR/issue-2392.rs:45:14
    |
 LL | struct BoxedObj {
@@ -51,7 +51,7 @@
 LL |     (boxed_fn.boxed_closure)();
    |     ^                      ^
 
-error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope
   --> $DIR/issue-2392.rs:48:19
    |
 LL | struct BoxedObj {
@@ -65,7 +65,7 @@
 LL |     (boxed_closure.boxed_closure)();
    |     ^                           ^
 
-error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:53:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -79,7 +79,7 @@
 LL |     (w.wrap.closure)();
    |     ^              ^
 
-error[E0599]: no method named `not_closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:55:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -90,7 +90,7 @@
    |            |
    |            field, not a method
 
-error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
   --> $DIR/issue-2392.rs:58:24
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -104,7 +104,7 @@
 LL |     (check_expression().closure)();
    |     ^                          ^
 
-error[E0599]: no method named `f1` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f1` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:64:31
    |
 LL | struct FuncContainer {
@@ -118,7 +118,7 @@
 LL |             ((*self.container).f1)(1);
    |             ^                    ^
 
-error[E0599]: no method named `f2` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f2` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:65:31
    |
 LL | struct FuncContainer {
@@ -132,7 +132,7 @@
 LL |             ((*self.container).f2)(1);
    |             ^                    ^
 
-error[E0599]: no method named `f3` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f3` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:66:31
    |
 LL | struct FuncContainer {
diff --git a/src/test/ui/confuse-field-and-method/issue-32128.stderr b/src/test/ui/confuse-field-and-method/issue-32128.stderr
index b2f7894..a8d97bd 100644
--- a/src/test/ui/confuse-field-and-method/issue-32128.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-32128.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `example` found for type `Example` in the current scope
+error[E0599]: no method named `example` found for struct `Example` in the current scope
   --> $DIR/issue-32128.rs:12:10
    |
 LL | struct Example {
diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr
index af29a99..c109896 100644
--- a/src/test/ui/confuse-field-and-method/issue-33784.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
   --> $DIR/issue-33784.rs:27:7
    |
 LL |     p.closure();
@@ -9,7 +9,7 @@
 LL |     (p.closure)();
    |     ^         ^
 
-error[E0599]: no method named `fn_ptr` found for type `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
   --> $DIR/issue-33784.rs:29:7
    |
 LL |     q.fn_ptr();
@@ -20,7 +20,7 @@
 LL |     (q.fn_ptr)();
    |     ^        ^
 
-error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scope
+error[E0599]: no method named `c_fn_ptr` found for reference `&D` in the current scope
   --> $DIR/issue-33784.rs:32:7
    |
 LL |     s.c_fn_ptr();
diff --git a/src/test/ui/confuse-field-and-method/private-field.stderr b/src/test/ui/confuse-field-and-method/private-field.stderr
index 97c949e..82cb235 100644
--- a/src/test/ui/confuse-field-and-method/private-field.stderr
+++ b/src/test/ui/confuse-field-and-method/private-field.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `dog_age` found for type `animal::Dog` in the current scope
+error[E0599]: no method named `dog_age` found for struct `animal::Dog` in the current scope
   --> $DIR/private-field.rs:16:23
    |
 LL |     pub struct Dog {
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
index 47b090c..19e7d20 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -4,7 +4,7 @@
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
    |                                  ^^ unexpected const argument
 
-error[E0599]: no method named `f` found for type `S` in the current scope
+error[E0599]: no method named `f` found for struct `S` in the current scope
   --> $DIR/invalid-const-arg-for-type-param.rs:7:7
    |
 LL | struct S;
diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs
index 1de6baf..64aeb46 100644
--- a/src/test/ui/consts/array-literal-index-oob.rs
+++ b/src/test/ui/consts/array-literal-index-oob.rs
@@ -1,7 +1,10 @@
-// build-fail
+// build-pass
+
+#![warn(const_err)]
 
 fn main() {
-    &{[1, 2, 3][4]};
-    //~^ ERROR index out of bounds
-    //~| ERROR reaching this expression at runtime will panic or abort
+    &{ [1, 2, 3][4] };
+    //~^ WARN index out of bounds
+    //~| WARN reaching this expression at runtime will panic or abort
+    //~| WARN erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr
index f3ef166..50ad8e8 100644
--- a/src/test/ui/consts/array-literal-index-oob.stderr
+++ b/src/test/ui/consts/array-literal-index-oob.stderr
@@ -1,18 +1,26 @@
-error: index out of bounds: the len is 3 but the index is 4
-  --> $DIR/array-literal-index-oob.rs:4:7
+warning: index out of bounds: the len is 3 but the index is 4
+  --> $DIR/array-literal-index-oob.rs:6:8
    |
-LL |     &{[1, 2, 3][4]};
-   |       ^^^^^^^^^^^^
+LL |     &{ [1, 2, 3][4] };
+   |        ^^^^^^^^^^^^
    |
-   = note: `#[deny(const_err)]` on by default
+note: lint level defined here
+  --> $DIR/array-literal-index-oob.rs:3:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/array-literal-index-oob.rs:4:7
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/array-literal-index-oob.rs:6:8
    |
-LL |     &{[1, 2, 3][4]};
-   |     --^^^^^^^^^^^^-
-   |       |
-   |       indexing out of bounds: the len is 3 but the index is 4
+LL |     &{ [1, 2, 3][4] };
+   |     ---^^^^^^^^^^^^--
+   |        |
+   |        indexing out of bounds: the len is 3 but the index is 4
 
-error: aborting due to 2 previous errors
+warning: erroneous constant used
+  --> $DIR/array-literal-index-oob.rs:6:5
+   |
+LL |     &{ [1, 2, 3][4] };
+   |     ^^^^^^^^^^^^^^^^^ referenced constant has errors
 
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs
index 96f67c9..2058d2e 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.rs
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs
@@ -10,4 +10,5 @@
 fn main() {
     println!("{}", FOO);
     //~^ ERROR
+    //~| WARN erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
index ec18f8f..b5f5f84 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
@@ -18,6 +18,12 @@
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:11:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.rs b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
index 9369702..9300d95 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
@@ -14,6 +14,7 @@
     match -128i8 {
         NEG_NEG_128 => println!("A"),
         //~^ ERROR could not evaluate constant pattern
+        //~| ERROR could not evaluate constant pattern
         _ => println!("B"),
     }
 }
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
index 13f00c4..26728cf 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
@@ -4,5 +4,11 @@
 LL |         NEG_NEG_128 => println!("A"),
    |         ^^^^^^^^^^^
 
-error: aborting due to previous error
+error: could not evaluate constant pattern
+  --> $DIR/const-eval-overflow-2.rs:15:9
+   |
+LL |         NEG_NEG_128 => println!("A"),
+   |         ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
index a5f04d0..81f5382 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
@@ -4,7 +4,9 @@
 #![feature(const_fn)]
 #![allow(const_err)]
 
-fn double(x: usize) -> usize { x * 2 }
+fn double(x: usize) -> usize {
+    x * 2
+}
 const X: fn(usize) -> usize = double;
 
 const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
index 19f37fa..f99505c 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
@@ -1,11 +1,11 @@
 warning: skipping const checks
-  --> $DIR/const_fn_ptr_fail2.rs:11:5
+  --> $DIR/const_fn_ptr_fail2.rs:13:5
    |
 LL |     x(y)
    |     ^^^^
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/const_fn_ptr_fail2.rs:18:5
+  --> $DIR/const_fn_ptr_fail2.rs:20:5
    |
 LL |     assert_eq!(Y, 4);
    |     ^^^^^^^^^^^-^^^^^
@@ -15,7 +15,7 @@
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/const_fn_ptr_fail2.rs:20:5
+  --> $DIR/const_fn_ptr_fail2.rs:22:5
    |
 LL |     assert_eq!(Z, 4);
    |     ^^^^^^^^^^^-^^^^^
diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs
index 849c81a..9109307 100644
--- a/src/test/ui/consts/const-eval/issue-43197.rs
+++ b/src/test/ui/consts/const-eval/issue-43197.rs
@@ -7,11 +7,13 @@
 }
 
 fn main() {
-    const X: u32 = 0-1;
+    const X: u32 = 0 - 1;
     //~^ WARN any use of this value will cause
-    const Y: u32 = foo(0-1);
+    const Y: u32 = foo(0 - 1);
     //~^ WARN any use of this value will cause
     println!("{} {}", X, Y);
     //~^ ERROR evaluation of constant expression failed
     //~| ERROR evaluation of constant expression failed
+    //~| WARN erroneous constant used [const_err]
+    //~| WARN erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr
index a1b3a05..23b54d9 100644
--- a/src/test/ui/consts/const-eval/issue-43197.stderr
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr
@@ -1,8 +1,8 @@
 warning: any use of this value will cause an error
   --> $DIR/issue-43197.rs:10:20
    |
-LL |     const X: u32 = 0-1;
-   |     ---------------^^^-
+LL |     const X: u32 = 0 - 1;
+   |     ---------------^^^^^-
    |                    |
    |                    attempt to subtract with overflow
    |
@@ -15,8 +15,8 @@
 warning: any use of this value will cause an error
   --> $DIR/issue-43197.rs:12:24
    |
-LL |     const Y: u32 = foo(0-1);
-   |     -------------------^^^--
+LL |     const Y: u32 = foo(0 - 1);
+   |     -------------------^^^^^--
    |                        |
    |                        attempt to subtract with overflow
 
@@ -26,12 +26,24 @@
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/issue-43197.rs:14:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
 error[E0080]: evaluation of constant expression failed
   --> $DIR/issue-43197.rs:14:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/issue-43197.rs:14:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs
index 7da9256..f919470 100644
--- a/src/test/ui/consts/const-eval/issue-44578.rs
+++ b/src/test/ui/consts/const-eval/issue-44578.rs
@@ -25,5 +25,5 @@
 
 fn main() {
     println!("{}", <Bar<u16, u8> as Foo>::AMT);
-    //~^ ERROR E0080
+    //~^ ERROR evaluation of constant expression failed [E0080]
 }
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
index e589126..5c3635e 100644
--- a/src/test/ui/consts/const-eval/issue-50814.rs
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -12,11 +12,13 @@
 struct Sum<A,B>(A,B);
 
 impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
-    const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
+    const MAX: u8 = A::MAX + B::MAX;
+    //~^ ERROR any use of this value will cause an error [const_err]
 }
 
 fn foo<T>(_: T) -> &'static u8 {
-    &Sum::<U8,U8>::MAX //~ ERROR E0080
+    &Sum::<U8,U8>::MAX
+    //~^ ERROR E0080
 }
 
 fn main() {
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index f8b017e..2e5167a 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -9,7 +9,7 @@
    = note: `#[deny(const_err)]` on by default
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-50814.rs:19:5
+  --> $DIR/issue-50814.rs:20:5
    |
 LL |     &Sum::<U8,U8>::MAX
    |     ^-----------------
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index 2eed8ca..fee2321 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -1,20 +1,22 @@
-// build-fail
+// build-pass
 // compile-flags: -O
 
-#![deny(const_err)]
+#![warn(const_err)]
 
 fn main() {
     println!("{}", 0u32 - 1);
     let _x = 0u32 - 1;
-    //~^ ERROR const_err
-    println!("{}", 1/(1-1));
-    //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR const_err
-    let _x = 1/(1-1);
-    //~^ ERROR const_err
-    println!("{}", 1/(false as u32));
-    //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR const_err
-    let _x = 1/(false as u32);
-    //~^ ERROR const_err
+    //~^ WARN const_err
+    println!("{}", 1 / (1 - 1));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (1 - 1);
+    //~^ WARN const_err
+    println!("{}", 1 / (false as u32));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (false as u32);
+    //~^ WARN const_err
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
index 8f17ef0..4de22fd 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr
@@ -1,4 +1,4 @@
-error: this expression will panic at runtime
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:8:14
    |
 LL |     let _x = 0u32 - 1;
@@ -7,44 +7,54 @@
 note: lint level defined here
   --> $DIR/promoted_errors.rs:4:9
    |
-LL | #![deny(const_err)]
+LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-error: attempt to divide by zero
+warning: attempt to divide by zero
   --> $DIR/promoted_errors.rs:10:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
+warning: reaching this expression at runtime will panic or abort
   --> $DIR/promoted_errors.rs:10:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ dividing by zero
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:13:14
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:10:20
    |
-LL |     let _x = 1/(1-1);
-   |              ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ referenced constant has errors
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:15:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:14:14
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^
+LL |     let _x = 1 / (1 - 1);
+   |              ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:15:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:16:20
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:18:14
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:16:20
    |
-LL |     let _x = 1/(false as u32);
-   |              ^^^^^^^^^^^^^^^^
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
 
-error: aborting due to 7 previous errors
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:20:14
+   |
+LL |     let _x = 1 / (false as u32);
+   |              ^^^^^^^^^^^^^^^^^^
 
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs
index ae680b4..41a989d 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors2.rs
@@ -1,21 +1,23 @@
-// build-fail
+// build-pass
 // compile-flags: -C overflow-checks=on -O
 
-#![deny(const_err)]
+#![warn(const_err)]
 
 fn main() {
     println!("{}", 0u32 - 1);
-    //~^ ERROR attempt to subtract with overflow
+    //~^ WARN attempt to subtract with overflow
     let _x = 0u32 - 1;
-    //~^ ERROR attempt to subtract with overflow
-    println!("{}", 1/(1-1));
-    //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR const_err
-    let _x = 1/(1-1);
-    //~^ ERROR const_err
-    println!("{}", 1/(false as u32));
-    //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR const_err
-    let _x = 1/(false as u32);
-    //~^ ERROR const_err
+    //~^ WARN attempt to subtract with overflow
+    println!("{}", 1 / (1 - 1));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (1 - 1);
+    //~^ WARN const_err
+    println!("{}", 1 / (false as u32));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (false as u32);
+    //~^ WARN const_err
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr
index 60a3cba..4f7ba8b 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr
@@ -1,4 +1,4 @@
-error: attempt to subtract with overflow
+warning: attempt to subtract with overflow
   --> $DIR/promoted_errors2.rs:7:20
    |
 LL |     println!("{}", 0u32 - 1);
@@ -7,50 +7,60 @@
 note: lint level defined here
   --> $DIR/promoted_errors2.rs:4:9
    |
-LL | #![deny(const_err)]
+LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-error: attempt to subtract with overflow
+warning: attempt to subtract with overflow
   --> $DIR/promoted_errors2.rs:9:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^
 
-error: attempt to divide by zero
+warning: attempt to divide by zero
   --> $DIR/promoted_errors2.rs:11:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
+warning: reaching this expression at runtime will panic or abort
   --> $DIR/promoted_errors2.rs:11:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ dividing by zero
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:14:14
+warning: erroneous constant used
+  --> $DIR/promoted_errors2.rs:11:20
    |
-LL |     let _x = 1/(1-1);
-   |              ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ referenced constant has errors
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:16:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:15:14
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^
+LL |     let _x = 1 / (1 - 1);
+   |              ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:16:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:17:20
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:19:14
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors2.rs:17:20
    |
-LL |     let _x = 1/(false as u32);
-   |              ^^^^^^^^^^^^^^^^
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
 
-error: aborting due to 8 previous errors
+warning: erroneous constant used
+  --> $DIR/promoted_errors2.rs:17:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:21:14
+   |
+LL |     let _x = 1 / (false as u32);
+   |              ^^^^^^^^^^^^^^^^^^
 
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.rs b/src/test/ui/consts/const-eval/ref_to_int_match.rs
index 45ce040..87136a1 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.rs
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.rs
@@ -5,6 +5,7 @@
     match n {
         0..=10 => {},
         10..=BAR => {}, //~ ERROR could not evaluate constant pattern
+                        //~| ERROR could not evaluate constant pattern
         _ => {},
     }
 }
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr
index b72a5b8..17f8744 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ref_to_int_match.rs:24:1
+  --> $DIR/ref_to_int_match.rs:25:1
    |
 LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
@@ -12,6 +12,12 @@
 LL |         10..=BAR => {},
    |              ^^^
 
-error: aborting due to 2 previous errors
+error: could not evaluate constant pattern
+  --> $DIR/ref_to_int_match.rs:7:14
+   |
+LL |         10..=BAR => {},
+   |              ^^^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
index 80d80a9..ea9fffa 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -13,7 +13,7 @@
 LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
 LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
 LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 6 which has size 1
+   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 9 which has size 1
 LL | |     mem::transmute(out_of_bounds_ptr)
 LL | | } };
    | |____-
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs
new file mode 100644
index 0000000..7ced248
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs
@@ -0,0 +1,7 @@
+fn main() {}
+
+#[cfg(FALSE)]
+fn container() {
+    const unsafe WhereIsFerris Now() {}
+    //~^ ERROR expected one of `extern` or `fn`
+}
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr
new file mode 100644
index 0000000..5ec9e2a
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `extern` or `fn`, found `WhereIsFerris`
+  --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs:5:18
+   |
+LL |     const unsafe WhereIsFerris Now() {}
+   |                  ^^^^^^^^^^^^^ expected one of `extern` or `fn`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs
new file mode 100644
index 0000000..1886bfc
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs
@@ -0,0 +1,8 @@
+fn main() {}
+
+#[cfg(FALSE)]
+fn container() {
+    const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
+    //~^ ERROR expected `fn`
+    //~| ERROR `const extern fn` definitions are unstable
+}
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr
new file mode 100644
index 0000000..cf71ed4d
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr
@@ -0,0 +1,18 @@
+error: expected `fn`, found `PUT_ANYTHING_YOU_WANT_HERE`
+  --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier.rs:5:25
+   |
+LL |     const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `fn`
+
+error[E0658]: `const extern fn` definitions are unstable
+  --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier.rs:5:5
+   |
+LL |     const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
+   |     ^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/64926
+   = help: add `#![feature(const_extern_fn)]` 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/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
index 2d4175e..df793d7 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
@@ -4,17 +4,21 @@
 LL |     random()
    |     ^^^^^^^^
 
-error[E0013]: constant functions cannot refer to statics, use a constant instead
+error[E0013]: constant functions cannot refer to statics
   --> $DIR/const-fn-not-safe-for-const.rs:20:5
    |
 LL |     Y
    |     ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0013]: constant functions cannot refer to statics, use a constant instead
+error[E0013]: constant functions cannot refer to statics
   --> $DIR/const-fn-not-safe-for-const.rs:25:6
    |
 LL |     &Y
    |      ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
index 33abfec..99006a2 100644
--- a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -1,7 +1,6 @@
 // run-pass
 
 #![feature(const_mut_refs)]
-#![feature(const_fn)]
 
 struct Foo {
     x: usize
diff --git a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
index 7887fd1..6bbbdd9 100644
--- a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
+++ b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
@@ -3,7 +3,6 @@
 // check-pass
 
 #![feature(const_if_match)]
-#![feature(const_fn)]
 
 enum E {
     A,
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
index 9509672..21e3f2a 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/feature-gate-const-if-match.rs:109:1
+  --> $DIR/feature-gate-const-if-match.rs:108:1
    |
 LL | / fn main() {
 LL | |     let _ = [0; {
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
index e4b6525..00576d5 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
@@ -6,7 +6,6 @@
 
 #![feature(rustc_attrs)]
 #![cfg_attr(if_match, feature(const_if_match))]
-#![feature(const_fn)]
 
 const _: i32 = if true { //[stock]~ ERROR `if` is not allowed in a `const`
     5
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
index e846ee4..d3c6a51 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:11:16
+  --> $DIR/feature-gate-const-if-match.rs:10:16
    |
 LL |   const _: i32 = if true {
    |  ________________^
@@ -13,7 +13,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:17:16
+  --> $DIR/feature-gate-const-if-match.rs:16:16
    |
 LL |   const _: i32 = if let Some(true) = Some(false) {
    |  ________________^
@@ -27,7 +27,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:23:16
+  --> $DIR/feature-gate-const-if-match.rs:22:16
    |
 LL |   const _: i32 = match 1 {
    |  ________________^
@@ -41,7 +41,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:30:13
+  --> $DIR/feature-gate-const-if-match.rs:29:13
    |
 LL |     let x = if true { 0 } else { 1 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +50,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:32:13
+  --> $DIR/feature-gate-const-if-match.rs:31:13
    |
 LL |     let x = match x { 0 => 1, _ => 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:34:5
+  --> $DIR/feature-gate-const-if-match.rs:33:5
    |
 LL |     if let Some(x) = Some(x) { x } else { 1 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:39:13
+  --> $DIR/feature-gate-const-if-match.rs:38:13
    |
 LL |     let x = if true { 0 } else { 1 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:41:13
+  --> $DIR/feature-gate-const-if-match.rs:40:13
    |
 LL |     let x = match x { 0 => 1, _ => 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +86,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:43:5
+  --> $DIR/feature-gate-const-if-match.rs:42:5
    |
 LL |     if let Some(x) = Some(x) { x } else { 1 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:48:5
+  --> $DIR/feature-gate-const-if-match.rs:47:5
    |
 LL |     if true { 5 } else { 6 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:52:5
+  --> $DIR/feature-gate-const-if-match.rs:51:5
    |
 LL | /     if let Some(true) = a {
 LL | |         0
@@ -117,7 +117,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:60:5
+  --> $DIR/feature-gate-const-if-match.rs:59:5
    |
 LL | /     match i {
 LL | |         i if i > 10 => i,
@@ -130,7 +130,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:91:17
+  --> $DIR/feature-gate-const-if-match.rs:90:17
    |
 LL |         let x = if y { 0 } else { 1 };
    |                 ^^^^^^^^^^^^^^^^^^^^^
@@ -139,7 +139,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:93:17
+  --> $DIR/feature-gate-const-if-match.rs:92:17
    |
 LL |         let x = match x { 0 => 1, _ => 0 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:95:9
+  --> $DIR/feature-gate-const-if-match.rs:94:9
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:111:17
+  --> $DIR/feature-gate-const-if-match.rs:110:17
    |
 LL |         let x = if false { 0 } else { 1 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +166,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:113:17
+  --> $DIR/feature-gate-const-if-match.rs:112:17
    |
 LL |         let x = match x { 0 => 1, _ => 0 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -175,7 +175,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:115:9
+  --> $DIR/feature-gate-const-if-match.rs:114:9
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +184,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:68:21
+  --> $DIR/feature-gate-const-if-match.rs:67:21
    |
 LL |     const IF: i32 = if true { 5 } else { 6 };
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:71:25
+  --> $DIR/feature-gate-const-if-match.rs:70:25
    |
 LL |     const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -202,7 +202,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:74:24
+  --> $DIR/feature-gate-const-if-match.rs:73:24
    |
 LL |     const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -211,7 +211,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:79:21
+  --> $DIR/feature-gate-const-if-match.rs:78:21
    |
 LL |     const IF: i32 = if true { 5 } else { 6 };
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +220,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:82:25
+  --> $DIR/feature-gate-const-if-match.rs:81:25
    |
 LL |     const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,7 +229,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:85:24
+  --> $DIR/feature-gate-const-if-match.rs:84:24
    |
 LL |     const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -238,7 +238,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/feature-gate-const-if-match.rs:115:21
+  --> $DIR/feature-gate-const-if-match.rs:114:21
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |                     ^
diff --git a/src/test/ui/consts/control-flow/short-circuit-let.rs b/src/test/ui/consts/control-flow/short-circuit-let.rs
index 4b20a21..8cee2a5 100644
--- a/src/test/ui/consts/control-flow/short-circuit-let.rs
+++ b/src/test/ui/consts/control-flow/short-circuit-let.rs
@@ -4,7 +4,6 @@
 
 #![feature(const_if_match)]
 #![feature(const_panic)]
-#![feature(const_fn)]
 
 const X: i32 = {
     let mut x = 0;
diff --git a/src/test/ui/consts/control-flow/single_variant_match_ice.rs b/src/test/ui/consts/control-flow/single_variant_match_ice.rs
index bb0fce6..823605f 100644
--- a/src/test/ui/consts/control-flow/single_variant_match_ice.rs
+++ b/src/test/ui/consts/control-flow/single_variant_match_ice.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(const_if_match, const_fn)]
+#![feature(const_if_match)]
 
 enum Foo {
     Prob,
diff --git a/src/test/ui/consts/enum-discr-type-err.rs b/src/test/ui/consts/enum-discr-type-err.rs
index d66c4f4..5adb2fa 100644
--- a/src/test/ui/consts/enum-discr-type-err.rs
+++ b/src/test/ui/consts/enum-discr-type-err.rs
@@ -17,6 +17,7 @@
         enum E {
             $( $v = $s::V, )*
             //~^ ERROR mismatched types
+            //~| ERROR mismatched types
         }
     }
 }
diff --git a/src/test/ui/consts/enum-discr-type-err.stderr b/src/test/ui/consts/enum-discr-type-err.stderr
index 848ccf9..9935f88 100644
--- a/src/test/ui/consts/enum-discr-type-err.stderr
+++ b/src/test/ui/consts/enum-discr-type-err.stderr
@@ -15,6 +15,23 @@
 LL |             $( $v = $s::V.try_into().unwrap(), )*
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/enum-discr-type-err.rs:18:21
+   |
+LL |               $( $v = $s::V, )*
+   |                       ^^^^^ expected `isize`, found `i32`
+...
+LL | / mac! {
+LL | |     A = F,
+LL | |     B = T,
+LL | | }
+   | |_- in this macro invocation
+   |
+help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |             $( $v = $s::V.try_into().unwrap(), )*
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs
index 1c13bfc..1e49543 100644
--- a/src/test/ui/consts/match_ice.rs
+++ b/src/test/ui/consts/match_ice.rs
@@ -10,6 +10,7 @@
     match C {
         C => {}
         //~^ ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
+        //~| ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
     }
     const K: &T = &T;
     match K { //~ ERROR non-exhaustive patterns: `&T` not covered
diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr
index bf0bd3a..b25ac09 100644
--- a/src/test/ui/consts/match_ice.stderr
+++ b/src/test/ui/consts/match_ice.stderr
@@ -5,7 +5,7 @@
    |         ^
 
 error[E0004]: non-exhaustive patterns: `&T` not covered
-  --> $DIR/match_ice.rs:15:11
+  --> $DIR/match_ice.rs:16:11
    |
 LL | struct T;
    | --------- `T` defined here
@@ -15,6 +15,12 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error: aborting due to 2 previous errors
+error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match_ice.rs:11:9
+   |
+LL |         C => {}
+   |         ^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
index e07db3f..edbf0e0 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
@@ -28,6 +28,7 @@
 static mut MUTABLE: u32 = 0;
 const READ_MUT: u32 = unsafe { MUTABLE }; //~ WARN any use of this value will cause an error
 //~^ WARN skipping const checks
+//~| WARN skipping const checks
 
 // ok some day perhaps
 const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
index eae76c1..243efbb 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
@@ -29,7 +29,13 @@
    |                                ^^^^^^^
 
 warning: skipping const checks
-  --> $DIR/const_refers_to_static.rs:35:6
+  --> $DIR/const_refers_to_static.rs:29:32
+   |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+   |                                ^^^^^^^
+
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:36:6
    |
 LL |     &FOO
    |      ^^^
@@ -84,7 +90,7 @@
    |                                constant accesses static
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const_refers_to_static.rs:33:1
+  --> $DIR/const_refers_to_static.rs:34:1
    |
 LL | / const READ_IMMUT: &usize = {
 LL | |     static FOO: usize = 0;
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
index 3493b7c..88418e5 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
@@ -10,7 +10,7 @@
 LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17
+thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:346:17
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 error: internal compiler error: unexpected panic
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
index 32a713e..cfb57d2 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.rs
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
@@ -11,5 +11,7 @@
 //~^ WARN any use of this value will cause an error
 
 fn main() {
-    println!("{:?}", C); //~ ERROR: evaluation of constant expression failed
+    println!("{:?}", C);
+    //~^ ERROR: evaluation of constant expression failed
+    //~| WARN: erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
index 75f532a..6a7df85 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
@@ -24,6 +24,12 @@
 LL |     println!("{:?}", C);
    |                      ^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/non_const_fn.rs:14:22
+   |
+LL |     println!("{:?}", C);
+   |                      ^ referenced constant has errors
+
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr
index 2fb9977..599d1d7 100644
--- a/src/test/ui/consts/too_generic_eval_ice.stderr
+++ b/src/test/ui/consts/too_generic_eval_ice.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `HOST_SIZE` found for type `Foo<A, B>` in the current scope
+error[E0599]: no associated item named `HOST_SIZE` found for struct `Foo<A, B>` in the current scope
   --> $DIR/too_generic_eval_ice.rs:7:19
    |
 LL | pub struct Foo<A, B>(A, B);
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
index b5d2b43..2817abf 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
@@ -8,6 +8,7 @@
 fn main() {
     match &b""[..] {
         ZST => {} //~ ERROR could not evaluate constant pattern
+                  //~| ERROR could not evaluate constant pattern
     }
 }
 
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
index 5f84204..296a55e 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:14:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:15:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -15,7 +15,7 @@
    |         ^^^
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:14:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:15:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    |                             ^^^^^^^^^^^^^^^^^^^
@@ -23,6 +23,12 @@
    = note: source type: `usize` (word size)
    = note: target type: `&'static [u8]` (2 * word size)
 
-error: aborting due to 3 previous errors
+error: could not evaluate constant pattern
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9
+   |
+LL |         ZST => {}
+   |         ^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/consts/zst_no_llvm_alloc.rs b/src/test/ui/consts/zst_no_llvm_alloc.rs
index 5d77935..2a41f70 100644
--- a/src/test/ui/consts/zst_no_llvm_alloc.rs
+++ b/src/test/ui/consts/zst_no_llvm_alloc.rs
@@ -7,13 +7,15 @@
 
 fn main() {
     let x: &'static () = &();
-    assert_eq!(x as *const () as usize, 1);
+    assert_ne!(x as *const () as usize, 1);
     let x: &'static Foo = &Foo;
-    assert_eq!(x as *const Foo as usize, 4);
+    assert_ne!(x as *const Foo as usize, 4);
 
     // statics must have a unique address
     assert_ne!(&FOO as *const Foo as usize, 4);
 
-    assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
-    assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
+    // FIXME this two tests should be assert_eq!
+    // this stopped working since we are promoting to constants instead of statics
+    assert_ne!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
+    assert_ne!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
 }
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
index 054bd09..c95e8d2 100644
--- a/src/test/ui/copy-a-resource.stderr
+++ b/src/test/ui/copy-a-resource.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Foo` in the current scope
+error[E0599]: no method named `clone` found for struct `Foo` in the current scope
   --> $DIR/copy-a-resource.rs:18:16
    |
 LL | struct Foo {
diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
index 6175b7d..b2edc1a 100644
--- a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
+++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
@@ -3,6 +3,7 @@
 
 trait Foo<X = Box<dyn Foo>> {
     //~^ ERROR cycle detected
+    //~| ERROR cycle detected
 }
 
 fn main() { }
diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
index e89d257..6b38d85 100644
--- a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
+++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
@@ -11,6 +11,19 @@
 LL | trait Foo<X = Box<dyn Foo>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0391]: cycle detected when processing `Foo::X`
+  --> $DIR/cycle-trait-default-type-trait.rs:4:23
+   |
+LL | trait Foo<X = Box<dyn Foo>> {
+   |                       ^^^
+   |
+   = note: ...which again requires processing `Foo::X`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/cycle-trait-default-type-trait.rs:4:1
+   |
+LL | trait Foo<X = Box<dyn Foo>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr
new file mode 100644
index 0000000..7a28c64
--- /dev/null
+++ b/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr
@@ -0,0 +1,28 @@
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:11:9
+   |
+LL |         2.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
diff --git a/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr
new file mode 100644
index 0000000..4fff3a8
--- /dev/null
+++ b/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr
@@ -0,0 +1,37 @@
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:11:9
+   |
+LL |         2.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:11:9
+   |
+LL |         2.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
diff --git a/src/test/ui/deduplicate-diagnostics-2.rs b/src/test/ui/deduplicate-diagnostics-2.rs
new file mode 100644
index 0000000..f46a7c0
--- /dev/null
+++ b/src/test/ui/deduplicate-diagnostics-2.rs
@@ -0,0 +1,17 @@
+// build-pass
+// revisions: duplicate deduplicate
+//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes
+
+fn main() {
+    match 0.0 {
+        1.0 => {} //~ WARNING floating-point types cannot be used in patterns
+                  //~| WARNING this was previously accepted
+                  //~| WARNING floating-point types cannot be used in patterns
+                  //~| WARNING this was previously accepted
+        2.0 => {} //~ WARNING floating-point types cannot be used in patterns
+                  //~| WARNING this was previously accepted
+                  //[duplicate]~| WARNING floating-point types cannot be used in patterns
+                  //[duplicate]~| WARNING this was previously accepted
+        _ => {}
+    }
+}
diff --git a/src/test/ui/deduplicate-diagnostics.deduplicate.stderr b/src/test/ui/deduplicate-diagnostics.deduplicate.stderr
index 1acfce5..5df2c68 100644
--- a/src/test/ui/deduplicate-diagnostics.deduplicate.stderr
+++ b/src/test/ui/deduplicate-diagnostics.deduplicate.stderr
@@ -1,8 +1,15 @@
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
+
 error: cannot find derive macro `Unresolved` in this scope
   --> $DIR/deduplicate-diagnostics.rs:4:10
    |
 LL | #[derive(Unresolved)]
    |          ^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/deduplicate-diagnostics.duplicate.stderr b/src/test/ui/deduplicate-diagnostics.duplicate.stderr
index 325da3b..3b100b5 100644
--- a/src/test/ui/deduplicate-diagnostics.duplicate.stderr
+++ b/src/test/ui/deduplicate-diagnostics.duplicate.stderr
@@ -1,3 +1,9 @@
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
+
 error: cannot find derive macro `Unresolved` in this scope
   --> $DIR/deduplicate-diagnostics.rs:4:10
    |
@@ -10,5 +16,18 @@
 LL | #[derive(Unresolved)]
    |          ^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
 
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/deduplicate-diagnostics.rs b/src/test/ui/deduplicate-diagnostics.rs
index 4a1f503..c5d41ff 100644
--- a/src/test/ui/deduplicate-diagnostics.rs
+++ b/src/test/ui/deduplicate-diagnostics.rs
@@ -1,8 +1,11 @@
 // revisions: duplicate deduplicate
-//[duplicate] compile-flags: -Z deduplicate-diagnostics=no
+//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes
 
 #[derive(Unresolved)] //~ ERROR cannot find derive macro `Unresolved` in this scope
                       //[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope
 struct S;
 
+#[deny("literal")] //~ ERROR malformed lint attribute input
+                   //[duplicate]~| ERROR malformed lint attribute input
+                   //[duplicate]~| ERROR malformed lint attribute input
 fn main() {}
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index 038de80..2083a1d 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Bar<NotClone>` in the current scope
+error[E0599]: no method named `clone` found for struct `Bar<NotClone>` in the current scope
   --> $DIR/derive-assoc-type-not-impl.rs:18:30
    |
 LL | struct Bar<T: Foo> {
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
index 2a5d09d..beef639 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
@@ -10,7 +10,11 @@
 #[derive(PartialOrd,PartialEq)]
 enum Enum {
    A {
-     x: Error //~ ERROR
+     x: Error //~ ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
    }
 }
 
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
index 3f669c2..80b896f 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.rs b/src/test/ui/derives/derives-span-PartialOrd-enum.rs
index e69c182..b02828d 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum.rs
@@ -10,7 +10,11 @@
 #[derive(PartialOrd,PartialEq)]
 enum Enum {
    A(
-     Error //~ ERROR
+     Error //~ ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
      )
 }
 
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
index a78af9e..f12038f 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.rs b/src/test/ui/derives/derives-span-PartialOrd-struct.rs
index b5d1df9..bfcfc3d 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-struct.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-struct.rs
@@ -9,7 +9,11 @@
 
 #[derive(PartialOrd,PartialEq)]
 struct Struct {
-    x: Error //~ ERROR
+    x: Error //~ ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
 }
 
 fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
index 8e85f1a..dbb0147 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
index 7dfb33b..c8bdd64 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
@@ -9,7 +9,11 @@
 
 #[derive(PartialOrd,PartialEq)]
 struct Struct(
-    Error //~ ERROR
+    Error //~ ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
 );
 
 fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
index bf91578..f6f1694 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/deriving-bounds.rs b/src/test/ui/derives/deriving-bounds.rs
index 52659bd..95d4404 100644
--- a/src/test/ui/derives/deriving-bounds.rs
+++ b/src/test/ui/derives/deriving-bounds.rs
@@ -1,9 +1,11 @@
 #[derive(Send)]
 //~^ ERROR cannot find derive macro `Send` in this scope
+//~| ERROR cannot find derive macro `Send` in this scope
 struct Test;
 
 #[derive(Sync)]
 //~^ ERROR cannot find derive macro `Sync` in this scope
+//~| ERROR cannot find derive macro `Sync` in this scope
 struct Test1;
 
 pub fn main() {}
diff --git a/src/test/ui/derives/deriving-bounds.stderr b/src/test/ui/derives/deriving-bounds.stderr
index b18df35..74ca372 100644
--- a/src/test/ui/derives/deriving-bounds.stderr
+++ b/src/test/ui/derives/deriving-bounds.stderr
@@ -1,11 +1,23 @@
 error: cannot find derive macro `Sync` in this scope
-  --> $DIR/deriving-bounds.rs:5:10
+  --> $DIR/deriving-bounds.rs:6:10
    |
 LL | #[derive(Sync)]
    |          ^^^^
    |
 note: unsafe traits like `Sync` should be implemented explicitly
-  --> $DIR/deriving-bounds.rs:5:10
+  --> $DIR/deriving-bounds.rs:6:10
+   |
+LL | #[derive(Sync)]
+   |          ^^^^
+
+error: cannot find derive macro `Sync` in this scope
+  --> $DIR/deriving-bounds.rs:6:10
+   |
+LL | #[derive(Sync)]
+   |          ^^^^
+   |
+note: unsafe traits like `Sync` should be implemented explicitly
+  --> $DIR/deriving-bounds.rs:6:10
    |
 LL | #[derive(Sync)]
    |          ^^^^
@@ -22,5 +34,17 @@
 LL | #[derive(Send)]
    |          ^^^^
 
-error: aborting due to 2 previous errors
+error: cannot find derive macro `Send` in this scope
+  --> $DIR/deriving-bounds.rs:1:10
+   |
+LL | #[derive(Send)]
+   |          ^^^^
+   |
+note: unsafe traits like `Send` should be implemented explicitly
+  --> $DIR/deriving-bounds.rs:1:10
+   |
+LL | #[derive(Send)]
+   |          ^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.rs b/src/test/ui/derives/deriving-meta-unknown-trait.rs
index f4a6f3f..d1af5b4 100644
--- a/src/test/ui/derives/deriving-meta-unknown-trait.rs
+++ b/src/test/ui/derives/deriving-meta-unknown-trait.rs
@@ -1,5 +1,10 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 #[derive(Eqr)]
 //~^ ERROR cannot find derive macro `Eqr` in this scope
+//~| ERROR cannot find derive macro `Eqr` in this scope
 struct Foo;
 
 pub fn main() {}
diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.stderr b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
index 1b8e689..ead1313 100644
--- a/src/test/ui/derives/deriving-meta-unknown-trait.stderr
+++ b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
@@ -1,8 +1,24 @@
 error: cannot find derive macro `Eqr` in this scope
-  --> $DIR/deriving-meta-unknown-trait.rs:1:10
+  --> $DIR/deriving-meta-unknown-trait.rs:5:10
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+   | 
+  ::: $SRC_DIR/libcore/cmp.rs:LL:COL
+   |
+LL | pub macro Eq($item:item) {
+   | ------------------------ similarly named derive macro `Eq` defined here
 
-error: aborting due to previous error
+error: cannot find derive macro `Eqr` in this scope
+  --> $DIR/deriving-meta-unknown-trait.rs:5:10
+   |
+LL | #[derive(Eqr)]
+   |          ^^^ help: a derive macro with a similar name exists: `Eq`
+   | 
+  ::: $SRC_DIR/libcore/cmp.rs:LL:COL
+   |
+LL | pub macro Eq($item:item) {
+   | ------------------------ similarly named derive macro `Eq` defined here
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/derives/deriving-primitive.rs b/src/test/ui/derives/deriving-primitive.rs
index c7098d4..1173eca 100644
--- a/src/test/ui/derives/deriving-primitive.rs
+++ b/src/test/ui/derives/deriving-primitive.rs
@@ -1,4 +1,5 @@
 #[derive(FromPrimitive)] //~ ERROR cannot find derive macro `FromPrimitive` in this scope
+                         //~| ERROR cannot find derive macro `FromPrimitive` in this scope
 enum Foo {}
 
 fn main() {}
diff --git a/src/test/ui/derives/deriving-primitive.stderr b/src/test/ui/derives/deriving-primitive.stderr
index d1b4449..ca64c9e 100644
--- a/src/test/ui/derives/deriving-primitive.stderr
+++ b/src/test/ui/derives/deriving-primitive.stderr
@@ -4,5 +4,11 @@
 LL | #[derive(FromPrimitive)]
    |          ^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: cannot find derive macro `FromPrimitive` in this scope
+  --> $DIR/deriving-primitive.rs:1:10
+   |
+LL | #[derive(FromPrimitive)]
+   |          ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.rs b/src/test/ui/did_you_mean/bad-assoc-pat.rs
index 7e7ba59..3f912f7 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.rs
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.rs
@@ -2,25 +2,25 @@
     match 0u8 {
         [u8]::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `[u8]` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
         (u8, u8)::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `(u8, u8)` in the current sco
+        //~| ERROR no associated item named `AssocItem` found
         _::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `_` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
     match &0u8 {
         &(u8,)::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `(u8,)` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
 }
 
 macro_rules! pat {
     ($ty: ty) => ($ty::AssocItem)
     //~^ ERROR missing angle brackets in associated item path
-    //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+    //~| ERROR no associated item named `AssocItem` found
 }
 macro_rules! ty {
     () => (u8)
@@ -31,6 +31,6 @@
         pat!(u8) => {}
         ty!()::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
 }
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
index 59b8654..3f1946b 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
@@ -37,13 +37,13 @@
 LL |         pat!(u8) => {}
    |         -------- in this macro invocation
 
-error[E0599]: no associated item named `AssocItem` found for type `[u8]` in the current scope
+error[E0599]: no associated item named `AssocItem` found for slice `[u8]` in the current scope
   --> $DIR/bad-assoc-pat.rs:3:15
    |
 LL |         [u8]::AssocItem => {}
    |               ^^^^^^^^^ associated item not found in `[u8]`
 
-error[E0599]: no associated item named `AssocItem` found for type `(u8, u8)` in the current scope
+error[E0599]: no associated item named `AssocItem` found for tuple `(u8, u8)` in the current scope
   --> $DIR/bad-assoc-pat.rs:6:19
    |
 LL |         (u8, u8)::AssocItem => {}
@@ -55,7 +55,7 @@
 LL |         _::AssocItem => {}
    |            ^^^^^^^^^ associated item not found in `_`
 
-error[E0599]: no associated item named `AssocItem` found for type `(u8,)` in the current scope
+error[E0599]: no associated item named `AssocItem` found for tuple `(u8,)` in the current scope
   --> $DIR/bad-assoc-pat.rs:14:17
    |
 LL |         &(u8,)::AssocItem => {}
diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs
index ea21592..60633c6 100644
--- a/src/test/ui/did_you_mean/issue-40006.rs
+++ b/src/test/ui/did_you_mean/issue-40006.rs
@@ -35,5 +35,5 @@
 }
 
 fn main() {
-    S.hello_method(); //~ no method named `hello_method` found for type `S` in the current scope
+    S.hello_method(); //~ no method named `hello_method` found
 }
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index d1e9950..072e61f 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -56,7 +56,7 @@
 LL |     pub hello_method(&self) {
    |        ^ missing `fn`, `type`, or `const`
 
-error[E0599]: no method named `hello_method` found for type `S` in the current scope
+error[E0599]: no method named `hello_method` found for struct `S` in the current scope
   --> $DIR/issue-40006.rs:38:7
    |
 LL | struct S;
diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs
index 1893355..e4e94bb 100644
--- a/src/test/ui/did_you_mean/issue-40396.rs
+++ b/src/test/ui/did_you_mean/issue-40396.rs
@@ -1,8 +1,8 @@
 fn main() {
     (0..13).collect<Vec<i32>>();
-    //~^ ERROR chained comparison
+    //~^ ERROR comparison operators cannot be chained
     Vec<i32>::new();
-    //~^ ERROR chained comparison
+    //~^ ERROR comparison operators cannot be chained
     (0..13).collect<Vec<i32>();
-    //~^ ERROR chained comparison
+    //~^ ERROR comparison operators cannot be chained
 }
diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr
index 749d109..f952136 100644
--- a/src/test/ui/did_you_mean/issue-40396.stderr
+++ b/src/test/ui/did_you_mean/issue-40396.stderr
@@ -1,15 +1,23 @@
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/issue-40396.rs:2:20
    |
 LL |     (0..13).collect<Vec<i32>>();
    |                    ^^^^^
    |
+help: split the comparison into two...
+   |
+LL |     (0..13).collect < Vec && Vec <i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     ((0..13).collect < Vec) <i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 help: use `::<...>` instead of `<...>` to specify type arguments
    |
 LL |     (0..13).collect::<Vec<i32>>();
    |                    ^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/issue-40396.rs:4:8
    |
 LL |     Vec<i32>::new();
@@ -20,12 +28,20 @@
 LL |     Vec::<i32>::new();
    |        ^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/issue-40396.rs:6:20
    |
 LL |     (0..13).collect<Vec<i32>();
    |                    ^^^^^
    |
+help: split the comparison into two...
+   |
+LL |     (0..13).collect < Vec && Vec <i32>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     ((0..13).collect < Vec) <i32>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 help: use `::<...>` instead of `<...>` to specify type arguments
    |
 LL |     (0..13).collect::<Vec<i32>();
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
index 44421b0..467daef 100644
--- a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
@@ -5,8 +5,10 @@
     let b = false;
 
     let _ = a and b; //~ ERROR `and` is not a logical operator
+                     //~| ERROR `and` is not a logical operator
 
     if a and b { //~ ERROR `and` is not a logical operator
+                 //~| ERROR `and` is not a logical operator
         println!("both");
     }
 
@@ -18,8 +20,10 @@
     let b = false;
 
     let _ = a or b; //~ ERROR `or` is not a logical operator
+                    //~| ERROR `or` is not a logical operator
 
     if a or b { //~ ERROR `or` is not a logical operator
+                //~| ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -28,6 +32,7 @@
     let a = true;
     let b = false;
     if (a and b) {  //~ ERROR `and` is not a logical operator
+                    //~| ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -36,6 +41,7 @@
     let a = true;
     let b = false;
     if (a or b) {  //~ ERROR `or` is not a logical operator
+                   //~| ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -44,6 +50,7 @@
     let a = true;
     let b = false;
     while a and b {  //~ ERROR `and` is not a logical operator
+                     //~| ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -52,6 +59,7 @@
     let a = true;
     let b = false;
     while a or b { //~ ERROR `or` is not a logical operator
+                   //~| ERROR `or` is not a logical operator
         println!("both");
     }
 }
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
index 528c62f..e8731cf23 100644
--- a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
@@ -7,7 +7,23 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `and` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:7:15
+   |
+LL |     let _ = a and b;
+   |               ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:10:10
+   |
+LL |     if a and b {
+   |          ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:10:10
    |
 LL |     if a and b {
    |          ^^^ help: use `&&` to perform logical conjunction
@@ -15,7 +31,7 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:15
    |
 LL |     let _ = a or b;
    |               ^^ help: use `||` to perform logical disjunction
@@ -23,7 +39,23 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:15
+   |
+LL |     let _ = a or b;
+   |               ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:25:10
+   |
+LL |     if a or b {
+   |          ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:25:10
    |
 LL |     if a or b {
    |          ^^ help: use `||` to perform logical disjunction
@@ -31,7 +63,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `and` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:34:11
+   |
+LL |     if (a and b) {
+   |           ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:34:11
    |
 LL |     if (a and b) {
    |           ^^^ help: use `&&` to perform logical conjunction
@@ -39,7 +79,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:43:11
+   |
+LL |     if (a or b) {
+   |           ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:43:11
    |
 LL |     if (a or b) {
    |           ^^ help: use `||` to perform logical disjunction
@@ -47,7 +95,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `and` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:52:13
+   |
+LL |     while a and b {
+   |             ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:52:13
    |
 LL |     while a and b {
    |             ^^^ help: use `&&` to perform logical conjunction
@@ -55,7 +111,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:61:13
+   |
+LL |     while a or b {
+   |             ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:61:13
    |
 LL |     while a or b {
    |             ^^ help: use `||` to perform logical disjunction
@@ -63,13 +127,13 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:15:33
    |
 LL |     let _recovery_witness: () = 0;
    |                            --   ^ expected `()`, found integer
    |                            |
    |                            expected due to this
 
-error: aborting due to 9 previous errors
+error: aborting due to 17 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dont-suggest-private-trait-method.rs b/src/test/ui/dont-suggest-private-trait-method.rs
index ef0904c..6e2b1ab 100644
--- a/src/test/ui/dont-suggest-private-trait-method.rs
+++ b/src/test/ui/dont-suggest-private-trait-method.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     T::new();
-    //~^ ERROR no function or associated item named `new` found for type `T` in the current scope
+    //~^ ERROR no function or associated item named `new` found
 }
diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr
index 5189ffa..fd7fdb4 100644
--- a/src/test/ui/dont-suggest-private-trait-method.stderr
+++ b/src/test/ui/dont-suggest-private-trait-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `new` found for type `T` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `T` in the current scope
   --> $DIR/dont-suggest-private-trait-method.rs:4:8
    |
 LL | struct T;
diff --git a/src/test/ui/empty/empty-struct-braces-expr.rs b/src/test/ui/empty/empty-struct-braces-expr.rs
index 1a38d3d..f414427 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.rs
+++ b/src/test/ui/empty/empty-struct-braces-expr.rs
@@ -22,8 +22,8 @@
     let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
     let xe1 = XEmpty1();
     //~^ ERROR expected function, tuple struct or tuple variant, found struct `XEmpty1`
-    let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for type
-    let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for type
+    let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for enum
+    let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for enum
 
-    XE::Empty1 {}; //~ ERROR no variant `Empty1` in enum `empty_struct::XE`
+    XE::Empty1 {}; //~ ERROR no variant named `Empty1` found for enum `empty_struct::XE`
 }
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index f427c1b..9da3a5f 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -9,6 +9,11 @@
    |              |
    |              did you mean `Empty1 { /* fields */ }`?
    |              help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-expr.rs:16:14
@@ -21,6 +26,11 @@
    |              |
    |              did you mean `Empty1 { /* fields */ }`?
    |              help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
 error[E0423]: expected value, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:18:14
@@ -48,6 +58,11 @@
    |               |
    |               did you mean `XEmpty1 { /* fields */ }`?
    |               help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:23:15
@@ -57,8 +72,13 @@
    |               |
    |               did you mean `XEmpty1 { /* fields */ }`?
    |               help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
-error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:25:19
    |
 LL |     let xe3 = XE::Empty3;
@@ -67,7 +87,7 @@
    |                   variant or associated item not found in `empty_struct::XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:26:19
    |
 LL |     let xe3 = XE::Empty3();
@@ -76,7 +96,7 @@
    |                   variant or associated item not found in `empty_struct::XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error: no variant `Empty1` in enum `empty_struct::XE`
+error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
   --> $DIR/empty-struct-braces-expr.rs:28:9
    |
 LL |     XE::Empty1 {};
diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
index 9b5f311..0ff21c9 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
@@ -15,6 +15,11 @@
    |         |   |
    |         |   help: a unit variant with a similar name exists: `XEmpty4`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:7:5
+   |
+LL |     XEmpty4,
+   |     ------- similarly named unit variant `XEmpty4` defined here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
index 0b3c9ae..80c29db 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
@@ -9,6 +9,11 @@
    |         |
    |         did you mean `Empty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:18:9
@@ -18,6 +23,11 @@
    |         |
    |         did you mean `XEmpty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-pat-2.rs:21:9
@@ -30,6 +40,11 @@
    |         |
    |         did you mean `Empty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:24:9
@@ -39,6 +54,11 @@
    |         |
    |         did you mean `XEmpty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
index 785396c..05439b3 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
@@ -15,6 +15,11 @@
    |         |   |
    |         |   help: a tuple variant with a similar name exists: `XEmpty5`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-3.rs:25:9
@@ -33,6 +38,11 @@
    |         |   |
    |         |   help: a tuple variant with a similar name exists: `XEmpty5`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr
index cfbb468..9388ed2 100644
--- a/src/test/ui/empty/empty-struct-tuple-pat.stderr
+++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr
@@ -33,6 +33,11 @@
    |         |   |
    |         |   help: a unit variant with a similar name exists: `XEmpty4`
    |         did you mean `XE::XEmpty5( /* fields */ )`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:7:5
+   |
+LL |     XEmpty4,
+   |     ------- similarly named unit variant `XEmpty4` defined here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-unit-pat.stderr b/src/test/ui/empty/empty-struct-unit-pat.stderr
index fd41a6e..8ee14a3 100644
--- a/src/test/ui/empty/empty-struct-unit-pat.stderr
+++ b/src/test/ui/empty/empty-struct-unit-pat.stderr
@@ -3,24 +3,44 @@
    |
 LL |         Empty2() => ()
    |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
   --> $DIR/empty-struct-unit-pat.rs:24:9
    |
 LL |         XEmpty2() => ()
    |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
   --> $DIR/empty-struct-unit-pat.rs:28:9
    |
 LL |         Empty2(..) => ()
    |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
   --> $DIR/empty-struct-unit-pat.rs:32:9
    |
 LL |         XEmpty2(..) => ()
    |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
   --> $DIR/empty-struct-unit-pat.rs:37:9
@@ -35,6 +55,11 @@
    |         ^^^^-------
    |             |
    |             help: a tuple variant with a similar name exists: `XEmpty5`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
   --> $DIR/empty-struct-unit-pat.rs:46:9
@@ -49,6 +74,11 @@
    |         ^^^^-------
    |             |
    |             help: a tuple variant with a similar name exists: `XEmpty5`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/error-codes/E0030.rs b/src/test/ui/error-codes/E0030.rs
index 58d856b..a5d8f87 100644
--- a/src/test/ui/error-codes/E0030.rs
+++ b/src/test/ui/error-codes/E0030.rs
@@ -2,5 +2,6 @@
     match 5u32 {
         1000 ..= 5 => {}
         //~^ ERROR lower range bound must be less than or equal to upper
+        //~| ERROR lower range bound must be less than or equal to upper
     }
 }
diff --git a/src/test/ui/error-codes/E0030.stderr b/src/test/ui/error-codes/E0030.stderr
index db8161d..8a61140 100644
--- a/src/test/ui/error-codes/E0030.stderr
+++ b/src/test/ui/error-codes/E0030.stderr
@@ -4,6 +4,12 @@
 LL |         1000 ..= 5 => {}
    |         ^^^^ lower bound larger than upper bound
 
-error: aborting due to previous error
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/E0030.rs:3:9
+   |
+LL |         1000 ..= 5 => {}
+   |         ^^^^ lower bound larger than upper bound
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0030`.
diff --git a/src/test/ui/error-codes/E0452.rs b/src/test/ui/error-codes/E0452.rs
index 940b9f6..4e5a6c9 100644
--- a/src/test/ui/error-codes/E0452.rs
+++ b/src/test/ui/error-codes/E0452.rs
@@ -1,4 +1,8 @@
 #![allow(foo = "")] //~ ERROR E0452
-
+                    //~| ERROR E0452
+                    //~| ERROR E0452
+                    //~| ERROR E0452
+                    //~| ERROR E0452
+                    //~| ERROR E0452
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0452.stderr b/src/test/ui/error-codes/E0452.stderr
index 7f07416..30c11e3 100644
--- a/src/test/ui/error-codes/E0452.stderr
+++ b/src/test/ui/error-codes/E0452.stderr
@@ -4,6 +4,36 @@
 LL | #![allow(foo = "")]
    |          ^^^^^^^^ bad attribute argument
 
-error: aborting due to previous error
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/error-codes/E0453.rs b/src/test/ui/error-codes/E0453.rs
index 46fa048..69155b0 100644
--- a/src/test/ui/error-codes/E0453.rs
+++ b/src/test/ui/error-codes/E0453.rs
@@ -2,5 +2,7 @@
 
 #[allow(non_snake_case)]
 //~^ ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
+//~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
+//~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0453.stderr b/src/test/ui/error-codes/E0453.stderr
index 03cc756..138e848 100644
--- a/src/test/ui/error-codes/E0453.stderr
+++ b/src/test/ui/error-codes/E0453.stderr
@@ -7,6 +7,24 @@
 LL | #[allow(non_snake_case)]
    |         ^^^^^^^^^^^^^^ overruled by previous forbid
 
-error: aborting due to previous error
+error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+  --> $DIR/E0453.rs:3:9
+   |
+LL | #![forbid(non_snake_case)]
+   |           -------------- `forbid` level set here
+LL | 
+LL | #[allow(non_snake_case)]
+   |         ^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+  --> $DIR/E0453.rs:3:9
+   |
+LL | #![forbid(non_snake_case)]
+   |           -------------- `forbid` level set here
+LL | 
+LL | #[allow(non_snake_case)]
+   |         ^^^^^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/error-codes/E0565.rs b/src/test/ui/error-codes/E0565.rs
index b09f5df..3bf4286 100644
--- a/src/test/ui/error-codes/E0565.rs
+++ b/src/test/ui/error-codes/E0565.rs
@@ -1,5 +1,6 @@
 // repr currently doesn't support literals
 #[repr("C")] //~ ERROR E0565
+             //~| ERROR E0565
 struct A {  }
 
 fn main() {  }
diff --git a/src/test/ui/error-codes/E0565.stderr b/src/test/ui/error-codes/E0565.stderr
index 6ed90c0..aa09515 100644
--- a/src/test/ui/error-codes/E0565.stderr
+++ b/src/test/ui/error-codes/E0565.stderr
@@ -4,6 +4,12 @@
 LL | #[repr("C")]
    |        ^^^
 
-error: aborting due to previous error
+error[E0565]: meta item in `repr` must be an identifier
+  --> $DIR/E0565.rs:2:8
+   |
+LL | #[repr("C")]
+   |        ^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/error-codes/E0586.stderr b/src/test/ui/error-codes/E0586.stderr
index d1e7e3f..0bbf9a6 100644
--- a/src/test/ui/error-codes/E0586.stderr
+++ b/src/test/ui/error-codes/E0586.stderr
@@ -1,10 +1,10 @@
 error[E0586]: inclusive range with no end
-  --> $DIR/E0586.rs:3:22
+  --> $DIR/E0586.rs:3:19
    |
 LL |     let x = &tmp[1..=];
-   |                      ^
+   |                   ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr
index 89bfccf..a78a003 100644
--- a/src/test/ui/error-codes/E0599.stderr
+++ b/src/test/ui/error-codes/E0599.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `NotEvenReal` found for type `Foo` in the current scope
+error[E0599]: no associated item named `NotEvenReal` found for struct `Foo` in the current scope
   --> $DIR/E0599.rs:4:20
    |
 LL | struct Foo;
diff --git a/src/test/ui/error-codes/E0602.stderr b/src/test/ui/error-codes/E0602.stderr
index 8636004..70137cb 100644
--- a/src/test/ui/error-codes/E0602.stderr
+++ b/src/test/ui/error-codes/E0602.stderr
@@ -2,6 +2,14 @@
    |
    = note: requested on the command line with `-D bogus`
 
-error: aborting due to previous error
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 73571a3..6b80d99 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -20,7 +20,7 @@
    |
    = note: an implementation of `std::ops::AddAssign` might be missing for `&str`
 
-error[E0599]: no method named `z` found for type `&str` in the current scope
+error[E0599]: no method named `z` found for reference `&str` in the current scope
   --> $DIR/error-festival.rs:16:7
    |
 LL |     x.z();
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
deleted file mode 100644
index d97b693..0000000
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(exclusive_range_pattern)]
-
-fn main() {
-    match [5..4, 99..105, 43..44] {
-        [_, 99.., _] => {},
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR mismatched types
-        _ => {},
-    }
-}
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
deleted file mode 100644
index 76ae724..0000000
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: `X..` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
-   |
-LL |         [_, 99.., _] => {},
-   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
-
-error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
-   |
-LL |     match [5..4, 99..105, 43..44] {
-   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
-LL |         [_, 99.., _] => {},
-   |             ^^ expected struct `std::ops::Range`, found integer
-   |
-   = note: expected struct `std::ops::Range<{integer}>`
-                found type `{integer}`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
deleted file mode 100644
index 09f459c..0000000
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(exclusive_range_pattern)]
-
-fn main() {
-    match [5..4, 99..105, 43..44] {
-        [_, 99..] => {},
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR pattern requires 2 elements but array has 3
-        //~| ERROR mismatched types
-        _ => {},
-    }
-}
diff --git a/src/test/ui/extern/extern-types-distinct-types.stderr b/src/test/ui/extern/extern-types-distinct-types.stderr
index 2e258d6..32b45ee 100644
--- a/src/test/ui/extern/extern-types-distinct-types.stderr
+++ b/src/test/ui/extern/extern-types-distinct-types.stderr
@@ -1,6 +1,11 @@
 error[E0308]: mismatched types
   --> $DIR/extern-types-distinct-types.rs:9:5
    |
+LL |     type A;
+   |     ------- the found foreign type
+LL |     type B;
+   |     ------- the expected foreign type
+...
 LL |     r
    |     ^ expected extern type `B`, found extern type `A`
    |
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index 0d804f0..92c5c20 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -12,7 +12,7 @@
 // the change when it happens.
 //
 // At the time of authoring, the attributes here are listed in the
-// order that they occur in libsyntax/feature_gate.rs.
+// order that they occur in `librustc_feature`.
 //
 // Any builtin attributes that:
 //
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
index 5f276f6..3276309 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
@@ -3,14 +3,17 @@
 mod derive {
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
+    //~| ERROR cannot find derive macro `x3300` in this scope
     union U { f: i32 }
 
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
+    //~| ERROR cannot find derive macro `x3300` in this scope
     enum E { }
 
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
+    //~| ERROR cannot find derive macro `x3300` in this scope
     struct S;
 }
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
index f14591c..ab16591 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
@@ -1,11 +1,23 @@
 error: cannot find derive macro `x3300` in this scope
-  --> $DIR/issue-43106-gating-of-derive-2.rs:12:14
+  --> $DIR/issue-43106-gating-of-derive-2.rs:14:14
    |
 LL |     #[derive(x3300)]
    |              ^^^^^
 
 error: cannot find derive macro `x3300` in this scope
-  --> $DIR/issue-43106-gating-of-derive-2.rs:8:14
+  --> $DIR/issue-43106-gating-of-derive-2.rs:14:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:9:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:9:14
    |
 LL |     #[derive(x3300)]
    |              ^^^^^
@@ -16,5 +28,11 @@
 LL |     #[derive(x3300)]
    |              ^^^^^
 
-error: aborting due to 3 previous errors
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:4:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
index 60873f9..a01d855 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
@@ -18,6 +18,7 @@
 
     #[rustc_deprecated()] struct S;
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR stability attributes may not be used outside of the standard library
 
     #[rustc_deprecated()] type T = S;
     //~^ ERROR stability attributes may not be used outside of the standard library
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
index 8c6c26f..3c4dcfe 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
@@ -29,17 +29,23 @@
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:22:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:19:5
+   |
+LL |     #[rustc_deprecated()] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0734]: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:23:5
    |
 LL |     #[rustc_deprecated()] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:25:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:26:5
    |
 LL |     #[rustc_deprecated()] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
index e3ac274..73ff965 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
@@ -18,6 +18,7 @@
 
     #[stable()] struct S;
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR stability attributes may not be used outside of the standard library
 
     #[stable()] type T = S;
     //~^ ERROR stability attributes may not be used outside of the standard library
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
index 09dabd2..2573db1 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
@@ -29,17 +29,23 @@
    |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:22:5
+  --> $DIR/issue-43106-gating-of-stable.rs:19:5
+   |
+LL |     #[stable()] struct S;
+   |     ^^^^^^^^^^^
+
+error[E0734]: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:23:5
    |
 LL |     #[stable()] type T = S;
    |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:25:5
+  --> $DIR/issue-43106-gating-of-stable.rs:26:5
    |
 LL |     #[stable()] impl S { }
    |     ^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
index 8d519c3..d8339b0 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
@@ -18,6 +18,7 @@
 
     #[unstable()] struct S;
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR stability attributes may not be used outside of the standard library
 
     #[unstable()] type T = S;
     //~^ ERROR stability attributes may not be used outside of the standard library
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
index 49da2c5..500675e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
@@ -29,17 +29,23 @@
    |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:22:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:19:5
+   |
+LL |     #[unstable()] struct S;
+   |     ^^^^^^^^^^^^^
+
+error[E0734]: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:23:5
    |
 LL |     #[unstable()] type T = S;
    |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:25:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:26:5
    |
 LL |     #[unstable()] impl S { }
    |     ^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.rs b/src/test/ui/feature-gates/feature-gate-external_doc.rs
index 9d68d3e..4e6e293 100644
--- a/src/test/ui/feature-gates/feature-gate-external_doc.rs
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.rs
@@ -1,2 +1,3 @@
 #[doc(include="asdf.md")] //~ ERROR: `#[doc(include)]` is experimental
+                          //~| ERROR: `#[doc(include)]` is experimental
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
index 683c0ad..0534018 100644
--- a/src/test/ui/feature-gates/feature-gate-external_doc.stderr
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
@@ -7,6 +7,15 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/44732
    = help: add `#![feature(external_doc)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: `#[doc(include)]` is experimental
+  --> $DIR/feature-gate-external_doc.rs:1:1
+   |
+LL | #[doc(include="asdf.md")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44732
+   = help: add `#![feature(external_doc)]` 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/feature-gates/feature-gate-lint-reasons.rs b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
index 1a7b9c9..b124e9b 100644
--- a/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
+++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
@@ -1,4 +1,6 @@
 #![warn(nonstandard_style, reason = "the standard should be respected")]
 //~^ ERROR lint reasons are experimental
+//~| ERROR lint reasons are experimental
+//~| ERROR lint reasons are experimental
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
index 390a1bf..08ba9d0 100644
--- a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
+++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
@@ -7,6 +7,24 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/54503
    = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: lint reasons are experimental
+  --> $DIR/feature-gate-lint-reasons.rs:1:28
+   |
+LL | #![warn(nonstandard_style, reason = "the standard should be respected")]
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54503
+   = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
+
+error[E0658]: lint reasons are experimental
+  --> $DIR/feature-gate-lint-reasons.rs:1:28
+   |
+LL | #![warn(nonstandard_style, reason = "the standard should be respected")]
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54503
+   = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.rs b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
index 9d28f43..1e4a404f 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.rs
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
@@ -1,7 +1,7 @@
 #[repr(simd)] //~ error: SIMD types are experimental
 struct Foo(u64, u64);
 
-#[repr(C)] //~ warn: conflicting representation hints
+#[repr(C)] //~ ERROR conflicting representation hints
 #[repr(simd)] //~ error: SIMD types are experimental
 struct Bar(u64, u64);
 
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
index 02c8400..37a7bd0 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
@@ -16,7 +16,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add `#![feature(repr_simd)]` to the crate attributes to enable
 
-warning[E0566]: conflicting representation hints
+error[E0566]: conflicting representation hints
   --> $DIR/feature-gate-repr-simd.rs:4:8
    |
 LL | #[repr(C)]
@@ -24,7 +24,7 @@
 LL | #[repr(simd)]
    |        ^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0566, E0658.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
deleted file mode 100644
index 3b972c1..0000000
--- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
deleted file mode 100644
index b13ec21..0000000
--- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
-  --> $DIR/feature-gate-sanitizer-runtime.rs:1:1
-   |
-LL | #![sanitizer_runtime]
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(sanitizer_runtime)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/generator/auto-trait-regions.nll.stderr b/src/test/ui/generator/auto-trait-regions.nll.stderr
index 4c157a0..bf87aea 100644
--- a/src/test/ui/generator/auto-trait-regions.nll.stderr
+++ b/src/test/ui/generator/auto-trait-regions.nll.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/auto-trait-regions.rs:44:24
+  --> $DIR/auto-trait-regions.rs:45:24
    |
 LL |         let a = A(&mut true, &mut true, No);
    |                        ^^^^                - temporary value is freed at the end of this statement
@@ -12,7 +12,7 @@
    = note: consider using a `let` binding to create a longer lived value
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/auto-trait-regions.rs:44:35
+  --> $DIR/auto-trait-regions.rs:45:35
    |
 LL |         let a = A(&mut true, &mut true, No);
    |                                   ^^^^     - temporary value is freed at the end of this statement
@@ -31,7 +31,7 @@
    |     ^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/auto-trait-regions.rs:48:5
+  --> $DIR/auto-trait-regions.rs:49:5
    |
 LL |     assert_foo(gen);
    |     ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs
index 46d7289..dbd8965 100644
--- a/src/test/ui/generator/auto-trait-regions.rs
+++ b/src/test/ui/generator/auto-trait-regions.rs
@@ -29,6 +29,7 @@
     };
     assert_foo(gen);
     //~^ ERROR implementation of `Foo` is not general enough
+    //~| ERROR implementation of `Foo` is not general enough
 
     // Allow impls which matches any lifetime
     let x = &OnlyFooIfRef(No);
@@ -47,4 +48,5 @@
     };
     assert_foo(gen);
     //~^ ERROR not general enough
+    //~| ERROR not general enough
 }
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
index dab4d34..29a3907 100644
--- a/src/test/ui/generator/auto-trait-regions.stderr
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -11,7 +11,19 @@
    = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
-  --> $DIR/auto-trait-regions.rs:48:5
+  --> $DIR/auto-trait-regions.rs:30:5
+   |
+LL | auto trait Foo {}
+   | ----------------- trait `Foo` defined here
+...
+LL |     assert_foo(gen);
+   |     ^^^^^^^^^^ implementation of `Foo` is not general enough
+   |
+   = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`...
+   = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:49:5
    |
 LL | auto trait Foo {}
    | ----------------- trait `Foo` defined here
@@ -22,5 +34,17 @@
    = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
    = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
 
-error: aborting due to 2 previous errors
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:49:5
+   |
+LL | auto trait Foo {}
+   | ----------------- trait `Foo` defined here
+...
+LL |     assert_foo(gen);
+   |     ^^^^^^^^^^ implementation of `Foo` is not general enough
+   |
+   = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
+   = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
new file mode 100644
index 0000000..3f4c178
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
@@ -0,0 +1,10 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match [5..4, 99..105, 43..44] {
+        [_, 99.., _] => {},
+        //~^ ERROR mismatched types
+        _ => {},
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
new file mode 100644
index 0000000..a6f8563
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13
+   |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
+LL |         [_, 99.., _] => {},
+   |             ^^ expected struct `std::ops::Range`, found integer
+   |
+   = note: expected struct `std::ops::Range<{integer}>`
+                found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
new file mode 100644
index 0000000..dedc854
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
@@ -0,0 +1,11 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match [5..4, 99..105, 43..44] {
+        [_, 99..] => {},
+        //~^ ERROR pattern requires 2 elements but array has 3
+        //~| ERROR mismatched types
+        _ => {},
+    }
+}
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
similarity index 62%
rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
index 5c96f80..4e0102c 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
@@ -1,17 +1,11 @@
-error: `X..` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
-   |
-LL |         [_, 99..] => {},
-   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
-
 error[E0527]: pattern requires 2 elements but array has 3
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:9
    |
 LL |         [_, 99..] => {},
    |         ^^^^^^^^^ expected 3 elements
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -21,7 +15,7 @@
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0308, E0527.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
similarity index 69%
rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
index 1557f59..6a9b562 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
@@ -1,10 +1,10 @@
+#![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 
 fn main() {
     match [5..4, 99..105, 43..44] {
         [..9, 99..100, _] => {},
-        //~^ ERROR `..X` range patterns are not supported
-        //~| ERROR mismatched types
+        //~^ ERROR mismatched types
         //~| ERROR mismatched types
         //~| ERROR mismatched types
         _ => {},
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
similarity index 75%
rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index 17e1032..665eef2 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -1,11 +1,5 @@
-error: `..X` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
-   |
-LL |         [..9, 99..100, _] => {},
-   |          ^^^ help: try using the minimum value for the type: `MIN..9`
-
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:12
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -16,7 +10,7 @@
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:15
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -29,7 +23,7 @@
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:19
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -41,6 +35,6 @@
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
new file mode 100644
index 0000000..1733012
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
@@ -0,0 +1,22 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn foo() {
+    if let ..=5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let ...5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR range-to patterns with `...` are not allowed
+    if let ..5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let 5.. = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let 5..= = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR inclusive range with no end
+    if let 5... = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR inclusive range with no end
+}
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
new file mode 100644
index 0000000..99db339
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
@@ -0,0 +1,80 @@
+error: range-to patterns with `...` are not allowed
+  --> $DIR/feature-gate-half-open-range-patterns.rs:9:12
+   |
+LL |     if let ...5 = 0 {}
+   |            ^^^ help: use `..=` instead
+
+error[E0586]: inclusive range with no end
+  --> $DIR/feature-gate-half-open-range-patterns.rs:16:13
+   |
+LL |     if let 5..= = 0 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/feature-gate-half-open-range-patterns.rs:19:13
+   |
+LL |     if let 5... = 0 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:7:12
+   |
+LL |     if let ..=5 = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:9:12
+   |
+LL |     if let ...5 = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:12:12
+   |
+LL |     if let ..5 = 0 {}
+   |            ^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:14:12
+   |
+LL |     if let 5.. = 0 {}
+   |            ^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:16:12
+   |
+LL |     if let 5..= = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:19:12
+   |
+LL |     if let 5... = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0586, E0658.
+For more information about an error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
new file mode 100644
index 0000000..7cddf5f
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
@@ -0,0 +1,8 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let "a".. = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+    let .."a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+    let ..="a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
new file mode 100644
index 0000000..68ca363
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
@@ -0,0 +1,21 @@
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:5:9
+   |
+LL |     let "a".. = "a";
+   |         ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:6:11
+   |
+LL |     let .."a" = "a";
+   |           ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:7:12
+   |
+LL |     let ..="a" = "a";
+   |            ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
new file mode 100644
index 0000000..b135891
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
@@ -0,0 +1,168 @@
+// Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+fn main() {}
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn floats() {
+    m!(0f32, core::f32::NEG_INFINITY..); //~ ERROR non-exhaustive patterns: `_` not covered
+    m!(0f32, ..core::f32::INFINITY); //~ ERROR non-exhaustive patterns: `_` not covered
+}
+
+fn khar() {
+    const ALMOST_MAX: char = '\u{10fffe}';
+    const ALMOST_MIN: char = '\u{1}';
+    const VAL: char = 'a';
+    const VAL_1: char = 'b';
+    const VAL_2: char = 'c';
+    m!('a', ..core::char::MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+    m!('a', ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+    m!('a', ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+}
+
+mod unsigned {
+    fn u8() {
+        const ALMOST_MAX: u8 = core::u8::MAX - 1;
+        const ALMOST_MIN: u8 = core::u8::MIN + 1;
+        const VAL: u8 = 42;
+        const VAL_1: u8 = VAL + 1;
+        const VAL_2: u8 = VAL + 2;
+        m!(0, ..core::u8::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u16() {
+        const ALMOST_MAX: u16 = core::u16::MAX - 1;
+        const ALMOST_MIN: u16 = core::u16::MIN + 1;
+        const VAL: u16 = 42;
+        const VAL_1: u16 = VAL + 1;
+        const VAL_2: u16 = VAL + 2;
+        m!(0, ..core::u16::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u32() {
+        const ALMOST_MAX: u32 = core::u32::MAX - 1;
+        const ALMOST_MIN: u32 = core::u32::MIN + 1;
+        const VAL: u32 = 42;
+        const VAL_1: u32 = VAL + 1;
+        const VAL_2: u32 = VAL + 2;
+        m!(0, ..core::u32::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u64() {
+        const ALMOST_MAX: u64 = core::u64::MAX - 1;
+        const ALMOST_MIN: u64 = core::u64::MIN + 1;
+        const VAL: u64 = 42;
+        const VAL_1: u64 = VAL + 1;
+        const VAL_2: u64 = VAL + 2;
+        m!(0, ..core::u64::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u128() {
+        const ALMOST_MAX: u128 = core::u128::MAX - 1;
+        const ALMOST_MIN: u128 = core::u128::MIN + 1;
+        const VAL: u128 = 42;
+        const VAL_1: u128 = VAL + 1;
+        const VAL_2: u128 = VAL + 2;
+        m!(0, ..core::u128::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+}
+
+mod signed {
+    fn i8() {
+        const ALMOST_MAX: i8 = core::i8::MAX - 1;
+        const ALMOST_MIN: i8 = core::i8::MIN + 1;
+        const VAL: i8 = 42;
+        const VAL_1: i8 = VAL + 1;
+        const VAL_2: i8 = VAL + 2;
+        m!(0, ..core::i8::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i16() {
+        const ALMOST_MAX: i16 = core::i16::MAX - 1;
+        const ALMOST_MIN: i16 = core::i16::MIN + 1;
+        const VAL: i16 = 42;
+        const VAL_1: i16 = VAL + 1;
+        const VAL_2: i16 = VAL + 2;
+        m!(0, ..core::i16::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i32() {
+        const ALMOST_MAX: i32 = core::i32::MAX - 1;
+        const ALMOST_MIN: i32 = core::i32::MIN + 1;
+        const VAL: i32 = 42;
+        const VAL_1: i32 = VAL + 1;
+        const VAL_2: i32 = VAL + 2;
+        m!(0, ..core::i32::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i64() {
+        const ALMOST_MAX: i64 = core::i64::MAX - 1;
+        const ALMOST_MIN: i64 = core::i64::MIN + 1;
+        const VAL: i64 = 42;
+        const VAL_1: i64 = VAL + 1;
+        const VAL_2: i64 = VAL + 2;
+        m!(0, ..core::i64::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i128() {
+        const ALMOST_MAX: i128 = core::i128::MAX - 1;
+        const ALMOST_MIN: i128 = core::i128::MIN + 1;
+        const VAL: i128 = 42;
+        const VAL_1: i128 = VAL + 1;
+        const VAL_2: i128 = VAL + 2;
+        m!(0, ..core::i128::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
new file mode 100644
index 0000000..26d0cf9
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -0,0 +1,547 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8
+   |
+LL |     m!(0f32, core::f32::NEG_INFINITY..);
+   |        ^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:17:8
+   |
+LL |     m!(0f32, ..core::f32::INFINITY);
+   |        ^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
+   |
+LL |     m!('a', ..core::char::MAX);
+   |        ^^^ pattern `'\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
+   |
+LL |     m!('a', ..ALMOST_MAX);
+   |        ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
+   |
+LL |     m!('a', ALMOST_MIN..);
+   |        ^^^ pattern `'\u{0}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
+   |
+LL |     m!('a', ..=ALMOST_MAX);
+   |        ^^^ pattern `'\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'b'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
+   |
+LL |     m!('a', ..=VAL | VAL_2..);
+   |        ^^^ pattern `'b'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'b'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:31:8
+   |
+LL |     m!('a', ..VAL_1 | VAL_2..);
+   |        ^^^ pattern `'b'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
+   |
+LL |         m!(0, ..core::u8::MAX);
+   |            ^ pattern `std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `254u8..=std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `254u8..=std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:46:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
+   |
+LL |         m!(0, ..core::u16::MAX);
+   |            ^ pattern `std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `65534u16..=std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `65534u16..=std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:59:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
+   |
+LL |         m!(0, ..core::u32::MAX);
+   |            ^ pattern `std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `4294967294u32..=std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `4294967294u32..=std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:72:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
+   |
+LL |         m!(0, ..core::u64::MAX);
+   |            ^ pattern `std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `18446744073709551614u64..=std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `18446744073709551614u64..=std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:85:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
+   |
+LL |         m!(0, ..core::u128::MAX);
+   |            ^ pattern `std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:98:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
+   |
+LL |         m!(0, ..core::i8::MAX);
+   |            ^ pattern `std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `126i8..=std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `126i8..=std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i8::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:114:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
+   |
+LL |         m!(0, ..core::i16::MAX);
+   |            ^ pattern `std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `32766i16..=std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `32766i16..=std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i16::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:127:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
+   |
+LL |         m!(0, ..core::i32::MAX);
+   |            ^ pattern `std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `2147483646i32..=std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `2147483646i32..=std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i32::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:140:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
+   |
+LL |         m!(0, ..core::i64::MAX);
+   |            ^ pattern `std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `9223372036854775806i64..=std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `9223372036854775806i64..=std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i64::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:153:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
+   |
+LL |         m!(0, ..core::i128::MAX);
+   |            ^ pattern `std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i128::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:166:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 68 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
new file mode 100644
index 0000000..efac0df
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
@@ -0,0 +1,49 @@
+// check-pass
+
+// Test various exhaustive matches for `X..`, `..=X` and `..X` ranges.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {}
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+macro_rules! test_int {
+    ($s:expr, $min:path, $max:path) => {
+        m!($s, $min..);
+        m!($s, $min..5 | 5..);
+        m!($s, ..5 | 5..);
+        m!($s, ..=4 | 5..);
+        m!($s, ..=$max);
+        m!($s, ..$max | $max);
+        m!(($s, true), (..5, true) | (5.., true) | ($min.., false));
+    }
+}
+
+fn unsigned_int() {
+    test_int!(0u8, core::u8::MIN, core::u8::MAX);
+    test_int!(0u16, core::u16::MIN, core::u16::MAX);
+    test_int!(0u32, core::u32::MIN, core::u32::MAX);
+    test_int!(0u64, core::u64::MIN, core::u64::MAX);
+    test_int!(0u128, core::u128::MIN, core::u128::MAX);
+}
+
+fn signed_int() {
+    test_int!(0i8, core::i8::MIN, core::i8::MAX);
+    test_int!(0i16, core::i16::MIN, core::i16::MAX);
+    test_int!(0i32, core::i32::MIN, core::i32::MAX);
+    test_int!(0i64, core::i64::MIN, core::i64::MAX);
+    test_int!(0i128, core::i128::MIN, core::i128::MAX);
+}
+
+fn khar() {
+    m!('a', ..=core::char::MAX);
+    m!('a', '\u{0}'..);
+    m!('a', ..='\u{D7FF}' | '\u{E000}'..);
+    m!('a', ..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..);
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs
new file mode 100644
index 0000000..904efda
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs
@@ -0,0 +1,54 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn main() {
+    m!(0, ..core::u8::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u16::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u32::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u64::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u128::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!(0, ..core::i8::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i16::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i32::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i64::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i128::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!(0f32, ..core::f32::NEG_INFINITY);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0f64, ..core::f64::NEG_INFINITY);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!('a', ..'\u{0}');
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr
new file mode 100644
index 0000000..b536e1b
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr
@@ -0,0 +1,159 @@
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+   |
+LL |     m!(0, ..core::u8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+   |
+LL |     m!(0, ..core::u16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+   |
+LL |     m!(0, ..core::u32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+   |
+LL |     m!(0, ..core::u64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+   |
+LL |     m!(0, ..core::u128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+   |
+LL |     m!(0, ..core::i8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+   |
+LL |     m!(0, ..core::i16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+   |
+LL |     m!(0, ..core::i32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+   |
+LL |     m!(0, ..core::i64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+   |
+LL |     m!(0, ..core::i128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+   |
+LL |     m!(0f32, ..core::f32::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+   |
+LL |     m!(0f64, ..core::f64::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+   |
+LL |     m!('a', ..'\u{0}');
+   |             ^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+   |
+LL |     m!(0, ..core::u8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+   |
+LL |     m!(0, ..core::u16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+   |
+LL |     m!(0, ..core::u32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+   |
+LL |     m!(0, ..core::u64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+   |
+LL |     m!(0, ..core::u128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+   |
+LL |     m!(0, ..core::i8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+   |
+LL |     m!(0, ..core::i16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+   |
+LL |     m!(0, ..core::i32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+   |
+LL |     m!(0, ..core::i64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+   |
+LL |     m!(0, ..core::i128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+   |
+LL |     m!(0f32, ..core::f32::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+   |
+LL |     m!(0f64, ..core::f64::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+   |
+LL |     m!('a', ..'\u{0}');
+   |             ^^^^^^^^^
+
+error: aborting due to 26 previous errors
+
+For more information about this error, try `rustc --explain E0579`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
new file mode 100644
index 0000000..daed775
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
@@ -0,0 +1,32 @@
+// Test that `...X` range-to patterns are syntactically invalid.
+//
+// See https://github.com/rust-lang/rust/pull/67258#issuecomment-565656155
+// for the reason why. To summarize, we might want to introduce `...expr` as
+// an expression form for splatting (or "untupling") in an expression context.
+// While there is no syntactic ambiguity with `...X` in a pattern context,
+// there's a potential confusion factor here, and we would prefer to keep patterns
+// and expressions in-sync. As such, we do not allow `...X` in patterns either.
+
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match scrutinee {
+        ...X => {} //~ ERROR range-to patterns with `...` are not allowed
+        ...0 => {} //~ ERROR range-to patterns with `...` are not allowed
+        ...'a' => {} //~ ERROR range-to patterns with `...` are not allowed
+        ...0.0f32 => {} //~ ERROR range-to patterns with `...` are not allowed
+    }
+}
+
+fn syntax2() {
+    macro_rules! mac {
+        ($e:expr) => {
+            let ...$e; //~ ERROR range-to patterns with `...` are not allowed
+        }
+    }
+
+    mac!(0);
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
new file mode 100644
index 0000000..ba2e7ea
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
@@ -0,0 +1,35 @@
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:17:9
+   |
+LL |         ...X => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:18:9
+   |
+LL |         ...0 => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:19:9
+   |
+LL |         ...'a' => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:20:9
+   |
+LL |         ...0.0f32 => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:27:17
+   |
+LL |             let ...$e;
+   |                 ^^^ help: use `..=` instead
+...
+LL |     mac!(0);
+   |     -------- in this macro invocation
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
new file mode 100644
index 0000000..9ace0c3
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
@@ -0,0 +1,26 @@
+// Test `X...` and `X..=` range patterns not being allowed syntactically.
+// FIXME(Centril): perhaps these should be semantic restrictions.
+
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn foo() {
+    if let 0... = 1 {} //~ ERROR inclusive range with no end
+    if let 0..= = 1 {} //~ ERROR inclusive range with no end
+    const X: u8 = 0;
+    if let X... = 1 {} //~ ERROR inclusive range with no end
+    if let X..= = 1 {} //~ ERROR inclusive range with no end
+}
+
+fn bar() {
+    macro_rules! mac {
+        ($e:expr) => {
+            let $e...; //~ ERROR inclusive range with no end
+            let $e..=; //~ ERROR inclusive range with no end
+        }
+    }
+
+    mac!(0);
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
new file mode 100644
index 0000000..2bdb8ea
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
@@ -0,0 +1,57 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:10:13
+   |
+LL |     if let 0... = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13
+   |
+LL |     if let 0..= = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:13:13
+   |
+LL |     if let X... = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:14:13
+   |
+LL |     if let X..= = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19
+   |
+LL |             let $e...;
+   |                   ^^^ help: use `..` instead
+...
+LL |     mac!(0);
+   |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:21:19
+   |
+LL |             let $e..=;
+   |                   ^^^ help: use `..` instead
+...
+LL |     mac!(0);
+   |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
new file mode 100644
index 0000000..f054bbe
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
@@ -0,0 +1,26 @@
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match &0 {
+        &0.. | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &0..= | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        //~| ERROR inclusive range with no end
+        &0... | _ => {}
+        //~^ ERROR inclusive range with no end
+    }
+
+    match &0 {
+        &..0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &..=0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &...0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        //~| ERROR range-to patterns with `...` are not allowed
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
new file mode 100644
index 0000000..a5f7c39
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
@@ -0,0 +1,55 @@
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10
+   |
+LL |         &0.. | _ => {}
+   |          ^^^ help: add parentheses to clarify the precedence: `(0 ..)`
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11
+   |
+LL |         &0..= | _ => {}
+   |           ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:10
+   |
+LL |         &0..= | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(0 ..=)`
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11
+   |
+LL |         &0... | _ => {}
+   |           ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10
+   |
+LL |         &..0 | _ => {}
+   |          ^^^ help: add parentheses to clarify the precedence: `(..0)`
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10
+   |
+LL |         &..=0 | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(..=0)`
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
+   |
+LL |         &...0 | _ => {}
+   |          ^^^ help: use `..=` instead
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
+   |
+LL |         &...0 | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(..=0)`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
new file mode 100644
index 0000000..416c59a
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
@@ -0,0 +1,160 @@
+// run-pass
+
+// Test half-open range patterns against their expression equivalents
+// via `.contains(...)` and make sure the dynamic semantics match.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+#![allow(unreachable_patterns)]
+
+macro_rules! yes {
+    ($scrutinee:expr, $($t:tt)+) => {
+        {
+            let m = match $scrutinee { $($t)+ => true, _ => false, };
+            let c = ($($t)+).contains(&$scrutinee);
+            assert_eq!(m, c);
+            m
+        }
+    }
+}
+
+fn range_to_inclusive() {
+    // `..=X` (`RangeToInclusive`-equivalent):
+    //---------------------------------------
+
+    // u8; `..=X`
+    assert!(yes!(core::u8::MIN, ..=core::u8::MIN));
+    assert!(yes!(core::u8::MIN, ..=5));
+    assert!(yes!(5u8, ..=5));
+    assert!(!yes!(6u8, ..=5));
+
+    // i16; `..=X`
+    assert!(yes!(core::i16::MIN, ..=core::i16::MIN));
+    assert!(yes!(core::i16::MIN, ..=0));
+    assert!(yes!(core::i16::MIN, ..=-5));
+    assert!(yes!(-5, ..=-5));
+    assert!(!yes!(-4, ..=-5));
+
+    // char; `..=X`
+    assert!(yes!('\u{0}', ..='\u{0}'));
+    assert!(yes!('\u{0}', ..='a'));
+    assert!(yes!('a', ..='a'));
+    assert!(!yes!('b', ..='a'));
+
+    // f32; `..=X`
+    assert!(yes!(core::f32::NEG_INFINITY, ..=core::f32::NEG_INFINITY));
+    assert!(yes!(core::f32::NEG_INFINITY, ..=1.0f32));
+    assert!(yes!(1.5f32, ..=1.5f32));
+    assert!(!yes!(1.6f32, ..=-1.5f32));
+
+    // f64; `..=X`
+    assert!(yes!(core::f64::NEG_INFINITY, ..=core::f64::NEG_INFINITY));
+    assert!(yes!(core::f64::NEG_INFINITY, ..=1.0f64));
+    assert!(yes!(1.5f64, ..=1.5f64));
+    assert!(!yes!(1.6f64, ..=-1.5f64));
+}
+
+fn range_to() {
+    // `..X` (`RangeTo`-equivalent):
+    //-----------------------------
+
+    // u8; `..X`
+    assert!(yes!(0u8, ..1));
+    assert!(yes!(0u8, ..5));
+    assert!(!yes!(5u8, ..5));
+    assert!(!yes!(6u8, ..5));
+
+    // u8; `..X`
+    const NU8: u8 = core::u8::MIN + 1;
+    assert!(yes!(core::u8::MIN, ..NU8));
+    assert!(yes!(0u8, ..5));
+    assert!(!yes!(5u8, ..5));
+    assert!(!yes!(6u8, ..5));
+
+    // i16; `..X`
+    const NI16: i16 = core::i16::MIN + 1;
+    assert!(yes!(core::i16::MIN, ..NI16));
+    assert!(yes!(core::i16::MIN, ..5));
+    assert!(yes!(-6, ..-5));
+    assert!(!yes!(-5, ..-5));
+
+    // char; `..X`
+    assert!(yes!('\u{0}', ..'\u{1}'));
+    assert!(yes!('\u{0}', ..'a'));
+    assert!(yes!('a', ..'b'));
+    assert!(!yes!('a', ..'a'));
+    assert!(!yes!('b', ..'a'));
+
+    // f32; `..X`
+    assert!(yes!(core::f32::NEG_INFINITY, ..1.0f32));
+    assert!(!yes!(1.5f32, ..1.5f32));
+    const E32: f32 = 1.5f32 + core::f32::EPSILON;
+    assert!(yes!(1.5f32, ..E32));
+    assert!(!yes!(1.6f32, ..1.5f32));
+
+    // f64; `..X`
+    assert!(yes!(core::f64::NEG_INFINITY, ..1.0f64));
+    assert!(!yes!(1.5f64, ..1.5f64));
+    const E64: f64 = 1.5f64 + core::f64::EPSILON;
+    assert!(yes!(1.5f64, ..E64));
+    assert!(!yes!(1.6f64, ..1.5f64));
+}
+
+fn range_from() {
+    // `X..` (`RangeFrom`-equivalent):
+    //--------------------------------
+
+    // u8; `X..`
+    assert!(yes!(core::u8::MIN, core::u8::MIN..));
+    assert!(yes!(core::u8::MAX, core::u8::MIN..));
+    assert!(!yes!(core::u8::MIN, 1..));
+    assert!(!yes!(4, 5..));
+    assert!(yes!(5, 5..));
+    assert!(yes!(6, 5..));
+    assert!(yes!(core::u8::MAX, core::u8::MAX..));
+
+    // i16; `X..`
+    assert!(yes!(core::i16::MIN, core::i16::MIN..));
+    assert!(yes!(core::i16::MAX, core::i16::MIN..));
+    const NI16: i16 = core::i16::MIN + 1;
+    assert!(!yes!(core::i16::MIN, NI16..));
+    assert!(!yes!(-4, 5..));
+    assert!(yes!(-4, -4..));
+    assert!(yes!(-3, -4..));
+    assert!(yes!(core::i16::MAX, core::i16::MAX..));
+
+    // char; `X..`
+    assert!(yes!('\u{0}', '\u{0}'..));
+    assert!(yes!(core::char::MAX, '\u{0}'..));
+    assert!(yes!('a', 'a'..));
+    assert!(yes!('b', 'a'..));
+    assert!(!yes!('a', 'b'..));
+    assert!(yes!(core::char::MAX, core::char::MAX..));
+
+    // f32; `X..`
+    assert!(yes!(core::f32::NEG_INFINITY, core::f32::NEG_INFINITY..));
+    assert!(yes!(core::f32::INFINITY, core::f32::NEG_INFINITY..));
+    assert!(!yes!(core::f32::NEG_INFINITY, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, 1.0f32..));
+    assert!(!yes!(1.0f32 - core::f32::EPSILON, 1.0f32..));
+    assert!(yes!(1.0f32, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, core::f32::INFINITY..));
+
+    // f64; `X..`
+    assert!(yes!(core::f64::NEG_INFINITY, core::f64::NEG_INFINITY..));
+    assert!(yes!(core::f64::INFINITY, core::f64::NEG_INFINITY..));
+    assert!(!yes!(core::f64::NEG_INFINITY, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, 1.0f64..));
+    assert!(!yes!(1.0f64 - core::f64::EPSILON, 1.0f64..));
+    assert!(yes!(1.0f64, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, core::f64::INFINITY..));
+}
+
+fn main() {
+    range_to_inclusive();
+    range_to();
+    range_from();
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
new file mode 100644
index 0000000..8bb98d3
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+// Test the parsing of half-open ranges.
+
+#![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match scrutinee {
+        X.. | 0.. | 'a'.. | 0.0f32.. => {}
+        ..=X | ..X => {}
+        ..=0 | ..0 => {}
+        ..='a' | ..'a' => {}
+        ..=0.0f32 | ..0.0f32 => {}
+    }
+}
+
+fn syntax2() {
+    macro_rules! mac {
+        ($e:expr) => {
+            match 0u8 { ..$e => {}, _ => {} }
+            match 0u8 { ..=$e => {}, _ => {} }
+            match 0u8 { $e.. => {}, _ => {} }
+        }
+    }
+    mac!(42u8);
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-4.rs b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
new file mode 100644
index 0000000..bd79536
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    const PAT: u8 = 1;
+
+    match 0 {
+        (.. PAT) => {}
+        _ => {}
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.rs b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
new file mode 100644
index 0000000..613d907
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
@@ -0,0 +1,10 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    const PAT: u8 = 1;
+
+    match (0, 1) {
+        (PAT ..) => {} //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
new file mode 100644
index 0000000..307ad71
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-5.rs:8:10
+   |
+LL |     match (0, 1) {
+   |           ------ this expression has type `({integer}, {integer})`
+LL |         (PAT ..) => {}
+   |          ^^^ expected tuple, found `u8`
+   |
+   = note: expected tuple `({integer}, {integer})`
+               found type `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
index afa07cc..303c0cc 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
@@ -39,6 +39,7 @@
 ...  |
 LL | |     foo_hrtb_bar_not(&mut t);
    | |     ------------------------ recursive call site
+LL | |
 LL | | }
    | |_^ cannot return without recursing
    |
@@ -62,7 +63,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: function cannot return without recursing
-  --> $DIR/hrtb-perfect-forwarding.rs:49:1
+  --> $DIR/hrtb-perfect-forwarding.rs:50:1
    |
 LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T)
 LL | |     where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
index 63db695..0303a76 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
@@ -44,6 +44,7 @@
     // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where
     // clause only specifies `T : Bar<&'b isize>`.
     foo_hrtb_bar_not(&mut t); //~ ERROR mismatched types
+                              //~| ERROR mismatched types
 }
 
 fn foo_hrtb_bar_hrtb<T>(mut t: T)
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
index 9bc8cd6..1ceb0c9 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -7,6 +7,15 @@
    = note: expected type `Bar<&'a isize>`
               found type `Bar<&'b isize>`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+   |
+LL |     foo_hrtb_bar_not(&mut t);
+   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `Bar<&'a isize>`
+              found type `Bar<&'b isize>`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
index cd1272d..c736c54 100644
--- a/src/test/ui/hrtb/issue-30786.nll.stderr
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -11,10 +11,46 @@
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:116:17
+  --> $DIR/issue-30786.rs:114:18
+   |
+LL |     let filter = map.filter(|x: &_| true);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:114:18
+   |
+LL |     let filter = map.filter(|x: &_| true);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:114:18
+   |
+LL |     let filter = map.filter(|x: &_| true);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
    |
 LL |     let count = filter.count(); // Assert that we still have a valid stream.
    |                 ^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
+   |
+LL |     let count = filter.count(); // Assert that we still have a valid stream.
+   |                 ^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
+   |
+LL |     let count = filter.count(); // Assert that we still have a valid stream.
+   |                 ^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
+   |
+LL |     let count = filter.count(); // Assert that we still have a valid stream.
+   |                 ^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
index 34d6b19f..c656f843 100644
--- a/src/test/ui/hrtb/issue-30786.rs
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -113,7 +113,12 @@
     //[migrate]~| NOTE  implementation of `Stream` is not general enough
     let filter = map.filter(|x: &_| true);
     //[nll]~^ ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
     let count = filter.count(); // Assert that we still have a valid stream.
     //[nll]~^ ERROR higher-ranked subtype error
-
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
 }
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index 736369d..5d75f50 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -15,7 +15,7 @@
 LL |         Vec::new();
    |         ^^^ use of undeclared type or module `Vec`
 
-error[E0599]: no method named `clone` found for type `()` in the current scope
+error[E0599]: no method named `clone` found for unit type `()` in the current scope
   --> $DIR/no_implicit_prelude.rs:12:12
    |
 LL |     fn f() { ::bar::m!(); }
diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs
index a116c5b..15c4acb 100644
--- a/src/test/ui/hygiene/trait_items.rs
+++ b/src/test/ui/hygiene/trait_items.rs
@@ -14,7 +14,7 @@
 }
 
 mod baz {
-    pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
+    pub macro m() { ().f() } //~ ERROR no method named `f` found
     fn f() { ::bar::m!(); }
 }
 
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
index c3ce484..8e36092 100644
--- a/src/test/ui/hygiene/trait_items.stderr
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `()` in the current scope
+error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/trait_items.rs:17:24
    |
 LL |     fn f() { ::baz::m!(); }
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index 1c601bc..a601283 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -12,6 +12,7 @@
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
     //~| ERROR cycle detected
+    //~| ERROR cycle detected
     send(cycle2().clone());
     //~^ ERROR cannot be sent between threads safely
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index d11941f..0ebaac8 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -11,12 +11,12 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:21:16
+  --> $DIR/auto-trait-leak.rs:22:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:21:1
+  --> $DIR/auto-trait-leak.rs:22:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,12 +47,47 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:21:16
+  --> $DIR/auto-trait-leak.rs:22:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:21:1
+  --> $DIR/auto-trait-leak.rs:22:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/auto-trait-leak.rs:1:1
+   |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+...  |
+LL | |     Rc::new(String::from("foo"))
+LL | | }
+   | |_^
+
+error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0`
+  --> $DIR/auto-trait-leak.rs:12:16
+   |
+LL | fn cycle1() -> impl Clone {
+   |                ^^^^^^^^^^
+   |
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+note: ...which requires processing `cycle2::{{opaque}}#0`...
+  --> $DIR/auto-trait-leak.rs:22:16
+   |
+LL | fn cycle2() -> impl Clone {
+   |                ^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:22:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,18 +105,21 @@
    | |_^
 
 error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak.rs:15:5
+  --> $DIR/auto-trait-leak.rs:16:5
    |
 LL | fn send<T: Send>(_: T) {}
    |    ----    ---- required by this bound in `send`
 ...
 LL |     send(cycle2().clone());
    |     ^^^^ `std::rc::Rc<std::string::String>` cannot be sent between threads safely
+...
+LL | fn cycle2() -> impl Clone {
+   |                ---------- within this `impl std::clone::Clone`
    |
    = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
    = note: required because it appears within the type `impl std::clone::Clone`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0391.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr
index d163e1d..a93b3db 100644
--- a/src/test/ui/impl-trait/auto-trait-leak2.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
   --> $DIR/auto-trait-leak2.rs:13:5
    |
+LL | fn before() -> impl Fn(i32) {
+   |                ------------ within this `impl std::ops::Fn<(i32,)>`
+...
 LL | fn send<T: Send>(_: T) {}
    |    ----    ---- required by this bound in `send`
 ...
@@ -19,6 +22,9 @@
 ...
 LL |     send(after());
    |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+...
+LL | fn after() -> impl Fn(i32) {
+   |               ------------ within this `impl std::ops::Fn<(i32,)>`
    |
    = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
    = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr
index 644d26b..1605f34 100644
--- a/src/test/ui/impl-trait/bindings-opaque.stderr
+++ b/src/test/ui/impl-trait/bindings-opaque.stderr
@@ -6,19 +6,19 @@
    |
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:11:17
    |
 LL |     let _ = FOO.count_ones();
    |                 ^^^^^^^^^^ method not found in `impl std::marker::Copy`
 
-error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:13:17
    |
 LL |     let _ = BAR.count_ones();
    |                 ^^^^^^^^^^ method not found in `impl std::marker::Copy`
 
-error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:15:17
    |
 LL |     let _ = foo.count_ones();
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index 312976b..b882514 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:25:18
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          -------- the found opaque type
+...
 LL |     let _: u32 = hide(0_u32);
    |            ---   ^^^^^^^^^^^ expected `u32`, found opaque type
    |            |
@@ -12,6 +15,9 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:31:18
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          -------- the found opaque type
+...
 LL |     let _: i32 = Leak::leak(hide(0_i32));
    |            ---   ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
    |            |
@@ -25,6 +31,12 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:38:10
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          --------
+   |                          |
+   |                          the expected opaque type
+   |                          the found opaque type
+...
 LL |     x = (x.1,
    |          ^^^ expected `u32`, found `i32`
    |
@@ -34,6 +46,12 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:41:10
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          --------
+   |                          |
+   |                          the expected opaque type
+   |                          the found opaque type
+...
 LL |          x.0);
    |          ^^^ expected `i32`, found `u32`
    |
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
index 2bff01b..41f48cb 100644
--- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
@@ -18,5 +18,5 @@
     let f1 = Bar;
 
     f1.foo(1usize);
-    //~^ error: method named `foo` found for type `Bar` in the current scope
+    //~^ error: method named `foo` found for struct `Bar` in the current scope
 }
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
index 441191b..5741797 100644
--- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `Bar` in the current scope
+error[E0599]: no method named `foo` found for struct `Bar` in the current scope
   --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8
    |
 LL | struct Bar;
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
index fb870d6..7f2eb0c 100644
--- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `is_empty` found for type `Foo` in the current scope
+error[E0599]: no method named `is_empty` found for struct `Foo` in the current scope
   --> $DIR/method-suggestion-no-duplication.rs:7:15
    |
 LL | struct Foo;
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
index 4c38f0a..5957ecb 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -7,7 +7,7 @@
    = help: consider replacing `'a` with `'static`
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
    |
-LL | type E<'a, 'b> = impl Sized; + 'a
+LL | type E<'a, 'b> = impl Sized + 'a;
    |
 
 error: aborting due to previous error
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.rs b/src/test/ui/impl-trait/no-method-suggested-traits.rs
index c912873..c8abc2d 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.rs
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.rs
@@ -25,7 +25,7 @@
     //~|items from traits can only be used if the trait is in scope
     std::rc::Rc::new(&mut Box::new(&1u32)).method();
     //~^items from traits can only be used if the trait is in scope
-    //~| ERROR no method named `method` found for type
+    //~| ERROR no method named `method` found for struct
 
     'a'.method();
     //~^ ERROR no method named
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index f0a03e1..da25617 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -16,7 +16,7 @@
 LL | use no_method_suggested_traits::Reexported;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:26:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u32)).method();
@@ -46,7 +46,7 @@
 LL | use foo::Bar;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:32:43
    |
 LL |         fn method(&self) {}
@@ -78,7 +78,7 @@
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&i32>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&i32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:37:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1i32)).method();
@@ -90,7 +90,7 @@
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 
-error[E0599]: no method named `method` found for type `Foo` in the current scope
+error[E0599]: no method named `method` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:40:9
    |
 LL | struct Foo;
@@ -106,7 +106,7 @@
            candidate #3: `no_method_suggested_traits::qux::PrivPub`
            candidate #4: `no_method_suggested_traits::Reexported`
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:42:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method();
@@ -129,7 +129,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:47:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u64)).method2();
@@ -139,7 +139,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:50:37
    |
 LL |     no_method_suggested_traits::Foo.method2();
@@ -149,7 +149,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:52:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
@@ -159,7 +159,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:54:40
    |
 LL |     no_method_suggested_traits::Bar::X.method2();
@@ -169,7 +169,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:56:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
@@ -179,7 +179,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method3` found for type `Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:59:9
    |
 LL | struct Foo;
@@ -192,7 +192,7 @@
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:61:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method3();
@@ -202,7 +202,7 @@
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:63:12
    |
 LL | enum Bar { X }
@@ -215,7 +215,7 @@
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:65:46
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
@@ -231,31 +231,31 @@
 LL |     1_usize.method3();
    |             ^^^^^^^ method not found in `usize`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&usize>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&usize>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:70:47
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
    |                                               ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&usize>>`
 
-error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:71:37
    |
 LL |     no_method_suggested_traits::Foo.method3();
    |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:72:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
    |                                                                       ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>`
 
-error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:74:40
    |
 LL |     no_method_suggested_traits::Bar::X.method3();
    |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:75:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
diff --git a/src/test/ui/imports/issue-55457.rs b/src/test/ui/imports/issue-55457.rs
index 9c6750f..c1f0488 100644
--- a/src/test/ui/imports/issue-55457.rs
+++ b/src/test/ui/imports/issue-55457.rs
@@ -3,6 +3,8 @@
 
 #[non_existent] //~ ERROR cannot determine resolution for the attribute macro `non_existent`
 #[derive(NonExistent)] //~ ERROR cannot determine resolution for the derive macro `NonExistent`
+                       //~| ERROR cannot determine resolution for the derive macro `NonExistent`
+                       //~| ERROR cannot determine resolution for the derive macro `NonExistent`
 struct S;
 
 fn main() {}
diff --git a/src/test/ui/imports/issue-55457.stderr b/src/test/ui/imports/issue-55457.stderr
index aa103ba..07de3d9 100644
--- a/src/test/ui/imports/issue-55457.stderr
+++ b/src/test/ui/imports/issue-55457.stderr
@@ -29,6 +29,22 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to 4 previous errors
+error: cannot determine resolution for the derive macro `NonExistent`
+  --> $DIR/issue-55457.rs:5:10
+   |
+LL | #[derive(NonExistent)]
+   |          ^^^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `NonExistent`
+  --> $DIR/issue-55457.rs:5:10
+   |
+LL | #[derive(NonExistent)]
+   |          ^^^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
index 29e9b8e..37fe0ec 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
@@ -26,6 +26,7 @@
 }
 
 exported!(); //~ ERROR `exported` is ambiguous
+             //~| ERROR `exported` is ambiguous
 
 mod inner2 {
     define_exported!();
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
index 7d01382..c9498fe 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -21,8 +21,31 @@
    |     ^^^^^^^^^
    = help: consider adding an explicit import of `exported` to disambiguate
 
+error[E0659]: `exported` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+  --> $DIR/local-modularized-tricky-fail-1.rs:28:1
+   |
+LL | exported!();
+   | ^^^^^^^^ ambiguous name
+   |
+note: `exported` could refer to the macro defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:5:5
+   |
+LL | /     macro_rules! exported {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_exported!();
+   |       ------------------- in this macro invocation
+note: `exported` could also refer to the macro imported here
+  --> $DIR/local-modularized-tricky-fail-1.rs:22:5
+   |
+LL | use inner1::*;
+   |     ^^^^^^^^^
+   = help: consider adding an explicit import of `exported` to disambiguate
+
 error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/local-modularized-tricky-fail-1.rs:35:5
+  --> $DIR/local-modularized-tricky-fail-1.rs:36:5
    |
 LL |     panic!();
    |     ^^^^^ ambiguous name
@@ -41,7 +64,7 @@
    = help: use `crate::panic` to refer to this macro unambiguously
 
 error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/local-modularized-tricky-fail-1.rs:46:1
+  --> $DIR/local-modularized-tricky-fail-1.rs:47:1
    |
 LL | include!();
    | ^^^^^^^ ambiguous name
@@ -59,6 +82,6 @@
    |       ------------------ in this macro invocation
    = help: use `crate::include` to refer to this macro unambiguously
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/macros.rs b/src/test/ui/imports/macros.rs
index f2a22ad..f397118 100644
--- a/src/test/ui/imports/macros.rs
+++ b/src/test/ui/imports/macros.rs
@@ -14,6 +14,7 @@
 mod m2 {
     use two_macros::*;
     m! { //~ ERROR ambiguous
+         //~| ERROR ambiguous
         use foo::m;
     }
 }
diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr
index 3b9e6fe..27b34fe 100644
--- a/src/test/ui/imports/macros.stderr
+++ b/src/test/ui/imports/macros.stderr
@@ -5,7 +5,25 @@
    |     ^ ambiguous name
    |
 note: `m` could refer to the macro imported here
-  --> $DIR/macros.rs:17:13
+  --> $DIR/macros.rs:18:13
+   |
+LL |         use foo::m;
+   |             ^^^^^^
+note: `m` could also refer to the macro imported here
+  --> $DIR/macros.rs:15:9
+   |
+LL |     use two_macros::*;
+   |         ^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `m` to disambiguate
+
+error[E0659]: `m` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+  --> $DIR/macros.rs:16:5
+   |
+LL |     m! {
+   |     ^ ambiguous name
+   |
+note: `m` could refer to the macro imported here
+  --> $DIR/macros.rs:18:13
    |
 LL |         use foo::m;
    |             ^^^^^^
@@ -17,23 +35,23 @@
    = help: consider adding an explicit import of `m` to disambiguate
 
 error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/macros.rs:29:9
+  --> $DIR/macros.rs:30:9
    |
 LL |         m! {
    |         ^ ambiguous name
    |
 note: `m` could refer to the macro imported here
-  --> $DIR/macros.rs:30:17
+  --> $DIR/macros.rs:31:17
    |
 LL |             use two_macros::n as m;
    |                 ^^^^^^^^^^^^^^^^^^
 note: `m` could also refer to the macro imported here
-  --> $DIR/macros.rs:22:9
+  --> $DIR/macros.rs:23:9
    |
 LL |     use two_macros::m;
    |         ^^^^^^^^^^^^^
    = help: use `self::m` to refer to this macro unambiguously
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/impossible_range.rs b/src/test/ui/impossible_range.rs
index 6345af0..21e5c03 100644
--- a/src/test/ui/impossible_range.rs
+++ b/src/test/ui/impossible_range.rs
@@ -1,4 +1,4 @@
-// Make sure that invalid ranges generate an error during HIR lowering, not an ICE
+// Make sure that invalid ranges generate an error during parsing, not an ICE
 
 pub fn main() {
     ..;
@@ -6,12 +6,12 @@
     ..1;
     0..1;
     ..=; //~ERROR inclusive range with no end
-         //~^HELP bounded at the end
+         //~^HELP use `..` instead
 }
 
 fn _foo1() {
     ..=1;
     0..=1;
     0..=; //~ERROR inclusive range with no end
-          //~^HELP bounded at the end
+          //~^HELP use `..` instead
 }
diff --git a/src/test/ui/impossible_range.stderr b/src/test/ui/impossible_range.stderr
index 091fe37..ea2ab0f 100644
--- a/src/test/ui/impossible_range.stderr
+++ b/src/test/ui/impossible_range.stderr
@@ -1,18 +1,18 @@
 error[E0586]: inclusive range with no end
-  --> $DIR/impossible_range.rs:8:8
+  --> $DIR/impossible_range.rs:8:5
    |
 LL |     ..=;
-   |        ^
+   |     ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/impossible_range.rs:15:9
+  --> $DIR/impossible_range.rs:15:6
    |
 LL |     0..=;
-   |         ^
+   |      ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index f456755..8c59fbd 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -37,7 +37,7 @@
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
 
-error[E0599]: no method named `bar` found for type `Foo` in the current scope
+error[E0599]: no method named `bar` found for struct `Foo` in the current scope
   --> $DIR/infinite-autoderef.rs:26:9
    |
 LL | struct Foo;
diff --git a/src/test/ui/internal/internal-unstable-const.rs b/src/test/ui/internal/internal-unstable-const.rs
new file mode 100644
index 0000000..ce306c8
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-const.rs
@@ -0,0 +1,10 @@
+#![feature(staged_api)]
+#![feature(const_if_match)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
+const fn foo() -> i32 {
+    if true { 4 } else { 5 } //~ loops and conditional expressions are not stable in const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/internal/internal-unstable-const.stderr b/src/test/ui/internal/internal-unstable-const.stderr
new file mode 100644
index 0000000..58bbe79
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-const.stderr
@@ -0,0 +1,12 @@
+error[E0723]: loops and conditional expressions are not stable in const fn
+  --> $DIR/internal-unstable-const.rs:7:5
+   |
+LL |     if true { 4 } else { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/invalid_const_promotion.rs b/src/test/ui/invalid_const_promotion.rs
deleted file mode 100644
index 5d7664c..0000000
--- a/src/test/ui/invalid_const_promotion.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-// run-pass
-
-#![allow(unused_mut)]
-// ignore-wasm32
-// ignore-emscripten
-// ignore-sgx no processes
-
-// compile-flags: -C debug_assertions=yes
-
-#![stable(feature = "rustc", since = "1.0.0")]
-#![feature(const_fn, rustc_private, staged_api, rustc_attrs)]
-#![allow(const_err)]
-
-extern crate libc;
-
-use std::env;
-use std::process::{Command, Stdio};
-
-// this will panic in debug mode and overflow in release mode
-//
-// NB we give bar an unused argument because otherwise memoization
-// of the const fn kicks in, causing a different code path in the
-// compiler to be executed (see PR #66294).
-#[stable(feature = "rustc", since = "1.0.0")]
-#[rustc_const_stable(feature = "rustc", since = "1.0.0")]
-#[rustc_promotable]
-const fn bar(_: bool) -> usize { 0 - 1 }
-
-fn foo() {
-    let _: &'static _ = &bar(true);
-}
-
-#[cfg(unix)]
-fn check_status(status: std::process::ExitStatus)
-{
-    use std::os::unix::process::ExitStatusExt;
-
-    assert!(status.signal() == Some(libc::SIGILL)
-            || status.signal() == Some(libc::SIGTRAP)
-            || status.signal() == Some(libc::SIGABRT));
-}
-
-#[cfg(not(unix))]
-fn check_status(status: std::process::ExitStatus)
-{
-    assert!(!status.success());
-}
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    if args.len() > 1 && args[1] == "test" {
-        foo();
-        return;
-    }
-
-    let mut p = Command::new(&args[0])
-        .stdout(Stdio::piped())
-        .stdin(Stdio::piped())
-        .arg("test").output().unwrap();
-    check_status(p.status);
-}
diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr
index 80ca051..666fb6a 100644
--- a/src/test/ui/issues/issue-10465.stderr
+++ b/src/test/ui/issues/issue-10465.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&b::B` in the current scope
+error[E0599]: no method named `foo` found for reference `&b::B` in the current scope
   --> $DIR/issue-10465.rs:17:15
    |
 LL |             b.foo();
diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr
index cdb261a..2f31636 100644
--- a/src/test/ui/issues/issue-13853.stderr
+++ b/src/test/ui/issues/issue-13853.stderr
@@ -12,7 +12,7 @@
    = help: type parameters must be constrained to match other types
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
-error[E0599]: no method named `iter` found for type `&G` in the current scope
+error[E0599]: no method named `iter` found for reference `&G` in the current scope
   --> $DIR/issue-13853.rs:27:23
    |
 LL |     for node in graph.iter() {
diff --git a/src/test/ui/issues/issue-14221.stderr b/src/test/ui/issues/issue-14221.stderr
index 3e5e25a..9864c08 100644
--- a/src/test/ui/issues/issue-14221.stderr
+++ b/src/test/ui/issues/issue-14221.stderr
@@ -3,6 +3,8 @@
    |
 LL |             A => "A",
    |             ^ help: to match on the variant, qualify the path: `E::A`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `B` is named the same as one of the variants of the type `E`
   --> $DIR/issue-14221.rs:15:13
diff --git a/src/test/ui/issues/issue-17546.rs b/src/test/ui/issues/issue-17546.rs
index dbfdad2..c93a03c 100644
--- a/src/test/ui/issues/issue-17546.rs
+++ b/src/test/ui/issues/issue-17546.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 use foo::MyEnum::Result;
 use foo::NoResult; // Through a re-export
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index f324291..2d532cd 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -1,8 +1,13 @@
 error[E0573]: expected type, found variant `NoResult`
-  --> $DIR/issue-17546.rs:12:17
+  --> $DIR/issue-17546.rs:16:17
    |
 LL |     fn new() -> NoResult<MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   | --------------------- similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
@@ -14,7 +19,7 @@
    |                 ^^^^^^
 
 error[E0573]: expected type, found variant `Result`
-  --> $DIR/issue-17546.rs:22:17
+  --> $DIR/issue-17546.rs:26:17
    |
 LL |     fn new() -> Result<foo::MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
@@ -32,7 +37,7 @@
      and 1 other candidate
 
 error[E0573]: expected type, found variant `Result`
-  --> $DIR/issue-17546.rs:28:13
+  --> $DIR/issue-17546.rs:32:13
    |
 LL | fn new() -> Result<foo::MyEnum, String> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
@@ -50,10 +55,15 @@
      and 1 other candidate
 
 error[E0573]: expected type, found variant `NoResult`
-  --> $DIR/issue-17546.rs:33:15
+  --> $DIR/issue-17546.rs:37:15
    |
 LL | fn newer() -> NoResult<foo::MyEnum, String> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   | --------------------- similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.rs b/src/test/ui/issues/issue-17718-const-bad-values.rs
index 97657f8..9355c8a 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.rs
+++ b/src/test/ui/issues/issue-17718-const-bad-values.rs
@@ -4,6 +4,7 @@
 static mut S: usize = 3;
 const C2: &'static mut usize = unsafe { &mut S };
 //~^ ERROR: constants cannot refer to statics
+//~| ERROR: constants cannot refer to statics
 //~| ERROR: references in constants may only refer to immutable values
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr
index 7e4a62a..e45d8b6 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.stderr
+++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr
@@ -7,11 +7,21 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/57349
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-const-bad-values.rs:5:46
    |
 LL | const C2: &'static mut usize = unsafe { &mut S };
    |                                              ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/issue-17718-const-bad-values.rs:5:46
+   |
+LL | const C2: &'static mut usize = unsafe { &mut S };
+   |                                              ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0658]: references in constants may only refer to immutable values
   --> $DIR/issue-17718-const-bad-values.rs:5:41
@@ -22,7 +32,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/57349
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0013, E0658.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-17718-references.stderr b/src/test/ui/issues/issue-17718-references.stderr
index 27aad9c..e3c3b36 100644
--- a/src/test/ui/issues/issue-17718-references.stderr
+++ b/src/test/ui/issues/issue-17718-references.stderr
@@ -1,20 +1,26 @@
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-references.rs:9:29
    |
 LL | const T2: &'static usize = &S;
    |                             ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-references.rs:14:19
    |
 LL | const T6: usize = S;
    |                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-references.rs:19:33
    |
 LL | const T10: Struct = Struct { a: S };
    |                                 ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-17732.rs b/src/test/ui/issues/issue-17732.rs
index 5e11fc4..8f63d5b 100644
--- a/src/test/ui/issues/issue-17732.rs
+++ b/src/test/ui/issues/issue-17732.rs
@@ -1,5 +1,6 @@
 // check-pass
 #![allow(dead_code)]
+#![allow(non_camel_case_types)]
 // pretty-expanded FIXME #23616
 
 trait Person {
diff --git a/src/test/ui/issues/issue-18118-2.rs b/src/test/ui/issues/issue-18118-2.rs
index 6d52156..f712a2e 100644
--- a/src/test/ui/issues/issue-18118-2.rs
+++ b/src/test/ui/issues/issue-18118-2.rs
@@ -1,7 +1,6 @@
 pub fn main() {
     const z: &'static isize = {
         static p: isize = 3;
-        &p
-        //~^ ERROR constants cannot refer to statics, use a constant instead
+        &p //~ ERROR constants cannot refer to statics
     };
 }
diff --git a/src/test/ui/issues/issue-18118-2.stderr b/src/test/ui/issues/issue-18118-2.stderr
index d58822f..4fc3ca7 100644
--- a/src/test/ui/issues/issue-18118-2.stderr
+++ b/src/test/ui/issues/issue-18118-2.stderr
@@ -1,8 +1,10 @@
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-18118-2.rs:4:10
    |
 LL |         &p
    |          ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19100.stderr b/src/test/ui/issues/issue-19100.stderr
index 1ab1347..01e5313 100644
--- a/src/test/ui/issues/issue-19100.stderr
+++ b/src/test/ui/issues/issue-19100.stderr
@@ -3,6 +3,8 @@
    |
 LL | Bar if true
    | ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
   --> $DIR/issue-19100.rs:22:1
diff --git a/src/test/ui/issues/issue-19521.stderr b/src/test/ui/issues/issue-19521.stderr
index c15c539..b6847cd 100644
--- a/src/test/ui/issues/issue-19521.stderr
+++ b/src/test/ui/issues/issue-19521.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `homura` found for type `&'static str` in the current scope
+error[E0599]: no method named `homura` found for reference `&'static str` in the current scope
   --> $DIR/issue-19521.rs:2:8
    |
 LL |     "".homura()();
diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr
index fe920c1..b412d7b 100644
--- a/src/test/ui/issues/issue-19692.stderr
+++ b/src/test/ui/issues/issue-19692.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `kaname` found for type `Homura` in the current scope
+error[E0599]: no method named `kaname` found for struct `Homura` in the current scope
   --> $DIR/issue-19692.rs:4:40
    |
 LL | struct Homura;
diff --git a/src/test/ui/issues/issue-20831-debruijn.rs b/src/test/ui/issues/issue-20831-debruijn.rs
index ef4b158..d0e15cb 100644
--- a/src/test/ui/issues/issue-20831-debruijn.rs
+++ b/src/test/ui/issues/issue-20831-debruijn.rs
@@ -28,6 +28,7 @@
     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
         // Not obvious, but there is an implicit lifetime here -------^
         //~^^ ERROR cannot infer
+        //~| ERROR cannot infer
         //~| ERROR mismatched types
         //~| ERROR mismatched types
         //
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index c7fd134..a4ea1cd 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -102,7 +102,49 @@
    = note: expected  `Publisher<'_>`
               found  `Publisher<'_>`
 
-error: aborting due to 3 previous errors
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6...
+  --> $DIR/issue-20831-debruijn.rs:26:6
+   |
+LL | impl<'a> Publisher<'a> for MyStruct<'a> {
+   |      ^^
+note: ...so that the types are compatible
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+   = note: expected  `Publisher<'_>`
+              found  `Publisher<'_>`
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0308, E0495.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr
index 4e5cace..efde161 100644
--- a/src/test/ui/issues/issue-21596.stderr
+++ b/src/test/ui/issues/issue-21596.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `to_string` found for type `*const u8` in the current scope
+error[E0599]: no method named `to_string` found for raw pointer `*const u8` in the current scope
   --> $DIR/issue-21596.rs:4:22
    |
 LL |     println!("{}", z.to_string());
diff --git a/src/test/ui/issues/issue-22933-2.rs b/src/test/ui/issues/issue-22933-2.rs
index 98a354b..dfd84b9 100644
--- a/src/test/ui/issues/issue-22933-2.rs
+++ b/src/test/ui/issues/issue-22933-2.rs
@@ -2,7 +2,7 @@
     Pie      = 0x1,
     Apple    = 0x2,
     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-    //~^ ERROR no variant or associated item named `PIE` found for type `Delicious`
+    //~^ ERROR no variant or associated item named `PIE` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr
index 72038ea..584b05e 100644
--- a/src/test/ui/issues/issue-22933-2.stderr
+++ b/src/test/ui/issues/issue-22933-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `PIE` found for type `Delicious` in the current scope
+error[E0599]: no variant or associated item named `PIE` found for enum `Delicious` in the current scope
   --> $DIR/issue-22933-2.rs:4:55
    |
 LL | enum Delicious {
diff --git a/src/test/ui/issues/issue-22933-3.rs b/src/test/ui/issues/issue-22933-3.rs
index 8518ed3..fbcce4b 100644
--- a/src/test/ui/issues/issue-22933-3.rs
+++ b/src/test/ui/issues/issue-22933-3.rs
@@ -1,4 +1,4 @@
 const FOO: [u32; u8::MIN as usize] = [];
-//~^ ERROR no associated item named `MIN` found for type `u8`
+//~^ ERROR no associated item named `MIN` found
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-23173.rs b/src/test/ui/issues/issue-23173.rs
index 7c15598..92f4c54 100644
--- a/src/test/ui/issues/issue-23173.rs
+++ b/src/test/ui/issues/issue-23173.rs
@@ -7,7 +7,7 @@
 
 fn main() {
     use_token(&Token::Homura); //~ ERROR no variant or associated item named `Homura`
-    Struct::method(); //~ ERROR no function or associated item named `method` found for type
-    Struct::method; //~ ERROR no function or associated item named `method` found for type
-    Struct::Assoc; //~ ERROR no associated item named `Assoc` found for type `Struct` in
+    Struct::method(); //~ ERROR no function or associated item named `method` found
+    Struct::method; //~ ERROR no function or associated item named `method` found
+    Struct::Assoc; //~ ERROR no associated item named `Assoc` found
 }
diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr
index 699e411..89f70fd 100644
--- a/src/test/ui/issues/issue-23173.stderr
+++ b/src/test/ui/issues/issue-23173.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Homura` found for type `Token` in the current scope
+error[E0599]: no variant or associated item named `Homura` found for enum `Token` in the current scope
   --> $DIR/issue-23173.rs:9:23
    |
 LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
@@ -7,7 +7,7 @@
 LL |     use_token(&Token::Homura);
    |                       ^^^^^^ variant or associated item not found in `Token`
 
-error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:10:13
    |
 LL | struct Struct {
@@ -16,7 +16,7 @@
 LL |     Struct::method();
    |             ^^^^^^ function or associated item not found in `Struct`
 
-error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:11:13
    |
 LL | struct Struct {
@@ -25,7 +25,7 @@
 LL |     Struct::method;
    |             ^^^^^^ function or associated item not found in `Struct`
 
-error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope
+error[E0599]: no associated item named `Assoc` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:12:13
    |
 LL | struct Struct {
diff --git a/src/test/ui/issues/issue-23217.rs b/src/test/ui/issues/issue-23217.rs
index 157f20d..09f9ebc 100644
--- a/src/test/ui/issues/issue-23217.rs
+++ b/src/test/ui/issues/issue-23217.rs
@@ -1,5 +1,5 @@
 pub enum SomeEnum {
-    B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found for type `SomeEnum`
+    B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr
index 97100ed..a81b459 100644
--- a/src/test/ui/issues/issue-23217.stderr
+++ b/src/test/ui/issues/issue-23217.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `A` found for type `SomeEnum` in the current scope
+error[E0599]: no variant or associated item named `A` found for enum `SomeEnum` in the current scope
   --> $DIR/issue-23217.rs:2:19
    |
 LL | pub enum SomeEnum {
diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr
index b0e729a..036c05f 100644
--- a/src/test/ui/issues/issue-24036.stderr
+++ b/src/test/ui/issues/issue-24036.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-24036.rs:3:9
    |
+LL |     let mut x = |c| c + 1;
+   |                 --------- the expected closure
 LL |     x = |c| c + 1;
    |         ^^^^^^^^^ expected closure, found a different closure
    |
diff --git a/src/test/ui/issues/issue-25385.rs b/src/test/ui/issues/issue-25385.rs
index adad6c3..ea042a6 100644
--- a/src/test/ui/issues/issue-25385.rs
+++ b/src/test/ui/issues/issue-25385.rs
@@ -1,6 +1,6 @@
 macro_rules! foo {
     ($e:expr) => { $e.foo() }
-    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+    //~^ ERROR no method named `foo` found
 }
 
 fn main() {
@@ -8,5 +8,5 @@
     foo!(a);
 
     foo!(1i32.foo());
-    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+    //~^ ERROR no method named `foo` found
 }
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
index c9ede03..aa720fd 100644
--- a/src/test/ui/issues/issue-2823.stderr
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `C` in the current scope
+error[E0599]: no method named `clone` found for struct `C` in the current scope
   --> $DIR/issue-2823.rs:13:16
    |
 LL | struct C {
diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr
index e315317..77bc829 100644
--- a/src/test/ui/issues/issue-28344.stderr
+++ b/src/test/ui/issues/issue-28344.stderr
@@ -4,7 +4,7 @@
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
    |                 ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
 
-error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+error[E0599]: no function or associated item named `bitor` found for trait object `dyn std::ops::BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:4:25
    |
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
@@ -19,7 +19,7 @@
 LL |     let g = BitXor::bitor;
    |             ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
 
-error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+error[E0599]: no function or associated item named `bitor` found for trait object `dyn std::ops::BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:8:21
    |
 LL |     let g = BitXor::bitor;
diff --git a/src/test/ui/issues/issue-28586.rs b/src/test/ui/issues/issue-28586.rs
index 4d286be..c543ef9 100644
--- a/src/test/ui/issues/issue-28586.rs
+++ b/src/test/ui/issues/issue-28586.rs
@@ -2,6 +2,6 @@
 
 pub trait Foo {}
 impl Foo for [u8; usize::BYTES] {}
-//~^ ERROR no associated item named `BYTES` found for type `usize`
+//~^ ERROR no associated item named `BYTES` found
 
 fn main() { }
diff --git a/src/test/ui/issues/issue-28837.rs b/src/test/ui/issues/issue-28837.rs
index 438a4c5..f874b00 100644
--- a/src/test/ui/issues/issue-28837.rs
+++ b/src/test/ui/issues/issue-28837.rs
@@ -5,7 +5,7 @@
 
     a + a; //~ ERROR cannot add `A` to `A`
 
-    a - a; //~ ERROR cannot substract `A` from `A`
+    a - a; //~ ERROR cannot subtract `A` from `A`
 
     a * a; //~ ERROR cannot multiply `A` to `A`
 
diff --git a/src/test/ui/issues/issue-28837.stderr b/src/test/ui/issues/issue-28837.stderr
index 2ef571b..b63e168 100644
--- a/src/test/ui/issues/issue-28837.stderr
+++ b/src/test/ui/issues/issue-28837.stderr
@@ -8,7 +8,7 @@
    |
    = note: an implementation of `std::ops::Add` might be missing for `A`
 
-error[E0369]: cannot substract `A` from `A`
+error[E0369]: cannot subtract `A` from `A`
   --> $DIR/issue-28837.rs:8:7
    |
 LL |     a - a;
diff --git a/src/test/ui/issues/issue-28971.rs b/src/test/ui/issues/issue-28971.rs
index 6493565..f0a1e2d 100644
--- a/src/test/ui/issues/issue-28971.rs
+++ b/src/test/ui/issues/issue-28971.rs
@@ -5,7 +5,7 @@
     foo(|| {
         match Foo::Bar(1) {
             Foo::Baz(..) => (),
-            //~^ ERROR no variant or associated item named `Baz` found for type `Foo`
+            //~^ ERROR no variant or associated item named `Baz` found
             _ => (),
         }
     });
diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr
index 7411896..2736ee8 100644
--- a/src/test/ui/issues/issue-28971.stderr
+++ b/src/test/ui/issues/issue-28971.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Baz` found for type `Foo` in the current scope
+error[E0599]: no variant or associated item named `Baz` found for enum `Foo` in the current scope
   --> $DIR/issue-28971.rs:7:18
    |
 LL | enum Foo {
diff --git a/src/test/ui/issues/issue-29124.rs b/src/test/ui/issues/issue-29124.rs
index 1cd3f84..dd27848 100644
--- a/src/test/ui/issues/issue-29124.rs
+++ b/src/test/ui/issues/issue-29124.rs
@@ -13,7 +13,7 @@
 
 fn main() {
     Obj::func.x();
-    //~^ ERROR no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+    //~^ ERROR no method named `x` found
     func.x();
-    //~^ ERROR no method named `x` found for type `fn() -> Ret {func}` in the current scope
+    //~^ ERROR no method named `x` found
 }
diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr
index c537c61..fff2024 100644
--- a/src/test/ui/issues/issue-29124.stderr
+++ b/src/test/ui/issues/issue-29124.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+error[E0599]: no method named `x` found for fn item `fn() -> Ret {Obj::func}` in the current scope
   --> $DIR/issue-29124.rs:15:15
    |
 LL |     Obj::func.x();
@@ -6,7 +6,7 @@
    |
    = note: Obj::func is a function, perhaps you wish to call it
 
-error[E0599]: no method named `x` found for type `fn() -> Ret {func}` in the current scope
+error[E0599]: no method named `x` found for fn item `fn() -> Ret {func}` in the current scope
   --> $DIR/issue-29124.rs:17:10
    |
 LL |     func.x();
diff --git a/src/test/ui/issues/issue-30123.rs b/src/test/ui/issues/issue-30123.rs
index 4fc32e0..705355d 100644
--- a/src/test/ui/issues/issue-30123.rs
+++ b/src/test/ui/issues/issue-30123.rs
@@ -5,5 +5,5 @@
 
 fn main() {
     let ug = Graph::<i32, i32>::new_undirected();
-    //~^ ERROR no function or associated item named `new_undirected` found for type
+    //~^ ERROR no function or associated item named `new_undirected` found
 }
diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr
index 32bbd4d..bc67316 100644
--- a/src/test/ui/issues/issue-30123.stderr
+++ b/src/test/ui/issues/issue-30123.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `new_undirected` found for type `issue_30123_aux::Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
   --> $DIR/issue-30123.rs:7:33
    |
 LL |     let ug = Graph::<i32, i32>::new_undirected();
diff --git a/src/test/ui/issues/issue-30302.stderr b/src/test/ui/issues/issue-30302.stderr
index d762d6f..ac1b523 100644
--- a/src/test/ui/issues/issue-30302.stderr
+++ b/src/test/ui/issues/issue-30302.stderr
@@ -3,6 +3,8 @@
    |
 LL |         Nil => true,
    |         ^^^ help: to match on the variant, qualify the path: `Stack::Nil`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 error: unreachable pattern
   --> $DIR/issue-30302.rs:15:9
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index 38cf3c4..a614b96 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -7,7 +7,7 @@
    = note:   expected type `u8`
            found reference `&_`
 
-error[E0599]: no method named `collect` found for type `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
+error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
   --> $DIR/issue-31173.rs:14:10
    |
 LL |         .collect();
diff --git a/src/test/ui/issues/issue-32963.rs b/src/test/ui/issues/issue-32963.rs
index ee09906..3e6cf44 100644
--- a/src/test/ui/issues/issue-32963.rs
+++ b/src/test/ui/issues/issue-32963.rs
@@ -7,5 +7,6 @@
 fn main() {
     size_of_copy::<dyn Misc + Copy>();
     //~^ ERROR only auto traits can be used as additional traits in a trait object
+    //~| ERROR only auto traits can be used as additional traits in a trait object
     //~| ERROR the trait bound `dyn Misc: std::marker::Copy` is not satisfied
 }
diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr
index e3564e8..450c37f 100644
--- a/src/test/ui/issues/issue-32963.stderr
+++ b/src/test/ui/issues/issue-32963.stderr
@@ -9,6 +9,17 @@
    |                        first non-auto trait
    |                        trait alias used in trait object type (first use)
 
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/issue-32963.rs:8:31
+   |
+LL |     size_of_copy::<dyn Misc + Copy>();
+   |                        ----   ^^^^
+   |                        |      |
+   |                        |      additional non-auto trait
+   |                        |      trait alias used in trait object type (additional use)
+   |                        first non-auto trait
+   |                        trait alias used in trait object type (first use)
+
 error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
   --> $DIR/issue-32963.rs:8:5
    |
@@ -18,7 +29,7 @@
 LL |     size_of_copy::<dyn Misc + Copy>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0225, E0277.
 For more information about an error, try `rustc --explain E0225`.
diff --git a/src/test/ui/issues/issue-33571.rs b/src/test/ui/issues/issue-33571.rs
index 147fb3f..2713f47 100644
--- a/src/test/ui/issues/issue-33571.rs
+++ b/src/test/ui/issues/issue-33571.rs
@@ -1,5 +1,6 @@
 #[derive(Clone,
          Sync, //~ ERROR cannot find derive macro `Sync` in this scope
+               //~| ERROR cannot find derive macro `Sync` in this scope
          Copy)]
 enum Foo {}
 
diff --git a/src/test/ui/issues/issue-33571.stderr b/src/test/ui/issues/issue-33571.stderr
index 78e7202..2a9ba5b 100644
--- a/src/test/ui/issues/issue-33571.stderr
+++ b/src/test/ui/issues/issue-33571.stderr
@@ -10,5 +10,17 @@
 LL |          Sync,
    |          ^^^^
 
-error: aborting due to previous error
+error: cannot find derive macro `Sync` in this scope
+  --> $DIR/issue-33571.rs:2:10
+   |
+LL |          Sync,
+   |          ^^^^
+   |
+note: unsafe traits like `Sync` should be implemented explicitly
+  --> $DIR/issue-33571.rs:2:10
+   |
+LL |          Sync,
+   |          ^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-33575.rs b/src/test/ui/issues/issue-33575.rs
index 09c4994..de544af 100644
--- a/src/test/ui/issues/issue-33575.rs
+++ b/src/test/ui/issues/issue-33575.rs
@@ -1,4 +1,4 @@
 fn main() {
-    let baz = ().foo(); //~ ERROR no method named `foo` found for type `()` in the current scope
+    let baz = ().foo(); //~ ERROR no method named `foo` found
     <i32 as std::str::FromStr>::from_str(&baz); // No complaints about `str` being unsized
 }
diff --git a/src/test/ui/issues/issue-33575.stderr b/src/test/ui/issues/issue-33575.stderr
index e6b74d2..bbd8042 100644
--- a/src/test/ui/issues/issue-33575.stderr
+++ b/src/test/ui/issues/issue-33575.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `()` in the current scope
+error[E0599]: no method named `foo` found for unit type `()` in the current scope
   --> $DIR/issue-33575.rs:2:18
    |
 LL |     let baz = ().foo();
diff --git a/src/test/ui/issues/issue-34209.rs b/src/test/ui/issues/issue-34209.rs
index fc2c367..632ddb9 100644
--- a/src/test/ui/issues/issue-34209.rs
+++ b/src/test/ui/issues/issue-34209.rs
@@ -4,7 +4,7 @@
 
 fn bug(l: S) {
     match l {
-        S::B {} => {}, //~ ERROR no variant `B` in enum `S`
+        S::B {} => {}, //~ ERROR no variant named `B` found for enum `S`
     }
 }
 
diff --git a/src/test/ui/issues/issue-34209.stderr b/src/test/ui/issues/issue-34209.stderr
index 194bb2b..f9a25b6 100644
--- a/src/test/ui/issues/issue-34209.stderr
+++ b/src/test/ui/issues/issue-34209.stderr
@@ -1,4 +1,4 @@
-error: no variant `B` in enum `S`
+error[E0599]: no variant named `B` found for enum `S`
   --> $DIR/issue-34209.rs:7:12
    |
 LL | enum S {
@@ -9,3 +9,4 @@
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-34229.rs b/src/test/ui/issues/issue-34229.rs
index 13e627a..625fcb0 100644
--- a/src/test/ui/issues/issue-34229.rs
+++ b/src/test/ui/issues/issue-34229.rs
@@ -1,5 +1,9 @@
 #[derive(PartialEq)] struct Comparable;
 #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
 //~^ ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-34229.stderr b/src/test/ui/issues/issue-34229.stderr
index c57f80c..9e17348 100644
--- a/src/test/ui/issues/issue-34229.stderr
+++ b/src/test/ui/issues/issue-34229.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs
index e34b5c9..afe4d42 100644
--- a/src/test/ui/issues/issue-34334.rs
+++ b/src/test/ui/issues/issue-34334.rs
@@ -7,5 +7,5 @@
     //~| ERROR expected expression, found reserved identifier `_`
     //~| ERROR expected expression, found reserved identifier `_`
     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-    //~^ ERROR no method named `iter` found for type `()` in the current scope
+    //~^ ERROR no method named `iter` found
 }
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 3055e31..c52ea4e 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -43,7 +43,7 @@
    |             |
    |             cannot assign to this expression
 
-error[E0599]: no method named `iter` found for type `()` in the current scope
+error[E0599]: no method named `iter` found for unit type `()` in the current scope
   --> $DIR/issue-34334.rs:9:36
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
diff --git a/src/test/ui/issues/issue-35600.rs b/src/test/ui/issues/issue-35600.rs
index 9d74726..f0bab60 100644
--- a/src/test/ui/issues/issue-35600.rs
+++ b/src/test/ui/issues/issue-35600.rs
@@ -1,5 +1,7 @@
 // run-pass
+#![allow(non_camel_case_types)]
 #![allow(unused_variables)]
+
 trait Foo {
     type bar;
     fn bar();
diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr
index b381203..a998f95 100644
--- a/src/test/ui/issues/issue-35677.stderr
+++ b/src/test/ui/issues/issue-35677.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `is_subset` found for type `&std::collections::HashSet<T>` in the current scope
+error[E0599]: no method named `is_subset` found for reference `&std::collections::HashSet<T>` in the current scope
   --> $DIR/issue-35677.rs:4:10
    |
 LL |     this.is_subset(other)
diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs
index 1102f3c..58f44f4 100644
--- a/src/test/ui/issues/issue-36617.rs
+++ b/src/test/ui/issues/issue-36617.rs
@@ -1,4 +1,5 @@
 #![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
                  //~| ERROR cannot determine resolution for the derive macro `Copy`
+                 //~| ERROR cannot determine resolution for the derive macro `Copy`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-36617.stderr b/src/test/ui/issues/issue-36617.stderr
index b5db98f..98b41b0 100644
--- a/src/test/ui/issues/issue-36617.stderr
+++ b/src/test/ui/issues/issue-36617.stderr
@@ -12,5 +12,13 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to 2 previous errors
+error: cannot determine resolution for the derive macro `Copy`
+  --> $DIR/issue-36617.rs:1:11
+   |
+LL | #![derive(Copy)]
+   |           ^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-3707.rs b/src/test/ui/issues/issue-3707.rs
index 844a2dc..0817c51 100644
--- a/src/test/ui/issues/issue-3707.rs
+++ b/src/test/ui/issues/issue-3707.rs
@@ -7,7 +7,7 @@
         return 1+1 == 2
     }
     pub fn chirp(&self) {
-        self.boom(); //~ ERROR no method named `boom` found for type `&Obj` in the current scope
+        self.boom(); //~ ERROR no method named `boom` found
     }
 }
 
diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr
index b98bc57..6ca2dee 100644
--- a/src/test/ui/issues/issue-3707.stderr
+++ b/src/test/ui/issues/issue-3707.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `boom` found for type `&Obj` in the current scope
+error[E0599]: no method named `boom` found for reference `&Obj` in the current scope
   --> $DIR/issue-3707.rs:10:14
    |
 LL |         self.boom();
diff --git a/src/test/ui/issues/issue-38919.rs b/src/test/ui/issues/issue-38919.rs
index 60a8793..3d28f19 100644
--- a/src/test/ui/issues/issue-38919.rs
+++ b/src/test/ui/issues/issue-38919.rs
@@ -1,5 +1,5 @@
 fn foo<T: Iterator>() {
-    T::Item; //~ ERROR no associated item named `Item` found for type `T` in the current scope
+    T::Item; //~ ERROR no associated item named `Item` found
 }
 
 fn main() { }
diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr
index 603d42c..0022065 100644
--- a/src/test/ui/issues/issue-38919.stderr
+++ b/src/test/ui/issues/issue-38919.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `Item` found for type `T` in the current scope
+error[E0599]: no associated item named `Item` found for type parameter `T` in the current scope
   --> $DIR/issue-38919.rs:2:8
    |
 LL |     T::Item;
diff --git a/src/test/ui/issues/issue-39175.stderr b/src/test/ui/issues/issue-39175.stderr
index 8b173e1..2f6e676 100644
--- a/src/test/ui/issues/issue-39175.stderr
+++ b/src/test/ui/issues/issue-39175.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `exec` found for type `&mut std::process::Command` in the current scope
+error[E0599]: no method named `exec` found for mutable reference `&mut std::process::Command` in the current scope
   --> $DIR/issue-39175.rs:15:39
    |
 LL |     Command::new("echo").arg("hello").exec();
diff --git a/src/test/ui/issues/issue-39559.rs b/src/test/ui/issues/issue-39559.rs
index 5af48ca..3a75956 100644
--- a/src/test/ui/issues/issue-39559.rs
+++ b/src/test/ui/issues/issue-39559.rs
@@ -12,7 +12,7 @@
 
 pub struct Vector<T, D: Dim> {
     entries: [T; D::dim()],
-    //~^ ERROR no function or associated item named `dim` found for type `D` in the current scope
+    //~^ ERROR no function or associated item named `dim` found
     _dummy: D,
 }
 
diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr
index b945b5e..0554b23 100644
--- a/src/test/ui/issues/issue-39559.stderr
+++ b/src/test/ui/issues/issue-39559.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `dim` found for type `D` in the current scope
+error[E0599]: no function or associated item named `dim` found for type parameter `D` in the current scope
   --> $DIR/issue-39559.rs:14:21
    |
 LL |     entries: [T; D::dim()],
diff --git a/src/test/ui/issues/issue-39720.rs b/src/test/ui/issues/issue-39720.rs
index 1a4775f..8cf841f 100644
--- a/src/test/ui/issues/issue-39720.rs
+++ b/src/test/ui/issues/issue-39720.rs
@@ -1,26 +1,22 @@
 // run-pass
-#![allow(non_snake_case)]
-
 // ignore-emscripten FIXME(#45351)
 
 #![feature(repr_simd, platform_intrinsics)]
 
-#[repr(C)] //~ WARNING conflicting representation hints
 #[repr(simd)]
 #[derive(Copy, Clone, Debug)]
-pub struct char3(pub i8, pub i8, pub i8);
+pub struct Char3(pub i8, pub i8, pub i8);
 
-#[repr(C)]  //~ WARNING conflicting representation hints
 #[repr(simd)]
 #[derive(Copy, Clone, Debug)]
-pub struct short3(pub i16, pub i16, pub i16);
+pub struct Short3(pub i16, pub i16, pub i16);
 
 extern "platform-intrinsic" {
     fn simd_cast<T, U>(x: T) -> U;
 }
 
 fn main() {
-    let cast: short3 = unsafe { simd_cast(char3(10, -3, -9)) };
+    let cast: Short3 = unsafe { simd_cast(Char3(10, -3, -9)) };
 
     println!("{:?}", cast);
 }
diff --git a/src/test/ui/issues/issue-39720.stderr b/src/test/ui/issues/issue-39720.stderr
deleted file mode 100644
index 8121ed2..0000000
--- a/src/test/ui/issues/issue-39720.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-39720.rs:8:8
-   |
-LL | #[repr(C)]
-   |        ^
-LL | #[repr(simd)]
-   |        ^^^^
-
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-39720.rs:13:8
-   |
-LL | #[repr(C)]
-   |        ^
-LL | #[repr(simd)]
-   |        ^^^^
-
diff --git a/src/test/ui/issues/issue-3973.rs b/src/test/ui/issues/issue-3973.rs
index 4e00915..a5ed5b8 100644
--- a/src/test/ui/issues/issue-3973.rs
+++ b/src/test/ui/issues/issue-3973.rs
@@ -20,6 +20,6 @@
 
 fn main() {
     let p = Point::new(0.0, 0.0);
-    //~^ ERROR no function or associated item named `new` found for type `Point`
+    //~^ ERROR no function or associated item named `new` found for struct `Point`
     println!("{}", p.to_string());
 }
diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr
index ee07a41..63282e8 100644
--- a/src/test/ui/issues/issue-3973.stderr
+++ b/src/test/ui/issues/issue-3973.stderr
@@ -7,7 +7,7 @@
 LL | |     }
    | |_____^ not a member of trait `ToString_`
 
-error[E0599]: no function or associated item named `new` found for type `Point` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
   --> $DIR/issue-3973.rs:22:20
    |
 LL | struct Point {
diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/issues/issue-41255.rs
index 60fdf7c..5b95a73 100644
--- a/src/test/ui/issues/issue-41255.rs
+++ b/src/test/ui/issues/issue-41255.rs
@@ -1,6 +1,7 @@
 // Matching against float literals should result in a linter error
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 #![allow(unused)]
 #![forbid(illegal_floating_point_literal_pattern)]
 
@@ -12,23 +13,53 @@
                    //~| ERROR floating-point types cannot be used in patterns
                    //~| WARNING this was previously accepted by the compiler but is being
         5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
+                      //~| ERROR floating-point types cannot be used in patterns
+                      //~| WARNING hard error
                       //~| WARNING hard error
         -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                    //~| ERROR floating-point types cannot be used in patterns
+                    //~| WARNING hard error
                     //~| WARNING hard error
         1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
                            //~| WARNING hard error
                            //~| ERROR floating-point types cannot be used in patterns
                            //~| WARNING hard error
+                           //~| ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
+                           //~| ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
         39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                             //~| WARNING hard error
                              //~| ERROR floating-point types cannot be used in patterns
                              //~| WARNING hard error
+                             //~| ERROR floating-point types cannot be used in patterns
+                             //~| ERROR floating-point types cannot be used in patterns
+                             //~| WARNING hard error
+                             //~| WARNING hard error
+                             //~| WARNING hard error
+
+        ..71.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
+        ..=72.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
+        71.0.. => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
         _ => {},
     };
     let y = 5.0;
     // Same for tuples
     match (x, 5) {
         (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
+                         //~| ERROR floating-point types cannot be used
+                         //~| WARNING hard error
                          //~| WARNING hard error
         _ => {},
     }
@@ -36,6 +67,8 @@
     struct Foo { x: f32 };
     match (Foo { x }) {
         Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
+                              //~| ERROR floating-point types cannot be used
+                              //~| WARNING hard error
                               //~| WARNING hard error
         _ => {},
     }
diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/issues/issue-41255.stderr
index c334742..1ff5815 100644
--- a/src/test/ui/issues/issue-41255.stderr
+++ b/src/test/ui/issues/issue-41255.stderr
@@ -1,11 +1,11 @@
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:10:9
+  --> $DIR/issue-41255.rs:11:9
    |
 LL |         5.0 => {},
    |         ^^^
    |
 note: lint level defined here
-  --> $DIR/issue-41255.rs:5:11
+  --> $DIR/issue-41255.rs:6:11
    |
 LL | #![forbid(illegal_floating_point_literal_pattern)]
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:14:9
+  --> $DIR/issue-41255.rs:15:9
    |
 LL |         5.0f32 => {},
    |         ^^^^^^
@@ -22,7 +22,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:16:10
+  --> $DIR/issue-41255.rs:19:10
    |
 LL |         -5.0 => {},
    |          ^^^
@@ -31,7 +31,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:18:9
+  --> $DIR/issue-41255.rs:23:9
    |
 LL |         1.0 .. 33.0 => {},
    |         ^^^
@@ -40,7 +40,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:18:16
+  --> $DIR/issue-41255.rs:23:16
    |
 LL |         1.0 .. 33.0 => {},
    |                ^^^^
@@ -49,7 +49,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:9
+  --> $DIR/issue-41255.rs:31:9
    |
 LL |         39.0 ..= 70.0 => {},
    |         ^^^^
@@ -58,7 +58,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:18
+  --> $DIR/issue-41255.rs:31:18
    |
 LL |         39.0 ..= 70.0 => {},
    |                  ^^^^
@@ -67,7 +67,34 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:31:10
+  --> $DIR/issue-41255.rs:40:11
+   |
+LL |         ..71.0 => {}
+   |           ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:45:12
+   |
+LL |         ..=72.0 => {}
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:50:9
+   |
+LL |         71.0.. => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:60:10
    |
 LL |         (3.14, 1) => {},
    |          ^^^^
@@ -76,7 +103,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:38:18
+  --> $DIR/issue-41255.rs:69:18
    |
 LL |         Foo { x: 2.0 } => {},
    |                  ^^^
@@ -85,7 +112,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:10:9
+  --> $DIR/issue-41255.rs:11:9
    |
 LL |         5.0 => {},
    |         ^^^
@@ -93,5 +120,104 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: aborting due to 10 previous errors
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:15:9
+   |
+LL |         5.0f32 => {},
+   |         ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:19:10
+   |
+LL |         -5.0 => {},
+   |          ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:23:9
+   |
+LL |         1.0 .. 33.0 => {},
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:23:16
+   |
+LL |         1.0 .. 33.0 => {},
+   |                ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:31:9
+   |
+LL |         39.0 ..= 70.0 => {},
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:31:18
+   |
+LL |         39.0 ..= 70.0 => {},
+   |                  ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:40:11
+   |
+LL |         ..71.0 => {}
+   |           ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:45:12
+   |
+LL |         ..=72.0 => {}
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:50:9
+   |
+LL |         71.0.. => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:60:10
+   |
+LL |         (3.14, 1) => {},
+   |          ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:69:18
+   |
+LL |         Foo { x: 2.0 } => {},
+   |                  ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/issues/issue-41880.rs b/src/test/ui/issues/issue-41880.rs
index 16facc5..10cde21 100644
--- a/src/test/ui/issues/issue-41880.rs
+++ b/src/test/ui/issues/issue-41880.rs
@@ -25,5 +25,5 @@
 fn main() {
     let a = iterate(0, |x| x+1);
     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
-    //~^ ERROR no method named `iter` found for type `Iterate<{integer}
+    //~^ ERROR no method named `iter` found
 }
diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr
index 0e1d55c..09d5594 100644
--- a/src/test/ui/issues/issue-41880.stderr
+++ b/src/test/ui/issues/issue-41880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `iter` found for type `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
+error[E0599]: no method named `iter` found for struct `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
   --> $DIR/issue-41880.rs:27:24
    |
 LL | pub struct Iterate<T, F> {
diff --git a/src/test/ui/issues/issue-42880.stderr b/src/test/ui/issues/issue-42880.stderr
index 763bb9a..82cdc20 100644
--- a/src/test/ui/issues/issue-42880.stderr
+++ b/src/test/ui/issues/issue-42880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `String` found for type `std::string::String` in the current scope
+error[E0599]: no associated item named `String` found for struct `std::string::String` in the current scope
   --> $DIR/issue-42880.rs:4:22
    |
 LL |     let f = |&Value::String(_)| ();
diff --git a/src/test/ui/issues/issue-43105.rs b/src/test/ui/issues/issue-43105.rs
index f61b65b..231af76 100644
--- a/src/test/ui/issues/issue-43105.rs
+++ b/src/test/ui/issues/issue-43105.rs
@@ -8,6 +8,7 @@
     match 1 {
         NUM => unimplemented!(),
         //~^ ERROR could not evaluate constant pattern
+        //~| ERROR could not evaluate constant pattern
         _ => unimplemented!(),
     }
 }
diff --git a/src/test/ui/issues/issue-43105.stderr b/src/test/ui/issues/issue-43105.stderr
index e3609c5..1a7b67b 100644
--- a/src/test/ui/issues/issue-43105.stderr
+++ b/src/test/ui/issues/issue-43105.stderr
@@ -20,6 +20,12 @@
 LL |         NUM => unimplemented!(),
    |         ^^^
 
-error: aborting due to 3 previous errors
+error: could not evaluate constant pattern
+  --> $DIR/issue-43105.rs:9:9
+   |
+LL |         NUM => unimplemented!(),
+   |         ^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-43189.rs b/src/test/ui/issues/issue-43189.rs
index f4f4dce..ce667a5 100644
--- a/src/test/ui/issues/issue-43189.rs
+++ b/src/test/ui/issues/issue-43189.rs
@@ -8,5 +8,5 @@
 extern crate xcrate_issue_43189_b;
 fn main() {
     ().a();
-    //~^ ERROR no method named `a` found for type `()` in the current scope [E0599]
+    //~^ ERROR no method named `a` found
 }
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
index 4dae6c1..3f63cb8e7 100644
--- a/src/test/ui/issues/issue-43189.stderr
+++ b/src/test/ui/issues/issue-43189.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `a` found for type `()` in the current scope
+error[E0599]: no method named `a` found for unit type `()` in the current scope
   --> $DIR/issue-43189.rs:10:8
    |
 LL |     ().a();
diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs
index 8b1343b..7c8bf29 100644
--- a/src/test/ui/issues/issue-46101.rs
+++ b/src/test/ui/issues/issue-46101.rs
@@ -1,6 +1,7 @@
 #![feature(use_extern_macros)]
 trait Foo {}
 #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
+                         //~| ERROR failed to resolve: partially resolved path in a derive macro
 struct S;
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-46101.stderr b/src/test/ui/issues/issue-46101.stderr
index 9c88d3b..2ffa152 100644
--- a/src/test/ui/issues/issue-46101.stderr
+++ b/src/test/ui/issues/issue-46101.stderr
@@ -4,6 +4,12 @@
 LL | #[derive(Foo::Anything)]
    |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: partially resolved path in a derive macro
+  --> $DIR/issue-46101.rs:3:10
+   |
+LL | #[derive(Foo::Anything)]
+   |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/issues/issue-47094.rs b/src/test/ui/issues/issue-47094.rs
index 97da984..3258ee9 100644
--- a/src/test/ui/issues/issue-47094.rs
+++ b/src/test/ui/issues/issue-47094.rs
@@ -1,12 +1,10 @@
-// check-pass
-
-#[repr(C,u8)] //~ WARNING conflicting representation hints
+#[repr(C, u8)] //~ ERROR conflicting representation hints
 enum Foo {
     A,
     B,
 }
 
-#[repr(C)] //~ WARNING conflicting representation hints
+#[repr(C)] //~ ERROR conflicting representation hints
 #[repr(u8)]
 enum Bar {
     A,
diff --git a/src/test/ui/issues/issue-47094.stderr b/src/test/ui/issues/issue-47094.stderr
index 16bcec0..c807f64 100644
--- a/src/test/ui/issues/issue-47094.stderr
+++ b/src/test/ui/issues/issue-47094.stderr
@@ -1,14 +1,17 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-47094.rs:3:8
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:1:8
    |
-LL | #[repr(C,u8)]
-   |        ^ ^^
+LL | #[repr(C, u8)]
+   |        ^  ^^
 
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-47094.rs:9:8
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:7:8
    |
 LL | #[repr(C)]
    |        ^
 LL | #[repr(u8)]
    |        ^^
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0566`.
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
index 24c6142..5b6b8f8 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _result = &Some(42).as_deref();
-//~^ ERROR no method named `as_deref` found for type `std::option::Option<{integer}>`
+//~^ ERROR no method named `as_deref` found for enum `std::option::Option<{integer}>`
 }
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
index 0eb7bf0..f91f6e8 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref` found for type `std::option::Option<{integer}>` in the current scope
+error[E0599]: no method named `as_deref` found for enum `std::option::Option<{integer}>` in the current scope
   --> $DIR/option-as_deref.rs:2:29
    |
 LL |     let _result = &Some(42).as_deref();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
index 67ad73f..c5fe6ea 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _result = &mut Some(42).as_deref_mut();
-//~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>`
+//~^ ERROR no method named `as_deref_mut` found for enum `std::option::Option<{integer}>`
 }
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
index 845ddb5..5832363 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope
+error[E0599]: no method named `as_deref_mut` found for enum `std::option::Option<{integer}>` in the current scope
   --> $DIR/option-as_deref_mut.rs:2:33
    |
 LL |     let _result = &mut Some(42).as_deref_mut();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
index 5e01674..fae11fe 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref.rs:4:27
    |
 LL |     let _result = &Ok(42).as_deref();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
index 6dc13da..1d98361 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
@@ -1,8 +1,8 @@
-error[E0599]: no method named `as_deref_err` found for type `std::result::Result<_, {integer}>` in the current scope
+error[E0599]: no method named `as_deref_err` found for enum `std::result::Result<_, {integer}>` in the current scope
   --> $DIR/result-as_deref_err.rs:4:28
    |
 LL |     let _result = &Err(41).as_deref_err();
-   |                            ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_ok`
+   |                            ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_err` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::Deref`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
index f21e973..2c6231f 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref_mut.rs:4:31
    |
 LL |     let _result = &mut Ok(42).as_deref_mut();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
index 44c0c95..950a050 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
@@ -1,8 +1,8 @@
-error[E0599]: no method named `as_deref_mut_err` found for type `std::result::Result<_, {integer}>` in the current scope
+error[E0599]: no method named `as_deref_mut_err` found for enum `std::result::Result<_, {integer}>` in the current scope
   --> $DIR/result-as_deref_mut_err.rs:4:32
    |
 LL |     let _result = &mut Err(41).as_deref_mut_err();
-   |                                ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_ok`
+   |                                ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::DerefMut`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs
deleted file mode 100644
index 54b695a..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(inner_deref)]
-
-fn main() {
-    let _result = &mut Ok(42).as_deref_mut_ok();
-//~^ ERROR no method named `as_deref_mut_ok` found
-}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr
deleted file mode 100644
index b8369c9..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0599]: no method named `as_deref_mut_ok` found for type `std::result::Result<{integer}, _>` in the current scope
-  --> $DIR/result-as_deref_mut_ok.rs:4:31
-   |
-LL |     let _result = &mut Ok(42).as_deref_mut_ok();
-   |                               ^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_err`
-   |
-   = note: the method `as_deref_mut_ok` exists but the following trait bounds were not satisfied:
-           `{integer} : std::ops::DerefMut`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs
deleted file mode 100644
index ebb0500..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(inner_deref)]
-
-fn main() {
-    let _result = &Ok(42).as_deref_ok();
-//~^ ERROR no method named `as_deref_ok` found
-}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr
deleted file mode 100644
index b26705a..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0599]: no method named `as_deref_ok` found for type `std::result::Result<{integer}, _>` in the current scope
-  --> $DIR/result-as_deref_ok.rs:4:27
-   |
-LL |     let _result = &Ok(42).as_deref_ok();
-   |                           ^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err`
-   |
-   = note: the method `as_deref_ok` exists but the following trait bounds were not satisfied:
-           `{integer} : std::ops::Deref`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50480.rs b/src/test/ui/issues/issue-50480.rs
index 31dbb75..deb6387 100644
--- a/src/test/ui/issues/issue-50480.rs
+++ b/src/test/ui/issues/issue-50480.rs
@@ -2,6 +2,7 @@
 //~^ ERROR the trait `Copy` may not be implemented for this type
 struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
 //~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `NotDefined` in this scope
 //~| ERROR `i32` is not an iterator
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-50480.stderr b/src/test/ui/issues/issue-50480.stderr
index 9022bfa..2b92664 100644
--- a/src/test/ui/issues/issue-50480.stderr
+++ b/src/test/ui/issues/issue-50480.stderr
@@ -4,6 +4,12 @@
 LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |            ^^^^^^^^^^ not found in this scope
 
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:3:12
+   |
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |            ^^^^^^^^^^ not found in this scope
+
 error[E0277]: `i32` is not an iterator
   --> $DIR/issue-50480.rs:3:24
    |
@@ -24,7 +30,7 @@
    |                                                 |
    |                                                 this field does not implement `Copy`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0204, E0277, E0412.
 For more information about an error, try `rustc --explain E0204`.
diff --git a/src/test/ui/issues/issue-5153.rs b/src/test/ui/issues/issue-5153.rs
index e673766..5bf0579 100644
--- a/src/test/ui/issues/issue-5153.rs
+++ b/src/test/ui/issues/issue-5153.rs
@@ -8,5 +8,5 @@
 
 fn main() {
     (&5isize as &dyn Foo).foo();
-    //~^ ERROR: no method named `foo` found for type `&dyn Foo` in the current scope
+    //~^ ERROR: no method named `foo` found for reference `&dyn Foo` in the current scope
 }
diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr
index 5034e6d..4680c8b 100644
--- a/src/test/ui/issues/issue-5153.stderr
+++ b/src/test/ui/issues/issue-5153.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&dyn Foo` in the current scope
+error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope
   --> $DIR/issue-5153.rs:10:27
    |
 LL |     (&5isize as &dyn Foo).foo();
diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr
index c69145c..502825e 100644
--- a/src/test/ui/issues/issue-52060.stderr
+++ b/src/test/ui/issues/issue-52060.stderr
@@ -1,8 +1,10 @@
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-52060.rs:4:26
    |
 LL | static B: [u32; 1] = [0; A.len()];
    |                          ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-52060.rs:4:26
diff --git a/src/test/ui/issues/issue-53251.rs b/src/test/ui/issues/issue-53251.rs
index 0751b0a..b5d5514 100644
--- a/src/test/ui/issues/issue-53251.rs
+++ b/src/test/ui/issues/issue-53251.rs
@@ -10,6 +10,7 @@
             fn $n() {
                 S::f::<i64>();
                 //~^ ERROR wrong number of type arguments
+                //~| ERROR wrong number of type arguments
             }
         )*
     }
diff --git a/src/test/ui/issues/issue-53251.stderr b/src/test/ui/issues/issue-53251.stderr
index 9fbffaf..21e4157 100644
--- a/src/test/ui/issues/issue-53251.stderr
+++ b/src/test/ui/issues/issue-53251.stderr
@@ -7,6 +7,15 @@
 LL | impl_add!(a b);
    | --------------- in this macro invocation
 
-error: aborting due to previous error
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/issue-53251.rs:11:24
+   |
+LL |                 S::f::<i64>();
+   |                        ^^^ unexpected type argument
+...
+LL | impl_add!(a b);
+   | --------------- in this macro invocation
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-54062.stderr b/src/test/ui/issues/issue-54062.stderr
index 3830ad4..5222e3e 100644
--- a/src/test/ui/issues/issue-54062.stderr
+++ b/src/test/ui/issues/issue-54062.stderr
@@ -4,7 +4,7 @@
 LL |     let _ = test.comps.inner.lock().unwrap();
    |             ^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `unwrap` found for type `std::sys_common::mutex::MutexGuard<'_>` in the current scope
+error[E0599]: no method named `unwrap` found for struct `std::sys_common::mutex::MutexGuard<'_>` in the current scope
   --> $DIR/issue-54062.rs:10:37
    |
 LL |     let _ = test.comps.inner.lock().unwrap();
diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr
index c4000c8..e762b7b 100644
--- a/src/test/ui/issues/issue-57362-1.stderr
+++ b/src/test/ui/issues/issue-57362-1.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `fn(&u8)` in the current scope
+error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope
   --> $DIR/issue-57362-1.rs:20:7
    |
 LL |     a.f();
diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr
index 2e713cc..3528084 100644
--- a/src/test/ui/issues/issue-57362-2.stderr
+++ b/src/test/ui/issues/issue-57362-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `make_g` found for type `for<'r> fn(&'r ())` in the current scope
+error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope
   --> $DIR/issue-57362-2.rs:22:25
    |
 LL |     let x = <fn (&())>::make_g();
diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr
index ef0d66d..70a7c38 100644
--- a/src/test/ui/issues/issue-58022.stderr
+++ b/src/test/ui/issues/issue-58022.stderr
@@ -11,9 +11,13 @@
    |     ------------------ required by `Foo::SIZE`
 LL | 
 LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-   |                         ^^^^^^^^^ cannot infer type
+   |                         ^^^^^^^^^
+   |                         |
+   |                         cannot infer type
+   |                         help: use the fully qualified path to an implementation: `<Type as Foo>::SIZE`
    |
    = note: cannot resolve `_: Foo`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-58734.rs b/src/test/ui/issues/issue-58734.rs
index bbdfebe..b253c13 100644
--- a/src/test/ui/issues/issue-58734.rs
+++ b/src/test/ui/issues/issue-58734.rs
@@ -18,5 +18,5 @@
     Trait::exists(());
     // no object safety error
     Trait::nonexistent(());
-    //~^ ERROR no function or associated item named `nonexistent` found for type `dyn Trait`
+    //~^ ERROR no function or associated item named `nonexistent` found
 }
diff --git a/src/test/ui/issues/issue-58734.stderr b/src/test/ui/issues/issue-58734.stderr
index 07f2a04..5e98cfa 100644
--- a/src/test/ui/issues/issue-58734.stderr
+++ b/src/test/ui/issues/issue-58734.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `nonexistent` found for type `dyn Trait` in the current scope
+error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope
   --> $DIR/issue-58734.rs:20:12
    |
 LL |     Trait::nonexistent(());
diff --git a/src/test/ui/issues/issue-59029-1.rs b/src/test/ui/issues/issue-59029-1.rs
index e98a4d0..8ab47a4 100644
--- a/src/test/ui/issues/issue-59029-1.rs
+++ b/src/test/ui/issues/issue-59029-1.rs
@@ -4,5 +4,6 @@
 
 trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
 //~^ ERROR associated type `Res` not found for `Self`
+//~| ERROR associated type `Res` not found for `Self`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-59029-1.stderr b/src/test/ui/issues/issue-59029-1.stderr
index fb1de97..53cdb8b 100644
--- a/src/test/ui/issues/issue-59029-1.stderr
+++ b/src/test/ui/issues/issue-59029-1.stderr
@@ -4,6 +4,12 @@
 LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
    |                                                    ^^^ associated type `Res` not found
 
-error: aborting due to previous error
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:52
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                                    ^^^ associated type `Res` not found
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-62554.rs b/src/test/ui/issues/issue-62554.rs
index 20e84ec..cfd0218 100644
--- a/src/test/ui/issues/issue-62554.rs
+++ b/src/test/ui/issues/issue-62554.rs
@@ -1,5 +1,6 @@
+// error-pattern:this file contains an unclosed delimiter
+// error-pattern:xpected `{`, found `macro_rules`
+
 fn main() {}
 
 fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-//~^ ERROR expected `{`, found `macro_rules`
-//~ ERROR this file contains an unclosed delimiter
diff --git a/src/test/ui/issues/issue-62554.stderr b/src/test/ui/issues/issue-62554.stderr
index 692bfe0..935d384 100644
--- a/src/test/ui/issues/issue-62554.stderr
+++ b/src/test/ui/issues/issue-62554.stderr
@@ -1,18 +1,60 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:5:52
+  --> $DIR/issue-62554.rs:6:89
    |
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |               -                       -         -                  -                  - unclosed delimiter
-   |               |                       |         |                  |
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
    |               |                       |         |                  unclosed delimiter
    |               |                       |         unclosed delimiter
    |               unclosed delimiter      unclosed delimiter
-LL |
-LL |
-   |                                                    ^
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
 
 error: expected `{`, found `macro_rules`
-  --> $DIR/issue-62554.rs:3:23
+  --> $DIR/issue-62554.rs:6:23
    |
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
    |                 --    ^^^^^^^^^^^ expected `{`
@@ -22,10 +64,8 @@
 help: try placing this code inside a block
    |
 LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-LL |
-LL |
 LL |  }
    |
 
-error: aborting due to 2 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr
index f1b2de8..e7a244e 100644
--- a/src/test/ui/issues/issue-64430.stderr
+++ b/src/test/ui/issues/issue-64430.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `bar` found for type `Foo` in the current scope
+error[E0599]: no method named `bar` found for struct `Foo` in the current scope
   --> $DIR/issue-64430.rs:7:9
    |
 LL | pub struct Foo;
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
index e0eaafd..018ce04 100644
--- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
@@ -5,7 +5,7 @@
 trait Bar {}
 
 fn do_stuff<T : Bar>(t : T) {
-    t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope
+    t.foo() //~ ERROR no method named `foo` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
index 24bf60a..4807a09 100644
--- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `T` in the current scope
+error[E0599]: no method named `foo` found for type parameter `T` in the current scope
   --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7
    |
 LL |     t.foo()
diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs
new file mode 100644
index 0000000..3c49a5a
--- /dev/null
+++ b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs
@@ -0,0 +1,6 @@
+pub struct Foo {
+    pub bar: Vec<i32>ö
+    //~^ ERROR expected `,`, or `}`, found `ö`
+} //~ ERROR expected `:`, found `}`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr
new file mode 100644
index 0000000..ef365a6
--- /dev/null
+++ b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr
@@ -0,0 +1,17 @@
+error: expected `,`, or `}`, found `ö`
+  --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:2:22
+   |
+LL |     pub bar: Vec<i32>ö
+   |                      ^ help: try adding a comma: `,`
+
+error: expected `:`, found `}`
+  --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:4:1
+   |
+LL |     pub bar: Vec<i32>ö
+   |                       - expected `:`
+LL |
+LL | }
+   | ^ unexpected token
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-6804.rs b/src/test/ui/issues/issue-6804.rs
index b4af358..3251373 100644
--- a/src/test/ui/issues/issue-6804.rs
+++ b/src/test/ui/issues/issue-6804.rs
@@ -17,7 +17,9 @@
 
     match [x, 1.0] {
         [NAN, _] => {}, //~ ERROR floating-point types cannot be used
-        //~^ WARN this was previously accepted by the compiler but is being phased out
+                        //~| ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        //~| WARN this was previously accepted by the compiler but is being phased out
         _ => {},
     };
 }
diff --git a/src/test/ui/issues/issue-6804.stderr b/src/test/ui/issues/issue-6804.stderr
index ab4467e..f4188dc 100644
--- a/src/test/ui/issues/issue-6804.stderr
+++ b/src/test/ui/issues/issue-6804.stderr
@@ -30,5 +30,14 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: aborting due to 3 previous errors
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:19:10
+   |
+LL |         [NAN, _] => {},
+   |          ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs b/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs
new file mode 100644
index 0000000..00f90cc
--- /dev/null
+++ b/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs
@@ -0,0 +1,9 @@
+macro_rules! x {
+    ($($c:tt)*) => {
+        $($c)ö* {} //~ ERROR missing condition for `if` expression
+    };             //~| ERROR mismatched types
+}
+
+fn main() {
+    x!(if);
+}
diff --git a/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr
new file mode 100644
index 0000000..8d1a03a
--- /dev/null
+++ b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr
@@ -0,0 +1,18 @@
+error: missing condition for `if` expression
+  --> $DIR/issue-68091-unicode-ident-after-if.rs:3:14
+   |
+LL |         $($c)ö* {}
+   |              ^ expected if condition here
+
+error[E0308]: mismatched types
+  --> $DIR/issue-68091-unicode-ident-after-if.rs:3:17
+   |
+LL |         $($c)ö* {}
+   |                 ^^ expected `bool`, found `()`
+...
+LL |     x!(if);
+   |     ------- in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs
new file mode 100644
index 0000000..1a90b47
--- /dev/null
+++ b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs
@@ -0,0 +1,9 @@
+macro_rules! x {
+    ($($c:tt)*) => {
+        $($c)ö* //~ ERROR macro expansion ends with an incomplete expression: expected expression
+    };
+}
+
+fn main() {
+    x!(!);
+}
diff --git a/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr
new file mode 100644
index 0000000..0b9c364
--- /dev/null
+++ b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr
@@ -0,0 +1,8 @@
+error: macro expansion ends with an incomplete expression: expected expression
+  --> $DIR/issue-68092-unicode-ident-after-incomplete-expr.rs:3:14
+   |
+LL |         $($c)ö*
+   |              ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-68103.rs b/src/test/ui/issues/issue-68103.rs
new file mode 100644
index 0000000..e775678
--- /dev/null
+++ b/src/test/ui/issues/issue-68103.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+pub extern crate self as name;
+pub use name::name as bug;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-7607-1.rs b/src/test/ui/issues/issue-7607-1.rs
index 5221f2c..1571cd2 100644
--- a/src/test/ui/issues/issue-7607-1.rs
+++ b/src/test/ui/issues/issue-7607-1.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 struct Foo {
     x: isize
 }
diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr
index 9320943..94f489e 100644
--- a/src/test/ui/issues/issue-7607-1.stderr
+++ b/src/test/ui/issues/issue-7607-1.stderr
@@ -1,8 +1,13 @@
 error[E0412]: cannot find type `Fo` in this scope
-  --> $DIR/issue-7607-1.rs:5:6
+  --> $DIR/issue-7607-1.rs:9:6
    |
 LL | impl Fo {
    |      ^^ help: a trait with a similar name exists: `Fn`
+   | 
+  ::: $SRC_DIR/libcore/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-7950.rs b/src/test/ui/issues/issue-7950.rs
index 7add8af..d3dcb33 100644
--- a/src/test/ui/issues/issue-7950.rs
+++ b/src/test/ui/issues/issue-7950.rs
@@ -4,5 +4,5 @@
 
 fn main() {
     Foo::bar();
-    //~^ ERROR no function or associated item named `bar` found for type `Foo`
+    //~^ ERROR no function or associated item named `bar` found for struct `Foo`
 }
diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr
index bbeab40..73e13c6 100644
--- a/src/test/ui/issues/issue-7950.stderr
+++ b/src/test/ui/issues/issue-7950.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `bar` found for type `Foo` in the current scope
+error[E0599]: no function or associated item named `bar` found for struct `Foo` in the current scope
   --> $DIR/issue-7950.rs:6:10
    |
 LL | struct Foo;
diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr
index 40b67f8..39640e3 100644
--- a/src/test/ui/kindck/kindck-nonsendable-1.stderr
+++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr
@@ -5,7 +5,9 @@
    |    ---              ---- required by this bound in `bar`
 ...
 LL |     bar(move|| foo(x));
-   |     ^^^ `std::rc::Rc<usize>` cannot be sent between threads safely
+   |     ^^^ ------------- within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`
+   |     |
+   |     `std::rc::Rc<usize>` cannot be sent between threads safely
    |
    = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<usize>`
    = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index a7843a9..6bb0877 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -9,7 +9,7 @@
 LL | use T;
    |
 
-error[E0599]: no function or associated item named `f` found for type `Foo` in the current scope
+error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope
   --> $DIR/lexical-scopes.rs:10:10
    |
 LL |     Foo::f();
diff --git a/src/test/ui/lint/lint-forbid-attr.rs b/src/test/ui/lint/lint-forbid-attr.rs
index 082b543..13b28e8 100644
--- a/src/test/ui/lint/lint-forbid-attr.rs
+++ b/src/test/ui/lint/lint-forbid-attr.rs
@@ -2,5 +2,7 @@
 
 #[allow(deprecated)]
 //~^ ERROR allow(deprecated) overruled by outer forbid(deprecated)
+//~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
+//~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
 }
diff --git a/src/test/ui/lint/lint-forbid-attr.stderr b/src/test/ui/lint/lint-forbid-attr.stderr
index 6e1e2b3..bf138c3 100644
--- a/src/test/ui/lint/lint-forbid-attr.stderr
+++ b/src/test/ui/lint/lint-forbid-attr.stderr
@@ -7,6 +7,24 @@
 LL | #[allow(deprecated)]
    |         ^^^^^^^^^^ overruled by previous forbid
 
-error: aborting due to previous error
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-attr.rs:3:9
+   |
+LL | #![forbid(deprecated)]
+   |           ---------- `forbid` level set here
+LL | 
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-attr.rs:3:9
+   |
+LL | #![forbid(deprecated)]
+   |           ---------- `forbid` level set here
+LL | 
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/lint-forbid-cmdline.rs b/src/test/ui/lint/lint-forbid-cmdline.rs
index 150685c..821470c 100644
--- a/src/test/ui/lint/lint-forbid-cmdline.rs
+++ b/src/test/ui/lint/lint-forbid-cmdline.rs
@@ -1,5 +1,7 @@
 // compile-flags: -F deprecated
 
 #[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
+                     //~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
+                     //~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
 }
diff --git a/src/test/ui/lint/lint-forbid-cmdline.stderr b/src/test/ui/lint/lint-forbid-cmdline.stderr
index bece477..89a4445 100644
--- a/src/test/ui/lint/lint-forbid-cmdline.stderr
+++ b/src/test/ui/lint/lint-forbid-cmdline.stderr
@@ -6,6 +6,22 @@
    |
    = note: `forbid` lint level was set on command line
 
-error: aborting due to previous error
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-cmdline.rs:3:9
+   |
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-cmdline.rs:3:9
+   |
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/lint-malformed.rs b/src/test/ui/lint/lint-malformed.rs
index 0d32767..cf55707 100644
--- a/src/test/ui/lint/lint-malformed.rs
+++ b/src/test/ui/lint/lint-malformed.rs
@@ -1,4 +1,8 @@
 #![deny = "foo"] //~ ERROR malformed `deny` attribute input
 #![allow(bar = "baz")] //~ ERROR malformed lint attribute
-
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
 fn main() { }
diff --git a/src/test/ui/lint/lint-malformed.stderr b/src/test/ui/lint/lint-malformed.stderr
index f487629..6dc8d49 100644
--- a/src/test/ui/lint/lint-malformed.stderr
+++ b/src/test/ui/lint/lint-malformed.stderr
@@ -4,12 +4,42 @@
 LL | #![allow(bar = "baz")]
    |          ^^^^^^^^^^^ bad attribute argument
 
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
 error: malformed `deny` attribute input
   --> $DIR/lint-malformed.rs:1:1
    |
 LL | #![deny = "foo"]
    | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]`
 
-error: aborting due to 2 previous errors
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/lint/lint-non-camel-case-types.rs b/src/test/ui/lint/lint-non-camel-case-types.rs
index d3b119a..acd5c5d 100644
--- a/src/test/ui/lint/lint-non-camel-case-types.rs
+++ b/src/test/ui/lint/lint-non-camel-case-types.rs
@@ -23,6 +23,7 @@
 }
 
 trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name
+    type foo7; //~ ERROR associated type `foo7` should have an upper camel case name
     fn dummy(&self) { }
 }
 
diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr
index 177f8c8..f82eefe 100644
--- a/src/test/ui/lint/lint-non-camel-case-types.stderr
+++ b/src/test/ui/lint/lint-non-camel-case-types.stderr
@@ -46,11 +46,17 @@
 LL | trait foo6 {
    |       ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo6`
 
+error: associated type `foo7` should have an upper camel case name
+  --> $DIR/lint-non-camel-case-types.rs:26:10
+   |
+LL |     type foo7;
+   |          ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo7`
+
 error: type parameter `ty` should have an upper camel case name
-  --> $DIR/lint-non-camel-case-types.rs:29:6
+  --> $DIR/lint-non-camel-case-types.rs:30:6
    |
 LL | fn f<ty>(_: ty) {}
    |      ^^ help: convert the identifier to upper camel case: `Ty`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/lint/lint-removed-cmdline.stderr b/src/test/ui/lint/lint-removed-cmdline.stderr
index 69b0d26..b4ab5f5 100644
--- a/src/test/ui/lint/lint-removed-cmdline.stderr
+++ b/src/test/ui/lint/lint-removed-cmdline.stderr
@@ -2,6 +2,18 @@
    |
    = note: requested on the command line with `-D raw_pointer_derive`
 
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+
 error: unused variable: `unused`
   --> $DIR/lint-removed-cmdline.rs:12:17
    |
diff --git a/src/test/ui/lint/lint-renamed-cmdline.stderr b/src/test/ui/lint/lint-renamed-cmdline.stderr
index c978981..6401d9b 100644
--- a/src/test/ui/lint/lint-renamed-cmdline.stderr
+++ b/src/test/ui/lint/lint-renamed-cmdline.stderr
@@ -2,6 +2,18 @@
    |
    = note: requested on the command line with `-D bare_trait_object`
 
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+   |
+   = note: requested on the command line with `-D bare_trait_object`
+
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+   |
+   = note: requested on the command line with `-D bare_trait_object`
+
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+   |
+   = note: requested on the command line with `-D bare_trait_object`
+
 error: unused variable: `unused`
   --> $DIR/lint-renamed-cmdline.rs:8:17
    |
diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs
index 0585fec..0bac9bb 100644
--- a/src/test/ui/lint/lint-stability-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-deprecated.rs
@@ -97,10 +97,13 @@
         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
         //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+        //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
         type A = dyn TraitWithAssociatedTypes<
             TypeUnstable = u8,
             TypeDeprecated = u16,
             //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
+            //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
+            //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
         >;
 
         let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct'
diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr
index 6238013..650373c 100644
--- a/src/test/ui/lint/lint-stability-deprecated.stderr
+++ b/src/test/ui/lint/lint-stability-deprecated.stderr
@@ -77,241 +77,241 @@
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedStruct': text
-  --> $DIR/lint-stability-deprecated.rs:106:17
+  --> $DIR/lint-stability-deprecated.rs:109:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct': text
-  --> $DIR/lint-stability-deprecated.rs:109:17
+  --> $DIR/lint-stability-deprecated.rs:112:17
    |
 LL |         let _ = DeprecatedUnstableStruct {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:116:17
+  --> $DIR/lint-stability-deprecated.rs:119:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:117:17
+  --> $DIR/lint-stability-deprecated.rs:120:17
    |
 LL |         let _ = DeprecatedUnstableUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Enum::DeprecatedVariant': text
-  --> $DIR/lint-stability-deprecated.rs:121:17
+  --> $DIR/lint-stability-deprecated.rs:124:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant': text
-  --> $DIR/lint-stability-deprecated.rs:122:17
+  --> $DIR/lint-stability-deprecated.rs:125:17
    |
 LL |         let _ = Enum::DeprecatedUnstableVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:126:17
+  --> $DIR/lint-stability-deprecated.rs:129:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:127:17
+  --> $DIR/lint-stability-deprecated.rs:130:17
    |
 LL |         let _ = DeprecatedUnstableTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:136:25
+  --> $DIR/lint-stability-deprecated.rs:139:25
    |
 LL |         macro_test_arg!(deprecated_text());
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:137:25
+  --> $DIR/lint-stability-deprecated.rs:140:25
    |
 LL |         macro_test_arg!(deprecated_unstable_text());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:138:41
+  --> $DIR/lint-stability-deprecated.rs:141:41
    |
 LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:143:9
+  --> $DIR/lint-stability-deprecated.rs:146:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:145:9
+  --> $DIR/lint-stability-deprecated.rs:148:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:147:9
+  --> $DIR/lint-stability-deprecated.rs:150:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:149:9
+  --> $DIR/lint-stability-deprecated.rs:152:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:151:9
+  --> $DIR/lint-stability-deprecated.rs:154:9
    |
 LL |         Trait::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:153:9
+  --> $DIR/lint-stability-deprecated.rs:156:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:155:9
+  --> $DIR/lint-stability-deprecated.rs:158:9
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:157:9
+  --> $DIR/lint-stability-deprecated.rs:160:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:185:10
+  --> $DIR/lint-stability-deprecated.rs:188:10
    |
 LL |     impl DeprecatedTrait for S {}
    |          ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:187:25
+  --> $DIR/lint-stability-deprecated.rs:190:25
    |
 LL |     trait LocalTrait2 : DeprecatedTrait { }
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:206:9
+  --> $DIR/lint-stability-deprecated.rs:209:9
    |
 LL |         unstable_mod::deprecated();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:328:9
+  --> $DIR/lint-stability-deprecated.rs:331:9
    |
 LL |         deprecated();
    |         ^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:333:9
+  --> $DIR/lint-stability-deprecated.rs:336:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:335:9
+  --> $DIR/lint-stability-deprecated.rs:338:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:337:9
+  --> $DIR/lint-stability-deprecated.rs:340:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:342:9
+  --> $DIR/lint-stability-deprecated.rs:345:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:344:9
+  --> $DIR/lint-stability-deprecated.rs:347:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedStruct': text
-  --> $DIR/lint-stability-deprecated.rs:382:17
+  --> $DIR/lint-stability-deprecated.rs:385:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:389:17
+  --> $DIR/lint-stability-deprecated.rs:392:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
-  --> $DIR/lint-stability-deprecated.rs:393:17
+  --> $DIR/lint-stability-deprecated.rs:396:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:397:17
+  --> $DIR/lint-stability-deprecated.rs:400:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:404:9
+  --> $DIR/lint-stability-deprecated.rs:407:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:406:9
+  --> $DIR/lint-stability-deprecated.rs:409:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:408:9
+  --> $DIR/lint-stability-deprecated.rs:411:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:410:9
+  --> $DIR/lint-stability-deprecated.rs:413:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
-  --> $DIR/lint-stability-deprecated.rs:437:9
+  --> $DIR/lint-stability-deprecated.rs:440:9
    |
 LL |         fn_in_body();
    |         ^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:457:10
+  --> $DIR/lint-stability-deprecated.rs:460:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:459:24
+  --> $DIR/lint-stability-deprecated.rs:462:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
-  --> $DIR/lint-stability-deprecated.rs:445:13
+  --> $DIR/lint-stability-deprecated.rs:448:13
    |
 LL |             fn_in_body();
    |             ^^^^^^^^^^
@@ -323,7 +323,7 @@
    |                                                ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
-  --> $DIR/lint-stability-deprecated.rs:102:13
+  --> $DIR/lint-stability-deprecated.rs:103:13
    |
 LL |             TypeDeprecated = u16,
    |             ^^^^^^^^^^^^^^^^^^^^
@@ -449,188 +449,206 @@
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:107:13
+  --> $DIR/lint-stability-deprecated.rs:110:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:111:13
+  --> $DIR/lint-stability-deprecated.rs:114:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:142:13
+  --> $DIR/lint-stability-deprecated.rs:145:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:144:9
+  --> $DIR/lint-stability-deprecated.rs:147:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:146:13
+  --> $DIR/lint-stability-deprecated.rs:149:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:148:9
+  --> $DIR/lint-stability-deprecated.rs:151:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:150:13
+  --> $DIR/lint-stability-deprecated.rs:153:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:152:9
+  --> $DIR/lint-stability-deprecated.rs:155:9
    |
 LL |         <Foo>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:154:13
+  --> $DIR/lint-stability-deprecated.rs:157:13
    |
 LL |         foo.trait_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:156:9
+  --> $DIR/lint-stability-deprecated.rs:159:9
    |
 LL | ...   <Foo>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:173:13
+  --> $DIR/lint-stability-deprecated.rs:176:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:174:13
+  --> $DIR/lint-stability-deprecated.rs:177:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:175:13
+  --> $DIR/lint-stability-deprecated.rs:178:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:176:13
+  --> $DIR/lint-stability-deprecated.rs:179:13
    |
 LL |         foo.trait_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:329:13
+  --> $DIR/lint-stability-deprecated.rs:332:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:330:9
+  --> $DIR/lint-stability-deprecated.rs:333:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:331:9
+  --> $DIR/lint-stability-deprecated.rs:334:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:332:13
+  --> $DIR/lint-stability-deprecated.rs:335:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:334:9
+  --> $DIR/lint-stability-deprecated.rs:337:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:338:13
+  --> $DIR/lint-stability-deprecated.rs:341:13
    |
 LL |         foo.method_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:339:9
+  --> $DIR/lint-stability-deprecated.rs:342:9
    |
 LL |         Foo::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:340:9
+  --> $DIR/lint-stability-deprecated.rs:343:9
    |
 LL |         <Foo>::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:341:13
+  --> $DIR/lint-stability-deprecated.rs:344:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:343:9
+  --> $DIR/lint-stability-deprecated.rs:346:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:384:13
+  --> $DIR/lint-stability-deprecated.rs:387:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:403:13
+  --> $DIR/lint-stability-deprecated.rs:406:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:405:9
+  --> $DIR/lint-stability-deprecated.rs:408:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:407:13
+  --> $DIR/lint-stability-deprecated.rs:410:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:409:9
+  --> $DIR/lint-stability-deprecated.rs:412:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:426:13
+  --> $DIR/lint-stability-deprecated.rs:429:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:427:13
+  --> $DIR/lint-stability-deprecated.rs:430:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:98:48
+   |
+LL |         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+   |                                                ^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:103:13
+   |
+LL |             TypeDeprecated = u16,
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:103:13
+   |
+LL |             TypeDeprecated = u16,
+   |             ^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/lint-unexported-no-mangle.stderr b/src/test/ui/lint/lint-unexported-no-mangle.stderr
index c2cbf5f..3a78ed2 100644
--- a/src/test/ui/lint/lint-unexported-no-mangle.stderr
+++ b/src/test/ui/lint/lint-unexported-no-mangle.stderr
@@ -6,6 +6,30 @@
    |
    = note: requested on the command line with `-F private_no_mangle_statics`
 
+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 a warning, `#[no_mangle]` statics always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_statics`
+
+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 a warning, `#[no_mangle]` statics always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_statics`
+
+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 a warning, `#[no_mangle]` statics always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_statics`
+
 error: const items should never be `#[no_mangle]`
   --> $DIR/lint-unexported-no-mangle.rs:9:1
    |
diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
index 58fdae3..27e7ee7 100644
--- a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
+++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
@@ -7,6 +7,24 @@
    = help: did you mean: `dead_code`
    = note: requested on the command line with `-D dead_cod`
 
-error: aborting due to 2 previous errors
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error[E0602]: unknown lint: `dead_cod`
+   |
+   = help: did you mean: `dead_code`
+   = note: requested on the command line with `-D dead_cod`
+
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error[E0602]: unknown lint: `dead_cod`
+   |
+   = help: did you mean: `dead_code`
+   = note: requested on the command line with `-D dead_cod`
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr
index f614d5d..b937832 100644
--- a/src/test/ui/lint/lint-uppercase-variables.stderr
+++ b/src/test/ui/lint/lint-uppercase-variables.stderr
@@ -3,6 +3,8 @@
    |
 LL |         Foo => {}
    |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning: unused variable: `Foo`
   --> $DIR/lint-uppercase-variables.rs:22:9
diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs
index 950533c..2a38565 100644
--- a/src/test/ui/lint/outer-forbid.rs
+++ b/src/test/ui/lint/outer-forbid.rs
@@ -7,12 +7,18 @@
 #![forbid(unused, non_snake_case)]
 
 #[allow(unused_variables)] //~ ERROR overruled
+                           //~| ERROR overruled
+                           //~| ERROR overruled
 fn foo() {}
 
 #[allow(unused)] //~ ERROR overruled
+                 //~| ERROR overruled
+                 //~| ERROR overruled
 fn bar() {}
 
 #[allow(nonstandard_style)] //~ ERROR overruled
+                            //~| ERROR overruled
+                            //~| ERROR overruled
 fn main() {
     println!("hello forbidden world")
 }
diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr
index 310a5d88..b2e638e 100644
--- a/src/test/ui/lint/outer-forbid.stderr
+++ b/src/test/ui/lint/outer-forbid.stderr
@@ -8,7 +8,7 @@
    |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
 
 error[E0453]: allow(unused) overruled by outer forbid(unused)
-  --> $DIR/outer-forbid.rs:12:9
+  --> $DIR/outer-forbid.rs:14:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |           ------ `forbid` level set here
@@ -17,7 +17,7 @@
    |         ^^^^^^ overruled by previous forbid
 
 error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
-  --> $DIR/outer-forbid.rs:15:9
+  --> $DIR/outer-forbid.rs:19:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |                   -------------- `forbid` level set here
@@ -25,6 +25,60 @@
 LL | #[allow(nonstandard_style)]
    |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
 
-error: aborting due to 3 previous errors
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:9:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+LL | 
+LL | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:14:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
+  --> $DIR/outer-forbid.rs:19:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |                   -------------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:9:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+LL | 
+LL | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:14:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
+  --> $DIR/outer-forbid.rs:19:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |                   -------------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/reasons-erroneous.rs b/src/test/ui/lint/reasons-erroneous.rs
index 21c2ddd..03cf067 100644
--- a/src/test/ui/lint/reasons-erroneous.rs
+++ b/src/test/ui/lint/reasons-erroneous.rs
@@ -2,24 +2,70 @@
 
 #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason must be a string literal
+//~| NOTE reason must be a string literal
 //~| NOTE reason must be a string literal
 #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason must be a string literal
+//~| NOTE reason must be a string literal
 //~| NOTE reason must be a string literal
 #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason in lint attribute must come last
+//~| NOTE reason in lint attribute must come last
 //~| NOTE reason in lint attribute must come last
 #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason in lint attribute must come last
+//~| NOTE reason in lint attribute must come last
 //~| NOTE reason in lint attribute must come last
 #![warn(missing_copy_implementations, reason)]
 //~^ WARN unknown lint
diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr
index 3f925f1..a84167f 100644
--- a/src/test/ui/lint/reasons-erroneous.stderr
+++ b/src/test/ui/lint/reasons-erroneous.stderr
@@ -5,49 +5,187 @@
    |                                                          ^ reason must be a string literal
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:6:40
+  --> $DIR/reasons-erroneous.rs:10:40
    |
 LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:9:29
+  --> $DIR/reasons-erroneous.rs:17:29
    |
 LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:12:23
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
    |
 LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:15:36
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
    |
 LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:18:44
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:56:44
    |
 LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
    |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:21:25
+  --> $DIR/reasons-erroneous.rs:63:25
    |
 LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
 warning: unknown lint: `reason`
-  --> $DIR/reasons-erroneous.rs:24:39
+  --> $DIR/reasons-erroneous.rs:70:39
    |
 LL | #![warn(missing_copy_implementations, reason)]
    |                                       ^^^^^^
    |
    = note: `#[warn(unknown_lints)]` on by default
 
-error: aborting due to 7 previous errors
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:3:58
+   |
+LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
+   |                                                          ^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:10:40
+   |
+LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:56:44
+   |
+LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:63:25
+   |
+LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:3:58
+   |
+LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
+   |                                                          ^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:10:40
+   |
+LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:56:44
+   |
+LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:63:25
+   |
+LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error: aborting due to 30 previous errors
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/lint/reasons-forbidden.rs b/src/test/ui/lint/reasons-forbidden.rs
index 19ab767..6a71176 100644
--- a/src/test/ui/lint/reasons-forbidden.rs
+++ b/src/test/ui/lint/reasons-forbidden.rs
@@ -3,6 +3,8 @@
 #![forbid(
     unsafe_code,
     //~^ NOTE `forbid` level set here
+    //~| NOTE `forbid` level set here
+    //~| NOTE `forbid` level set here
     reason = "our errors & omissions insurance policy doesn't cover unsafe Rust"
 )]
 
@@ -13,7 +15,13 @@
 
     #[allow(unsafe_code)]
     //~^ ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
+    //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
+    //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
     //~| NOTE overruled by previous forbid
+    //~| NOTE overruled by previous forbid
+    //~| NOTE overruled by previous forbid
+    //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
+    //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
     //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
     unsafe {
         *a_billion_dollar_mistake
diff --git a/src/test/ui/lint/reasons-forbidden.stderr b/src/test/ui/lint/reasons-forbidden.stderr
index ea09e59..0954ede 100644
--- a/src/test/ui/lint/reasons-forbidden.stderr
+++ b/src/test/ui/lint/reasons-forbidden.stderr
@@ -1,5 +1,5 @@
 error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
-  --> $DIR/reasons-forbidden.rs:14:13
+  --> $DIR/reasons-forbidden.rs:16:13
    |
 LL |     unsafe_code,
    |     ----------- `forbid` level set here
@@ -9,6 +9,28 @@
    |
    = note: our errors & omissions insurance policy doesn't cover unsafe Rust
 
-error: aborting due to previous error
+error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
+  --> $DIR/reasons-forbidden.rs:16:13
+   |
+LL |     unsafe_code,
+   |     ----------- `forbid` level set here
+...
+LL |     #[allow(unsafe_code)]
+   |             ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: our errors & omissions insurance policy doesn't cover unsafe Rust
+
+error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
+  --> $DIR/reasons-forbidden.rs:16:13
+   |
+LL |     unsafe_code,
+   |     ----------- `forbid` level set here
+...
+LL |     #[allow(unsafe_code)]
+   |             ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: our errors & omissions insurance policy doesn't cover unsafe Rust
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/macros/builtin-std-paths-fail.rs b/src/test/ui/macros/builtin-std-paths-fail.rs
index 33de3d5..c1a4e32 100644
--- a/src/test/ui/macros/builtin-std-paths-fail.rs
+++ b/src/test/ui/macros/builtin-std-paths-fail.rs
@@ -1,6 +1,8 @@
 #[derive(
     core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core`
+                          //~| ERROR could not find `RustcDecodable` in `core`
     core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core`
+                          //~| ERROR could not find `RustcDecodable` in `core`
 )]
 #[core::bench] //~ ERROR could not find `bench` in `core`
 #[core::global_allocator] //~ ERROR could not find `global_allocator` in `core`
@@ -10,7 +12,9 @@
 
 #[derive(
     std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std`
+                         //~| ERROR could not find `RustcDecodable` in `std`
     std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std`
+                         //~| ERROR could not find `RustcDecodable` in `std`
 )]
 #[std::bench] //~ ERROR could not find `bench` in `std`
 #[std::global_allocator] //~ ERROR could not find `global_allocator` in `std`
diff --git a/src/test/ui/macros/builtin-std-paths-fail.stderr b/src/test/ui/macros/builtin-std-paths-fail.stderr
index 6de6890..9831e46 100644
--- a/src/test/ui/macros/builtin-std-paths-fail.stderr
+++ b/src/test/ui/macros/builtin-std-paths-fail.stderr
@@ -1,23 +1,23 @@
 error[E0433]: failed to resolve: could not find `bench` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:5:9
+  --> $DIR/builtin-std-paths-fail.rs:7:9
    |
 LL | #[core::bench]
    |         ^^^^^ could not find `bench` in `core`
 
 error[E0433]: failed to resolve: could not find `global_allocator` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:6:9
+  --> $DIR/builtin-std-paths-fail.rs:8:9
    |
 LL | #[core::global_allocator]
    |         ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `core`
 
 error[E0433]: failed to resolve: could not find `test_case` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:7:9
+  --> $DIR/builtin-std-paths-fail.rs:9:9
    |
 LL | #[core::test_case]
    |         ^^^^^^^^^ could not find `test_case` in `core`
 
 error[E0433]: failed to resolve: could not find `test` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:8:9
+  --> $DIR/builtin-std-paths-fail.rs:10:9
    |
 LL | #[core::test]
    |         ^^^^ could not find `test` in `core`
@@ -29,47 +29,71 @@
    |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:3:11
+  --> $DIR/builtin-std-paths-fail.rs:4:11
+   |
+LL |     core::RustcDecodable,
+   |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
+
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
+  --> $DIR/builtin-std-paths-fail.rs:4:11
+   |
+LL |     core::RustcDecodable,
+   |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
+
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
+  --> $DIR/builtin-std-paths-fail.rs:2:11
    |
 LL |     core::RustcDecodable,
    |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
 
 error[E0433]: failed to resolve: could not find `bench` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:15:8
+  --> $DIR/builtin-std-paths-fail.rs:19:8
    |
 LL | #[std::bench]
    |        ^^^^^ could not find `bench` in `std`
 
 error[E0433]: failed to resolve: could not find `global_allocator` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:16:8
+  --> $DIR/builtin-std-paths-fail.rs:20:8
    |
 LL | #[std::global_allocator]
    |        ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `std`
 
 error[E0433]: failed to resolve: could not find `test_case` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:17:8
+  --> $DIR/builtin-std-paths-fail.rs:21:8
    |
 LL | #[std::test_case]
    |        ^^^^^^^^^ could not find `test_case` in `std`
 
 error[E0433]: failed to resolve: could not find `test` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:18:8
+  --> $DIR/builtin-std-paths-fail.rs:22:8
    |
 LL | #[std::test]
    |        ^^^^ could not find `test` in `std`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:12:10
+  --> $DIR/builtin-std-paths-fail.rs:14:10
    |
 LL |     std::RustcDecodable,
    |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:13:10
+  --> $DIR/builtin-std-paths-fail.rs:16:10
    |
 LL |     std::RustcDecodable,
    |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
 
-error: aborting due to 12 previous errors
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
+  --> $DIR/builtin-std-paths-fail.rs:16:10
+   |
+LL |     std::RustcDecodable,
+   |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
+
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
+  --> $DIR/builtin-std-paths-fail.rs:14:10
+   |
+LL |     std::RustcDecodable,
+   |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
+
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/issue-68058.rs b/src/test/ui/macros/issue-68058.rs
new file mode 100644
index 0000000..24da262
--- /dev/null
+++ b/src/test/ui/macros/issue-68058.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+macro_rules! foo {
+    ($doc: expr) => {
+        fn f() {
+            #[doc = $doc]
+            ()
+        }
+    };
+}
+
+foo!("doc");
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-name-typo.rs b/src/test/ui/macros/macro-name-typo.rs
index 1ddc419..b2892f3 100644
--- a/src/test/ui/macros/macro-name-typo.rs
+++ b/src/test/ui/macros/macro-name-typo.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 fn main() {
     printlx!("oh noes!"); //~ ERROR cannot find
 }
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
index ce2e198..00afbde 100644
--- a/src/test/ui/macros/macro-name-typo.stderr
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -1,8 +1,13 @@
 error: cannot find macro `printlx` in this scope
-  --> $DIR/macro-name-typo.rs:2:5
+  --> $DIR/macro-name-typo.rs:6:5
    |
 LL |     printlx!("oh noes!");
    |     ^^^^^^^ help: a macro with a similar name exists: `println`
+   | 
+  ::: $SRC_DIR/libstd/macros.rs:LL:COL
+   |
+LL | macro_rules! println {
+   | -------------------- similarly named macro `println` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs
index 68eb350..3c3948c 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.rs
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 fn main() {
     inline!(); //~ ERROR cannot find macro `inline` in this scope
 }
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index ec00760..5364590 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -1,8 +1,13 @@
 error: cannot find macro `inline` in this scope
-  --> $DIR/macro-path-prelude-fail-3.rs:2:5
+  --> $DIR/macro-path-prelude-fail-3.rs:6:5
    |
 LL |     inline!();
    |     ^^^^^^ help: a macro with a similar name exists: `line`
+   | 
+  ::: $SRC_DIR/libcore/macros/mod.rs:LL:COL
+   |
+LL |     macro_rules! line {
+   |     ----------------- similarly named macro `line` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-use-wrong-name.stderr b/src/test/ui/macros/macro-use-wrong-name.stderr
index 8b4e90a..74fb519 100644
--- a/src/test/ui/macros/macro-use-wrong-name.stderr
+++ b/src/test/ui/macros/macro-use-wrong-name.stderr
@@ -3,6 +3,11 @@
    |
 LL |     macro_two!();
    |     ^^^^^^^^^ help: a macro with a similar name exists: `macro_one`
+   | 
+  ::: $DIR/auxiliary/two_macros.rs:2:1
+   |
+LL | macro_rules! macro_one { () => ("one") }
+   | ---------------------- similarly named macro `macro_one` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/meta-item-absolute-path.rs b/src/test/ui/macros/meta-item-absolute-path.rs
index 14d23be..8ed911c 100644
--- a/src/test/ui/macros/meta-item-absolute-path.rs
+++ b/src/test/ui/macros/meta-item-absolute-path.rs
@@ -1,4 +1,5 @@
 #[derive(::Absolute)] //~ ERROR failed to resolve
+                      //~| ERROR failed to resolve
 struct S;
 
 fn main() {}
diff --git a/src/test/ui/macros/meta-item-absolute-path.stderr b/src/test/ui/macros/meta-item-absolute-path.stderr
index 711fa4d..c53971e 100644
--- a/src/test/ui/macros/meta-item-absolute-path.stderr
+++ b/src/test/ui/macros/meta-item-absolute-path.stderr
@@ -4,6 +4,12 @@
 LL | #[derive(::Absolute)]
    |            ^^^^^^^^ maybe a missing crate `Absolute`?
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: maybe a missing crate `Absolute`?
+  --> $DIR/meta-item-absolute-path.rs:1:12
+   |
+LL | #[derive(::Absolute)]
+   |            ^^^^^^^^ maybe a missing crate `Absolute`?
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/match/match-range-fail-2.rs b/src/test/ui/match/match-range-fail-2.rs
index 19e6e12..792664e 100644
--- a/src/test/ui/match/match-range-fail-2.rs
+++ b/src/test/ui/match/match-range-fail-2.rs
@@ -6,16 +6,19 @@
         _ => { }
     };
     //~^^^ ERROR lower range bound must be less than or equal to upper
+    //~| ERROR lower range bound must be less than or equal to upper
 
     match 5 {
         0 .. 0 => { }
         _ => { }
     };
     //~^^^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
 
     match 5u64 {
         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
         _ => { }
     };
     //~^^^ ERROR lower range bound must be less than or equal to upper
+    //~| ERROR lower range bound must be less than or equal to upper
 }
diff --git a/src/test/ui/match/match-range-fail-2.stderr b/src/test/ui/match/match-range-fail-2.stderr
index 52a2bf2..7a0852d 100644
--- a/src/test/ui/match/match-range-fail-2.stderr
+++ b/src/test/ui/match/match-range-fail-2.stderr
@@ -5,18 +5,36 @@
    |         ^ lower bound larger than upper bound
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/match-range-fail-2.rs:11:9
+  --> $DIR/match-range-fail-2.rs:12:9
    |
 LL |         0 .. 0 => { }
    |         ^
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/match-range-fail-2.rs:17:9
+  --> $DIR/match-range-fail-2.rs:19:9
    |
 LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
    |         ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
 
-error: aborting due to 3 previous errors
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/match-range-fail-2.rs:5:9
+   |
+LL |         6 ..= 1 => { }
+   |         ^ lower bound larger than upper bound
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/match-range-fail-2.rs:12:9
+   |
+LL |         0 .. 0 => { }
+   |         ^
+
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/match-range-fail-2.rs:19:9
+   |
+LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
+   |         ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
+
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0030, E0579.
 For more information about an error, try `rustc --explain E0030`.
diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs
index e0dec0a..5ff4b41 100644
--- a/src/test/ui/methods/method-call-err-msg.rs
+++ b/src/test/ui/methods/method-call-err-msg.rs
@@ -15,6 +15,6 @@
 
     let y = Foo;
     y.zero()
-     .take()    //~ ERROR no method named `take` found for type `Foo` in the current scope
+     .take()    //~ ERROR no method named `take` found
      .one(0);
 }
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index 94c27b7..7efdd91 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -25,7 +25,7 @@
 LL |      .two(0);
    |       ^^^ expected 2 parameters
 
-error[E0599]: no method named `take` found for type `Foo` in the current scope
+error[E0599]: no method named `take` found for struct `Foo` in the current scope
   --> $DIR/method-call-err-msg.rs:18:7
    |
 LL | pub struct Foo;
diff --git a/src/test/ui/mir/issue-67947.rs b/src/test/ui/mir/issue-67947.rs
new file mode 100644
index 0000000..79e75e6
--- /dev/null
+++ b/src/test/ui/mir/issue-67947.rs
@@ -0,0 +1,7 @@
+struct Bug {
+    A: [(); { *"" }.len()],
+    //~^ ERROR: cannot move a value of type str
+    //~| ERROR: cannot move out of a shared reference
+}
+
+fn main() {}
diff --git a/src/test/ui/mir/issue-67947.stderr b/src/test/ui/mir/issue-67947.stderr
new file mode 100644
index 0000000..d526218
--- /dev/null
+++ b/src/test/ui/mir/issue-67947.stderr
@@ -0,0 +1,16 @@
+error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+  --> $DIR/issue-67947.rs:2:13
+   |
+LL |     A: [(); { *"" }.len()],
+   |             ^^^^^^^
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/issue-67947.rs:2:15
+   |
+LL |     A: [(); { *"" }.len()],
+   |               ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index da018aa..f8d677b 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `count` found for type `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
+error[E0599]: no method named `count` found for struct `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
   --> $DIR/issue-36053-2.rs:7:55
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
index 83cea16..58ceaff 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
@@ -3,5 +3,5 @@
 fn main() {
     let a: Result<(), Foo> = Ok(());
     a.unwrap();
-    //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
+    //~^ ERROR no method named `unwrap` found
 }
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index 865092e..bbfb000 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `unwrap` found for type `std::result::Result<(), Foo>` in the current scope
+error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), Foo>` in the current scope
   --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index 0484661..13d727d 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -24,6 +24,11 @@
    |
 LL |     check(xm1::S);
    |           ^^^^^^
+   | 
+  ::: $DIR/auxiliary/namespace-mix.rs:3:5
+   |
+LL |     pub struct TS();
+   |     ---------------- similarly named tuple struct `TS` defined here
    |
    = note: can't use a type alias as a constructor
 help: a tuple struct with a similar name exists
@@ -64,6 +69,11 @@
    |
 LL |     check(xm7::V);
    |           ^^^^^^ did you mean `xm7::V { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/namespace-mix.rs:7:9
+   |
+LL |         TV(),
+   |         ---- similarly named tuple variant `TV` defined here
    |
 help: a tuple variant with a similar name exists
    |
diff --git a/src/test/ui/never_type/issue-2149.rs b/src/test/ui/never_type/issue-2149.rs
index d46f0e6..d6426d2 100644
--- a/src/test/ui/never_type/issue-2149.rs
+++ b/src/test/ui/never_type/issue-2149.rs
@@ -11,5 +11,5 @@
 }
 fn main() {
     ["hi"].bind(|x| [x] );
-    //~^ ERROR no method named `bind` found for type `[&str; 1]` in the current scope
+    //~^ ERROR no method named `bind` found
 }
diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr
index 8ce2ba0..9645244 100644
--- a/src/test/ui/never_type/issue-2149.stderr
+++ b/src/test/ui/never_type/issue-2149.stderr
@@ -6,7 +6,7 @@
    |
    = help: the trait `std::ops::Add<std::vec::Vec<B>>` is not implemented for `()`
 
-error[E0599]: no method named `bind` found for type `[&str; 1]` in the current scope
+error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope
   --> $DIR/issue-2149.rs:13:12
    |
 LL |     ["hi"].bind(|x| [x] );
diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr
index 8cb690a..65946ee 100644
--- a/src/test/ui/no-send-res-ports.stderr
+++ b/src/test/ui/no-send-res-ports.stderr
@@ -1,13 +1,20 @@
 error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
   --> $DIR/no-send-res-ports.rs:29:5
    |
-LL |     thread::spawn(move|| {
-   |     ^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
+LL |       thread::spawn(move|| {
+   |  _____^^^^^^^^^^^^^_-
+   | |     |
+   | |     `std::rc::Rc<()>` cannot be sent between threads safely
+LL | |
+LL | |         let y = x;
+LL | |         println!("{:?}", y);
+LL | |     });
+   | |_____- within this `[closure@$DIR/no-send-res-ports.rs:29:19: 33:6 x:main::Foo]`
    | 
   ::: $SRC_DIR/libstd/thread/mod.rs:LL:COL
    |
-LL |     F: Send + 'static,
-   |        ---- required by this bound in `std::thread::spawn`
+LL |       F: Send + 'static,
+   |          ---- required by this bound in `std::thread::spawn`
    |
    = help: within `[closure@$DIR/no-send-res-ports.rs:29:19: 33:6 x:main::Foo]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
    = note: required because it appears within the type `Port<()>`
diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr
index b05c29c..074ed66 100644
--- a/src/test/ui/non-copyable-void.stderr
+++ b/src/test/ui/non-copyable-void.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `libc::c_void` in the current scope
+error[E0599]: no method named `clone` found for enum `libc::c_void` in the current scope
   --> $DIR/non-copyable-void.rs:11:23
    |
 LL |         let _z = (*y).clone();
diff --git a/src/test/ui/non-ice-error-on-worker-io-fail.rs b/src/test/ui/non-ice-error-on-worker-io-fail.rs
new file mode 100644
index 0000000..8af1774
--- /dev/null
+++ b/src/test/ui/non-ice-error-on-worker-io-fail.rs
@@ -0,0 +1,37 @@
+// Issue #66530: We would ICE if someone compiled with `-o /dev/null`,
+// because we would try to generate auxiliary files in `/dev/` (which
+// at least the OS X file system rejects).
+//
+// An attempt to `-o` into a directory we cannot write into should indeed
+// be an error; but not an ICE.
+
+// compile-flags: -o /dev/null
+
+// The error-pattern check occurs *before* normalization, and the error patterns
+// are wildly different between build environments. So this is a cop-out (and we
+// rely on the checking of the normalized stderr output as our actual
+// "verification" of the diagnostic).
+
+// error-pattern: error
+
+// On Mac OS X, we get an error like the below
+// normalize-stderr-test "failed to write bytecode to /dev/null.non_ice_error_on_worker_io_fail.*" -> "io error modifying /dev/"
+
+// On Linux, we get an error like the below
+// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /dev/"
+
+// ignore-tidy-linelength
+// ignore-windows - this is a unix-specific test
+// ignore-emscripten - the file-system issues do not replicate here
+// ignore-wasm - the file-system issues do not replicate here
+// ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu
+
+#![crate_type="lib"]
+
+#![cfg_attr(not(feature = "std"), no_std)]
+pub mod task {
+    pub mod __internal {
+        use crate::task::Waker;
+    }
+    pub use core::task::Waker;
+}
diff --git a/src/test/ui/non-ice-error-on-worker-io-fail.stderr b/src/test/ui/non-ice-error-on-worker-io-fail.stderr
new file mode 100644
index 0000000..f5601ad
--- /dev/null
+++ b/src/test/ui/non-ice-error-on-worker-io-fail.stderr
@@ -0,0 +1,6 @@
+warning: ignoring --out-dir flag due to -o flag
+
+error: io error modifying /dev/
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
index c1c5021..6c3c4a6 100644
--- a/src/test/ui/noncopyable-class.stderr
+++ b/src/test/ui/noncopyable-class.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Foo` in the current scope
+error[E0599]: no method named `clone` found for struct `Foo` in the current scope
   --> $DIR/noncopyable-class.rs:34:16
    |
 LL | struct Foo {
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr
index b66391b..20c7f81 100644
--- a/src/test/ui/not-clone-closure.stderr
+++ b/src/test/ui/not-clone-closure.stderr
@@ -1,8 +1,14 @@
 error[E0277]: the trait bound `S: std::clone::Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
   --> $DIR/not-clone-closure.rs:11:23
    |
-LL |     let hello = hello.clone();
-   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S`
+LL |       let hello = move || {
+   |  _________________-
+LL | |         println!("Hello {}", a.0);
+LL | |     };
+   | |_____- within this `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
+LL | 
+LL |       let hello = hello.clone();
+   |                         ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S`
    |
    = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
 
diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr
index 2df628e..855894b 100644
--- a/src/test/ui/object-pointer-types.stderr
+++ b/src/test/ui/object-pointer-types.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `owned` found for type `&dyn Foo` in the current scope
+error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope
   --> $DIR/object-pointer-types.rs:11:7
    |
 LL |     x.owned();
@@ -8,7 +8,7 @@
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
            candidate #1: `Foo`
 
-error[E0599]: no method named `owned` found for type `&mut dyn Foo` in the current scope
+error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope
   --> $DIR/object-pointer-types.rs:17:7
    |
 LL |     x.owned();
@@ -18,7 +18,7 @@
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
            candidate #1: `Foo`
 
-error[E0599]: no method named `managed` found for type `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
+error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
   --> $DIR/object-pointer-types.rs:23:7
    |
 LL |     x.managed();
diff --git a/src/test/ui/parse-error-correct.rs b/src/test/ui/parse-error-correct.rs
index f167b35..13759a2 100644
--- a/src/test/ui/parse-error-correct.rs
+++ b/src/test/ui/parse-error-correct.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Test that the parser is error correcting missing idents. Despite a parsing
 // error (or two), we still run type checking (and don't get extra errors there).
 
diff --git a/src/test/ui/parse-error-correct.stderr b/src/test/ui/parse-error-correct.stderr
index d593431..c54baf0 100644
--- a/src/test/ui/parse-error-correct.stderr
+++ b/src/test/ui/parse-error-correct.stderr
@@ -1,17 +1,17 @@
 error: unexpected token: `;`
-  --> $DIR/parse-error-correct.rs:8:15
+  --> $DIR/parse-error-correct.rs:6:15
    |
 LL |     let x = y.;
    |               ^
 
 error: unexpected token: `(`
-  --> $DIR/parse-error-correct.rs:9:15
+  --> $DIR/parse-error-correct.rs:7:15
    |
 LL |     let x = y.();
    |               ^
 
 error[E0618]: expected function, found `{integer}`
-  --> $DIR/parse-error-correct.rs:9:13
+  --> $DIR/parse-error-correct.rs:7:13
    |
 LL |     let y = 42;
    |         - `{integer}` defined here
@@ -22,7 +22,7 @@
    |             call expression requires function
 
 error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
-  --> $DIR/parse-error-correct.rs:11:15
+  --> $DIR/parse-error-correct.rs:9:15
    |
 LL |     let x = y.foo;
    |               ^^^
diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser-recovery-1.rs
index dcc0dc0..7e26b4f 100644
--- a/src/test/ui/parser-recovery-1.rs
+++ b/src/test/ui/parser-recovery-1.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Test that we can recover from missing braces in the parser.
 
 trait Foo {
diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser-recovery-1.stderr
index 4d88191..f56060c 100644
--- a/src/test/ui/parser-recovery-1.stderr
+++ b/src/test/ui/parser-recovery-1.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/parser-recovery-1.rs:15:54
+  --> $DIR/parser-recovery-1.rs:13:54
    |
 LL | trait Foo {
    |           - unclosed delimiter
@@ -13,19 +13,19 @@
    |                                                      ^
 
 error: unexpected token: `;`
-  --> $DIR/parser-recovery-1.rs:12:15
+  --> $DIR/parser-recovery-1.rs:10:15
    |
 LL |     let x = y.;
    |               ^
 
 error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/parser-recovery-1.rs:7:17
+  --> $DIR/parser-recovery-1.rs:5:17
    |
 LL |         let x = foo();
    |                 ^^^ not found in this scope
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/parser-recovery-1.rs:12:13
+  --> $DIR/parser-recovery-1.rs:10:13
    |
 LL |     let x = y.;
    |             ^ not found in this scope
diff --git a/src/test/ui/parser-recovery-2.rs b/src/test/ui/parser-recovery-2.rs
index dc5be96..48b22af 100644
--- a/src/test/ui/parser-recovery-2.rs
+++ b/src/test/ui/parser-recovery-2.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Test that we can recover from mismatched braces in the parser.
 
 trait Foo {
diff --git a/src/test/ui/parser-recovery-2.stderr b/src/test/ui/parser-recovery-2.stderr
index c48211d..cd3da4c 100644
--- a/src/test/ui/parser-recovery-2.stderr
+++ b/src/test/ui/parser-recovery-2.stderr
@@ -1,11 +1,11 @@
 error: unexpected token: `;`
-  --> $DIR/parser-recovery-2.rs:12:15
+  --> $DIR/parser-recovery-2.rs:10:15
    |
 LL |     let x = y.;
    |               ^
 
 error: mismatched closing delimiter: `)`
-  --> $DIR/parser-recovery-2.rs:8:5
+  --> $DIR/parser-recovery-2.rs:6:5
    |
 LL |     fn bar() {
    |              - unclosed delimiter
@@ -14,13 +14,13 @@
    |     ^ mismatched closing delimiter
 
 error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/parser-recovery-2.rs:7:17
+  --> $DIR/parser-recovery-2.rs:5:17
    |
 LL |         let x = foo();
    |                 ^^^ not found in this scope
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/parser-recovery-2.rs:12:13
+  --> $DIR/parser-recovery-2.rs:10:13
    |
 LL |     let x = y.;
    |             ^ not found in this scope
diff --git a/src/test/ui/parser/ascii-only-character-escape.rs b/src/test/ui/parser/ascii-only-character-escape.rs
index f1b028e..20d3edf 100644
--- a/src/test/ui/parser/ascii-only-character-escape.rs
+++ b/src/test/ui/parser/ascii-only-character-escape.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     let x = "\x80"; //~ ERROR may only be used
     let y = "\xff"; //~ ERROR may only be used
diff --git a/src/test/ui/parser/ascii-only-character-escape.stderr b/src/test/ui/parser/ascii-only-character-escape.stderr
index 3916779..cf51b00 100644
--- a/src/test/ui/parser/ascii-only-character-escape.stderr
+++ b/src/test/ui/parser/ascii-only-character-escape.stderr
@@ -1,17 +1,17 @@
 error: this form of character escape may only be used with characters in the range [\x00-\x7f]
-  --> $DIR/ascii-only-character-escape.rs:4:14
+  --> $DIR/ascii-only-character-escape.rs:2:14
    |
 LL |     let x = "\x80";
    |              ^^^^
 
 error: this form of character escape may only be used with characters in the range [\x00-\x7f]
-  --> $DIR/ascii-only-character-escape.rs:5:14
+  --> $DIR/ascii-only-character-escape.rs:3:14
    |
 LL |     let y = "\xff";
    |              ^^^^
 
 error: this form of character escape may only be used with characters in the range [\x00-\x7f]
-  --> $DIR/ascii-only-character-escape.rs:6:14
+  --> $DIR/ascii-only-character-escape.rs:4:14
    |
 LL |     let z = "\xe2";
    |              ^^^^
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
index f6d2bee..118bff8 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
@@ -1,3 +1,5 @@
+#![feature(half_open_range_patterns)]
+
 fn main() {}
 
 #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
@@ -90,15 +92,15 @@
 // note: requires parens in patterns to allow disambiguation
 
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
 //~^ ERROR unexpected token: `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 
 #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
index 0123006..4775b9b 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -1,5 +1,5 @@
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:3:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:5:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
    |                                    ^^^^^^^^
@@ -7,19 +7,19 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `]`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:5:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:7:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
    |                                        ^ expected expression
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:7:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:9:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
    |                                   ^ expected one of 7 possible tokens
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:9:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:11:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                    ^^^^^^^^
@@ -27,13 +27,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `)`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:9:44
+  --> $DIR/attr-stmt-expr-attr-bad.rs:11:44
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                            ^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:12:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:14:38
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                      ^^^^^^^^
@@ -41,13 +41,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `)`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:12:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:14:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                              ^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:15:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:17:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
    |                                    ^^^^^^^^
@@ -55,7 +55,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:17:33
+  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
    |
 LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
    |                                 ^^^^^^^^
@@ -63,7 +63,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
+  --> $DIR/attr-stmt-expr-attr-bad.rs:21:33
    |
 LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
    |                                 ^^^^^^^^
@@ -71,13 +71,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:21:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:23:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
    |                                  ^ expected one of 7 possible tokens
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:23:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:25:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
    |                                   ^^^^^^^^
@@ -85,7 +85,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:25:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:27:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
    |                                        ^^^^^^^^
@@ -93,7 +93,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:27:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:29:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
    |                                   ^^^^^^^^
@@ -101,7 +101,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:29:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
    |                                        ^^^^^^^^
@@ -109,19 +109,19 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `..`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
    |                                        ^^ expected expression
 
 error: expected expression, found `..`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:35:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
    |                                        ^^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:35:41
+  --> $DIR/attr-stmt-expr-attr-bad.rs:37:41
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
    |                                         ^^^^^^^^
@@ -129,7 +129,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:37:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:39:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    |                                             ^^^^^^^^
@@ -137,13 +137,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:39:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:41:32
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
    |                                ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
+  --> $DIR/attr-stmt-expr-attr-bad.rs:43:37
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
    |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -152,7 +152,7 @@
    |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:45:38
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    |                                      ^^^^^^^^
@@ -160,13 +160,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:47:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
    |                                        ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:49:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
    |                                             ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -174,7 +174,7 @@
    |                                             expected `{`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    |                                              ^^^^^^^^
@@ -182,13 +182,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
    |                                             ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
    |                                             ^       -------- help: try placing this code inside a block: `{ if 0 {}; }`
@@ -196,7 +196,7 @@
    |                                             expected `{`
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:54:50
+  --> $DIR/attr-stmt-expr-attr-bad.rs:56:50
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
    |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -205,7 +205,7 @@
    |                                             this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:56:51
+  --> $DIR/attr-stmt-expr-attr-bad.rs:58:51
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    |                                                   ^^^^^^^^
@@ -213,13 +213,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:58:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:60:32
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
    |                                ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:60:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:62:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
    |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -228,7 +228,7 @@
    |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:62:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:64:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    |                                              ^^^^^^^^
@@ -236,13 +236,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:64:48
+  --> $DIR/attr-stmt-expr-attr-bad.rs:66:48
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
    |                                                ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:66:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:68:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
    |                                                     ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -250,7 +250,7 @@
    |                                                     expected `{`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:68:54
+  --> $DIR/attr-stmt-expr-attr-bad.rs:70:54
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    |                                                      ^^^^^^^^
@@ -258,13 +258,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
    |                                                     ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
    |                                                     ^       ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
@@ -272,7 +272,7 @@
    |                                                     expected `{`
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:73:66
+  --> $DIR/attr-stmt-expr-attr-bad.rs:75:66
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
    |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -281,7 +281,7 @@
    |                                                     this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:75:67
+  --> $DIR/attr-stmt-expr-attr-bad.rs:77:67
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
    |                                                                   ^^^^^^^^
@@ -289,7 +289,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -299,7 +299,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -309,7 +309,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -319,7 +319,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -329,7 +329,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:88:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -338,83 +338,90 @@
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:92:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:94:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:92:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:94:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:95:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:97:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:95:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:97:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:98:39
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:39
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
    |                                       ^
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:102:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:100:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:102:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:104:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:104:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:107:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:107:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:112:44
+  --> $DIR/attr-stmt-expr-attr-bad.rs:114:44
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
    |                                            ^
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:114:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:116:45
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
    |                                             ^
 
 error: aborting due to 57 previous errors
 
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/parser/bad-char-literals.rs b/src/test/ui/parser/bad-char-literals.rs
index 1c9b597..11696b8 100644
--- a/src/test/ui/parser/bad-char-literals.rs
+++ b/src/test/ui/parser/bad-char-literals.rs
Binary files differ
diff --git a/src/test/ui/parser/bad-char-literals.stderr b/src/test/ui/parser/bad-char-literals.stderr
index 8e96ea2..093978f 100644
--- a/src/test/ui/parser/bad-char-literals.stderr
+++ b/src/test/ui/parser/bad-char-literals.stderr
Binary files differ
diff --git a/src/test/ui/parser/bounds-type.rs b/src/test/ui/parser/bounds-type.rs
index 9122cb4..7a187a0 100644
--- a/src/test/ui/parser/bounds-type.rs
+++ b/src/test/ui/parser/bounds-type.rs
@@ -8,6 +8,11 @@
     T: ?for<'a> Trait, // OK
     T: Tr +, // OK
     T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
+
+    T: ?const Tr, // OK
+    T: ?const ?Tr, // OK
+    T: ?const Tr + 'a, // OK
+    T: ?const 'a, //~ ERROR `?const` may only modify trait bounds, not lifetime bounds
 >;
 
 fn main() {}
diff --git a/src/test/ui/parser/bounds-type.stderr b/src/test/ui/parser/bounds-type.stderr
index 0b714e4..9a1f2ed 100644
--- a/src/test/ui/parser/bounds-type.stderr
+++ b/src/test/ui/parser/bounds-type.stderr
@@ -4,5 +4,11 @@
 LL |     T: ?'a,
    |        ^
 
-error: aborting due to previous error
+error: `?const` may only modify trait bounds, not lifetime bounds
+  --> $DIR/bounds-type.rs:15:8
+   |
+LL |     T: ?const 'a,
+   |        ^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/byte-literals.rs b/src/test/ui/parser/byte-literals.rs
index bd358af..dadf397 100644
--- a/src/test/ui/parser/byte-literals.rs
+++ b/src/test/ui/parser/byte-literals.rs
@@ -1,6 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
-
 // ignore-tidy-tab
 
 static FOO: u8 = b'\f';  //~ ERROR unknown byte escape
diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr
index 58a5797..53d50af 100644
--- a/src/test/ui/parser/byte-literals.stderr
+++ b/src/test/ui/parser/byte-literals.stderr
@@ -1,41 +1,41 @@
 error: unknown byte escape: f
-  --> $DIR/byte-literals.rs:6:21
+  --> $DIR/byte-literals.rs:3:21
    |
 LL | static FOO: u8 = b'\f';
    |                     ^ unknown byte escape
 
 error: unknown byte escape: f
-  --> $DIR/byte-literals.rs:9:8
+  --> $DIR/byte-literals.rs:6:8
    |
 LL |     b'\f';
    |        ^ unknown byte escape
 
 error: invalid character in numeric character escape: Z
-  --> $DIR/byte-literals.rs:10:10
+  --> $DIR/byte-literals.rs:7:10
    |
 LL |     b'\x0Z';
    |          ^
 
 error: byte constant must be escaped: \t
-  --> $DIR/byte-literals.rs:11:7
+  --> $DIR/byte-literals.rs:8:7
    |
 LL |     b'    ';
    |       ^^^^
 
 error: byte constant must be escaped: '
-  --> $DIR/byte-literals.rs:12:7
+  --> $DIR/byte-literals.rs:9:7
    |
 LL |     b''';
    |       ^
 
 error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
-  --> $DIR/byte-literals.rs:13:7
+  --> $DIR/byte-literals.rs:10:7
    |
 LL |     b'é';
    |       ^
 
 error: unterminated byte constant
-  --> $DIR/byte-literals.rs:14:6
+  --> $DIR/byte-literals.rs:11:6
    |
 LL |     b'a
    |      ^^^^
diff --git a/src/test/ui/parser/byte-string-literals.rs b/src/test/ui/parser/byte-string-literals.rs
index 8d8ee4d..caffd9e 100644
--- a/src/test/ui/parser/byte-string-literals.rs
+++ b/src/test/ui/parser/byte-string-literals.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 static FOO: &'static [u8] = b"\f";  //~ ERROR unknown byte escape
 
 pub fn main() {
diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr
index eeb2fcd..ca964cd 100644
--- a/src/test/ui/parser/byte-string-literals.stderr
+++ b/src/test/ui/parser/byte-string-literals.stderr
@@ -1,29 +1,29 @@
 error: unknown byte escape: f
-  --> $DIR/byte-string-literals.rs:3:32
+  --> $DIR/byte-string-literals.rs:1:32
    |
 LL | static FOO: &'static [u8] = b"\f";
    |                                ^ unknown byte escape
 
 error: unknown byte escape: f
-  --> $DIR/byte-string-literals.rs:6:8
+  --> $DIR/byte-string-literals.rs:4:8
    |
 LL |     b"\f";
    |        ^ unknown byte escape
 
 error: invalid character in numeric character escape: Z
-  --> $DIR/byte-string-literals.rs:7:10
+  --> $DIR/byte-string-literals.rs:5:10
    |
 LL |     b"\x0Z";
    |          ^
 
 error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
-  --> $DIR/byte-string-literals.rs:8:7
+  --> $DIR/byte-string-literals.rs:6:7
    |
 LL |     b"é";
    |       ^
 
 error: unterminated double quote byte string
-  --> $DIR/byte-string-literals.rs:9:6
+  --> $DIR/byte-string-literals.rs:7:6
    |
 LL |       b"a
    |  ______^
diff --git a/src/test/ui/parser/chained-comparison-suggestion.rs b/src/test/ui/parser/chained-comparison-suggestion.rs
new file mode 100644
index 0000000..0431196
--- /dev/null
+++ b/src/test/ui/parser/chained-comparison-suggestion.rs
@@ -0,0 +1,40 @@
+// Check that we get nice suggestions when attempting a chained comparison.
+
+fn comp1() {
+    1 < 2 <= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp2() {
+    1 < 2 < 3; //~ ERROR comparison operators cannot be chained
+}
+
+fn comp3() {
+    1 <= 2 < 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp4() {
+    1 <= 2 <= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp5() {
+    1 > 2 >= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp6() {
+    1 > 2 > 3; //~ ERROR comparison operators cannot be chained
+}
+
+fn comp7() {
+    1 >= 2 > 3; //~ ERROR comparison operators cannot be chained
+}
+
+fn comp8() {
+    1 >= 2 >= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/chained-comparison-suggestion.stderr b/src/test/ui/parser/chained-comparison-suggestion.stderr
new file mode 100644
index 0000000..5c10a45
--- /dev/null
+++ b/src/test/ui/parser/chained-comparison-suggestion.stderr
@@ -0,0 +1,159 @@
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:4:7
+   |
+LL |     1 < 2 <= 3;
+   |       ^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 < 2 && 2 <= 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 < 2) <= 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:9:7
+   |
+LL |     1 < 2 < 3;
+   |       ^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+help: split the comparison into two...
+   |
+LL |     1 < 2 && 2 < 3;
+   |     ^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 < 2) < 3;
+   |     ^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:13:7
+   |
+LL |     1 <= 2 < 3;
+   |       ^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 <= 2 && 2 < 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 <= 2) < 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:18:7
+   |
+LL |     1 <= 2 <= 3;
+   |       ^^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 <= 2 && 2 <= 3;
+   |     ^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 <= 2) <= 3;
+   |     ^^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:23:7
+   |
+LL |     1 > 2 >= 3;
+   |       ^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 > 2 && 2 >= 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 > 2) >= 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:28:7
+   |
+LL |     1 > 2 > 3;
+   |       ^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+help: split the comparison into two...
+   |
+LL |     1 > 2 && 2 > 3;
+   |     ^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 > 2) > 3;
+   |     ^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:32:7
+   |
+LL |     1 >= 2 > 3;
+   |       ^^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+help: split the comparison into two...
+   |
+LL |     1 >= 2 && 2 > 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 >= 2) > 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:36:7
+   |
+LL |     1 >= 2 >= 3;
+   |       ^^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 >= 2 && 2 >= 3;
+   |     ^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 >= 2) >= 3;
+   |     ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:4:14
+   |
+LL |     1 < 2 <= 3;
+   |              ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:13:14
+   |
+LL |     1 <= 2 < 3;
+   |              ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:18:15
+   |
+LL |     1 <= 2 <= 3;
+   |               ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:23:14
+   |
+LL |     1 > 2 >= 3;
+   |              ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:36:15
+   |
+LL |     1 >= 2 >= 3;
+   |               ^ expected `bool`, found integer
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs
index c2a80e8..270c8b4 100644
--- a/src/test/ui/parser/impl-parsing.rs
+++ b/src/test/ui/parser/impl-parsing.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 impl ! {} // OK
 impl ! where u8: Copy {} // OK
 
diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr
index e929fa5..7c2a793 100644
--- a/src/test/ui/parser/impl-parsing.stderr
+++ b/src/test/ui/parser/impl-parsing.stderr
@@ -1,29 +1,29 @@
 error: missing `for` in a trait impl
-  --> $DIR/impl-parsing.rs:6:11
+  --> $DIR/impl-parsing.rs:4:11
    |
 LL | impl Trait Type {}
    |           ^ help: add `for` here
 
 error: missing `for` in a trait impl
-  --> $DIR/impl-parsing.rs:7:11
+  --> $DIR/impl-parsing.rs:5:11
    |
 LL | impl Trait .. {}
    |           ^ help: add `for` here
 
 error: expected a trait, found type
-  --> $DIR/impl-parsing.rs:8:6
+  --> $DIR/impl-parsing.rs:6:6
    |
 LL | impl ?Sized for Type {}
    |      ^^^^^^
 
 error: expected a trait, found type
-  --> $DIR/impl-parsing.rs:9:6
+  --> $DIR/impl-parsing.rs:7:6
    |
 LL | impl ?Sized for .. {}
    |      ^^^^^^
 
 error: expected `impl`, found `FAIL`
-  --> $DIR/impl-parsing.rs:11:16
+  --> $DIR/impl-parsing.rs:9:16
    |
 LL | default unsafe FAIL
    |                ^^^^ expected `impl`
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issue-23620-invalid-escapes.rs
index 5362997..ab445a9 100644
--- a/src/test/ui/parser/issue-23620-invalid-escapes.rs
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     let _ = b"\u{a66e}";
     //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
index 5fabc1d..b391ac7 100644
--- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
@@ -1,17 +1,17 @@
 error: unicode escape sequences cannot be used as a byte or in a byte string
-  --> $DIR/issue-23620-invalid-escapes.rs:4:15
+  --> $DIR/issue-23620-invalid-escapes.rs:2:15
    |
 LL |     let _ = b"\u{a66e}";
    |               ^^^^^^^^
 
 error: unicode escape sequences cannot be used as a byte or in a byte string
-  --> $DIR/issue-23620-invalid-escapes.rs:7:15
+  --> $DIR/issue-23620-invalid-escapes.rs:5:15
    |
 LL |     let _ = b'\u{a66e}';
    |               ^^^^^^^^
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:10:15
+  --> $DIR/issue-23620-invalid-escapes.rs:8:15
    |
 LL |     let _ = b'\u';
    |               ^^ incorrect unicode escape sequence
@@ -19,43 +19,43 @@
    = help: format of unicode escape sequences is `\u{...}`
 
 error: numeric character escape is too short
-  --> $DIR/issue-23620-invalid-escapes.rs:13:15
+  --> $DIR/issue-23620-invalid-escapes.rs:11:15
    |
 LL |     let _ = b'\x5';
    |               ^^^
 
 error: invalid character in numeric character escape: x
-  --> $DIR/issue-23620-invalid-escapes.rs:16:17
+  --> $DIR/issue-23620-invalid-escapes.rs:14:17
    |
 LL |     let _ = b'\xxy';
    |                 ^
 
 error: numeric character escape is too short
-  --> $DIR/issue-23620-invalid-escapes.rs:19:14
+  --> $DIR/issue-23620-invalid-escapes.rs:17:14
    |
 LL |     let _ = '\x5';
    |              ^^^
 
 error: invalid character in numeric character escape: x
-  --> $DIR/issue-23620-invalid-escapes.rs:22:16
+  --> $DIR/issue-23620-invalid-escapes.rs:20:16
    |
 LL |     let _ = '\xxy';
    |                ^
 
 error: unicode escape sequences cannot be used as a byte or in a byte string
-  --> $DIR/issue-23620-invalid-escapes.rs:25:15
+  --> $DIR/issue-23620-invalid-escapes.rs:23:15
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
    |               ^^^^^^^^
 
 error: invalid character in numeric character escape:  
-  --> $DIR/issue-23620-invalid-escapes.rs:25:27
+  --> $DIR/issue-23620-invalid-escapes.rs:23:27
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
    |                           ^
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:25:28
+  --> $DIR/issue-23620-invalid-escapes.rs:23:28
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
    |                            ^^ incorrect unicode escape sequence
@@ -63,13 +63,13 @@
    = help: format of unicode escape sequences is `\u{...}`
 
 error: invalid character in numeric character escape:  
-  --> $DIR/issue-23620-invalid-escapes.rs:30:17
+  --> $DIR/issue-23620-invalid-escapes.rs:28:17
    |
 LL |     let _ = "\xf \u";
    |                 ^
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:30:18
+  --> $DIR/issue-23620-invalid-escapes.rs:28:18
    |
 LL |     let _ = "\xf \u";
    |                  ^^ incorrect unicode escape sequence
@@ -77,7 +77,7 @@
    = help: format of unicode escape sequences is `\u{...}`
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:34:14
+  --> $DIR/issue-23620-invalid-escapes.rs:32:14
    |
 LL |     let _ = "\u8f";
    |              ^^--
diff --git a/src/test/ui/parser/issue-62913.rs b/src/test/ui/parser/issue-62913.rs
index cfa19a2..0db06f6 100644
--- a/src/test/ui/parser/issue-62913.rs
+++ b/src/test/ui/parser/issue-62913.rs
@@ -1,3 +1,4 @@
 "\u\\"
 //~^ ERROR incorrect unicode escape sequence
 //~| ERROR invalid trailing slash in literal
+//~| ERROR expected item, found `"\u\\"`
diff --git a/src/test/ui/parser/issue-62913.stderr b/src/test/ui/parser/issue-62913.stderr
index 05c5c4d..f72174f 100644
--- a/src/test/ui/parser/issue-62913.stderr
+++ b/src/test/ui/parser/issue-62913.stderr
@@ -12,5 +12,11 @@
 LL | "\u\"
    |     ^
 
-error: aborting due to 2 previous errors
+error: expected item, found `"\u\"`
+  --> $DIR/issue-62913.rs:1:1
+   |
+LL | "\u\"
+   | ^^^^^^ expected item
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/issue-62973.rs b/src/test/ui/parser/issue-62973.rs
index 18bc51e..1c5d0c6 100644
--- a/src/test/ui/parser/issue-62973.rs
+++ b/src/test/ui/parser/issue-62973.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 6 previous errors
+// error-pattern: aborting due to 7 previous errors
 
 fn main() {}
 
diff --git a/src/test/ui/parser/issue-62973.stderr b/src/test/ui/parser/issue-62973.stderr
index e95e629..95ee52d 100644
--- a/src/test/ui/parser/issue-62973.stderr
+++ b/src/test/ui/parser/issue-62973.stderr
@@ -9,6 +9,17 @@
 LL | 
    |  ^
 
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62973.rs:8:2
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |        -         - unclosed delimiter
+   |        |
+   |        unclosed delimiter
+LL | 
+LL | 
+   |  ^
+
 error: expected one of `,` or `}`, found `{`
   --> $DIR/issue-62973.rs:6:25
    |
@@ -60,5 +71,5 @@
    |                              |
    |                              unclosed delimiter
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
index a7d10ca..8efb3c7 100644
--- a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
+++ b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
@@ -1,6 +1,7 @@
 // check-pass
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 
 #![allow(ellipsis_inclusive_range_patterns)]
 
@@ -10,6 +11,11 @@
             if let 2...$e = 3 {}
             if let 2..=$e = 3 {}
             if let 2..$e = 3 {}
+            if let ..$e = 3 {}
+            if let ..=$e = 3 {}
+            if let $e.. = 5 {}
+            if let $e..5 = 4 {}
+            if let $e..=5 = 4 {}
         }
     }
     mac_expr!(4);
diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issue-63135.rs
index a5a8de8..d5f5f14 100644
--- a/src/test/ui/parser/issue-63135.rs
+++ b/src/test/ui/parser/issue-63135.rs
@@ -1,3 +1,3 @@
-// error-pattern: aborting due to 5 previous errors
+// error-pattern: aborting due to 6 previous errors
 
 fn i(n{...,f #
diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issue-63135.stderr
index a6fb037..462fdf1 100644
--- a/src/test/ui/parser/issue-63135.stderr
+++ b/src/test/ui/parser/issue-63135.stderr
@@ -7,6 +7,15 @@
    |     | unclosed delimiter
    |     unclosed delimiter
 
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-63135.rs:3:16
+   |
+LL | fn i(n{...,f #
+   |     - -        ^
+   |     | |
+   |     | unclosed delimiter
+   |     unclosed delimiter
+
 error: expected field pattern, found `...`
   --> $DIR/issue-63135.rs:3:8
    |
@@ -34,5 +43,5 @@
 LL | fn i(n{...,f #
    |                ^ expected one of `:` or `|`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
index 1730adf..5ec143f 100644
--- a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
+++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 // The problem in #66357 was that the call trace:
 //
 // - parse_fn_block_decl
@@ -11,4 +13,4 @@
 
 fn f() { |[](* }
 //~^ ERROR expected one of `,` or `:`, found `(`
-//~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
index 00d84e2a..c381099 100644
--- a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
+++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
@@ -1,11 +1,11 @@
 error: expected one of `,` or `:`, found `(`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:13
+  --> $DIR/issue-66357-unexpected-unreachable.rs:14:13
    |
 LL | fn f() { |[](* }
    |             ^ expected one of `,` or `:`
 
-error: expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:14
+error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+  --> $DIR/issue-66357-unexpected-unreachable.rs:14:14
    |
 LL | fn f() { |[](* }
    |             -^ help: `)` may belong here
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.rs b/src/test/ui/parser/lex-bad-char-literals-1.rs
index 54d75ed..e7951cf 100644
--- a/src/test/ui/parser/lex-bad-char-literals-1.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-1.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
 static c3: char =
     '\x1' //~ ERROR: numeric character escape is too short
 ;
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/parser/lex-bad-char-literals-1.stderr
index 000d155..fcf4802 100644
--- a/src/test/ui/parser/lex-bad-char-literals-1.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-1.stderr
@@ -1,23 +1,23 @@
 error: numeric character escape is too short
-  --> $DIR/lex-bad-char-literals-1.rs:3:6
+  --> $DIR/lex-bad-char-literals-1.rs:2:6
    |
 LL |     '\x1'
    |      ^^^
 
 error: numeric character escape is too short
-  --> $DIR/lex-bad-char-literals-1.rs:7:6
+  --> $DIR/lex-bad-char-literals-1.rs:6:6
    |
 LL |     "\x1"
    |      ^^^
 
 error: unknown character escape: \u{25cf}
-  --> $DIR/lex-bad-char-literals-1.rs:11:7
+  --> $DIR/lex-bad-char-literals-1.rs:10:7
    |
 LL |     '\●'
    |       ^ unknown character escape
 
 error: unknown character escape: \u{25cf}
-  --> $DIR/lex-bad-char-literals-1.rs:15:7
+  --> $DIR/lex-bad-char-literals-1.rs:14:7
    |
 LL |     "\●"
    |       ^ unknown character escape
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.rs b/src/test/ui/parser/lex-bad-char-literals-7.rs
index 70eafcb..1580157 100644
--- a/src/test/ui/parser/lex-bad-char-literals-7.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-7.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
 fn main() {
     let _: char = '';
     //~^ ERROR: empty character literal
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.stderr b/src/test/ui/parser/lex-bad-char-literals-7.stderr
index e1ba3c3..ee9aa86 100644
--- a/src/test/ui/parser/lex-bad-char-literals-7.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-7.stderr
@@ -1,17 +1,17 @@
 error: empty character literal
-  --> $DIR/lex-bad-char-literals-7.rs:3:20
+  --> $DIR/lex-bad-char-literals-7.rs:2:20
    |
 LL |     let _: char = '';
    |                    ^
 
 error: empty unicode escape (must have at least 1 hex digit)
-  --> $DIR/lex-bad-char-literals-7.rs:5:20
+  --> $DIR/lex-bad-char-literals-7.rs:4:20
    |
 LL |     let _: char = '\u{}';
    |                    ^^^^
 
 error: unterminated character literal
-  --> $DIR/lex-bad-char-literals-7.rs:12:13
+  --> $DIR/lex-bad-char-literals-7.rs:11:13
    |
 LL |     let _ = ' hello // here's a comment
    |             ^^^^^^^^
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
index b588b00..9a9f9c4 100644
--- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
Binary files differ
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
index b0fe4b6..598da6b 100644
--- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
Binary files differ
diff --git a/src/test/ui/parser/missing_right_paren.rs b/src/test/ui/parser/missing_right_paren.rs
index 4f7c5ee..c35236c 100644
--- a/src/test/ui/parser/missing_right_paren.rs
+++ b/src/test/ui/parser/missing_right_paren.rs
@@ -1,3 +1,3 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 2 previous errors
+// error-pattern: aborting due to 3 previous errors
 fn main((ؼ
\ No newline at end of file
diff --git a/src/test/ui/parser/missing_right_paren.stderr b/src/test/ui/parser/missing_right_paren.stderr
index c98b6bb..d67e7c8 100644
--- a/src/test/ui/parser/missing_right_paren.stderr
+++ b/src/test/ui/parser/missing_right_paren.stderr
@@ -7,11 +7,20 @@
    |        |unclosed delimiter
    |        unclosed delimiter
 
+error: this file contains an unclosed delimiter
+  --> $DIR/missing_right_paren.rs:3:11
+   |
+LL | fn main((ؼ
+   |        -- ^
+   |        ||
+   |        |unclosed delimiter
+   |        unclosed delimiter
+
 error: expected one of `:` or `|`, found `)`
   --> $DIR/missing_right_paren.rs:3:11
    |
 LL | fn main((ؼ
    |           ^ expected one of `:` or `|`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs
deleted file mode 100644
index 2f03160..0000000
--- a/src/test/ui/parser/pat-tuple-4.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-fn main() {
-    const PAT: u8 = 0;
-
-    match 0 {
-        (.. PAT) => {}
-        //~^ ERROR `..X` range patterns are not supported
-        //~| ERROR exclusive range pattern syntax is experimental
-    }
-}
-
-const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr
deleted file mode 100644
index 6c64290..0000000
--- a/src/test/ui/parser/pat-tuple-4.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error: `..X` range patterns are not supported
-  --> $DIR/pat-tuple-4.rs:5:10
-   |
-LL |         (.. PAT) => {}
-   |          ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-4.rs:5:10
-   |
-LL |         (.. PAT) => {}
-   |          ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
-error[E0308]: mismatched types
-  --> $DIR/pat-tuple-4.rs:11:30
-   |
-LL | const RECOVERY_WITNESS: () = 0;
-   |                              ^ expected `()`, found integer
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs
deleted file mode 100644
index 5334ef9..0000000
--- a/src/test/ui/parser/pat-tuple-5.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    const PAT: u8 = 0;
-
-    match (0, 1) {
-        (PAT ..) => {}
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR exclusive range pattern syntax is experimental
-        //~| ERROR mismatched types
-    }
-}
diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr
deleted file mode 100644
index 8ff4f94..0000000
--- a/src/test/ui/parser/pat-tuple-5.stderr
+++ /dev/null
@@ -1,30 +0,0 @@
-error: `X..` range patterns are not supported
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |         (PAT ..) => {}
-   |          ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |         (PAT ..) => {}
-   |          ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
-error[E0308]: mismatched types
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |     match (0, 1) {
-   |           ------ this expression has type `({integer}, {integer})`
-LL |         (PAT ..) => {}
-   |          ^^^ expected tuple, found `u8`
-   |
-   = note: expected tuple `({integer}, {integer})`
-               found type `u8`
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/range_inclusive.rs b/src/test/ui/parser/range_inclusive.rs
index bc61c5b..7c3b906 100644
--- a/src/test/ui/parser/range_inclusive.rs
+++ b/src/test/ui/parser/range_inclusive.rs
@@ -2,5 +2,5 @@
 
 pub fn main() {
     for _ in 1..= {} //~ERROR inclusive range with no end
-                     //~^HELP bounded at the end
+                     //~^HELP use `..` instead
 }
diff --git a/src/test/ui/parser/range_inclusive.stderr b/src/test/ui/parser/range_inclusive.stderr
index 12b7eda..1dd4799 100644
--- a/src/test/ui/parser/range_inclusive.stderr
+++ b/src/test/ui/parser/range_inclusive.stderr
@@ -1,10 +1,10 @@
 error[E0586]: inclusive range with no end
-  --> $DIR/range_inclusive.rs:4:19
+  --> $DIR/range_inclusive.rs:4:15
    |
 LL |     for _ in 1..= {}
-   |                   ^
+   |               ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/raw-byte-string-literals.rs b/src/test/ui/parser/raw-byte-string-literals.rs
index 534afab..163c8ac 100644
--- a/src/test/ui/parser/raw-byte-string-literals.rs
+++ b/src/test/ui/parser/raw-byte-string-literals.rs
Binary files differ
diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs
index 260e108..e07ea62 100644
--- a/src/test/ui/parser/recover-range-pats.rs
+++ b/src/test/ui/parser/recover-range-pats.rs
@@ -4,6 +4,7 @@
 // 2. Or at least we have parser recovery if they don't.
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 #![deny(ellipsis_inclusive_range_patterns)]
 
 fn main() {}
@@ -55,70 +56,66 @@
 }
 
 fn exclusive_from() {
-    if let 0.. = 0 {} //~ ERROR `X..` range patterns are not supported
-    if let X.. = 0 {} //~ ERROR `X..` range patterns are not supported
-    if let true.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let 0.. = 0 {}
+    if let X.. = 0 {}
+    if let true.. = 0 {}
     //~^ ERROR only char and numeric types
-    if let .0.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let .0.. = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive_from() {
-    if let 0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
-    if let X..= = 0 {} //~ ERROR `X..=` range patterns are not supported
-    if let true..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let 0..= = 0 {} //~ ERROR inclusive range with no end
+    if let X..= = 0 {} //~ ERROR inclusive range with no end
+    if let true..= = 0 {} //~ ERROR inclusive range with no end
     //~| ERROR only char and numeric types
-    if let .0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let .0..= = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive2_from() {
-    if let 0... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let X... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let true... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
+    if let 0... = 0 {} //~ ERROR inclusive range with no end
+    if let X... = 0 {} //~ ERROR inclusive range with no end
+    if let true... = 0 {} //~ ERROR inclusive range with no end
     //~| ERROR only char and numeric types
-    if let .0... = 0 {} //~ ERROR `X...` range patterns are not supported
+    if let .0... = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
-    //~| ERROR `...` range patterns are deprecated
     //~| ERROR mismatched types
 }
 
 fn exclusive_to() {
-    if let ..0 = 0 {} //~ ERROR `..X` range patterns are not supported
-    if let ..Y = 0 {} //~ ERROR `..X` range patterns are not supported
-    if let ..true = 0 {} //~ ERROR `..X` range patterns are not supported
-    //~| ERROR only char and numeric types
-    if let .. .0 = 0 {} //~ ERROR `..X` range patterns are not supported
+    if let ..0 = 0 {}
+    if let ..Y = 0 {}
+    if let ..true = 0 {}
+    //~^ ERROR only char and numeric types
+    if let .. .0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive_to() {
-    if let ..=3 = 0 {} //~ ERROR `..=X` range patterns are not supported
-    if let ..=Y = 0 {} //~ ERROR `..=X` range patterns are not supported
-    if let ..=true = 0 {} //~ ERROR `..=X` range patterns are not supported
-    //~| ERROR only char and numeric types
-    if let ..=.0 = 0 {} //~ ERROR `..=X` range patterns are not supported
+    if let ..=3 = 0 {}
+    if let ..=Y = 0 {}
+    if let ..=true = 0 {}
+    //~^ ERROR only char and numeric types
+    if let ..=.0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive2_to() {
-    if let ...3 = 0 {} //~ ERROR `...X` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let ...Y = 0 {} //~ ERROR `...X` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let ...true = 0 {} //~ ERROR `...X` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
+    if let ...3 = 0 {}
+    //~^ ERROR range-to patterns with `...` are not allowed
+    if let ...Y = 0 {}
+    //~^ ERROR range-to patterns with `...` are not allowed
+    if let ...true = 0 {}
+    //~^ ERROR range-to patterns with `...` are not allowed
     //~| ERROR only char and numeric types
-    if let ....3 = 0 {} //~ ERROR `...X` range patterns are not supported
+    if let ....3 = 0 {}
     //~^ ERROR float literals must have an integer part
-    //~| ERROR `...` range patterns are deprecated
+    //~| ERROR range-to patterns with `...` are not allowed
     //~| ERROR mismatched types
 }
 
@@ -136,14 +133,13 @@
 
     macro_rules! mac {
         ($e:expr) => {
-            let ..$e; //~ ERROR `..X` range patterns are not supported
-            let ...$e; //~ ERROR `...X` range patterns are not supported
-            //~^ ERROR `...` range patterns are deprecated
-            let ..=$e; //~ ERROR `..=X` range patterns are not supported
-            let $e..; //~ ERROR `X..` range patterns are not supported
-            let $e...; //~ ERROR `X...` range patterns are not supported
-            //~^ ERROR `...` range patterns are deprecated
-            let $e..=; //~ ERROR `X..=` range patterns are not supported
+            let ..$e;
+            let ...$e;
+            //~^ ERROR range-to patterns with `...` are not allowed
+            let ..=$e;
+            let $e..;
+            let $e...; //~ ERROR inclusive range with no end
+            let $e..=; //~ ERROR inclusive range with no end
         }
     }
 
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index 3fed64c..f43f9bf 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -1,377 +1,250 @@
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:22:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:24:16
    |
 LL |     if let X.. .0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:35:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:37:16
    |
 LL |     if let X..=.0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:49:12
+  --> $DIR/recover-range-pats.rs:50:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:52:17
+  --> $DIR/recover-range-pats.rs:53:17
    |
 LL |     if let X... .0 = 0 {}
    |                 ^^ help: must have an integer part: `0.0`
 
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:58:12
-   |
-LL |     if let 0.. = 0 {}
-   |            ^^^ help: try using the maximum value for the type: `0..MAX`
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:59:12
-   |
-LL |     if let X.. = 0 {}
-   |            ^^^ help: try using the maximum value for the type: `X..MAX`
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:60:12
-   |
-LL |     if let true.. = 0 {}
-   |            ^^^^^^ help: try using the maximum value for the type: `true..MAX`
-
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:62:12
+  --> $DIR/recover-range-pats.rs:63:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:62:12
-   |
-LL |     if let .0.. = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0.0..MAX`
-
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:68:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:69:13
    |
 LL |     if let 0..= = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:69:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:70:13
    |
 LL |     if let X..= = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `X..=MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:70:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:71:16
    |
 LL |     if let true..= = 0 {}
-   |            ^^^^^^^ help: try using the maximum value for the type: `true..=MAX`
+   |                ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:72:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:72:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:73:14
    |
 LL |     if let .0..= = 0 {}
-   |            ^^^^^ help: try using the maximum value for the type: `0.0..=MAX`
+   |              ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:78:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:79:13
    |
 LL |     if let 0... = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0...MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:80:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:80:13
    |
 LL |     if let X... = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `X...MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:82:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:81:16
    |
 LL |     if let true... = 0 {}
-   |            ^^^^^^^ help: try using the maximum value for the type: `true...MAX`
+   |                ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:85:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0... = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:85:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:83:14
    |
 LL |     if let .0... = 0 {}
-   |            ^^^^^ help: try using the maximum value for the type: `0.0...MAX`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:92:12
+   |              ^^^ help: use `..` instead
    |
-LL |     if let ..0 = 0 {}
-   |            ^^^ help: try using the minimum value for the type: `MIN..0`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:93:12
-   |
-LL |     if let ..Y = 0 {}
-   |            ^^^ help: try using the minimum value for the type: `MIN..Y`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:94:12
-   |
-LL |     if let ..true = 0 {}
-   |            ^^^^^^ help: try using the minimum value for the type: `MIN..true`
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:96:15
+  --> $DIR/recover-range-pats.rs:93:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:96:12
-   |
-LL |     if let .. .0 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN..0.0`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:102:12
-   |
-LL |     if let ..=3 = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN..=3`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:103:12
-   |
-LL |     if let ..=Y = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN..=Y`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:104:12
-   |
-LL |     if let ..=true = 0 {}
-   |            ^^^^^^^ help: try using the minimum value for the type: `MIN..=true`
-
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:106:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:106:12
-   |
-LL |     if let ..=.0 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN..=0.0`
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:112:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:109:12
    |
 LL |     if let ...3 = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN...3`
+   |            ^^^ help: use `..=` instead
 
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:114:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:111:12
    |
 LL |     if let ...Y = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN...Y`
+   |            ^^^ help: use `..=` instead
 
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:116:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:113:12
    |
 LL |     if let ...true = 0 {}
-   |            ^^^^^^^ help: try using the minimum value for the type: `MIN...true`
+   |            ^^^ help: use `..=` instead
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:119:15
+  --> $DIR/recover-range-pats.rs:116:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^ help: must have an integer part: `0.3`
 
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:119:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:116:12
    |
 LL |     if let ....3 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN...0.3`
+   |            ^^^ help: use `..=` instead
 
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:139:17
-   |
-LL |             let ..$e;
-   |                 ^^ help: try using the minimum value for the type: `MIN..0`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:140:17
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:137:17
    |
 LL |             let ...$e;
-   |                 ^^^ help: try using the minimum value for the type: `MIN...0`
+   |                 ^^^ help: use `..=` instead
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
 
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:142:17
-   |
-LL |             let ..=$e;
-   |                 ^^^ help: try using the minimum value for the type: `MIN..=0`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:143:19
-   |
-LL |             let $e..;
-   |                   ^^ help: try using the maximum value for the type: `0..MAX`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:144:19
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:141:19
    |
 LL |             let $e...;
-   |                   ^^^ help: try using the maximum value for the type: `0...MAX`
+   |                   ^^^ help: use `..` instead
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:146:19
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:142:19
    |
 LL |             let $e..=;
-   |                   ^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                   ^^^ help: use `..` instead
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:41:13
+  --> $DIR/recover-range-pats.rs:42:13
    |
 LL |     if let 0...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
 note: lint level defined here
-  --> $DIR/recover-range-pats.rs:7:9
+  --> $DIR/recover-range-pats.rs:8:9
    |
 LL | #![deny(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:42:13
+  --> $DIR/recover-range-pats.rs:43:13
    |
 LL |     if let 0...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:43:13
+  --> $DIR/recover-range-pats.rs:44:13
    |
 LL |     if let X...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:44:13
+  --> $DIR/recover-range-pats.rs:45:13
    |
 LL |     if let X...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:45:16
+  --> $DIR/recover-range-pats.rs:46:16
    |
 LL |     if let true...Y = 0 {}
    |                ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:47:13
+  --> $DIR/recover-range-pats.rs:48:13
    |
 LL |     if let X...true = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:49:14
+  --> $DIR/recover-range-pats.rs:50:14
    |
 LL |     if let .0...Y = 0 {}
    |              ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:52:13
+  --> $DIR/recover-range-pats.rs:53:13
    |
 LL |     if let X... .0 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:78:13
-   |
-LL |     if let 0... = 0 {}
-   |             ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:80:13
-   |
-LL |     if let X... = 0 {}
-   |             ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:82:16
-   |
-LL |     if let true... = 0 {}
-   |                ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:85:14
-   |
-LL |     if let .0... = 0 {}
-   |              ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:112:12
-   |
-LL |     if let ...3 = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:114:12
-   |
-LL |     if let ...Y = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:116:12
-   |
-LL |     if let ...true = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:119:12
-   |
-LL |     if let ....3 = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:129:20
+  --> $DIR/recover-range-pats.rs:126:20
    |
 LL |             let $e1...$e2;
    |                    ^^^ help: use `..=` for an inclusive range
@@ -379,26 +252,8 @@
 LL |     mac2!(0, 1);
    |     ------------ in this macro invocation
 
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:140:17
-   |
-LL |             let ...$e;
-   |                 ^^^ help: use `..=` for an inclusive range
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:144:19
-   |
-LL |             let $e...;
-   |                   ^^^ help: use `..=` for an inclusive range
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:19:12
+  --> $DIR/recover-range-pats.rs:20:12
    |
 LL |     if let true..Y = 0 {}
    |            ^^^^  - this is of type `u8`
@@ -406,7 +261,7 @@
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:20:15
+  --> $DIR/recover-range-pats.rs:21:15
    |
 LL |     if let X..true = 0 {}
    |            -  ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -414,7 +269,7 @@
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:22:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^  - this is of type `u8`
@@ -422,7 +277,7 @@
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:24:16
    |
 LL |     if let X.. .0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -431,7 +286,7 @@
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:32:12
+  --> $DIR/recover-range-pats.rs:33:12
    |
 LL |     if let true..=Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -439,7 +294,7 @@
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:33:16
+  --> $DIR/recover-range-pats.rs:34:16
    |
 LL |     if let X..=true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -447,7 +302,7 @@
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:35:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^   - this is of type `u8`
@@ -455,7 +310,7 @@
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:37:16
    |
 LL |     if let X..=.0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -464,7 +319,7 @@
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:45:12
+  --> $DIR/recover-range-pats.rs:46:12
    |
 LL |     if let true...Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -472,7 +327,7 @@
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:47:16
+  --> $DIR/recover-range-pats.rs:48:16
    |
 LL |     if let X...true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -480,7 +335,7 @@
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:49:12
+  --> $DIR/recover-range-pats.rs:50:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^   - this is of type `u8`
@@ -488,7 +343,7 @@
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:52:17
+  --> $DIR/recover-range-pats.rs:53:17
    |
 LL |     if let X... .0 = 0 {}
    |            -    ^^   - this expression has type `u8`
@@ -497,78 +352,78 @@
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:60:12
+  --> $DIR/recover-range-pats.rs:61:12
    |
 LL |     if let true.. = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:62:12
+  --> $DIR/recover-range-pats.rs:63:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:70:12
+  --> $DIR/recover-range-pats.rs:71:12
    |
 LL |     if let true..= = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:72:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:82:12
+  --> $DIR/recover-range-pats.rs:81:12
    |
 LL |     if let true... = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:85:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0... = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:94:14
+  --> $DIR/recover-range-pats.rs:91:14
    |
 LL |     if let ..true = 0 {}
    |              ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:96:15
+  --> $DIR/recover-range-pats.rs:93:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:104:15
+  --> $DIR/recover-range-pats.rs:101:15
    |
 LL |     if let ..=true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:106:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:116:15
+  --> $DIR/recover-range-pats.rs:113:15
    |
 LL |     if let ...true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:119:15
+  --> $DIR/recover-range-pats.rs:116:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^ expected integer, found floating-point number
 
-error: aborting due to 85 previous errors
+error: aborting due to 60 previous errors
 
-Some errors have detailed explanations: E0029, E0308.
+Some errors have detailed explanations: E0029, E0308, E0586.
 For more information about an error, try `rustc --explain E0029`.
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs
index 9c7a25d..e27b03d 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.rs
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs
@@ -3,24 +3,26 @@
 
 fn main() {
     false == false == false;
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
 
     false == 0 < 2;
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 
     f<X>();
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
     //~| HELP use `::<...>` instead of `<...>` to specify type arguments
 
     f<Result<Option<X>, Option<Option<X>>>(1, 2);
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
+    //~| HELP split the comparison into two...
+    //~| ...or parenthesize one of the comparisons
     //~| HELP use `::<...>` instead of `<...>` to specify type arguments
 
     use std::convert::identity;
     let _ = identity<u8>;
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
     //~| HELP use `::<...>` instead of `<...>` to specify type arguments
     //~| HELP or use `(...)` if you meant to specify fn arguments
 }
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
index bece9a3..44edf2d 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
@@ -1,16 +1,16 @@
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:5:11
    |
 LL |     false == false == false;
    |           ^^^^^^^^^^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:8:11
    |
 LL |     false == 0 < 2;
    |           ^^^^^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:13:6
    |
 LL |     f<X>();
@@ -21,19 +21,27 @@
 LL |     f::<X>();
    |      ^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:17:6
    |
 LL |     f<Result<Option<X>, Option<Option<X>>>(1, 2);
    |      ^^^^^^^^
    |
+help: split the comparison into two...
+   |
+LL |     f < Result && Result <Option<X>, Option<Option<X>>>(1, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (f < Result) <Option<X>, Option<Option<X>>>(1, 2);
+   |     ^^^^^^^^^^^^^^
 help: use `::<...>` instead of `<...>` to specify type arguments
    |
 LL |     f::<Result<Option<X>, Option<Option<X>>>(1, 2);
    |      ^^
 
-error: chained comparison operators require parentheses
-  --> $DIR/require-parens-for-chained-comparison.rs:22:21
+error: comparison operators cannot be chained
+  --> $DIR/require-parens-for-chained-comparison.rs:24:21
    |
 LL |     let _ = identity<u8>;
    |                     ^^^^
diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.rs b/src/test/ui/parser/type-parameters-in-field-exprs.rs
index 1b8ed9f..6a3b2c1 100644
--- a/src/test/ui/parser/type-parameters-in-field-exprs.rs
+++ b/src/test/ui/parser/type-parameters-in-field-exprs.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct Foo {
     x: isize,
     y: isize,
diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.stderr b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
index 8f32fb0..306b475 100644
--- a/src/test/ui/parser/type-parameters-in-field-exprs.stderr
+++ b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
@@ -1,17 +1,17 @@
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:13:10
+  --> $DIR/type-parameters-in-field-exprs.rs:11:10
    |
 LL |     f.x::<isize>;
    |          ^^^^^^^
 
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:15:10
+  --> $DIR/type-parameters-in-field-exprs.rs:13:10
    |
 LL |     f.x::<>;
    |          ^^
 
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:17:7
+  --> $DIR/type-parameters-in-field-exprs.rs:15:7
    |
 LL |     f.x::();
    |       ^^^^^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
index 88eda9a..559925c 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
@@ -101,6 +101,7 @@
         //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
         //~| ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
         //~| ERROR cannot move out of `b` in pattern guard
+        //~| ERROR cannot move out of `b` in pattern guard
         _ => {}
     }
     match Ok(U) {
@@ -108,6 +109,7 @@
         //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable
         //~| ERROR cannot borrow `a` as immutable because it is also borrowed as mutable
         //~| ERROR cannot move out of `a` in pattern guard
+        //~| ERROR cannot move out of `a` in pattern guard
         _ => {}
     }
 
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index b068a61..b5c26a1 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -191,7 +191,7 @@
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |         ---------^^^^^^-----^
@@ -200,7 +200,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -209,7 +209,7 @@
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:114:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:116:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -219,7 +219,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -229,7 +229,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:126:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -239,7 +239,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -359,8 +359,24 @@
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
+error[E0507]: cannot move out of `b` in pattern guard
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66
+   |
+LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
+   |                                                                  ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66
+   |
+LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
+   |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error[E0507]: cannot move out of `a` in pattern guard
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -368,7 +384,7 @@
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -380,7 +396,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
@@ -392,7 +408,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:126:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -404,7 +420,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:126:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
@@ -415,7 +431,7 @@
 LL |     drop(a);
    |          - immutable borrow later used here
 
-error: aborting due to 43 previous errors
+error: aborting due to 45 previous errors
 
 Some errors have detailed explanations: E0502, E0507, E0594.
 For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr
index 7a0f144..7217fe1 100644
--- a/src/test/ui/pattern/const-pat-ice.stderr
+++ b/src/test/ui/pattern/const-pat-ice.stderr
@@ -1,4 +1,4 @@
-thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:LL:CC
+thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir_build/hair/pattern/_match.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 error: internal compiler error: unexpected panic
diff --git a/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr b/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
index abb8d69..21218d9 100644
--- a/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
+++ b/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
@@ -3,6 +3,8 @@
    |
 LL |         Bar => {},
    |         ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
   --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:19:9
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.rs b/src/test/ui/pattern/patkind-litrange-no-expr.rs
index def6c62..5b3db2e 100644
--- a/src/test/ui/pattern/patkind-litrange-no-expr.rs
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.rs
@@ -18,7 +18,8 @@
     Pos = 1,
     Neg = -1,
     Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
-                   //~^ ERROR only char and numeric types are allowed in range patterns
+                   //~| ERROR arbitrary expressions aren't allowed in patterns
+                   //~| ERROR only char and numeric types are allowed in range patterns
 });
 
 fn main() {}
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
index 78768d2..70dd1a9 100644
--- a/src/test/ui/pattern/patkind-litrange-no-expr.stderr
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
@@ -4,6 +4,12 @@
 LL |     Arith = 1 + 1,
    |             ^^^^^
 
+error: arbitrary expressions aren't allowed in patterns
+  --> $DIR/patkind-litrange-no-expr.rs:20:13
+   |
+LL |     Arith = 1 + 1,
+   |             ^^^^^
+
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/patkind-litrange-no-expr.rs:20:13
    |
@@ -13,6 +19,6 @@
 LL |     Arith = 1 + 1,
    |             ^^^^^ this is of type `_` but it should be `char` or numeric
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
index 7de7b7e..37c4ccd 100644
--- a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
+++ b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
@@ -34,11 +34,15 @@
       //~^ WARNING floating-point types cannot be used in patterns
       //~| WARNING floating-point types cannot be used in patterns
       //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       0.02f64 => {} //~ ERROR unreachable pattern
       //~^ WARNING floating-point types cannot be used in patterns
+      //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       _ => {}
     };
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
index c15186d..8412a11 100644
--- a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
+++ b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
@@ -48,7 +48,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:40:7
+  --> $DIR/match-range-fail-dominate.rs:42:7
    |
 LL |       0.02f64 => {}
    |       ^^^^^^^
@@ -57,7 +57,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:40:7
+  --> $DIR/match-range-fail-dominate.rs:42:7
    |
 LL |       0.02f64 => {}
    |       ^^^^^^^
@@ -71,5 +71,23 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:33:19
+   |
+LL |       0.01f64 ..= 6.5f64 => {}
+   |                   ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:42:7
+   |
+LL |       0.02f64 => {}
+   |       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs
index d376237..fcf7b19 100644
--- a/src/test/ui/privacy/privacy1.rs
+++ b/src/test/ui/privacy/privacy1.rs
@@ -131,6 +131,7 @@
     fn test2() {
         use bar::baz::{foo, bar};
         //~^ ERROR: module `baz` is private
+        //~| ERROR: module `baz` is private
 
         foo();
         bar();
diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr
index b647cc8..29f53cd 100644
--- a/src/test/ui/privacy/privacy1.stderr
+++ b/src/test/ui/privacy/privacy1.stderr
@@ -5,13 +5,19 @@
    |                  ^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:140:18
+  --> $DIR/privacy1.rs:132:18
+   |
+LL |         use bar::baz::{foo, bar};
+   |                  ^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:141:18
    |
 LL |         use bar::baz;
    |                  ^^^
 
 error[E0603]: module `i` is private
-  --> $DIR/privacy1.rs:164:20
+  --> $DIR/privacy1.rs:165:20
    |
 LL |     use self::foo::i::A;
    |                    ^
@@ -65,7 +71,7 @@
    |                ^^^
 
 error[E0603]: trait `B` is private
-  --> $DIR/privacy1.rs:156:17
+  --> $DIR/privacy1.rs:157:17
    |
 LL |     impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } }
    |                 ^
@@ -100,7 +106,7 @@
 LL |         ::bar::baz::A.bar2();
    |                       ^^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 18 previous errors
 
 Some errors have detailed explanations: E0603, E0624.
 For more information about an error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index 3c42f24..ad1052a 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -17,6 +17,8 @@
         //~^ WARN private trait `m::PrivTr` in public interface
         //~| WARN this was previously accepted
         //~| WARN private type `m::Priv` in public interface
+        //~| WARN private type `m::Priv` in public interface
+        //~| WARN this was previously accepted
         //~| WARN this was previously accepted
         type Alias1: PrivTr;
         type Alias2: PubTrAux1<Priv> = u8;
@@ -34,6 +36,7 @@
 
         type Exist = impl PrivTr;
         //~^ ERROR private trait `m::PrivTr` in public interface
+        //~| ERROR private trait `m::PrivTr` in public interface
         fn infer_exist() -> Self::Exist { Priv }
     }
 }
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index 158862f..3cc551c 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -29,8 +29,23 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
+warning: private type `m::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-assoc-ty.rs:16:5
+   |
+LL | /     pub trait PubTr {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         fn infer_exist() -> Self::Exist;
+LL | |     }
+   | |_____^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:25:9
+  --> $DIR/private-in-public-assoc-ty.rs:27:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -39,7 +54,7 @@
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:32:9
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -48,7 +63,7 @@
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:35:9
+  --> $DIR/private-in-public-assoc-ty.rs:37:9
    |
 LL |     trait PrivTr {}
    |     - `m::PrivTr` declared as private
@@ -56,7 +71,16 @@
 LL |         type Exist = impl PrivTr;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-error: aborting due to 3 previous errors
+error[E0445]: private trait `m::PrivTr` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:37:9
+   |
+LL |     trait PrivTr {}
+   |     - `m::PrivTr` declared as private
+...
+LL |         type Exist = impl PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0445, E0446.
 For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/proc-macro/issue-50493.rs b/src/test/ui/proc-macro/issue-50493.rs
index 5d1a9f2..f1934f6 100644
--- a/src/test/ui/proc-macro/issue-50493.rs
+++ b/src/test/ui/proc-macro/issue-50493.rs
@@ -4,6 +4,7 @@
 extern crate issue_50493;
 
 #[derive(Derive)] //~ ERROR field `field` of struct `Restricted` is private
+                  //~| ERROR field `field` of struct `Restricted` is private
 struct Restricted {
     pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules
 }
diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr
index 6b87244..56c7800 100644
--- a/src/test/ui/proc-macro/issue-50493.stderr
+++ b/src/test/ui/proc-macro/issue-50493.stderr
@@ -1,5 +1,5 @@
 error[E0742]: visibilities can only be restricted to ancestor modules
-  --> $DIR/issue-50493.rs:8:12
+  --> $DIR/issue-50493.rs:9:12
    |
 LL |     pub(in restricted) field: usize,
    |            ^^^^^^^^^^
@@ -10,7 +10,13 @@
 LL | #[derive(Derive)]
    |          ^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0616]: field `field` of struct `Restricted` is private
+  --> $DIR/issue-50493.rs:6:10
+   |
+LL | #[derive(Derive)]
+   |          ^^^^^^
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0616, E0742.
 For more information about an error, try `rustc --explain E0616`.
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
index b17c056..470b22b 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -46,6 +46,7 @@
 fn check_attr3() {}
 
 #[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope
+                    //~| ERROR cannot find derive macro `my_macro` in this scope
 #[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines
                            //~| ERROR expected derive macro, found macro `crate::my_macro`
 struct CheckDerive1;
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index c011a70..a617319 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -47,19 +47,19 @@
    |   ^^^^^^^ not an attribute
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:52:10
+  --> $DIR/macro-namespace-reserved-2.rs:53:10
    |
 LL | #[derive(my_macro_attr)]
    |          ^^^^^^^^^^^^^
 
 error: expected derive macro, found attribute macro `my_macro_attr`
-  --> $DIR/macro-namespace-reserved-2.rs:52:10
+  --> $DIR/macro-namespace-reserved-2.rs:53:10
    |
 LL | #[derive(my_macro_attr)]
    |          ^^^^^^^^^^^^^ not a derive macro
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:55:10
+  --> $DIR/macro-namespace-reserved-2.rs:56:10
    |
 LL | #[derive(MyTrait)]
    |          ^^^^^^^
@@ -77,13 +77,13 @@
    |   ^^^^^^^^^^^^^^^ not an attribute
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:49:10
+  --> $DIR/macro-namespace-reserved-2.rs:50:10
    |
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^
 
 error: expected derive macro, found macro `crate::my_macro`
-  --> $DIR/macro-namespace-reserved-2.rs:49:10
+  --> $DIR/macro-namespace-reserved-2.rs:50:10
    |
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^ not a derive macro
@@ -112,5 +112,11 @@
 LL | #[derive(my_macro)]
    |          ^^^^^^^^
 
-error: aborting due to 19 previous errors
+error: cannot find derive macro `my_macro` in this scope
+  --> $DIR/macro-namespace-reserved-2.rs:48:10
+   |
+LL | #[derive(my_macro)]
+   |          ^^^^^^^^
+
+error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/proc-macro/parent-source-spans.rs b/src/test/ui/proc-macro/parent-source-spans.rs
index 7b2ffef..95a3f96 100644
--- a/src/test/ui/proc-macro/parent-source-spans.rs
+++ b/src/test/ui/proc-macro/parent-source-spans.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 // aux-build:parent-source-spans.rs
 #![feature(decl_macro, proc_macro_hygiene)]
 
diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr
index 3e54a71..9f0fefc 100644
--- a/src/test/ui/proc-macro/parent-source-spans.stderr
+++ b/src/test/ui/proc-macro/parent-source-spans.stderr
@@ -1,5 +1,5 @@
 error: first final: "hello"
-  --> $DIR/parent-source-spans.rs:15:12
+  --> $DIR/parent-source-spans.rs:19:12
    |
 LL |     three!($a, $b);
    |            ^^
@@ -8,7 +8,7 @@
    |     ----------------------- in this macro invocation
 
 error: second final: "world"
-  --> $DIR/parent-source-spans.rs:15:16
+  --> $DIR/parent-source-spans.rs:19:16
    |
 LL |     three!($a, $b);
    |                ^^
@@ -17,7 +17,7 @@
    |     ----------------------- in this macro invocation
 
 error: first parent: "hello"
-  --> $DIR/parent-source-spans.rs:9:5
+  --> $DIR/parent-source-spans.rs:13:5
    |
 LL |     two!($a, $b);
    |     ^^^^^^^^^^^^^
@@ -26,7 +26,7 @@
    |     ----------------------- in this macro invocation
 
 error: second parent: "world"
-  --> $DIR/parent-source-spans.rs:9:5
+  --> $DIR/parent-source-spans.rs:13:5
    |
 LL |     two!($a, $b);
    |     ^^^^^^^^^^^^^
@@ -35,31 +35,31 @@
    |     ----------------------- in this macro invocation
 
 error: first grandparent: "hello"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: second grandparent: "world"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: first source: "hello"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: second source: "world"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: first final: "yay"
-  --> $DIR/parent-source-spans.rs:15:12
+  --> $DIR/parent-source-spans.rs:19:12
    |
 LL |     three!($a, $b);
    |            ^^
@@ -68,7 +68,7 @@
    |     -------------------- in this macro invocation
 
 error: second final: "rust"
-  --> $DIR/parent-source-spans.rs:15:16
+  --> $DIR/parent-source-spans.rs:19:16
    |
 LL |     three!($a, $b);
    |                ^^
@@ -77,79 +77,94 @@
    |     -------------------- in this macro invocation
 
 error: first parent: "yay"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: second parent: "rust"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: first source: "yay"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: second source: "rust"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: first final: "hip"
-  --> $DIR/parent-source-spans.rs:47:12
+  --> $DIR/parent-source-spans.rs:51:12
    |
 LL |     three!("hip", "hop");
    |            ^^^^^
 
 error: second final: "hop"
-  --> $DIR/parent-source-spans.rs:47:19
+  --> $DIR/parent-source-spans.rs:51:19
    |
 LL |     three!("hip", "hop");
    |                   ^^^^^
 
 error: first source: "hip"
-  --> $DIR/parent-source-spans.rs:47:12
+  --> $DIR/parent-source-spans.rs:51:12
    |
 LL |     three!("hip", "hop");
    |            ^^^^^
 
 error: second source: "hop"
-  --> $DIR/parent-source-spans.rs:47:19
+  --> $DIR/parent-source-spans.rs:51:19
    |
 LL |     three!("hip", "hop");
    |                   ^^^^^
 
 error[E0425]: cannot find value `ok` in this scope
-  --> $DIR/parent-source-spans.rs:28:5
+  --> $DIR/parent-source-spans.rs:32:5
    |
 LL |     parent_source_spans!($($tokens)*);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     one!("hello", "world");
    |     ----------------------- in this macro invocation
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+   |     --------------------------------------------------- similarly named tuple variant `Ok` defined here
 
 error[E0425]: cannot find value `ok` in this scope
-  --> $DIR/parent-source-spans.rs:28:5
+  --> $DIR/parent-source-spans.rs:32:5
    |
 LL |     parent_source_spans!($($tokens)*);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     two!("yay", "rust");
    |     -------------------- in this macro invocation
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+   |     --------------------------------------------------- similarly named tuple variant `Ok` defined here
 
 error[E0425]: cannot find value `ok` in this scope
-  --> $DIR/parent-source-spans.rs:28:5
+  --> $DIR/parent-source-spans.rs:32:5
    |
 LL |     parent_source_spans!($($tokens)*);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     three!("hip", "hop");
    |     --------------------- in this macro invocation
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+   |     --------------------------------------------------- similarly named tuple variant `Ok` defined here
 
 error: aborting due to 21 previous errors
 
diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs
index d2282af..8ff36ff 100644
--- a/src/test/ui/proc-macro/resolve-error.rs
+++ b/src/test/ui/proc-macro/resolve-error.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 // aux-build:derive-foo.rs
 // aux-build:derive-clona.rs
 // aux-build:test-macros.rs
@@ -21,6 +25,7 @@
 
 #[derive(FooWithLongNan)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct Foo;
 
 // Interpreted as an unstable custom attribute
@@ -33,14 +38,17 @@
 
 #[derive(Dlone)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct A;
 
 #[derive(Dlona)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct B;
 
 #[derive(attr_proc_macra)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct C;
 
 fn main() {
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
index 02c82c0..73a6ab1 100644
--- a/src/test/ui/proc-macro/resolve-error.stderr
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -1,17 +1,22 @@
 error: cannot find macro `bang_proc_macrp` in this scope
-  --> $DIR/resolve-error.rs:56:5
+  --> $DIR/resolve-error.rs:64:5
    |
 LL |     bang_proc_macrp!();
    |     ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro`
+   | 
+  ::: $DIR/auxiliary/test-macros.rs:15:1
+   |
+LL | pub fn empty(_: TokenStream) -> TokenStream {
+   | ------------------------------------------- similarly named macro `bang_proc_macro` defined here
 
 error: cannot find macro `Dlona` in this scope
-  --> $DIR/resolve-error.rs:53:5
+  --> $DIR/resolve-error.rs:61:5
    |
 LL |     Dlona!();
    |     ^^^^^
 
 error: cannot find macro `attr_proc_macra` in this scope
-  --> $DIR/resolve-error.rs:50:5
+  --> $DIR/resolve-error.rs:58:5
    |
 LL | / macro_rules! attr_proc_mac {
 LL | |     () => {}
@@ -22,7 +27,7 @@
    |       ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac`
 
 error: cannot find macro `FooWithLongNama` in this scope
-  --> $DIR/resolve-error.rs:47:5
+  --> $DIR/resolve-error.rs:55:5
    |
 LL | / macro_rules! FooWithLongNam {
 LL | |     () => {}
@@ -33,40 +38,99 @@
    |       ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam`
 
 error: cannot find derive macro `attr_proc_macra` in this scope
-  --> $DIR/resolve-error.rs:42:10
+  --> $DIR/resolve-error.rs:49:10
+   |
+LL | #[derive(attr_proc_macra)]
+   |          ^^^^^^^^^^^^^^^
+
+error: cannot find derive macro `attr_proc_macra` in this scope
+  --> $DIR/resolve-error.rs:49:10
    |
 LL | #[derive(attr_proc_macra)]
    |          ^^^^^^^^^^^^^^^
 
 error: cannot find derive macro `Dlona` in this scope
-  --> $DIR/resolve-error.rs:38:10
+  --> $DIR/resolve-error.rs:44:10
    |
 LL | #[derive(Dlona)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clona`
+   | 
+  ::: $DIR/auxiliary/derive-clona.rs:11:1
+   |
+LL | pub fn derive_clonea(input: TokenStream) -> TokenStream {
+   | ------------------------------------------------------- similarly named derive macro `Clona` defined here
+
+error: cannot find derive macro `Dlona` in this scope
+  --> $DIR/resolve-error.rs:44:10
+   |
+LL | #[derive(Dlona)]
+   |          ^^^^^ help: a derive macro with a similar name exists: `Clona`
+   | 
+  ::: $DIR/auxiliary/derive-clona.rs:11:1
+   |
+LL | pub fn derive_clonea(input: TokenStream) -> TokenStream {
+   | ------------------------------------------------------- similarly named derive macro `Clona` defined here
 
 error: cannot find derive macro `Dlone` in this scope
-  --> $DIR/resolve-error.rs:34:10
+  --> $DIR/resolve-error.rs:39:10
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+   | 
+  ::: $SRC_DIR/libcore/clone.rs:LL:COL
+   |
+LL | pub macro Clone($item:item) {
+   | --------------------------- similarly named derive macro `Clone` defined here
+
+error: cannot find derive macro `Dlone` in this scope
+  --> $DIR/resolve-error.rs:39:10
+   |
+LL | #[derive(Dlone)]
+   |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+   | 
+  ::: $SRC_DIR/libcore/clone.rs:LL:COL
+   |
+LL | pub macro Clone($item:item) {
+   | --------------------------- similarly named derive macro `Clone` defined here
 
 error: cannot find attribute `FooWithLongNan` in this scope
-  --> $DIR/resolve-error.rs:31:3
+  --> $DIR/resolve-error.rs:36:3
    |
 LL | #[FooWithLongNan]
    |   ^^^^^^^^^^^^^^
 
 error: cannot find attribute `attr_proc_macra` in this scope
-  --> $DIR/resolve-error.rs:27:3
+  --> $DIR/resolve-error.rs:32:3
    |
 LL | #[attr_proc_macra]
    |   ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro`
+   | 
+  ::: $DIR/auxiliary/test-macros.rs:20:1
+   |
+LL | pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+   | ---------------------------------------------------------------- similarly named attribute macro `attr_proc_macro` defined here
 
 error: cannot find derive macro `FooWithLongNan` in this scope
-  --> $DIR/resolve-error.rs:22:10
+  --> $DIR/resolve-error.rs:26:10
    |
 LL | #[derive(FooWithLongNan)]
    |          ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName`
+   | 
+  ::: $DIR/auxiliary/derive-foo.rs:11:1
+   |
+LL | pub fn derive_foo(input: TokenStream) -> TokenStream {
+   | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here
 
-error: aborting due to 10 previous errors
+error: cannot find derive macro `FooWithLongNan` in this scope
+  --> $DIR/resolve-error.rs:26:10
+   |
+LL | #[derive(FooWithLongNan)]
+   |          ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName`
+   | 
+  ::: $DIR/auxiliary/derive-foo.rs:11:1
+   |
+LL | pub fn derive_foo(input: TokenStream) -> TokenStream {
+   | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here
+
+error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/range/range_traits-1.rs b/src/test/ui/range/range_traits-1.rs
index e28e474..4f57c32 100644
--- a/src/test/ui/range/range_traits-1.rs
+++ b/src/test/ui/range/range_traits-1.rs
@@ -4,21 +4,45 @@
 struct AllTheRanges {
     a: Range<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     b: RangeTo<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     c: RangeFrom<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     d: RangeFull,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     e: RangeInclusive<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     f: RangeToInclusive<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
 }
 
diff --git a/src/test/ui/range/range_traits-1.stderr b/src/test/ui/range/range_traits-1.stderr
index d085cab..f60ec23 100644
--- a/src/test/ui/range/range_traits-1.stderr
+++ b/src/test/ui/range/range_traits-1.stderr
@@ -8,7 +8,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
-  --> $DIR/range_traits-1.rs:8:5
+  --> $DIR/range_traits-1.rs:12:5
    |
 LL |     b: RangeTo<usize>,
    |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
@@ -17,7 +17,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
-  --> $DIR/range_traits-1.rs:11:5
+  --> $DIR/range_traits-1.rs:19:5
    |
 LL |     c: RangeFrom<usize>,
    |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
@@ -26,7 +26,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
-  --> $DIR/range_traits-1.rs:14:5
+  --> $DIR/range_traits-1.rs:26:5
    |
 LL |     d: RangeFull,
    |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
@@ -35,7 +35,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
-  --> $DIR/range_traits-1.rs:17:5
+  --> $DIR/range_traits-1.rs:33:5
    |
 LL |     e: RangeInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
@@ -44,7 +44,223 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
-  --> $DIR/range_traits-1.rs:20:5
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
    |
 LL |     f: RangeToInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
@@ -61,7 +277,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeTo<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:8:5
+  --> $DIR/range_traits-1.rs:12:5
    |
 LL |     b: RangeTo<usize>,
    |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeTo<usize>`
@@ -69,7 +285,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeFrom<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:11:5
+  --> $DIR/range_traits-1.rs:19:5
    |
 LL |     c: RangeFrom<usize>,
    |     ^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeFrom<usize>`
@@ -77,7 +293,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeFull: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:14:5
+  --> $DIR/range_traits-1.rs:26:5
    |
 LL |     d: RangeFull,
    |     ^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeFull`
@@ -85,7 +301,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeInclusive<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:17:5
+  --> $DIR/range_traits-1.rs:33:5
    |
 LL |     e: RangeInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeInclusive<usize>`
@@ -93,13 +309,13 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeToInclusive<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:20:5
+  --> $DIR/range_traits-1.rs:40:5
    |
 LL |     f: RangeToInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeToInclusive<usize>`
    |
    = note: required by `std::cmp::Ord::cmp`
 
-error: aborting due to 12 previous errors
+error: aborting due to 36 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.rs b/src/test/ui/regions/regions-close-object-into-object-5.rs
index 609c8ce..2921a2b 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.rs
+++ b/src/test/ui/regions/regions-close-object-into-object-5.rs
@@ -21,6 +21,7 @@
         //~| ERROR the parameter type `T` may not live long enough
         //~| ERROR the parameter type `T` may not live long enough
         //~| ERROR the parameter type `T` may not live long enough
+        //~| ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr
index 01975d4..7c530ce 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr
@@ -88,6 +88,21 @@
 LL |     box B(&*v) as Box<X>
    |           ^^^
 
-error: aborting due to 6 previous errors
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:11
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+   |
+note: ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
+  --> $DIR/regions-close-object-into-object-5.rs:17:11
+   |
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
index e94e8b2..e912805 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
@@ -20,6 +20,8 @@
 
 // Here we get an error: we need `'a: 'b`.
 fn bar<'a, 'b>() //~ ERROR cannot infer
+                 //~| ERROR cannot infer
+                 //~| ERROR cannot infer
     where <() as Project<'a, 'b>>::Item : Eq
 {
 }
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
index 8a600d2..cc2245f 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -2,6 +2,8 @@
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
    |
 LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
 LL | | {
 LL | | }
@@ -21,6 +23,8 @@
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
    |
 LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
 LL | | {
 LL | | }
@@ -28,6 +32,74 @@
    = note: expected  `Project<'a, 'b>`
               found  `Project<'_, '_>`
 
-error: aborting due to previous error
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+   |
+LL | fn bar<'a, 'b>()
+   |        ^^
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+   |
+LL | fn bar<'a, 'b>()
+   |            ^^
+note: ...so that the types are compatible
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   = note: expected  `Project<'a, 'b>`
+              found  `Project<'_, '_>`
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+   |
+LL | fn bar<'a, 'b>()
+   |        ^^
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+   |
+LL | fn bar<'a, 'b>()
+   |            ^^
+note: ...so that the types are compatible
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   = note: expected  `Project<'a, 'b>`
+              found  `Project<'_, '_>`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/repr/repr-align-assign.fixed b/src/test/ui/repr/repr-align-assign.fixed
index 2e1d9a2..59ca22e 100644
--- a/src/test/ui/repr/repr-align-assign.fixed
+++ b/src/test/ui/repr/repr-align-assign.fixed
@@ -3,9 +3,11 @@
 #![allow(dead_code)]
 
 #[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
+                 //~| ERROR incorrect `repr(align)` attribute format
 struct A(u64);
 
 #[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
+                   //~| ERROR incorrect `repr(align)` attribute format
 struct B(u64);
 
 fn main() {}
diff --git a/src/test/ui/repr/repr-align-assign.rs b/src/test/ui/repr/repr-align-assign.rs
index b8f7c15..6b77992 100644
--- a/src/test/ui/repr/repr-align-assign.rs
+++ b/src/test/ui/repr/repr-align-assign.rs
@@ -3,9 +3,11 @@
 #![allow(dead_code)]
 
 #[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format
+                 //~| ERROR incorrect `repr(align)` attribute format
 struct A(u64);
 
 #[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format
+                   //~| ERROR incorrect `repr(align)` attribute format
 struct B(u64);
 
 fn main() {}
diff --git a/src/test/ui/repr/repr-align-assign.stderr b/src/test/ui/repr/repr-align-assign.stderr
index 177bd81..192312d 100644
--- a/src/test/ui/repr/repr-align-assign.stderr
+++ b/src/test/ui/repr/repr-align-assign.stderr
@@ -5,10 +5,22 @@
    |        ^^^^^^^ help: use parentheses instead: `align(8)`
 
 error[E0693]: incorrect `repr(align)` attribute format
-  --> $DIR/repr-align-assign.rs:8:8
+  --> $DIR/repr-align-assign.rs:9:8
    |
 LL | #[repr(align="8")]
    |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
 
-error: aborting due to 2 previous errors
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:5:8
+   |
+LL | #[repr(align=8)]
+   |        ^^^^^^^ help: use parentheses instead: `align(8)`
+
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:9:8
+   |
+LL | #[repr(align="8")]
+   |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/repr/repr-align.rs b/src/test/ui/repr/repr-align.rs
index bc6a9fe..58ecf9a 100644
--- a/src/test/ui/repr/repr-align.rs
+++ b/src/test/ui/repr/repr-align.rs
@@ -1,24 +1,30 @@
 #![allow(dead_code)]
 
 #[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+                     //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
 struct S0(i32);
 
 #[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+                   //~| ERROR: invalid `repr(align)` attribute: not a power of two
 struct S1(i32);
 
 #[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
+                           //~| ERROR: invalid `repr(align)` attribute: larger than 2^29
 struct S2(i32);
 
 #[repr(align(536870912))] // ok: this is the largest accepted alignment
 struct S3(i32);
 
 #[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+                     //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
 enum E0 { A, B }
 
 #[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+                   //~| ERROR: invalid `repr(align)` attribute: not a power of two
 enum E1 { A, B }
 
 #[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
+                           //~| ERROR: invalid `repr(align)` attribute: larger than 2^29
 enum E2 { A, B }
 
 #[repr(align(536870912))] // ok: this is the largest accepted alignment
diff --git a/src/test/ui/repr/repr-align.stderr b/src/test/ui/repr/repr-align.stderr
index 280cab2..900a811 100644
--- a/src/test/ui/repr/repr-align.stderr
+++ b/src/test/ui/repr/repr-align.stderr
@@ -5,35 +5,71 @@
    |        ^^^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: not a power of two
-  --> $DIR/repr-align.rs:6:8
+  --> $DIR/repr-align.rs:7:8
    |
 LL | #[repr(align(15))]
    |        ^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: larger than 2^29
-  --> $DIR/repr-align.rs:9:8
+  --> $DIR/repr-align.rs:11:8
    |
 LL | #[repr(align(4294967296))]
    |        ^^^^^^^^^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
-  --> $DIR/repr-align.rs:15:8
+  --> $DIR/repr-align.rs:18:8
    |
 LL | #[repr(align(16.0))]
    |        ^^^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: not a power of two
-  --> $DIR/repr-align.rs:18:8
+  --> $DIR/repr-align.rs:22:8
    |
 LL | #[repr(align(15))]
    |        ^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: larger than 2^29
-  --> $DIR/repr-align.rs:21:8
+  --> $DIR/repr-align.rs:26:8
    |
 LL | #[repr(align(4294967296))]
    |        ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+  --> $DIR/repr-align.rs:3:8
+   |
+LL | #[repr(align(16.0))]
+   |        ^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not a power of two
+  --> $DIR/repr-align.rs:7:8
+   |
+LL | #[repr(align(15))]
+   |        ^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+  --> $DIR/repr-align.rs:11:8
+   |
+LL | #[repr(align(4294967296))]
+   |        ^^^^^^^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+  --> $DIR/repr-align.rs:18:8
+   |
+LL | #[repr(align(16.0))]
+   |        ^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not a power of two
+  --> $DIR/repr-align.rs:22:8
+   |
+LL | #[repr(align(15))]
+   |        ^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+  --> $DIR/repr-align.rs:26:8
+   |
+LL | #[repr(align(4294967296))]
+   |        ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0589`.
diff --git a/src/test/ui/resolve/levenshtein.rs b/src/test/ui/resolve/levenshtein.rs
index a6f4716..6a98782 100644
--- a/src/test/ui/resolve/levenshtein.rs
+++ b/src/test/ui/resolve/levenshtein.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 const MAX_ITEM: usize = 10;
 
 fn foo_bar() {}
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
index 8d8f3f3..a622d6c 100644
--- a/src/test/ui/resolve/levenshtein.stderr
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -1,11 +1,11 @@
 error[E0412]: cannot find type `esize` in this scope
-  --> $DIR/levenshtein.rs:5:11
+  --> $DIR/levenshtein.rs:9:11
    |
 LL | fn foo(c: esize) {} // Misspelled primitive type name.
    |           ^^^^^ help: a builtin type with a similar name exists: `isize`
 
 error[E0412]: cannot find type `Baz` in this scope
-  --> $DIR/levenshtein.rs:10:10
+  --> $DIR/levenshtein.rs:14:10
    |
 LL | enum Bar { }
    | ------------ similarly named enum `Bar` defined here
@@ -14,19 +14,24 @@
    |          ^^^ help: an enum with a similar name exists: `Bar`
 
 error[E0412]: cannot find type `Opiton` in this scope
-  --> $DIR/levenshtein.rs:12:10
+  --> $DIR/levenshtein.rs:16:10
    |
 LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
    |          ^^^^^^ help: an enum with a similar name exists: `Option`
+   | 
+  ::: $SRC_DIR/libcore/option.rs:LL:COL
+   |
+LL | pub enum Option<T> {
+   | ------------------ similarly named enum `Option` defined here
 
 error[E0412]: cannot find type `Baz` in this scope
-  --> $DIR/levenshtein.rs:16:14
+  --> $DIR/levenshtein.rs:20:14
    |
 LL |     type A = Baz; // No suggestion here, Bar is not visible
    |              ^^^ not found in this scope
 
 error[E0425]: cannot find value `MAXITEM` in this scope
-  --> $DIR/levenshtein.rs:24:20
+  --> $DIR/levenshtein.rs:28:20
    |
 LL | const MAX_ITEM: usize = 10;
    | --------------------------- similarly named constant `MAX_ITEM` defined here
@@ -35,7 +40,7 @@
    |                    ^^^^^^^ help: a constant with a similar name exists: `MAX_ITEM`
 
 error[E0425]: cannot find function `foobar` in this scope
-  --> $DIR/levenshtein.rs:26:5
+  --> $DIR/levenshtein.rs:30:5
    |
 LL | fn foo_bar() {}
    | --------------- similarly named function `foo_bar` defined here
@@ -44,7 +49,7 @@
    |     ^^^^^^ help: a function with a similar name exists: `foo_bar`
 
 error[E0412]: cannot find type `first` in module `m`
-  --> $DIR/levenshtein.rs:28:15
+  --> $DIR/levenshtein.rs:32:15
    |
 LL |     pub struct First;
    |     ----------------- similarly named struct `First` defined here
@@ -53,7 +58,7 @@
    |               ^^^^^ help: a struct with a similar name exists (notice the capitalization): `First`
 
 error[E0425]: cannot find value `second` in module `m`
-  --> $DIR/levenshtein.rs:28:26
+  --> $DIR/levenshtein.rs:32:26
    |
 LL |     pub struct Second;
    |     ------------------ similarly named unit struct `Second` defined here
diff --git a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
new file mode 100644
index 0000000..be13076
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
@@ -0,0 +1,38 @@
+// run-pass
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![feature(option_expect_none, option_unwrap_none)]
+
+//! Test that panic locations for `#[track_caller]` functions in std have the correct
+//! location reported.
+
+fn main() {
+    // inspect the `PanicInfo` we receive to ensure the right file is the source
+    std::panic::set_hook(Box::new(|info| {
+        let actual = info.location().unwrap();
+        if actual.file() != file!() {
+            eprintln!("expected a location in the test file, found {:?}", actual);
+            panic!();
+        }
+    }));
+
+    fn assert_panicked(f: impl FnOnce() + std::panic::UnwindSafe) {
+        std::panic::catch_unwind(f).unwrap_err();
+    }
+
+    let nope: Option<()> = None;
+    assert_panicked(|| nope.unwrap());
+    assert_panicked(|| nope.expect(""));
+
+    let yep: Option<()> = Some(());
+    assert_panicked(|| yep.unwrap_none());
+    assert_panicked(|| yep.expect_none(""));
+
+    let oops: Result<(), ()> = Err(());
+    assert_panicked(|| oops.unwrap());
+    assert_panicked(|| oops.expect(""));
+
+    let fine: Result<(), ()> = Ok(());
+    assert_panicked(|| fine.unwrap_err());
+    assert_panicked(|| fine.expect_err(""));
+}
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
index 6498766..f5cb186 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
@@ -123,9 +123,11 @@
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR `let` expressions in this position are experimental [E0658]
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
     use_expr!((let 0 = 1));
     //~^ ERROR `let` expressions in this position are experimental [E0658]
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
     #[cfg(FALSE)] (let 0 = 1);
     //~^ ERROR `let` expressions in this position are experimental [E0658]
     use_expr!(let 0 = 1);
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
index abe2009..c14a45a 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
@@ -1,5 +1,5 @@
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:131:15
+  --> $DIR/feature-gate.rs:133:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -260,7 +260,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are experimental
-  --> $DIR/feature-gate.rs:129:20
+  --> $DIR/feature-gate.rs:131:20
    |
 LL |     #[cfg(FALSE)] (let 0 = 1);
    |                    ^^^^^^^^^
@@ -287,7 +287,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are experimental
-  --> $DIR/feature-gate.rs:126:16
+  --> $DIR/feature-gate.rs:127:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
@@ -557,7 +557,16 @@
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/feature-gate.rs:126:16
+  --> $DIR/feature-gate.rs:123:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:127:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
@@ -565,6 +574,15 @@
    = note: only supported directly in conditions of `if`- and `while`-expressions
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
-error: aborting due to 63 previous errors
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:127:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: aborting due to 65 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr
new file mode 100644
index 0000000..0bf337a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr
@@ -0,0 +1,8 @@
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/feature-gate.rs:11:29
+   |
+LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
+   |                             ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs
new file mode 100644
index 0000000..cf1ed30
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs
@@ -0,0 +1,15 @@
+// revisions: stock gated
+// gate-test-const_trait_bound_opt_out
+
+#![cfg_attr(gated, feature(const_trait_bound_opt_out))]
+#![allow(incomplete_features)]
+
+trait T {
+    const CONST: i32;
+}
+
+const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
+//[stock]~^ ERROR `?const` on trait bounds is experimental
+//[stock,gated]~^^ ERROR `?const` on trait bounds is not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr
new file mode 100644
index 0000000..6438800
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr
@@ -0,0 +1,18 @@
+error[E0658]: `?const` on trait bounds is experimental
+  --> $DIR/feature-gate.rs:11:29
+   |
+LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
+   |                             ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67794
+   = help: add `#![feature(const_trait_bound_opt_out)]` to the crate attributes to enable
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/feature-gate.rs:11:29
+   |
+LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
+   |                             ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs
new file mode 100644
index 0000000..e4e6bed
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs
@@ -0,0 +1,25 @@
+#![feature(const_trait_bound_opt_out)]
+#![feature(associated_type_bounds)]
+#![allow(incomplete_features)]
+
+trait T {}
+struct S;
+impl T for S {}
+
+fn rpit() -> impl ?const T { S }
+//~^ ERROR `?const` is not permitted in `impl Trait`
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn apit(_: impl ?const T) {}
+//~^ ERROR `?const` is not permitted in `impl Trait`
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
+//~^ ERROR `?const` is not permitted in `impl Trait`
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
+//~^ ERROR `?const` is not permitted in `impl Trait`
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr
new file mode 100644
index 0000000..f4abd4b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr
@@ -0,0 +1,50 @@
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:9:19
+   |
+LL | fn rpit() -> impl ?const T { S }
+   |                   ^^^^^^^^
+
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:13:17
+   |
+LL | fn apit(_: impl ?const T) {}
+   |                 ^^^^^^^^
+
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:17:50
+   |
+LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
+   |                                                  ^^^^^^^^
+
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:21:48
+   |
+LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
+   |                                                ^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-impl-trait.rs:9:19
+   |
+LL | fn rpit() -> impl ?const T { S }
+   |                   ^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-impl-trait.rs:13:17
+   |
+LL | fn apit(_: impl ?const T) {}
+   |                 ^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-impl-trait.rs:17:50
+   |
+LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
+   |                                                  ^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-impl-trait.rs:21:48
+   |
+LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
+   |                                                ^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs
new file mode 100644
index 0000000..4523b46
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+trait Super {}
+trait T: ?const Super {}
+//~^ ERROR `?const` is not permitted in supertraits
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr
new file mode 100644
index 0000000..8003361
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr
@@ -0,0 +1,14 @@
+error: `?const` is not permitted in supertraits
+  --> $DIR/in-trait-bounds.rs:5:10
+   |
+LL | trait T: ?const Super {}
+   |          ^^^^^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-trait-bounds.rs:5:10
+   |
+LL | trait T: ?const Super {}
+   |          ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs
new file mode 100644
index 0000000..6cfca71
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs
@@ -0,0 +1,22 @@
+#![feature(const_trait_bound_opt_out)]
+#![allow(bare_trait_objects)]
+#![allow(incomplete_features)]
+
+struct S;
+trait T {}
+impl T for S {}
+
+// An inherent impl for the trait object `?const T`.
+impl ?const T {}
+//~^ ERROR `?const` is not permitted in trait objects
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn trait_object() -> &'static dyn ?const T { &S }
+//~^ ERROR `?const` is not permitted in trait objects
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
+//~^ ERROR `?const` is not permitted in trait objects
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr
new file mode 100644
index 0000000..c059f16
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr
@@ -0,0 +1,38 @@
+error: `?const` is not permitted in trait objects
+  --> $DIR/in-trait-object.rs:10:6
+   |
+LL | impl ?const T {}
+   |      ^^^^^^^^
+
+error: `?const` is not permitted in trait objects
+  --> $DIR/in-trait-object.rs:14:35
+   |
+LL | fn trait_object() -> &'static dyn ?const T { &S }
+   |                                   ^^^^^^^^
+
+error: `?const` is not permitted in trait objects
+  --> $DIR/in-trait-object.rs:18:61
+   |
+LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
+   |                                                             ^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-trait-object.rs:10:6
+   |
+LL | impl ?const T {}
+   |      ^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-trait-object.rs:14:35
+   |
+LL | fn trait_object() -> &'static dyn ?const T { &S }
+   |                                   ^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/in-trait-object.rs:18:61
+   |
+LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
+   |                                                             ^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs
new file mode 100644
index 0000000..01e941a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<T: ?const ?const Tr>;
+//~^ ERROR expected identifier, found keyword `const`
+//~| ERROR expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr
new file mode 100644
index 0000000..f7924b3
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found keyword `const`
+  --> $DIR/opt-out-twice.rs:6:21
+   |
+LL | struct S<T: ?const ?const Tr>;
+   |                     ^^^^^ expected identifier, found keyword
+
+error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Tr`
+  --> $DIR/opt-out-twice.rs:6:27
+   |
+LL | struct S<T: ?const ?const Tr>;
+   |                           ^^ expected one of 7 possible tokens
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs
new file mode 100644
index 0000000..a0d9610
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<
+    T: ?const ?for<'a> Tr<'a> + 'static + ?const std::ops::Add,
+    T: ?const ?for<'a: 'b> m::Trait<'a>,
+>;
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs
new file mode 100644
index 0000000..425784f
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs
@@ -0,0 +1,8 @@
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
+//~^ ERROR `?const` and `?` are mutually exclusive
+//~| ERROR `?const` on trait bounds is not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr
new file mode 100644
index 0000000..44f6d46
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr
@@ -0,0 +1,14 @@
+error: `?const` and `?` are mutually exclusive
+  --> $DIR/with-maybe-sized.rs:4:13
+   |
+LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
+   |             ^^^^^^^^^^^^^
+
+error: `?const` on trait bounds is not yet implemented
+  --> $DIR/with-maybe-sized.rs:4:13
+   |
+LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs
new file mode 100644
index 0000000..b904a2e
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<T: const Tr>;
+//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr
new file mode 100644
index 0000000..0dbca95
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path, found keyword `const`
+  --> $DIR/without-question-mark.rs:6:13
+   |
+LL | struct S<T: const Tr>;
+   |             ^^^^^ expected one of 9 possible tokens
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
new file mode 100644
index 0000000..b196f9e
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
@@ -0,0 +1,8 @@
+error: const trait impls are not yet implemented
+  --> $DIR/feature-gate.rs:9:1
+   |
+LL | impl const T for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
new file mode 100644
index 0000000..49b6c09
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
@@ -0,0 +1,13 @@
+// revisions: stock gated
+// gate-test-const_trait_impl
+
+#![cfg_attr(gated, feature(const_trait_impl))]
+#![allow(incomplete_features)]
+
+struct S;
+trait T {}
+impl const T for S {}
+//[stock]~^ ERROR const trait impls are experimental
+//[stock,gated]~^^ ERROR const trait impls are not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
new file mode 100644
index 0000000..093946f
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
@@ -0,0 +1,18 @@
+error[E0658]: const trait impls are experimental
+  --> $DIR/feature-gate.rs:9:6
+   |
+LL | impl const T for S {}
+   |      ^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67792
+   = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: const trait impls are not yet implemented
+  --> $DIR/feature-gate.rs:9:1
+   |
+LL | impl const T for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs
new file mode 100644
index 0000000..98d3a22
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs
@@ -0,0 +1,11 @@
+#![feature(const_trait_bound_opt_out)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+struct S;
+trait T {}
+
+impl ?const T for S {}
+//~^ ERROR expected a trait, found type
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr
new file mode 100644
index 0000000..8f923ef
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr
@@ -0,0 +1,8 @@
+error: expected a trait, found type
+  --> $DIR/impl-opt-out-trait.rs:8:6
+   |
+LL | impl ?const T for S {}
+   |      ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs
new file mode 100644
index 0000000..9cffe75
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_impl)]
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+#![allow(bare_trait_objects)]
+
+struct S;
+trait T {}
+
+impl const T {}
+//~^ ERROR `const` cannot modify an inherent impl
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
new file mode 100644
index 0000000..1d24557
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
@@ -0,0 +1,10 @@
+error: `const` cannot modify an inherent impl
+  --> $DIR/inherent-impl.rs:11:6
+   |
+LL | impl const T {}
+   |      ^^^^^
+   |
+   = help: only a trait impl can be `const`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs
new file mode 100644
index 0000000..354d48d
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_bound_opt_out)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+// For now, this parses since an error does not occur until AST lowering.
+impl ?const T {}
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs
index b8949ae..e9dcb4f 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs
@@ -21,6 +21,7 @@
     match WRAP_DIRECT_INLINE {
         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
     }
 }
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr
index c73a6cf..9c7d1f3 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr
@@ -4,5 +4,11 @@
 LL |         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
    |         ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
+   |
+LL |         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs
index 584e7a0..ab1cb3b 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs
@@ -21,6 +21,7 @@
     match WRAP_DIRECT_PARAM {
         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
     }
 }
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr
index 6fdf9db..6f49a8a 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr
@@ -4,5 +4,11 @@
 LL |         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
    |         ^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-direct-struct-param.rs:22:9
+   |
+LL |         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/match-forbidden-without-eq.rs b/src/test/ui/rfc1445/match-forbidden-without-eq.rs
index 1cca275..59141ea 100644
--- a/src/test/ui/rfc1445/match-forbidden-without-eq.rs
+++ b/src/test/ui/rfc1445/match-forbidden-without-eq.rs
@@ -12,6 +12,7 @@
     match y {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { }
     }
 
diff --git a/src/test/ui/rfc1445/match-forbidden-without-eq.stderr b/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
index c05bb8f..b9476e3 100644
--- a/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
+++ b/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
@@ -5,7 +5,7 @@
    |         ^^^
 
 warning: floating-point types cannot be used in patterns
-  --> $DIR/match-forbidden-without-eq.rs:20:9
+  --> $DIR/match-forbidden-without-eq.rs:21:9
    |
 LL |         f32::INFINITY => { }
    |         ^^^^^^^^^^^^^
@@ -14,8 +14,14 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-forbidden-without-eq.rs:13:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
 warning: floating-point types cannot be used in patterns
-  --> $DIR/match-forbidden-without-eq.rs:20:9
+  --> $DIR/match-forbidden-without-eq.rs:21:9
    |
 LL |         f32::INFINITY => { }
    |         ^^^^^^^^^^^^^
@@ -23,5 +29,5 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs
index 3d56fb0..9ef8a68 100644
--- a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs
+++ b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs
@@ -15,5 +15,6 @@
     match [B(1)] {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
     }
 }
diff --git a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr
index 371f8a0..7e354bf 100644
--- a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr
+++ b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr
@@ -4,5 +4,11 @@
 LL |         FOO => { }
    |         ^^^
 
-error: aborting due to previous error
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
index 6b7d946..9530a1f 100644
--- a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
+++ b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
@@ -16,6 +16,7 @@
     match y {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { }
     }
 }
diff --git a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
index 4157cf6..7ef0828 100644
--- a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
+++ b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
@@ -4,5 +4,11 @@
 LL |         FOO => { }
    |         ^^^
 
-error: aborting due to previous error
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.rs b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
index 27d6dbf..0ca7fa3 100644
--- a/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
@@ -6,6 +6,7 @@
 
 #[built_in_attr] //~ ERROR cannot use a built-in attribute through an import
 #[tool_mod::skip] //~ ERROR cannot use a tool module through an import
+                  //~| ERROR cannot use a tool module through an import
 fn main() {
     let _: built_in_type; // OK
 }
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
index fdde75f..45f77a0 100644
--- a/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
@@ -22,5 +22,17 @@
 LL | use cross_crate::*;
    |     ^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: cannot use a tool module through an import
+  --> $DIR/cross-crate.rs:8:3
+   |
+LL | #[tool_mod::skip]
+   |   ^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/cross-crate.rs:5:5
+   |
+LL | use cross_crate::*;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
index 541fc1b..44da71d 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
@@ -15,5 +15,7 @@
 #[imported_inline] //~ ERROR cannot use a built-in attribute through an import
 #[builtin::imported_inline] //~ ERROR cannot use a built-in attribute through an import
 #[imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+                          //~| ERROR cannot use a tool module through an import
 #[tool_mod::imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+                                    //~| ERROR cannot use a tool module through an import
 fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
index fc64531..908bb49 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
@@ -29,7 +29,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: cannot use a tool module through an import
-  --> $DIR/prelude-fail-2.rs:18:13
+  --> $DIR/prelude-fail-2.rs:19:13
    |
 LL | #[tool_mod::imported_rustfmt::skip]
    |             ^^^^^^^^^^^^^^^^
@@ -40,5 +40,29 @@
 LL |     pub use rustfmt as imported_rustfmt;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: cannot use a tool module through an import
+  --> $DIR/prelude-fail-2.rs:17:3
+   |
+LL | #[imported_rustfmt::skip]
+   |   ^^^^^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/prelude-fail-2.rs:10:5
+   |
+LL | use rustfmt as imported_rustfmt;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+  --> $DIR/prelude-fail-2.rs:19:13
+   |
+LL | #[tool_mod::imported_rustfmt::skip]
+   |             ^^^^^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/prelude-fail-2.rs:12:13
+   |
+LL |     pub use rustfmt as imported_rustfmt;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
index dec5809..96401cb 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `A` in the current scope
+error[E0599]: no method named `foo` found for struct `A` in the current scope
   --> $DIR/point-at-arbitrary-self-type-method.rs:8:7
    |
 LL | struct A;
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
index e93c4da..28a7b68 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `A` in the current scope
+error[E0599]: no method named `foo` found for struct `A` in the current scope
   --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7
    |
 LL | trait B { fn foo(self: Box<Self>); }
diff --git a/src/test/ui/self/suggest-self-2.rs b/src/test/ui/self/suggest-self-2.rs
index d6bf543..1e00182 100644
--- a/src/test/ui/self/suggest-self-2.rs
+++ b/src/test/ui/self/suggest-self-2.rs
@@ -18,7 +18,7 @@
         //~^ ERROR cannot find function `bar` in this scope
 
         self.bar();
-        //~^ ERROR no method named `bar` found for type
+        //~^ ERROR no method named `bar` found for reference
     }
 }
 
diff --git a/src/test/ui/self/suggest-self-2.stderr b/src/test/ui/self/suggest-self-2.stderr
index 452c312..4bd025e 100644
--- a/src/test/ui/self/suggest-self-2.stderr
+++ b/src/test/ui/self/suggest-self-2.stderr
@@ -28,7 +28,7 @@
 LL |         bar();
    |         ^^^ not found in this scope
 
-error[E0599]: no method named `bar` found for type `&Foo` in the current scope
+error[E0599]: no method named `bar` found for reference `&Foo` in the current scope
   --> $DIR/suggest-self-2.rs:20:14
    |
 LL |         self.bar();
diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr
index 3597cc5..362907e 100644
--- a/src/test/ui/shadowed/shadowed-trait-methods.stderr
+++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `()` in the current scope
+error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/shadowed-trait-methods.rs:13:8
    |
 LL |     ().f()
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs
index 8f1599a..89b8eba 100644
--- a/src/test/ui/span/issue-43927-non-ADT-derive.rs
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.rs
@@ -5,6 +5,9 @@
 //~| ERROR cannot determine resolution for the derive macro `Debug`
 //~| ERROR cannot determine resolution for the derive macro `PartialEq`
 //~| ERROR cannot determine resolution for the derive macro `Eq`
+//~| ERROR cannot determine resolution for the derive macro `Debug`
+//~| ERROR cannot determine resolution for the derive macro `PartialEq`
+//~| ERROR cannot determine resolution for the derive macro `Eq`
 struct DerivedOn;
 
 fn main() {}
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
index 47ce718..b68681c 100644
--- a/src/test/ui/span/issue-43927-non-ADT-derive.stderr
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
@@ -28,5 +28,29 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to 4 previous errors
+error: cannot determine resolution for the derive macro `Eq`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:29
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |                             ^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `PartialEq`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:18
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |                  ^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `Debug`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:11
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |           ^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/span/issue-7575.rs b/src/test/ui/span/issue-7575.rs
index ea0a665..eddd158 100644
--- a/src/test/ui/span/issue-7575.rs
+++ b/src/test/ui/span/issue-7575.rs
@@ -60,15 +60,15 @@
 
 fn no_param_bound(u: usize, m: Myisize) -> usize {
     u.f8(42) + u.f9(342) + m.fff(42)
-            //~^ ERROR no method named `f9` found for type `usize` in the current scope
-            //~| ERROR no method named `fff` found for type `Myisize` in the current scope
+            //~^ ERROR no method named `f9` found
+            //~| ERROR no method named `fff` found
 
 
 }
 
 fn param_bound<T: ManyImplTrait>(t: T) -> bool {
     t.is_str()
-    //~^ ERROR no method named `is_str` found for type `T` in the current scope
+    //~^ ERROR no method named `is_str` found
 }
 
 fn main() {
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index 53a62384..eb85be0 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -38,7 +38,7 @@
 LL |     u.f8(42) + UnusedTrait::f9(u, 342) + m.fff(42)
    |                ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `fff` found for type `Myisize` in the current scope
+error[E0599]: no method named `fff` found for struct `Myisize` in the current scope
   --> $DIR/issue-7575.rs:62:30
    |
 LL | struct Myisize(isize);
@@ -57,7 +57,7 @@
 LL |     fn fff(i: isize) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `is_str` found for type `T` in the current scope
+error[E0599]: no method named `is_str` found for type parameter `T` in the current scope
   --> $DIR/issue-7575.rs:70:7
    |
 LL |     t.is_str()
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
index 34a1416..5c10444 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -20,5 +20,5 @@
 
 fn main() {
     println!("{}", MyStruct.foo_one());
-    //~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope
+    //~^ ERROR no method named `foo_one` found
 }
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index bbfe4c3..1980977 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo_one` found for type `MyStruct` in the current scope
+error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
   --> $DIR/specialization-trait-not-implemented.rs:22:29
    |
 LL | struct MyStruct;
diff --git a/src/test/ui/suffixed-literal-meta.rs b/src/test/ui/suffixed-literal-meta.rs
index a653149..c3a4eab 100644
--- a/src/test/ui/suffixed-literal-meta.rs
+++ b/src/test/ui/suffixed-literal-meta.rs
@@ -1,15 +1,27 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
+                     //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
+                     //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 fn main() {}
diff --git a/src/test/ui/suffixed-literal-meta.stderr b/src/test/ui/suffixed-literal-meta.stderr
index 83de173..ee35b53 100644
--- a/src/test/ui/suffixed-literal-meta.stderr
+++ b/src/test/ui/suffixed-literal-meta.stderr
@@ -7,7 +7,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:4:17
+  --> $DIR/suffixed-literal-meta.rs:5:17
    |
 LL | #[rustc_dummy = 1u8]
    |                 ^^^
@@ -15,7 +15,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:5:17
+  --> $DIR/suffixed-literal-meta.rs:7:17
    |
 LL | #[rustc_dummy = 1u16]
    |                 ^^^^
@@ -23,7 +23,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:6:17
+  --> $DIR/suffixed-literal-meta.rs:9:17
    |
 LL | #[rustc_dummy = 1u32]
    |                 ^^^^
@@ -31,7 +31,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:7:17
+  --> $DIR/suffixed-literal-meta.rs:11:17
    |
 LL | #[rustc_dummy = 1u64]
    |                 ^^^^
@@ -39,7 +39,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:8:17
+  --> $DIR/suffixed-literal-meta.rs:13:17
    |
 LL | #[rustc_dummy = 1isize]
    |                 ^^^^^^
@@ -47,7 +47,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:9:17
+  --> $DIR/suffixed-literal-meta.rs:15:17
    |
 LL | #[rustc_dummy = 1i8]
    |                 ^^^
@@ -55,7 +55,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:10:17
+  --> $DIR/suffixed-literal-meta.rs:17:17
    |
 LL | #[rustc_dummy = 1i16]
    |                 ^^^^
@@ -63,7 +63,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:11:17
+  --> $DIR/suffixed-literal-meta.rs:19:17
    |
 LL | #[rustc_dummy = 1i32]
    |                 ^^^^
@@ -71,7 +71,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:12:17
+  --> $DIR/suffixed-literal-meta.rs:21:17
    |
 LL | #[rustc_dummy = 1i64]
    |                 ^^^^
@@ -79,7 +79,7 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:13:17
+  --> $DIR/suffixed-literal-meta.rs:23:17
    |
 LL | #[rustc_dummy = 1.0f32]
    |                 ^^^^^^
@@ -87,12 +87,108 @@
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:14:17
+  --> $DIR/suffixed-literal-meta.rs:25:17
    |
 LL | #[rustc_dummy = 1.0f64]
    |                 ^^^^^^
    |
    = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
 
-error: aborting due to 12 previous errors
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:3:17
+   |
+LL | #[rustc_dummy = 1usize]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:5:17
+   |
+LL | #[rustc_dummy = 1u8]
+   |                 ^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:7:17
+   |
+LL | #[rustc_dummy = 1u16]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:9:17
+   |
+LL | #[rustc_dummy = 1u32]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:11:17
+   |
+LL | #[rustc_dummy = 1u64]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:13:17
+   |
+LL | #[rustc_dummy = 1isize]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:15:17
+   |
+LL | #[rustc_dummy = 1i8]
+   |                 ^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:17:17
+   |
+LL | #[rustc_dummy = 1i16]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:19:17
+   |
+LL | #[rustc_dummy = 1i32]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:21:17
+   |
+LL | #[rustc_dummy = 1i64]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:23:17
+   |
+LL | #[rustc_dummy = 1.0f32]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:25:17
+   |
+LL | #[rustc_dummy = 1.0f64]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+
+error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs
index 7c8231b..e1e3317 100644
--- a/src/test/ui/suggestions/attribute-typos.rs
+++ b/src/test/ui/suggestions/attribute-typos.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 #[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope
 fn foo() {}
 
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
index e403293..a094359 100644
--- a/src/test/ui/suggestions/attribute-typos.stderr
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -1,5 +1,5 @@
 error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
-  --> $DIR/attribute-typos.rs:7:3
+  --> $DIR/attribute-typos.rs:11:3
    |
 LL | #[rustc_err]
    |   ^^^^^^^^^
@@ -8,19 +8,24 @@
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: cannot find attribute `rustc_err` in this scope
-  --> $DIR/attribute-typos.rs:7:3
+  --> $DIR/attribute-typos.rs:11:3
    |
 LL | #[rustc_err]
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
 
 error: cannot find attribute `tests` in this scope
-  --> $DIR/attribute-typos.rs:4:3
+  --> $DIR/attribute-typos.rs:8:3
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
+   | 
+  ::: $SRC_DIR/libcore/macros/mod.rs:LL:COL
+   |
+LL |     pub macro test($item:item) {
+   |     -------------------------- similarly named attribute macro `test` defined here
 
 error: cannot find attribute `deprcated` in this scope
-  --> $DIR/attribute-typos.rs:1:3
+  --> $DIR/attribute-typos.rs:5:3
    |
 LL | #[deprcated]
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated`
diff --git a/src/test/ui/suggestions/constrain-trait.fixed b/src/test/ui/suggestions/constrain-trait.fixed
index dda9e93..f292f27 100644
--- a/src/test/ui/suggestions/constrain-trait.fixed
+++ b/src/test/ui/suggestions/constrain-trait.fixed
@@ -12,13 +12,13 @@
 
 trait UseString: std::fmt::Debug + GetString {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
 trait UseString2: GetString {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
diff --git a/src/test/ui/suggestions/constrain-trait.rs b/src/test/ui/suggestions/constrain-trait.rs
index 4ef0eff..99ccf7a 100644
--- a/src/test/ui/suggestions/constrain-trait.rs
+++ b/src/test/ui/suggestions/constrain-trait.rs
@@ -12,13 +12,13 @@
 
 trait UseString: std::fmt::Debug {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
 trait UseString2 {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
diff --git a/src/test/ui/suggestions/constrain-trait.stderr b/src/test/ui/suggestions/constrain-trait.stderr
index 3cc351a..f1c50e5 100644
--- a/src/test/ui/suggestions/constrain-trait.stderr
+++ b/src/test/ui/suggestions/constrain-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
   --> $DIR/constrain-trait.rs:15:31
    |
 LL |         println!("{:?}", self.get_a());
@@ -10,7 +10,7 @@
 LL | trait UseString: std::fmt::Debug + GetString {
    |                                  ^^^^^^^^^^^
 
-error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
   --> $DIR/constrain-trait.rs:21:31
    |
 LL |         println!("{:?}", self.get_a());
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 2f0a457..232e54b 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -236,7 +236,7 @@
   --> $DIR/fn-or-tuple-struct-without-args.rs:46:20
    |
 LL |     let closure = || 42;
-   |                   -- closure defined here
+   |                   ----- the found closure
 LL |     let _: usize = closure;
    |            -----   ^^^^^^^
    |            |       |
diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
index 4aec720..db54d04 100644
--- a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
+++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `hello` found for type `impl Foo` in the current scope
+error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope
   --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9
    |
 LL |     foo.hello();
diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr
index f2496f6..14c7b18 100644
--- a/src/test/ui/suggestions/issue-21673.stderr
+++ b/src/test/ui/suggestions/issue-21673.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `method` found for type `&T` in the current scope
+error[E0599]: no method named `method` found for reference `&T` in the current scope
   --> $DIR/issue-21673.rs:6:7
    |
 LL |     x.method()
@@ -10,7 +10,7 @@
 LL | fn call_method<T: Foo + std::fmt::Debug>(x: &T) {
    |                ^^^^^^^^
 
-error[E0599]: no method named `method` found for type `T` in the current scope
+error[E0599]: no method named `method` found for type parameter `T` in the current scope
   --> $DIR/issue-21673.rs:10:7
    |
 LL |     x.method()
diff --git a/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs
new file mode 100644
index 0000000..440bb65
--- /dev/null
+++ b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let a_longer_variable_name = 1;
+    println!("{}", a_variable_longer_name); //~ ERROR E0425
+}
diff --git a/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr
new file mode 100644
index 0000000..d7b33ea
--- /dev/null
+++ b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `a_variable_longer_name` in this scope
+  --> $DIR/issue-66968-suggest-sorted-words.rs:3:20
+   |
+LL |     println!("{}", a_variable_longer_name);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `a_longer_variable_name`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
index dcef2ad..f8b8637 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
@@ -19,5 +19,5 @@
     //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
     //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
 
-    writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for type
+    writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for struct
 }
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
index daa8e11..2c3c07c 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -25,7 +25,7 @@
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
    = note: required by `std::io::BufWriter`
 
-error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope
+error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope
   --> $DIR/mut-borrow-needed-by-trait.rs:22:5
    |
 LL |     writeln!(fp, "hello world").unwrap();
diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr
index 1465b9e..167d61b 100644
--- a/src/test/ui/suggestions/opaque-type-error.stderr
+++ b/src/test/ui/suggestions/opaque-type-error.stderr
@@ -1,6 +1,9 @@
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/opaque-type-error.rs:20:9
    |
+LL |   fn thing_two() -> impl Future<Output = Result<(), ()>> {
+   |                     ------------------------------------ the found opaque type
+...
 LL | /     if true {
 LL | |         thing_one()
    | |         ----------- expected because of this
diff --git a/src/test/ui/suggestions/remove-as_str.rs b/src/test/ui/suggestions/remove-as_str.rs
index d10300b..289a784 100644
--- a/src/test/ui/suggestions/remove-as_str.rs
+++ b/src/test/ui/suggestions/remove-as_str.rs
@@ -1,21 +1,21 @@
 fn foo1(s: &str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo2<'a>(s: &'a str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&'a str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo3(s: &mut str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&mut str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo4(s: &&str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&&str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn main() {}
diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr
index eae9cc0..534c497 100644
--- a/src/test/ui/suggestions/remove-as_str.stderr
+++ b/src/test/ui/suggestions/remove-as_str.stderr
@@ -1,22 +1,22 @@
-error[E0599]: no method named `as_str` found for type `&str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&str` in the current scope
   --> $DIR/remove-as_str.rs:2:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&'a str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&'a str` in the current scope
   --> $DIR/remove-as_str.rs:7:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&mut str` in the current scope
+error[E0599]: no method named `as_str` found for mutable reference `&mut str` in the current scope
   --> $DIR/remove-as_str.rs:12:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&&str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&&str` in the current scope
   --> $DIR/remove-as_str.rs:17:7
    |
 LL |     s.as_str();
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
index 5480adb..f738a1f 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
@@ -9,5 +9,5 @@
     let shared_state = RefCell::new(HasAssocMethod);
     let state = shared_state.borrow_mut();
     state.hello();
-    //~^ ERROR no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>`
+    //~^ ERROR no method named `hello` found
 }
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
index a1c0126..507f822 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` in the current scope
+error[E0599]: no method named `hello` found for struct `std::cell::RefMut<'_, HasAssocMethod>` in the current scope
   --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11
    |
 LL |     state.hello();
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
index ef4b38d..2a829db 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
@@ -7,5 +7,5 @@
 fn main() {
     let x = GenericAssocMethod(33i32);
     x.default_hello();
-    //~^ ERROR no method named `default_hello` found for type `GenericAssocMethod<i32>`
+    //~^ ERROR no method named `default_hello` found
 }
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
index 8cfa7de..dfc1887 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `default_hello` found for type `GenericAssocMethod<i32>` in the current scope
+error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope
   --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7
    |
 LL | struct GenericAssocMethod<T>(T);
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
index 4678410..a715c56 100644
--- a/src/test/ui/suggestions/suggest-methods.stderr
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `bat` found for type `Foo` in the current scope
+error[E0599]: no method named `bat` found for struct `Foo` in the current scope
   --> $DIR/suggest-methods.rs:18:7
    |
 LL | struct Foo;
@@ -7,7 +7,7 @@
 LL |     f.bat(1.0);
    |       ^^^ help: there is a method with a similar name: `bar`
 
-error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
+error[E0599]: no method named `is_emtpy` found for struct `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy();
diff --git a/src/test/ui/suggestions/suggest-variants.rs b/src/test/ui/suggestions/suggest-variants.rs
index d418834..dd05d0f 100644
--- a/src/test/ui/suggestions/suggest-variants.rs
+++ b/src/test/ui/suggestions/suggest-variants.rs
@@ -9,9 +9,9 @@
 }
 
 fn main() {
-    println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant `Squareee`
-    println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant `Circl`
-    println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant `Rombus`
+    println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant named `Squareee`
+    println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant named `Circl`
+    println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant named `Rombus`
     Shape::Squareee; //~ ERROR no variant
     Shape::Circl; //~ ERROR no variant
     Shape::Rombus; //~ ERROR no variant
diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr
index b4338e2..9227baa 100644
--- a/src/test/ui/suggestions/suggest-variants.stderr
+++ b/src/test/ui/suggestions/suggest-variants.stderr
@@ -1,4 +1,4 @@
-error: no variant `Squareee` in enum `Shape`
+error[E0599]: no variant named `Squareee` found for enum `Shape`
   --> $DIR/suggest-variants.rs:12:41
    |
 LL | enum Shape {
@@ -7,7 +7,7 @@
 LL |     println!("My shape is {:?}", Shape::Squareee { size: 5});
    |                                         ^^^^^^^^ help: there is a variant with a similar name: `Square`
 
-error: no variant `Circl` in enum `Shape`
+error[E0599]: no variant named `Circl` found for enum `Shape`
   --> $DIR/suggest-variants.rs:13:41
    |
 LL | enum Shape {
@@ -16,7 +16,7 @@
 LL |     println!("My shape is {:?}", Shape::Circl { size: 5});
    |                                         ^^^^^ help: there is a variant with a similar name: `Circle`
 
-error: no variant `Rombus` in enum `Shape`
+error[E0599]: no variant named `Rombus` found for enum `Shape`
   --> $DIR/suggest-variants.rs:14:41
    |
 LL | enum Shape {
@@ -25,7 +25,7 @@
 LL |     println!("My shape is {:?}", Shape::Rombus{ size: 5});
    |                                         ^^^^^^ variant not found in `Shape`
 
-error[E0599]: no variant or associated item named `Squareee` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Squareee` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:15:12
    |
 LL | enum Shape {
@@ -37,7 +37,7 @@
    |            variant or associated item not found in `Shape`
    |            help: there is a variant with a similar name: `Square`
 
-error[E0599]: no variant or associated item named `Circl` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Circl` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:16:12
    |
 LL | enum Shape {
@@ -49,7 +49,7 @@
    |            variant or associated item not found in `Shape`
    |            help: there is a variant with a similar name: `Circle`
 
-error[E0599]: no variant or associated item named `Rombus` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Rombus` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:17:12
    |
 LL | enum Shape {
diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr
index 53ab2f9..affb553 100644
--- a/src/test/ui/symbol-names/impl1.legacy.stderr
+++ b/src/test/ui/symbol-names/impl1.legacy.stderr
@@ -46,13 +46,13 @@
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h92c563325b7ff21aE)
+error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17hf07584432cd4d8beE)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h92c563325b7ff21a)
+error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::hf07584432cd4d8be)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
index d5698be..bf45ba2 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
@@ -2,6 +2,7 @@
 type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::skip`
 
 #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
+                   //~| ERROR cannot find derive macro `rustfmt` in this scope
 struct S;
 
 // Interpreted as an unstable custom attribute
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
index b831e62..71fd5f1 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
@@ -4,14 +4,20 @@
 LL | #[derive(rustfmt)]
    |          ^^^^^^^
 
+error: cannot find derive macro `rustfmt` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:4:10
+   |
+LL | #[derive(rustfmt)]
+   |          ^^^^^^^
+
 error: cannot find attribute `rustfmt` in this scope
-  --> $DIR/tool-attributes-misplaced-1.rs:8:3
+  --> $DIR/tool-attributes-misplaced-1.rs:9:3
    |
 LL | #[rustfmt]
    |   ^^^^^^^
 
 error: cannot find macro `rustfmt` in this scope
-  --> $DIR/tool-attributes-misplaced-1.rs:14:5
+  --> $DIR/tool-attributes-misplaced-1.rs:15:5
    |
 LL |     rustfmt!();
    |     ^^^^^^^
@@ -29,18 +35,18 @@
    |          ^^^^^^^^^^^^^ not a type
 
 error[E0423]: expected value, found tool module `rustfmt`
-  --> $DIR/tool-attributes-misplaced-1.rs:13:5
+  --> $DIR/tool-attributes-misplaced-1.rs:14:5
    |
 LL |     rustfmt;
    |     ^^^^^^^ not a value
 
 error[E0423]: expected value, found tool attribute `rustfmt::skip`
-  --> $DIR/tool-attributes-misplaced-1.rs:16:5
+  --> $DIR/tool-attributes-misplaced-1.rs:17:5
    |
 LL |     rustfmt::skip;
    |     ^^^^^^^^^^^^^ not a value
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0423, E0573.
 For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs
index fa8f041..9c8540e 100644
--- a/src/test/ui/tool_lints.rs
+++ b/src/test/ui/tool_lints.rs
@@ -1,3 +1,5 @@
 #[warn(foo::bar)]
 //~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
+//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr
index de94160..86f8778 100644
--- a/src/test/ui/tool_lints.stderr
+++ b/src/test/ui/tool_lints.stderr
@@ -4,5 +4,17 @@
 LL | #[warn(foo::bar)]
    |        ^^^
 
-error: aborting due to previous error
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/tool_lints.rs:1:8
+   |
+LL | #[warn(foo::bar)]
+   |        ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/tool_lints.rs:1:8
+   |
+LL | #[warn(foo::bar)]
+   |        ^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/traits/trait-impl-1.rs b/src/test/ui/traits/trait-impl-1.rs
index 43b8222..d22ac72 100644
--- a/src/test/ui/traits/trait-impl-1.rs
+++ b/src/test/ui/traits/trait-impl-1.rs
@@ -12,5 +12,5 @@
 
 fn main() {
     let x = &42i32;
-    x.foo(); //~ERROR: no method named `foo` found for type `&i32` in the current scope
+    x.foo(); //~ERROR: no method named `foo` found
 }
diff --git a/src/test/ui/traits/trait-impl-1.stderr b/src/test/ui/traits/trait-impl-1.stderr
index 0d61c3e..da0936e 100644
--- a/src/test/ui/traits/trait-impl-1.stderr
+++ b/src/test/ui/traits/trait-impl-1.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&i32` in the current scope
+error[E0599]: no method named `foo` found for reference `&i32` in the current scope
   --> $DIR/trait-impl-1.rs:15:7
    |
 LL |     x.foo();
diff --git a/src/test/ui/traits/trait-item-privacy.rs b/src/test/ui/traits/trait-item-privacy.rs
index d58bbef38..8507d8e 100644
--- a/src/test/ui/traits/trait-item-privacy.rs
+++ b/src/test/ui/traits/trait-item-privacy.rs
@@ -64,8 +64,8 @@
 
     // Methods, method call
     // a, b, c are resolved as trait items, their traits need to be in scope
-    S.a(); //~ ERROR no method named `a` found for type `S` in the current scope
-    S.b(); //~ ERROR no method named `b` found for type `S` in the current scope
+    S.a(); //~ ERROR no method named `a` found
+    S.b(); //~ ERROR no method named `b` found
     S.c(); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     let c = &S as &dyn C;
@@ -76,9 +76,9 @@
     // Methods, UFCS
     // a, b, c are resolved as trait items, their traits need to be in scope
     S::a(&S);
-    //~^ ERROR no function or associated item named `a` found for type `S`
+    //~^ ERROR no function or associated item named `a` found
     S::b(&S);
-    //~^ ERROR no function or associated item named `b` found for type `S`
+    //~^ ERROR no function or associated item named `b` found
     S::c(&S); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     C::a(&S); //~ ERROR method `a` is private
@@ -94,8 +94,8 @@
 
     // Associated constants
     // A, B, C are resolved as trait items, their traits need to be in scope
-    S::A; //~ ERROR no associated item named `A` found for type `S` in the current scope
-    S::B; //~ ERROR no associated item named `B` found for type `S` in the current scope
+    S::A; //~ ERROR no associated item named `A` found
+    S::B; //~ ERROR no associated item named `B` found
     S::C; // OK
     // A, B, C are resolved as inherent items, their traits don't need to be in scope
     C::A; //~ ERROR associated constant `A` is private
diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr
index 64a92c6..4df8845 100644
--- a/src/test/ui/traits/trait-item-privacy.stderr
+++ b/src/test/ui/traits/trait-item-privacy.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `a` found for type `S` in the current scope
+error[E0599]: no method named `a` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:67:7
    |
 LL | struct S;
@@ -11,7 +11,7 @@
    = note: the following trait defines an item `a`, perhaps you need to implement it:
            candidate #1: `method::A`
 
-error[E0599]: no method named `b` found for type `S` in the current scope
+error[E0599]: no method named `b` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:68:7
    |
 LL | struct S;
@@ -39,7 +39,7 @@
 LL |     c.a();
    |       ^
 
-error[E0599]: no function or associated item named `a` found for type `S` in the current scope
+error[E0599]: no function or associated item named `a` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:78:8
    |
 LL | struct S;
@@ -52,7 +52,7 @@
    = note: the following trait defines an item `a`, perhaps you need to implement it:
            candidate #1: `method::A`
 
-error[E0599]: no function or associated item named `b` found for type `S` in the current scope
+error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:80:8
    |
 LL | struct S;
@@ -73,7 +73,7 @@
 LL |     C::a(&S);
    |     ^^^^
 
-error[E0599]: no associated item named `A` found for type `S` in the current scope
+error[E0599]: no associated item named `A` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:97:8
    |
 LL | struct S;
@@ -86,7 +86,7 @@
    = note: the following trait defines an item `A`, perhaps you need to implement it:
            candidate #1: `assoc_const::A`
 
-error[E0599]: no associated item named `B` found for type `S` in the current scope
+error[E0599]: no associated item named `B` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:98:8
    |
 LL | struct S;
diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.rs b/src/test/ui/tuple/tuple-struct-fields/test2.rs
index fc0f78b..2b2a2c1 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test2.rs
+++ b/src/test/ui/tuple/tuple-struct-fields/test2.rs
@@ -9,6 +9,7 @@
 
 mod foo {
     define_struct! { (foo) } //~ ERROR cannot find type `foo` in this scope
+                             //~| ERROR cannot find type `foo` in this scope
 }
 
 fn main() {}
diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.stderr b/src/test/ui/tuple/tuple-struct-fields/test2.stderr
index d924c35..2f1ca2f 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test2.stderr
+++ b/src/test/ui/tuple/tuple-struct-fields/test2.stderr
@@ -15,6 +15,12 @@
 LL |     define_struct! { (foo) }
    |                       ^^^ not found in this scope
 
-error: aborting due to 2 previous errors
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test2.rs:11:23
+   |
+LL |     define_struct! { (foo) }
+   |                       ^^^ not found in this scope
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.rs b/src/test/ui/tuple/tuple-struct-fields/test3.rs
index 6b8534b..98d1942 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test3.rs
+++ b/src/test/ui/tuple/tuple-struct-fields/test3.rs
@@ -9,6 +9,7 @@
 
 mod foo {
     define_struct! { foo } //~ ERROR cannot find type `foo` in this scope
+                           //~| ERROR cannot find type `foo` in this scope
 }
 
 fn main() {}
diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.stderr b/src/test/ui/tuple/tuple-struct-fields/test3.stderr
index 50cac6c..5d42fe6 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test3.stderr
+++ b/src/test/ui/tuple/tuple-struct-fields/test3.stderr
@@ -15,6 +15,12 @@
 LL |     define_struct! { foo }
    |                      ^^^ not found in this scope
 
-error: aborting due to 2 previous errors
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test3.rs:11:22
+   |
+LL |     define_struct! { foo }
+   |                      ^^^ not found in this scope
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
index dc41cbc..9549074 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
@@ -11,6 +11,9 @@
    |            ---   ^ expected `i32`, found opaque type
    |            |
    |            expected due to this
+...
+LL | type WrongGeneric<T> = impl 'static;
+   | ------------------------------------ the found opaque type
    |
    = note:     expected type `i32`
            found opaque type `WrongGeneric::<&{integer}>`
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index 24d23de..5a7f9d7 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -11,6 +11,9 @@
    |            ---   ^ expected `i32`, found opaque type
    |            |
    |            expected due to this
+...
+LL | type WrongGeneric<T> = impl 'static;
+   | ------------------------------------ the found opaque type
    |
    = note:     expected type `i32`
            found opaque type `WrongGeneric::<&{integer}>`
diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
new file mode 100644
index 0000000..c46c471
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
@@ -0,0 +1,16 @@
+// Regression test for issue 67856
+
+#![feature(unboxed_closures)]
+#![feature(type_alias_impl_trait)]
+#![feature(fn_traits)]
+
+trait MyTrait {}
+impl MyTrait for () {}
+
+impl<F> FnOnce<()> for &F {
+    //~^ ERROR conflicting implementations
+    //~| ERROR type parameter `F` must be used
+    type Output = impl MyTrait;
+    extern "rust-call" fn call_once(self, _: ()) -> Self::Output {}
+}
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
new file mode 100644
index 0000000..f8e1e55
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
@@ -0,0 +1,23 @@
+error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_`:
+  --> $DIR/incoherent-assoc-imp-trait.rs:10:1
+   |
+LL | impl<F> FnOnce<()> for &F {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<A, F> std::ops::FnOnce<A> for &F
+             where F: std::ops::Fn<A>, F: ?Sized;
+
+error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct<F>`)
+  --> $DIR/incoherent-assoc-imp-trait.rs:10:6
+   |
+LL | impl<F> FnOnce<()> for &F {
+   |      ^ type parameter `F` must be used as the type parameter for some local type
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0210.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
index 07962e3..70c99c9 100644
--- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/never_reveal_concrete_type.rs:13:27
    |
+LL | type NoReveal = impl std::fmt::Debug;
+   | ------------------------------------- the found opaque type
+...
 LL |     let _: &'static str = x;
    |            ------------   ^ expected `&str`, found opaque type
    |            |
diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
index a208142..375c0bc 100644
--- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:15:19
    |
+LL |     pub type Boo = impl ::std::fmt::Debug;
+   |     -------------------------------------- the found opaque type
+...
 LL |     let _: &str = bomp();
    |            ----   ^^^^^^ expected `&str`, found opaque type
    |            |
@@ -12,6 +15,9 @@
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:19:5
    |
+LL |     pub type Boo = impl ::std::fmt::Debug;
+   |     -------------------------------------- the expected opaque type
+...
 LL | fn bomp() -> boo::Boo {
    |              -------- expected `Boo` because of return type
 LL |     ""
diff --git a/src/test/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs b/src/test/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs
new file mode 100644
index 0000000..68aadcf
--- /dev/null
+++ b/src/test/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs
@@ -0,0 +1,8 @@
+// Regression test for issue #67690
+// Rustc endless loop out-of-memory and consequent SIGKILL in generic new type
+
+// check-pass
+pub type T<P: Send + Send + Send> = P;
+//~^ WARN bounds on generic parameters are not enforced in type aliases
+
+fn main() {}
diff --git a/src/test/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr b/src/test/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr
new file mode 100644
index 0000000..37b51b5
--- /dev/null
+++ b/src/test/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr
@@ -0,0 +1,12 @@
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15
+   |
+LL | pub type T<P: Send + Send + Send> = P;
+   |               ^^^^   ^^^^   ^^^^
+   |
+   = note: `#[warn(type_alias_bounds)]` on by default
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL | pub type T<P> = P;
+   |            --
+
diff --git a/src/test/ui/type/type-alias-bounds.rs b/src/test/ui/type/type-alias-bounds.rs
index 06705a2..65b7965 100644
--- a/src/test/ui/type/type-alias-bounds.rs
+++ b/src/test/ui/type/type-alias-bounds.rs
@@ -1,6 +1,6 @@
 // Test `ignored_generic_bounds` lint warning about bounds in type aliases.
 
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![allow(dead_code)]
 
 use std::rc::Rc;
diff --git a/src/test/ui/type/type-alias-bounds.stderr b/src/test/ui/type/type-alias-bounds.stderr
index c381d30..e4d3753 100644
--- a/src/test/ui/type/type-alias-bounds.stderr
+++ b/src/test/ui/type/type-alias-bounds.stderr
@@ -8,7 +8,7 @@
 help: the bound will not be checked when the type alias is used, and should be removed
    |
 LL | type SVec<T> = Vec<T>;
-   |     --    --
+   |           --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:10:21
@@ -30,7 +30,7 @@
 help: the bound will not be checked when the type alias is used, and should be removed
    |
 LL | type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>);
-   |            --  --
+   |                --
 
 warning: bounds on generic parameters are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:14:18
@@ -41,7 +41,7 @@
 help: the bound will not be checked when the type alias is used, and should be removed
    |
 LL | type WVec<'b, T> = (&'b u32, Vec<T>);
-   |           --  --
+   |               --
 
 warning: where clauses are not enforced in type aliases
   --> $DIR/type-alias-bounds.rs:16:25
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs
index 5b0ca2f..adecbd7 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs
@@ -1,3 +1,4 @@
+#![feature(type_alias_impl_trait)] // Needed for single test `type Y = impl Trait<_>`
 // This test checks that it is not possible to enable global type
 // inference by using the `_` type placeholder.
 
@@ -42,6 +43,16 @@
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 }
 
+fn test11(x: &usize) -> &_ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    &x
+}
+
+unsafe fn test12(x: *const usize) -> *const *const _ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    &x
+}
+
 impl Clone for Test9 {
     fn clone(&self) -> _ { Test9 }
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
@@ -131,3 +142,37 @@
     fn assoc_fn_test3() -> _;
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 }
+
+struct BadStruct<_>(_);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+trait BadTrait<_> {}
+//~^ ERROR expected identifier, found reserved identifier `_`
+impl BadTrait<_> for BadStruct<_> {}
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+fn impl_trait() -> impl BadTrait<_> {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    unimplemented!()
+}
+
+struct BadStruct1<_, _>(_);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the name `_` is already used
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+struct BadStruct2<_, T>(_, T);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+
+type X = Box<_>;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+struct Struct;
+trait Trait<T> {}
+impl Trait<usize> for Struct {}
+type Y = impl Trait<_>;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+fn foo() -> Y {
+    Struct
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
index 9fe7af4..05326a3 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -1,5 +1,43 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:146:18
+   |
+LL | struct BadStruct<_>(_);
+   |                  ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:149:16
+   |
+LL | trait BadTrait<_> {}
+   |                ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:159:19
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                   ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:159:22
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                      ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:164:19
+   |
+LL | struct BadStruct2<_, T>(_, T);
+   |                   ^ expected identifier, found reserved identifier
+
+error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/typeck_type_placeholder_item.rs:159:22
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                   -  ^ already used
+   |                   |
+   |                   first use of `_`
+
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:4:14
+  --> $DIR/typeck_type_placeholder_item.rs:5:14
    |
 LL | fn test() -> _ { 5 }
    |              ^
@@ -8,7 +46,7 @@
    |              help: replace with the correct return type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:7:16
+  --> $DIR/typeck_type_placeholder_item.rs:8:16
    |
 LL | fn test2() -> (_, _) { (5, 5) }
    |               -^--^-
@@ -18,7 +56,7 @@
    |               help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:10:15
+  --> $DIR/typeck_type_placeholder_item.rs:11:15
    |
 LL | static TEST3: _ = "test";
    |               ^
@@ -27,7 +65,7 @@
    |               help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:13:15
+  --> $DIR/typeck_type_placeholder_item.rs:14:15
    |
 LL | static TEST4: _ = 145;
    |               ^
@@ -36,13 +74,13 @@
    |               help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:16:15
+  --> $DIR/typeck_type_placeholder_item.rs:17:15
    |
 LL | static TEST5: (_, _) = (1, 2);
    |               ^^^^^^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:19:13
+  --> $DIR/typeck_type_placeholder_item.rs:20:13
    |
 LL | fn test6(_: _) { }
    |             ^ not allowed in type signatures
@@ -53,7 +91,7 @@
    |         ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:22:18
+  --> $DIR/typeck_type_placeholder_item.rs:23:18
    |
 LL | fn test6_b<T>(_: _, _: T) { }
    |                  ^ not allowed in type signatures
@@ -64,7 +102,7 @@
    |             ^^^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:25:30
+  --> $DIR/typeck_type_placeholder_item.rs:26:30
    |
 LL | fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
    |                              ^ not allowed in type signatures
@@ -75,7 +113,7 @@
    |                         ^^^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:28:13
+  --> $DIR/typeck_type_placeholder_item.rs:29:13
    |
 LL | fn test7(x: _) { let _x: usize = x; }
    |             ^ not allowed in type signatures
@@ -86,13 +124,13 @@
    |         ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:31:22
+  --> $DIR/typeck_type_placeholder_item.rs:32:22
    |
 LL | fn test8(_f: fn() -> _) { }
    |                      ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:31:22
+  --> $DIR/typeck_type_placeholder_item.rs:32:22
    |
 LL | fn test8(_f: fn() -> _) { }
    |                      ^ not allowed in type signatures
@@ -103,7 +141,25 @@
    |         ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:54:8
+  --> $DIR/typeck_type_placeholder_item.rs:46:26
+   |
+LL | fn test11(x: &usize) -> &_ {
+   |                         -^
+   |                         ||
+   |                         |not allowed in type signatures
+   |                         help: replace with the correct return type: `&&usize`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:51:52
+   |
+LL | unsafe fn test12(x: *const usize) -> *const *const _ {
+   |                                      --------------^
+   |                                      |             |
+   |                                      |             not allowed in type signatures
+   |                                      help: replace with the correct return type: `*const *const usize`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:65:8
    |
 LL |     a: _,
    |        ^ not allowed in type signatures
@@ -122,7 +178,7 @@
    |
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:60:21
+  --> $DIR/typeck_type_placeholder_item.rs:71:21
    |
 LL |     fn fn_test() -> _ { 5 }
    |                     ^
@@ -131,7 +187,7 @@
    |                     help: replace with the correct return type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:63:23
+  --> $DIR/typeck_type_placeholder_item.rs:74:23
    |
 LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      -^--^-
@@ -141,7 +197,7 @@
    |                      help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:66:22
+  --> $DIR/typeck_type_placeholder_item.rs:77:22
    |
 LL |     static FN_TEST3: _ = "test";
    |                      ^
@@ -150,7 +206,7 @@
    |                      help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:69:22
+  --> $DIR/typeck_type_placeholder_item.rs:80:22
    |
 LL |     static FN_TEST4: _ = 145;
    |                      ^
@@ -159,13 +215,13 @@
    |                      help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:72:22
+  --> $DIR/typeck_type_placeholder_item.rs:83:22
    |
 LL |     static FN_TEST5: (_, _) = (1, 2);
    |                      ^^^^^^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:75:20
+  --> $DIR/typeck_type_placeholder_item.rs:86:20
    |
 LL |     fn fn_test6(_: _) { }
    |                    ^ not allowed in type signatures
@@ -176,7 +232,7 @@
    |                ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:78:20
+  --> $DIR/typeck_type_placeholder_item.rs:89:20
    |
 LL |     fn fn_test7(x: _) { let _x: usize = x; }
    |                    ^ not allowed in type signatures
@@ -187,13 +243,13 @@
    |                ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:81:29
+  --> $DIR/typeck_type_placeholder_item.rs:92:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:81:29
+  --> $DIR/typeck_type_placeholder_item.rs:92:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
@@ -204,7 +260,7 @@
    |                ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:104:12
+  --> $DIR/typeck_type_placeholder_item.rs:115:12
    |
 LL |         a: _,
    |            ^ not allowed in type signatures
@@ -223,13 +279,13 @@
    |
 
 error[E0282]: type annotations needed
-  --> $DIR/typeck_type_placeholder_item.rs:109:27
+  --> $DIR/typeck_type_placeholder_item.rs:120:27
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                           ^^^^^^ cannot infer type
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:109:28
+  --> $DIR/typeck_type_placeholder_item.rs:120:28
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                            ^  ^ not allowed in type signatures
@@ -237,7 +293,7 @@
    |                            not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:113:30
+  --> $DIR/typeck_type_placeholder_item.rs:124:30
    |
 LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             -^--^-
@@ -247,7 +303,7 @@
    |                             help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:116:33
+  --> $DIR/typeck_type_placeholder_item.rs:127:33
    |
 LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           ------^-
@@ -256,7 +312,76 @@
    |                           help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:121:31
+  --> $DIR/typeck_type_placeholder_item.rs:146:21
+   |
+LL | struct BadStruct<_>(_);
+   |                     ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct<T>(T);
+   |                  ^  ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:151:15
+   |
+LL | impl BadTrait<_> for BadStruct<_> {}
+   |               ^                ^ not allowed in type signatures
+   |               |
+   |               not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | impl<T> BadTrait<T> for BadStruct<T> {}
+   |     ^^^          ^                ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:154:34
+   |
+LL | fn impl_trait() -> impl BadTrait<_> {
+   |                                  ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:159:25
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct1<T, _>(T);
+   |                   ^     ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:164:25
+   |
+LL | struct BadStruct2<_, T>(_, T);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct2<K, T>(K, T);
+   |                   ^     ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:168:14
+   |
+LL | type X = Box<_>;
+   |              ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:42:27
+   |
+LL |     fn test10(&self, _x : _) { }
+   |                           ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |     fn test10<T>(&self, _x : T) { }
+   |              ^^^             ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:132:31
    |
 LL |     fn method_test1(&self, x: _);
    |                               ^ not allowed in type signatures
@@ -267,7 +392,7 @@
    |                    ^^^           ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:123:31
+  --> $DIR/typeck_type_placeholder_item.rs:134:31
    |
 LL |     fn method_test2(&self, x: _) -> _;
    |                               ^     ^ not allowed in type signatures
@@ -280,7 +405,7 @@
    |                    ^^^           ^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:125:31
+  --> $DIR/typeck_type_placeholder_item.rs:136:31
    |
 LL |     fn method_test3(&self) -> _;
    |                               ^ not allowed in type signatures
@@ -291,7 +416,7 @@
    |                    ^^^           ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:127:26
+  --> $DIR/typeck_type_placeholder_item.rs:138:26
    |
 LL |     fn assoc_fn_test1(x: _);
    |                          ^ not allowed in type signatures
@@ -302,7 +427,7 @@
    |                      ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:129:26
+  --> $DIR/typeck_type_placeholder_item.rs:140:26
    |
 LL |     fn assoc_fn_test2(x: _) -> _;
    |                          ^     ^ not allowed in type signatures
@@ -315,7 +440,7 @@
    |                      ^^^    ^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:131:28
+  --> $DIR/typeck_type_placeholder_item.rs:142:28
    |
 LL |     fn assoc_fn_test3() -> _;
    |                            ^ not allowed in type signatures
@@ -326,36 +451,7 @@
    |                      ^^^      ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:38:24
-   |
-LL |     fn test9(&self) -> _ { () }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `()`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:41:27
-   |
-LL |     fn test10(&self, _x : _) { }
-   |                           ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn test10<T>(&self, _x : T) { }
-   |              ^^^             ^
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:46:24
-   |
-LL |     fn clone(&self) -> _ { Test9 }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `Test9`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:49:37
+  --> $DIR/typeck_type_placeholder_item.rs:60:37
    |
 LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
    |                                     ^ not allowed in type signatures
@@ -366,16 +462,7 @@
    |                  ^^^                   ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:88:31
-   |
-LL |         fn fn_test9(&self) -> _ { () }
-   |                               ^
-   |                               |
-   |                               not allowed in type signatures
-   |                               help: replace with the correct return type: `()`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:91:34
+  --> $DIR/typeck_type_placeholder_item.rs:102:34
    |
 LL |         fn fn_test10(&self, _x : _) { }
    |                                  ^ not allowed in type signatures
@@ -386,16 +473,7 @@
    |                     ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:96:28
-   |
-LL |         fn clone(&self) -> _ { FnTest9 }
-   |                            ^
-   |                            |
-   |                            not allowed in type signatures
-   |                            help: replace with the correct return type: `main::FnTest9`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:99:41
+  --> $DIR/typeck_type_placeholder_item.rs:110:41
    |
 LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
    |                                         ^ not allowed in type signatures
@@ -405,7 +483,49 @@
 LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
    |                      ^^^                   ^
 
-error: aborting due to 40 previous errors
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:174:21
+   |
+LL | type Y = impl Trait<_>;
+   |                     ^ not allowed in type signatures
 
-Some errors have detailed explanations: E0121, E0282.
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:39:24
+   |
+LL |     fn test9(&self) -> _ { () }
+   |                        ^
+   |                        |
+   |                        not allowed in type signatures
+   |                        help: replace with the correct return type: `()`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:57:24
+   |
+LL |     fn clone(&self) -> _ { Test9 }
+   |                        ^
+   |                        |
+   |                        not allowed in type signatures
+   |                        help: replace with the correct return type: `Test9`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:99:31
+   |
+LL |         fn fn_test9(&self) -> _ { () }
+   |                               ^
+   |                               |
+   |                               not allowed in type signatures
+   |                               help: replace with the correct return type: `()`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:107:28
+   |
+LL |         fn clone(&self) -> _ { FnTest9 }
+   |                            ^
+   |                            |
+   |                            not allowed in type signatures
+   |                            help: replace with the correct return type: `main::FnTest9`
+
+error: aborting due to 55 previous errors
+
+Some errors have detailed explanations: E0121, E0282, E0403.
 For more information about an error, try `rustc --explain E0121`.
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs
index 82a593f..66d4db3 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.rs
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs
@@ -35,7 +35,7 @@
     <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
     let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
     let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
-    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y`
+    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found
     <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
 
     let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
@@ -52,5 +52,5 @@
     let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
     let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
-    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X`
+    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found
 }
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index dbd41da..60ebe8e 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -207,13 +207,13 @@
 LL |     let _: <u8 as Tr>::Y::NN;
    |            ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
 
-error[E0599]: no associated item named `NN` found for type `<u8 as Tr>::Y` in the current scope
+error[E0599]: no associated item named `NN` found for associated type `<u8 as Tr>::Y` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:38:20
    |
 LL |     <u8 as Tr>::Y::NN;
    |                    ^^ associated item not found in `<u8 as Tr>::Y`
 
-error[E0599]: no associated item named `N` found for type `<u8 as Dr>::X` in the current scope
+error[E0599]: no associated item named `N` found for associated type `<u8 as Dr>::X` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:55:20
    |
 LL |     <u8 as Dr>::X::N;
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
index 18276d5..2d05852 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `call` found for type `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope
   --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
    |
 LL |     mut_.call((0, ));
diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr
index 44cfc5c..2983613 100644
--- a/src/test/ui/underscore-imports/hygiene.stderr
+++ b/src/test/ui/underscore-imports/hygiene.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `deref` found for type `&()` in the current scope
+error[E0599]: no method named `deref` found for reference `&()` in the current scope
   --> $DIR/hygiene.rs:38:11
    |
 LL |     (&()).deref();
@@ -10,7 +10,7 @@
 LL | use std::ops::Deref;
    |
 
-error[E0599]: no method named `deref_mut` found for type `&mut ()` in the current scope
+error[E0599]: no method named `deref_mut` found for mutable reference `&mut ()` in the current scope
   --> $DIR/hygiene.rs:39:15
    |
 LL |     (&mut ()).deref_mut();
diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr
index 102c17f..eb16fa9 100644
--- a/src/test/ui/underscore-imports/shadow.stderr
+++ b/src/test/ui/underscore-imports/shadow.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `deref` found for type `&()` in the current scope
+error[E0599]: no method named `deref` found for reference `&()` in the current scope
   --> $DIR/shadow.rs:19:11
    |
 LL |         x.deref();
diff --git a/src/test/ui/union/union-const-pat.rs b/src/test/ui/union/union-const-pat.rs
index e7cb248..cb2248c 100644
--- a/src/test/ui/union/union-const-pat.rs
+++ b/src/test/ui/union/union-const-pat.rs
@@ -8,6 +8,7 @@
 fn main() {
     match C {
         C => {} //~ ERROR cannot use unions in constant patterns
+                //~| ERROR cannot use unions in constant patterns
         _ => {}
     }
 }
diff --git a/src/test/ui/union/union-const-pat.stderr b/src/test/ui/union/union-const-pat.stderr
index dc87f4d..bec7204 100644
--- a/src/test/ui/union/union-const-pat.stderr
+++ b/src/test/ui/union/union-const-pat.stderr
@@ -4,5 +4,11 @@
 LL |         C => {}
    |         ^
 
-error: aborting due to previous error
+error: cannot use unions in constant patterns
+  --> $DIR/union-const-pat.rs:10:9
+   |
+LL |         C => {}
+   |         ^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs
index 60e280f..4a106cc 100644
--- a/src/test/ui/union/union-derive-clone.rs
+++ b/src/test/ui/union/union-derive-clone.rs
@@ -34,5 +34,5 @@
 
 fn main() {
     let u = U5 { a: ManuallyDrop::new(CloneNoCopy) };
-    let w = u.clone(); //~ ERROR no method named `clone` found for type `U5<CloneNoCopy>`
+    let w = u.clone(); //~ ERROR no method named `clone` found for union `U5<CloneNoCopy>`
 }
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
index 6893f91..0ef5753 100644
--- a/src/test/ui/union/union-derive-clone.stderr
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -6,7 +6,7 @@
    |
    = note: required by `std::clone::AssertParamIsCopy`
 
-error[E0599]: no method named `clone` found for type `U5<CloneNoCopy>` in the current scope
+error[E0599]: no method named `clone` found for union `U5<CloneNoCopy>` in the current scope
   --> $DIR/union-derive-clone.rs:37:15
    |
 LL | union U5<T> {
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index cd46878..92cda64 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `std::boxed::Box<dyn Foo>` in the current scope
+error[E0599]: no method named `clone` found for struct `std::boxed::Box<dyn Foo>` in the current scope
   --> $DIR/unique-object-noncopyable.rs:24:16
    |
 LL |     let _z = y.clone();
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index 19ef2b2..e5c3eac 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `std::boxed::Box<R>` in the current scope
+error[E0599]: no method named `clone` found for struct `std::boxed::Box<R>` in the current scope
   --> $DIR/unique-pinned-nocopy.rs:12:16
    |
 LL |     let _j = i.clone();
diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs
index c92a71e..182aec3 100644
--- a/src/test/ui/unknown-lint-tool-name.rs
+++ b/src/test/ui/unknown-lint-tool-name.rs
@@ -1,4 +1,8 @@
 #![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
 
 #[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr
index dd3070b..1940f61 100644
--- a/src/test/ui/unknown-lint-tool-name.stderr
+++ b/src/test/ui/unknown-lint-tool-name.stderr
@@ -5,10 +5,34 @@
    |         ^^^
 
 error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
-  --> $DIR/unknown-lint-tool-name.rs:3:9
+  --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
 
-error: aborting due to 2 previous errors
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:1:9
+   |
+LL | #![deny(foo::bar)]
+   |         ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:5:9
+   |
+LL | #[allow(foo::bar)]
+   |         ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:1:9
+   |
+LL | #![deny(foo::bar)]
+   |         ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:5:9
+   |
+LL | #[allow(foo::bar)]
+   |         ^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr
index b72d45e..e057a78 100644
--- a/src/test/ui/unspecified-self-in-trait-ref.stderr
+++ b/src/test/ui/unspecified-self-in-trait-ref.stderr
@@ -1,22 +1,22 @@
-error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:10:18
    |
 LL |     let a = Foo::lol();
    |                  ^^^ function or associated item not found in `dyn Foo<_>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:12:23
    |
 LL |     let b = Foo::<_>::lol();
    |                       ^^^ function or associated item not found in `dyn Foo<_>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Bar<_, _>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<_, _>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:14:18
    |
 LL |     let c = Bar::lol();
    |                  ^^^ function or associated item not found in `dyn Bar<_, _>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Bar<usize, _>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<usize, _>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:16:30
    |
 LL |     let d = Bar::<usize, _>::lol();
diff --git a/src/test/ui/use/use-super-global-path.rs b/src/test/ui/use/use-super-global-path.rs
index 3e0ebcc..27a4a65 100644
--- a/src/test/ui/use/use-super-global-path.rs
+++ b/src/test/ui/use/use-super-global-path.rs
@@ -5,6 +5,7 @@
 
 mod foo {
     use ::super::{S, Z}; //~ ERROR global paths cannot start with `super`
+                         //~| ERROR global paths cannot start with `super`
 
     pub fn g() {
         use ::super::main; //~ ERROR global paths cannot start with `super`
diff --git a/src/test/ui/use/use-super-global-path.stderr b/src/test/ui/use/use-super-global-path.stderr
index 3ca30eb..7f98ac7 100644
--- a/src/test/ui/use/use-super-global-path.stderr
+++ b/src/test/ui/use/use-super-global-path.stderr
@@ -5,13 +5,19 @@
    |           ^^^^^ global paths cannot start with `super`
 
 error[E0433]: failed to resolve: global paths cannot start with `super`
-  --> $DIR/use-super-global-path.rs:10:15
+  --> $DIR/use-super-global-path.rs:7:11
+   |
+LL |     use ::super::{S, Z};
+   |           ^^^^^ global paths cannot start with `super`
+
+error[E0433]: failed to resolve: global paths cannot start with `super`
+  --> $DIR/use-super-global-path.rs:11:15
    |
 LL |         use ::super::main;
    |               ^^^^^ global paths cannot start with `super`
 
 error[E0425]: cannot find function `main` in this scope
-  --> $DIR/use-super-global-path.rs:11:9
+  --> $DIR/use-super-global-path.rs:12:9
    |
 LL |         main();
    |         ^^^^ not found in this scope
@@ -21,7 +27,7 @@
 LL |     use main;
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0425, E0433.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/src/tools/cargo b/src/tools/cargo
index 86134e7..6e1ca92 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 86134e7666a088682f20b76278c3ee096a315218
+Subproject commit 6e1ca924a67dd1ac89c33f294ef26b5c43b89168
diff --git a/src/tools/clippy b/src/tools/clippy
index 732825d..43ac941 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit 732825dcff6d1f115225305ce5e0c9c9d876a0ff
+Subproject commit 43ac9416d935942d6c7d2b2e0c876c551652c4ec
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 487c1d5..efa9d05 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,7 +1,9 @@
 #![crate_name = "compiletest"]
-#![feature(test)]
 #![feature(vec_remove_item)]
 #![deny(warnings)]
+// The `test` crate is the only unstable feature
+// allowed here, just to share similar code.
+#![feature(test)]
 
 extern crate test;
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 226a12c..1912c9e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1864,12 +1864,14 @@
                     rustc.args(&["--error-format", "json"]);
                 }
                 rustc.arg("-Zui-testing");
+                rustc.arg("-Zdeduplicate-diagnostics=no");
             }
             Ui => {
                 if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) {
                     rustc.args(&["--error-format", "json"]);
                 }
                 rustc.arg("-Zui-testing");
+                rustc.arg("-Zdeduplicate-diagnostics=no");
             }
             MirOpt => {
                 rustc.args(&[
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 003f51a..2663b3d 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -67,6 +67,7 @@
     ("powerpc", "powerpc"),
     ("powerpc64", "powerpc64"),
     ("powerpc64le", "powerpc64"),
+    ("riscv64gc", "riscv64"),
     ("s390x", "s390x"),
     ("sparc", "sparc"),
     ("sparc64", "sparc64"),
diff --git a/src/tools/miri b/src/tools/miri
index 4da2b21..4e44aa0 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 4da2b2149ca1c6a3331260dfcbb2175c51f2842d
+Subproject commit 4e44aa010c4c7d616182a3078cafb39da6f6c0a2