Rollup merge of #63621 - jgalenson:dndebug, r=alexcrichton

Modify librustc_llvm to pass -DNDEBUG while compiling.

Currently, librustc_llvm builds are not reproducible because the LLVM files it compiles use the debug version of llvm_unreachable, which uses __FILE__.  To fix this, we propagate NDEBUG from bootstrap if applicable and use it when compiling librustc_llvm.

r? @alexcrichton
diff --git a/Cargo.lock b/Cargo.lock
index ab6731e..c784246 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -106,7 +106,7 @@
  "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -1138,19 +1138,12 @@
 
 [[package]]
 name = "hashbrown"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-alloc 1.0.0",
  "rustc-std-workspace-core 1.0.0",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
  "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2736,7 +2729,7 @@
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.15"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2894,7 +2887,7 @@
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_data_structures 0.0.0",
  "rustc_metadata 0.0.0",
  "rustc_target 0.0.0",
@@ -3534,7 +3527,7 @@
  "core 0.0.0",
  "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -4450,7 +4443,6 @@
 "checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454"
 "checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392"
 "checksum handlebars 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d"
-"checksum hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9529213c67695ca2d146e6f263b7b72df8fa973368beadf767e8ed80c03f2f36"
 "checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
 "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
 "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
@@ -4600,7 +4592,7 @@
 "checksum rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61673783f2089e01033ffa82d1988f55175402071b31253a358292e1624d4602"
 "checksum rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28f3dd1346d5b0269c07a4a78855e309a298ab569c9c1302d4d4f57f8eee4e84"
 "checksum rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45e67b526dbda3a0c7dab91c8947d43685e7697f52686a4949da3c179cd7c979"
-"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
+"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363"
 "checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543"
diff --git a/README.md b/README.md
index 40df6a4..724bc36 100644
--- a/README.md
+++ b/README.md
@@ -144,7 +144,7 @@
 by manually calling the appropriate vcvars file before running the bootstrap.
 
 ```batch
-> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
+> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
 > python x.py build
 ```
 
diff --git a/RELEASES.md b/RELEASES.md
index 7ad739d..f26f6e6 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -22,7 +22,7 @@
 - [You can now use `_` as an identifier for consts.][61347] e.g. You can write
   `const _: u32 = 5;`.
 - [You can now use `#[repr(align(X)]` on enums.][61229]
-- [The  `?`/_"Kleene"_ macro operator is now available in the
+- [The  `?` Kleene macro operator is now available in the
   2015 edition.][60932]
 
 Compiler
diff --git a/config.toml.example b/config.toml.example
index cb9f388..a3ec4f2 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -141,10 +141,10 @@
 # library and facade crates.
 #compiler-docs = false
 
-# Indicate whether submodules are managed and updated automatically.
+# Indicate whether git submodules are managed and updated automatically.
 #submodules = true
 
-# Update submodules only when the checked out commit in the submodules differs
+# Update git submodules only when the checked out commit in the submodules differs
 # from what is committed in the main rustc repo.
 #fast-submodules = true
 
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 54b689f..da37278 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -45,18 +45,6 @@
         }
     }
 
-    // Drop `--error-format json` because despite our desire for json messages
-    // from Cargo we don't want any from rustc itself.
-    if let Some(n) = args.iter().position(|n| n == "--error-format") {
-        args.remove(n);
-        args.remove(n);
-    }
-
-    if let Some(s) = env::var_os("RUSTC_ERROR_FORMAT") {
-        args.push("--error-format".into());
-        args.push(s);
-    }
-
     // Detect whether or not we're a build script depending on whether --target
     // is passed (a bit janky...)
     let target = args.windows(2)
@@ -110,8 +98,17 @@
 
     // Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift
     // compiler libraries and such from stage 1 to 2.
+    //
+    // FIXME: the fact that core here is excluded is due to core_arch from our stdarch submodule
+    // being broken on the beta compiler with bootstrap passed, so this is a temporary workaround
+    // (we've just snapped, so there are no cfg(bootstrap) related annotations in core).
     if stage == "0" {
-        cmd.arg("--cfg").arg("bootstrap");
+        if crate_name != Some("core") {
+            cmd.arg("--cfg").arg("bootstrap");
+        } else {
+            // NOTE(eddyb) see FIXME above, except now we need annotations again in core.
+            cmd.arg("--cfg").arg("boostrap_stdarch_ignore_this");
+        }
     }
 
     // Print backtrace in case of ICE
@@ -132,10 +129,7 @@
         cmd.arg("-Dwarnings");
         cmd.arg("-Drust_2018_idioms");
         cmd.arg("-Dunused_lifetimes");
-        // cfg(not(bootstrap)): Remove this during the next stage 0 compiler update.
-        // `-Drustc::internal` is a new feature and `rustc_version` mis-reports the `stage`.
-        let cfg_not_bootstrap = stage != "0" && crate_name != Some("rustc_version");
-        if cfg_not_bootstrap && use_internal_lints(crate_name) {
+        if use_internal_lints(crate_name) {
             cmd.arg("-Zunstable-options");
             cmd.arg("-Drustc::internal");
         }
@@ -287,10 +281,6 @@
                 cmd.arg("-C").arg("target-feature=-crt-static");
             }
         }
-
-        if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
-            cmd.arg("--remap-path-prefix").arg(&map);
-        }
     } else {
         // Override linker if necessary.
         if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
@@ -307,6 +297,10 @@
         }
     }
 
+    if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
+        cmd.arg("--remap-path-prefix").arg(&map);
+    }
+
     // Force all crates compiled by this compiler to (a) be unstable and (b)
     // allow the `rustc_private` feature to link to other unstable crates
     // also in the sysroot. We also do this for host crates, since those
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e54c936..f0054c3 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -145,7 +145,7 @@
             only_hosts: S::ONLY_HOSTS,
             should_run: S::should_run,
             make_run: S::make_run,
-            name: unsafe { ::std::intrinsics::type_name::<S>() },
+            name: std::any::type_name::<S>(),
         }
     }
 
@@ -754,76 +754,20 @@
         let mut cargo = Command::new(&self.initial_cargo);
         let out_dir = self.stage_out(compiler, mode);
 
-        // command specific path, we call clear_if_dirty with this
-        let mut my_out = match cmd {
-            "build" => self.cargo_out(compiler, mode, target),
-
-            // This is the intended out directory for crate documentation.
-            "doc" | "rustdoc" =>  self.crate_doc_out(target),
-
-            _ => self.stage_out(compiler, mode),
-        };
-
-        // This is for the original compiler, but if we're forced to use stage 1, then
-        // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
-        // we copy the libs forward.
-        let cmp = self.compiler_for(compiler.stage, compiler.host, target);
-
-        let libstd_stamp = match cmd {
-            "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target),
-            _ => compile::libstd_stamp(self, cmp, target),
-        };
-
-        let libtest_stamp = match cmd {
-            "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target),
-            _ => compile::libtest_stamp(self, cmp, target),
-        };
-
-        let librustc_stamp = match cmd {
-            "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target),
-            _ => compile::librustc_stamp(self, cmp, target),
-        };
+        // Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
+        // so we need to explicitly clear out if they've been updated.
+        for backend in self.codegen_backends(compiler) {
+            self.clear_if_dirty(&out_dir, &backend);
+        }
 
         if cmd == "doc" || cmd == "rustdoc" {
-            if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen {
+            let my_out = match mode {
                 // This is the intended out directory for compiler documentation.
-                my_out = self.compiler_doc_out(target);
-            }
+                Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target),
+                _ => self.crate_doc_out(target),
+            };
             let rustdoc = self.rustdoc(compiler);
             self.clear_if_dirty(&my_out, &rustdoc);
-        } else if cmd != "test" {
-            match mode {
-                Mode::Std => {
-                    self.clear_if_dirty(&my_out, &self.rustc(compiler));
-                    for backend in self.codegen_backends(compiler) {
-                        self.clear_if_dirty(&my_out, &backend);
-                    }
-                },
-                Mode::Test => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                },
-                Mode::Rustc => {
-                    self.clear_if_dirty(&my_out, &self.rustc(compiler));
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                    self.clear_if_dirty(&my_out, &libtest_stamp);
-                },
-                Mode::Codegen => {
-                    self.clear_if_dirty(&my_out, &librustc_stamp);
-                },
-                Mode::ToolBootstrap => { },
-                Mode::ToolStd => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                },
-                Mode::ToolTest => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                    self.clear_if_dirty(&my_out, &libtest_stamp);
-                },
-                Mode::ToolRustc => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                    self.clear_if_dirty(&my_out, &libtest_stamp);
-                    self.clear_if_dirty(&my_out, &librustc_stamp);
-                },
-            }
         }
 
         cargo
@@ -861,6 +805,19 @@
             },
         }
 
+        // This tells Cargo (and in turn, rustc) to output more complete
+        // dependency information.  Most importantly for rustbuild, this
+        // includes sysroot artifacts, like libstd, which means that we don't
+        // need to track those in rustbuild (an error prone process!). This
+        // feature is currently unstable as there may be some bugs and such, but
+        // it represents a big improvement in rustbuild's reliability on
+        // rebuilds, so we're using it here.
+        //
+        // For some additional context, see #63470 (the PR originally adding
+        // this), as well as #63012 which is the tracking issue for this
+        // feature on the rustc side.
+        cargo.arg("-Zbinary-dep-depinfo");
+
         cargo.arg("-j").arg(self.jobs().to_string());
         // Remove make-related flags to ensure Cargo can correctly set things up
         cargo.env_remove("MAKEFLAGS");
@@ -980,9 +937,6 @@
         if let Some(target_linker) = self.linker(target) {
             cargo.env("RUSTC_TARGET_LINKER", target_linker);
         }
-        if let Some(ref error_format) = self.config.rustc_error_format {
-            cargo.env("RUSTC_ERROR_FORMAT", error_format);
-        }
         if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc {
             cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler));
         }
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index c58a98b..a4cb81d3 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -46,7 +46,7 @@
     } else if target.contains("openbsd") {
         Some(PathBuf::from("ar"))
     } else if target.contains("vxworks") {
-        Some(PathBuf::from("vx-ar"))
+        Some(PathBuf::from("wr-ar"))
     } else {
         let parent = cc.parent().unwrap();
         let file = cc.file_name().unwrap().to_str().unwrap();
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 8e8d8f5..caa4843 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -13,7 +13,7 @@
 use crate::Build;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.38.0";
+pub const CFG_RELEASE_NUM: &str = "1.39.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 11b082a..6e6fea6 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -245,7 +245,6 @@
         let libdir = builder.sysroot_libdir(compiler, target);
         let hostdir = builder.sysroot_libdir(compiler, compiler.host);
         add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target));
-        builder.cargo(compiler, Mode::ToolRustc, target, "clean");
     }
 }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 8bd14fb..96987d0 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -15,7 +15,7 @@
 use std::process::{Command, Stdio, exit};
 use std::str;
 
-use build_helper::{output, mtime, t, up_to_date};
+use build_helper::{output, t, up_to_date};
 use filetime::FileTime;
 use serde::Deserialize;
 use serde_json;
@@ -274,8 +274,6 @@
             // for reason why the sanitizers are not built in stage0.
             copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
         }
-
-        builder.cargo(target_compiler, Mode::ToolStd, target, "clean");
     }
 }
 
@@ -480,8 +478,6 @@
             &builder.sysroot_libdir(target_compiler, compiler.host),
             &libtest_stamp(builder, compiler, target)
         );
-
-        builder.cargo(target_compiler, Mode::ToolTest, target, "clean");
     }
 }
 
@@ -639,7 +635,6 @@
             &builder.sysroot_libdir(target_compiler, compiler.host),
             &librustc_stamp(builder, compiler, target)
         );
-        builder.cargo(target_compiler, Mode::ToolRustc, target, "clean");
     }
 }
 
@@ -1119,10 +1114,6 @@
                 },
                 ..
             } => (filenames, crate_types),
-            CargoMessage::CompilerMessage { message } => {
-                eprintln!("{}", message.rendered);
-                return;
-            }
             _ => return,
         };
         for filename in filenames {
@@ -1209,41 +1200,13 @@
         deps.push((path_to_add.into(), false));
     }
 
-    // Now we want to update the contents of the stamp file, if necessary. First
-    // we read off the previous contents along with its mtime. If our new
-    // contents (the list of files to copy) is different or if any dep's mtime
-    // is newer then we rewrite the stamp file.
     deps.sort();
-    let stamp_contents = fs::read(stamp);
-    let stamp_mtime = mtime(&stamp);
     let mut new_contents = Vec::new();
-    let mut max = None;
-    let mut max_path = None;
     for (dep, proc_macro) in deps.iter() {
-        let mtime = mtime(dep);
-        if Some(mtime) > max {
-            max = Some(mtime);
-            max_path = Some(dep.clone());
-        }
         new_contents.extend(if *proc_macro { b"h" } else { b"t" });
         new_contents.extend(dep.to_str().unwrap().as_bytes());
         new_contents.extend(b"\0");
     }
-    let max = max.unwrap();
-    let max_path = max_path.unwrap();
-    let contents_equal = stamp_contents
-        .map(|contents| contents == new_contents)
-        .unwrap_or_default();
-    if contents_equal && max <= stamp_mtime {
-        builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}",
-                stamp, max, stamp_mtime));
-        return deps.into_iter().map(|(d, _)| d).collect()
-    }
-    if max > stamp_mtime {
-        builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
-    } else {
-        builder.verbose(&format!("updating {:?} as deps changed", stamp));
-    }
     t!(fs::write(&stamp, &new_contents));
     deps.into_iter().map(|(d, _)| d).collect()
 }
@@ -1259,8 +1222,12 @@
     }
     // Instruct Cargo to give us json messages on stdout, critically leaving
     // stderr as piped so we can get those pretty colors.
-    cargo.arg("--message-format").arg("json")
-         .stdout(Stdio::piped());
+    let mut message_format = String::from("json-render-diagnostics");
+    if let Some(s) = &builder.config.rustc_error_format  {
+        message_format.push_str(",json-diagnostic-");
+        message_format.push_str(s);
+    }
+    cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
 
     for arg in tail_args {
         cargo.arg(arg);
@@ -1313,12 +1280,4 @@
     BuildScriptExecuted {
         package_id: Cow<'a, str>,
     },
-    CompilerMessage {
-        message: ClippyMessage<'a>
-    }
-}
-
-#[derive(Deserialize)]
-pub struct ClippyMessage<'a> {
-    rendered: Cow<'a, str>,
 }
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 73d6fe5..e0a1f46 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -81,5 +81,14 @@
 ci-subset-2:
 	$(Q)$(BOOTSTRAP) test $(TESTS_IN_2)
 
+TESTS_IN_MINGW_2 := \
+	src/test/ui \
+	src/test/compile-fail
+
+ci-mingw-subset-1:
+	$(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2:%=--exclude %)
+ci-mingw-subset-2:
+	$(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2)
+
 
 .PHONY: dist
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 4e3930c..bffe748 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -202,10 +202,6 @@
                         panic!("couldn't find libc.a in musl dir: {}",
                                root.join("lib").display());
                     }
-                    if fs::metadata(root.join("lib/libunwind.a")).is_err() {
-                        panic!("couldn't find libunwind.a in musl dir: {}",
-                               root.join("lib").display());
-                    }
                 }
                 None => {
                     panic!("when targeting MUSL either the rust.musl-root \
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 687856c..77c9cda 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -272,8 +272,8 @@
       i686-mingw-1:
         MSYS_BITS: 32
         RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
-        SCRIPT: make ci-subset-1
-        MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
+        SCRIPT: make ci-mingw-subset-1
+        MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
         MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
         MINGW_DIR: mingw32
         # FIXME(#59637)
@@ -282,15 +282,15 @@
       i686-mingw-2:
         MSYS_BITS: 32
         RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
-        SCRIPT: make ci-subset-2
-        MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
+        SCRIPT: make ci-mingw-subset-2
+        MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
         MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
         MINGW_DIR: mingw32
       x86_64-mingw-1:
         MSYS_BITS: 64
-        SCRIPT: make ci-subset-1
+        SCRIPT: make ci-mingw-subset-1
         RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
-        MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
+        MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
         MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
         MINGW_DIR: mingw64
         # FIXME(#59637)
@@ -298,9 +298,9 @@
         NO_LLVM_ASSERTIONS: 1
       x86_64-mingw-2:
         MSYS_BITS: 64
-        SCRIPT: make ci-subset-2
+        SCRIPT: make ci-mingw-subset-2
         RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
-        MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
+        MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
         MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
         MINGW_DIR: mingw64
 
@@ -327,7 +327,7 @@
         MSYS_BITS: 32
         RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler
         SCRIPT: python x.py dist
-        MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
+        MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
         MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
         MINGW_DIR: mingw32
         DIST_REQUIRE_ALL_TOOLS: 1
@@ -336,7 +336,7 @@
         MSYS_BITS: 64
         SCRIPT: python x.py dist
         RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler
-        MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
+        MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
         MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
         MINGW_DIR: mingw64
         DIST_REQUIRE_ALL_TOOLS: 1
diff --git a/src/ci/azure-pipelines/steps/install-clang.yml b/src/ci/azure-pipelines/steps/install-clang.yml
index 45ec767..14daf81 100644
--- a/src/ci/azure-pipelines/steps/install-clang.yml
+++ b/src/ci/azure-pipelines/steps/install-clang.yml
@@ -36,7 +36,7 @@
     set -e
     mkdir -p citools
     cd citools
-    curl -f https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.tar.gz | tar xzf -
+    curl -f https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/LLVM-7.0.0-win64.tar.gz | tar xzf -
     echo "##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]$RUST_CONFIGURE_ARGS --set llvm.clang-cl=`pwd`/clang-rust/bin/clang-cl.exe"
   condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],''))
   displayName: Install clang (Windows)
diff --git a/src/ci/azure-pipelines/steps/install-sccache.yml b/src/ci/azure-pipelines/steps/install-sccache.yml
index 427e50f..d4679c1 100644
--- a/src/ci/azure-pipelines/steps/install-sccache.yml
+++ b/src/ci/azure-pipelines/steps/install-sccache.yml
@@ -2,14 +2,14 @@
 
 - bash: |
     set -e
-    curl -fo /usr/local/bin/sccache https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin
+    curl -fo /usr/local/bin/sccache https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-02-sccache-x86_64-apple-darwin
     chmod +x /usr/local/bin/sccache
   displayName: Install sccache (OSX)
   condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'))
 
 - script: |
     md sccache
-    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-26-sccache-x86_64-pc-windows-msvc"
     echo ##vso[task.prependpath]%CD%\sccache
   displayName: Install sccache (Windows)
   condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
diff --git a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml
index c42c231..9aaeb4b 100644
--- a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml
+++ b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml
@@ -4,7 +4,7 @@
 # https://github.com/wixtoolset/wix3 originally
 - bash: |
     set -e
-    curl -O https://rust-lang-ci2.s3-us-west-1.amazonaws.com/rust-ci-mirror/wix311-binaries.zip
+    curl -O https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/wix311-binaries.zip
     echo "##vso[task.setvariable variable=WIX]`pwd`/wix"
     mkdir -p wix/bin
     cd wix/bin
@@ -18,7 +18,7 @@
 # one is MSI installers and one is EXE, but they're not used so frequently at
 # this point anyway so perhaps it's a wash!
 - script: |
-    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf is-install.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-08-22-is.exe"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf is-install.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-08-22-is.exe"
     is-install.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
     echo ##vso[task.prependpath]C:\Program Files (x86)\Inno Setup 5
   displayName: Install InnoSetup
@@ -109,7 +109,7 @@
 # Note that this is originally from the github releases patch of Ninja
 - script: |
     md ninja
-    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-03-15-ninja-win.zip"
     7z x -oninja 2017-03-15-ninja-win.zip
     del 2017-03-15-ninja-win.zip
     set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja
diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml
index ca32888..ac6b344 100644
--- a/src/ci/azure-pipelines/steps/run.yml
+++ b/src/ci/azure-pipelines/steps/run.yml
@@ -199,7 +199,7 @@
 # Upload CPU usage statistics that we've been gathering this whole time. Always
 # execute this step in case we want to inspect failed builds, but don't let
 # errors here ever fail the build since this is just informational.
-- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$SYSTEM_JOBNAME.csv
+- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$CI_JOB_NAME.csv
   env:
     AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
   condition: variables['AWS_SECRET_ACCESS_KEY']
diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile
index 2359208..9493b33 100644
--- a/src/ci/docker/armhf-gnu/Dockerfile
+++ b/src/ci/docker/armhf-gnu/Dockerfile
@@ -72,7 +72,7 @@
 
 # TODO: What is this?!
 # Source of the file: https://github.com/vfdev-5/qemu-rpi2-vexpress/raw/master/vexpress-v2p-ca15-tc1.dtb
-RUN curl -O https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb
+RUN curl -O https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/vexpress-v2p-ca15-tc1.dtb
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/dist-various-1/install-mips-musl.sh b/src/ci/docker/dist-various-1/install-mips-musl.sh
index 60a96e3..29cfb5d 100755
--- a/src/ci/docker/dist-various-1/install-mips-musl.sh
+++ b/src/ci/docker/dist-various-1/install-mips-musl.sh
@@ -5,7 +5,7 @@
 # originally from
 # https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/
 # OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2
-URL="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror"
+URL="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc"
 FILE="OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2"
 curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mips-linux-musl --strip-components=2
 
diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
index 7bf8946..f04ee78 100755
--- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
@@ -5,7 +5,7 @@
 set -ex
 
 # Originally from https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz
-curl https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
+curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
   tar xJf -
 export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
 
diff --git a/src/ci/docker/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/dist-x86_64-linux/build-openssl.sh
index 13dae61..be8a6c9 100755
--- a/src/ci/docker/dist-x86_64-linux/build-openssl.sh
+++ b/src/ci/docker/dist-x86_64-linux/build-openssl.sh
@@ -4,7 +4,7 @@
 source shared.sh
 
 VERSION=1.0.2k
-URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/openssl-$VERSION.tar.gz
+URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz
 
 curl $URL | tar xzf -
 
diff --git a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh
index 2e9b9dc..797f674 100755
--- a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh
+++ b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh
@@ -25,7 +25,7 @@
 
 mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot
 
-URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
+URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
 
 # Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz
 curl $URL/2018-03-01-netbsd-src.tgz | tar xzf -
diff --git a/src/ci/docker/scripts/android-sdk-manager.py b/src/ci/docker/scripts/android-sdk-manager.py
index 7c9a8b8..c9e2961 100755
--- a/src/ci/docker/scripts/android-sdk-manager.py
+++ b/src/ci/docker/scripts/android-sdk-manager.py
@@ -23,8 +23,9 @@
 HOST_OS = "linux"
 
 # Mirroring options
-MIRROR_BUCKET = "rust-lang-ci2"
-MIRROR_BASE_DIR = "rust-ci-mirror/android/"
+MIRROR_BUCKET = "rust-lang-ci-mirrors"
+MIRROR_BUCKET_REGION = "us-west-1"
+MIRROR_BASE_DIR = "rustc/android/"
 
 import argparse
 import hashlib
@@ -144,7 +145,8 @@
     lockfile = Lockfile(args.lockfile)
     for package in lockfile.packages.values():
         # Download the file from the mirror into a temp file
-        url = "https://" + MIRROR_BUCKET + ".s3.amazonaws.com/" + MIRROR_BASE_DIR
+        url = "https://" + MIRROR_BUCKET + ".s3-" + MIRROR_BUCKET_REGION + \
+              ".amazonaws.com/" + MIRROR_BASE_DIR
         downloaded = package.download(url)
         # Extract the file in a temporary directory
         extract_dir = tempfile.mkdtemp()
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index 8cef69d..70155e7 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -59,7 +59,7 @@
 
 # Originally downloaded from:
 # https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
-URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
+URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
 curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
 
 # Fix up absolute symlinks from the system image.  This can be removed
diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh
index 55899fa..74ba2f0 100644
--- a/src/ci/docker/scripts/musl-toolchain.sh
+++ b/src/ci/docker/scripts/musl-toolchain.sh
@@ -54,29 +54,3 @@
         ln -s $TARGET-g++ /usr/local/bin/$exec
     done
 fi
-
-export CC=$TARGET-gcc
-export CXX=$TARGET-g++
-
-LLVM=70
-
-# may have been downloaded in a previous run
-if [ ! -d libunwind-release_$LLVM ]; then
-  curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
-  curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
-fi
-
-# fixme(mati865): Replace it with https://github.com/rust-lang/rust/pull/59089
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_$LLVM \
-          -DLLVM_PATH=/build/llvm-release_$LLVM \
-          -DLIBUNWIND_ENABLE_SHARED=0 \
-          -DCMAKE_C_COMPILER=$CC \
-          -DCMAKE_CXX_COMPILER=$CXX \
-          -DCMAKE_C_FLAGS="$CFLAGS" \
-          -DCMAKE_CXX_FLAGS="$CXXFLAGS"
-
-hide_output make -j$(nproc)
-cp lib/libunwind.a $OUTPUT/$TARGET/lib
-cd - && rm -rf libunwind-build
diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh
index c2cf77d..d847c40 100644
--- a/src/ci/docker/scripts/musl.sh
+++ b/src/ci/docker/scripts/musl.sh
@@ -20,6 +20,8 @@
 TAG=$1
 shift
 
+# Ancient binutils versions don't understand debug symbols produced by more recent tools.
+# Apparently applying `-fPIC` everywhere allows them to link successfully.
 export CFLAGS="-fPIC $CFLAGS"
 
 MUSL=musl-1.1.22
@@ -38,27 +40,3 @@
 fi
 hide_output make install
 hide_output make clean
-
-cd ..
-
-LLVM=70
-
-# may have been downloaded in a previous run
-if [ ! -d libunwind-release_$LLVM ]; then
-  curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
-  curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
-fi
-
-mkdir libunwind-build
-cd libunwind-build
-cmake ../libunwind-release_$LLVM \
-          -DLLVM_PATH=/build/llvm-release_$LLVM \
-          -DLIBUNWIND_ENABLE_SHARED=0 \
-          -DCMAKE_C_COMPILER=$CC \
-          -DCMAKE_CXX_COMPILER=$CXX \
-          -DCMAKE_C_FLAGS="$CFLAGS" \
-          -DCMAKE_CXX_FLAGS="$CXXFLAGS"
-
-hide_output make -j$(nproc)
-cp lib/libunwind.a /musl-$TAG/lib
-cd ../ && rm -rf libunwind-build
diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh
index 194de3c..efeb0ed 100644
--- a/src/ci/docker/scripts/sccache.sh
+++ b/src/ci/docker/scripts/sccache.sh
@@ -1,6 +1,6 @@
 set -ex
 
 curl -fo /usr/local/bin/sccache \
-  https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl
+  https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl
 
 chmod +x /usr/local/bin/sccache
diff --git a/src/ci/install-awscli.sh b/src/ci/install-awscli.sh
index d491b9f..69c8d2e 100755
--- a/src/ci/install-awscli.sh
+++ b/src/ci/install-awscli.sh
@@ -16,7 +16,7 @@
 set -euo pipefail
 IFS=$'\n\t'
 
-MIRROR="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-07-27-awscli.tar"
+MIRROR="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2019-07-27-awscli.tar"
 DEPS_DIR="/tmp/awscli-deps"
 
 pip="pip"
diff --git a/src/ci/run.sh b/src/ci/run.sh
index f1eb417..457ba97 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -78,6 +78,21 @@
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools"
 fi
 
+# Print the date from the local machine and the date from an external source to
+# check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure
+# Pipelines it happened that the certificates were marked as expired.
+datecheck() {
+  echo "== clock drift check =="
+  echo -n "  local time: "
+  date
+  echo -n "  network time: "
+  curl -fs --head http://detectportal.firefox.com/success.txt | grep ^Date: \
+      | sed 's/Date: //g' || true
+  echo "== end clock drift check =="
+}
+datecheck
+trap datecheck EXIT
+
 # We've had problems in the past of shell scripts leaking fds into the sccache
 # server (#48192) which causes Cargo to erroneously think that a build script
 # hasn't finished yet. Try to solve that problem by starting a very long-lived
diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs
index 9f531f5..3d04f30 100644
--- a/src/liballoc/collections/binary_heap.rs
+++ b/src/liballoc/collections/binary_heap.rs
@@ -1163,6 +1163,9 @@
 
 #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
+    /// Converts a `Vec<T>` into a `BinaryHeap<T>`.
+    ///
+    /// This conversion happens in-place, and has `O(n)` time complexity.
     fn from(vec: Vec<T>) -> BinaryHeap<T> {
         let mut heap = BinaryHeap { data: vec };
         heap.rebuild();
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index e067096..0b5a271 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -106,8 +106,8 @@
         LeafNode {
             // As a general policy, we leave fields uninitialized if they can be, as this should
             // be both slightly faster and easier to track in Valgrind.
-            keys: uninit_array![_; CAPACITY],
-            vals: uninit_array![_; CAPACITY],
+            keys: [MaybeUninit::UNINIT; CAPACITY],
+            vals: [MaybeUninit::UNINIT; CAPACITY],
             parent: ptr::null(),
             parent_idx: MaybeUninit::uninit(),
             len: 0
@@ -159,7 +159,7 @@
     unsafe fn new() -> Self {
         InternalNode {
             data: LeafNode::new(),
-            edges: uninit_array![_; 2*B],
+            edges: [MaybeUninit::UNINIT; 2*B]
         }
     }
 }
diff --git a/src/liballoc/collections/mod.rs b/src/liballoc/collections/mod.rs
index 5a33ddc..f1f22fe 100644
--- a/src/liballoc/collections/mod.rs
+++ b/src/liballoc/collections/mod.rs
@@ -41,32 +41,35 @@
 #[doc(no_inline)]
 pub use vec_deque::VecDeque;
 
-use crate::alloc::{AllocErr, LayoutErr};
+use crate::alloc::{Layout, LayoutErr};
 
-/// Augments `AllocErr` with a CapacityOverflow variant.
+/// The error type for `try_reserve` methods.
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-pub enum CollectionAllocErr {
+pub enum TryReserveError {
     /// Error due to the computed capacity exceeding the collection's maximum
     /// (usually `isize::MAX` bytes).
     CapacityOverflow,
-    /// Error due to the allocator (see the `AllocErr` type's docs).
-    AllocErr,
+
+    /// The memory allocator returned an error
+    AllocError {
+        /// The layout of allocation request that failed
+        layout: Layout,
+
+        #[doc(hidden)]
+        #[unstable(feature = "container_error_extra", issue = "0", reason = "\
+            Enable exposing the allocator’s custom error value \
+            if an associated type is added in the future: \
+            https://github.com/rust-lang/wg-allocators/issues/23")]
+        non_exhaustive: (),
+    },
 }
 
 #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-impl From<AllocErr> for CollectionAllocErr {
-    #[inline]
-    fn from(AllocErr: AllocErr) -> Self {
-        CollectionAllocErr::AllocErr
-    }
-}
-
-#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-impl From<LayoutErr> for CollectionAllocErr {
+impl From<LayoutErr> for TryReserveError {
     #[inline]
     fn from(_: LayoutErr) -> Self {
-        CollectionAllocErr::CapacityOverflow
+        TryReserveError::CapacityOverflow
     }
 }
 
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index 9240346..2fc8741 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -18,7 +18,7 @@
 use core::slice;
 use core::hash::{Hash, Hasher};
 
-use crate::collections::CollectionAllocErr;
+use crate::collections::TryReserveError;
 use crate::raw_vec::RawVec;
 use crate::vec::Vec;
 
@@ -576,10 +576,10 @@
     ///
     /// ```
     /// #![feature(try_reserve)]
-    /// use std::collections::CollectionAllocErr;
+    /// use std::collections::TryReserveError;
     /// use std::collections::VecDeque;
     ///
-    /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> {
+    /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> {
     ///     let mut output = VecDeque::new();
     ///
     ///     // Pre-reserve the memory, exiting if we can't
@@ -595,7 +595,7 @@
     /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
     /// ```
     #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr>  {
+    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError>  {
         self.try_reserve(additional)
     }
 
@@ -614,10 +614,10 @@
     ///
     /// ```
     /// #![feature(try_reserve)]
-    /// use std::collections::CollectionAllocErr;
+    /// use std::collections::TryReserveError;
     /// use std::collections::VecDeque;
     ///
-    /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> {
+    /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> {
     ///     let mut output = VecDeque::new();
     ///
     ///     // Pre-reserve the memory, exiting if we can't
@@ -633,12 +633,12 @@
     /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
     /// ```
     #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         let old_cap = self.cap();
         let used_cap = self.len() + 1;
         let new_cap = used_cap.checked_add(additional)
             .and_then(|needed_cap| needed_cap.checked_next_power_of_two())
-            .ok_or(CollectionAllocErr::CapacityOverflow)?;
+            .ok_or(TryReserveError::CapacityOverflow)?;
 
         if new_cap > old_cap {
             self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?;
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index a1936b3..4a48945 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -69,7 +69,7 @@
 #![warn(missing_debug_implementations)]
 #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
 #![allow(explicit_outlives_requirements)]
-#![cfg_attr(not(bootstrap), allow(incomplete_features))]
+#![allow(incomplete_features)]
 
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(test, feature(test))]
@@ -84,9 +84,10 @@
 #![feature(coerce_unsized)]
 #![feature(const_generic_impls_guard)]
 #![feature(const_generics)]
-#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))]
+#![feature(const_in_array_repeat_expressions)]
 #![feature(dispatch_from_dyn)]
 #![feature(core_intrinsics)]
+#![feature(container_error_extra)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
 #![feature(fmt_internals)]
@@ -118,7 +119,7 @@
 #![feature(rustc_const_unstable)]
 #![feature(const_vec_new)]
 #![feature(slice_partition_dedup)]
-#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
+#![feature(maybe_uninit_extra, maybe_uninit_slice)]
 #![feature(alloc_layout_extra)]
 #![feature(try_trait)]
 #![feature(mem_take)]
diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs
index 250c419..0b5e186d 100644
--- a/src/liballoc/macros.rs
+++ b/src/liballoc/macros.rs
@@ -98,5 +98,5 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! format {
-    ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
+    ($($arg:tt)*) => ($crate::fmt::format(::core::format_args!($($arg)*)))
 }
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 0abab45..bc8a38f 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -7,8 +7,8 @@
 use core::ptr::{self, NonNull, Unique};
 use core::slice;
 
-use crate::alloc::{Alloc, Layout, Global, handle_alloc_error};
-use crate::collections::CollectionAllocErr::{self, *};
+use crate::alloc::{Alloc, Layout, Global, AllocErr, handle_alloc_error};
+use crate::collections::TryReserveError::{self, *};
 use crate::boxed::Box;
 
 #[cfg(test)]
@@ -385,7 +385,7 @@
 
     /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
     pub fn try_reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize)
-           -> Result<(), CollectionAllocErr> {
+           -> Result<(), TryReserveError> {
 
         self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact)
     }
@@ -413,7 +413,7 @@
     pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
         match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) {
             Err(CapacityOverflow) => capacity_overflow(),
-            Err(AllocErr) => unreachable!(),
+            Err(AllocError { .. }) => unreachable!(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -422,7 +422,7 @@
     /// needed_extra_capacity` elements. This logic is used in amortized reserve methods.
     /// Returns `(new_capacity, new_alloc_size)`.
     fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize)
-        -> Result<usize, CollectionAllocErr> {
+        -> Result<usize, TryReserveError> {
 
         // Nothing we can really do about these checks :(
         let required_cap = used_capacity.checked_add(needed_extra_capacity)
@@ -435,7 +435,7 @@
 
     /// The same as `reserve`, but returns on errors instead of panicking or aborting.
     pub fn try_reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize)
-        -> Result<(), CollectionAllocErr> {
+        -> Result<(), TryReserveError> {
         self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized)
     }
 
@@ -494,7 +494,7 @@
     pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
         match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) {
             Err(CapacityOverflow) => capacity_overflow(),
-            Err(AllocErr) => unreachable!(),
+            Err(AllocError { .. }) => unreachable!(),
             Ok(()) => { /* yay */ }
         }
     }
@@ -640,10 +640,8 @@
         needed_extra_capacity: usize,
         fallibility: Fallibility,
         strategy: ReserveStrategy,
-    ) -> Result<(), CollectionAllocErr> {
+    ) -> Result<(), TryReserveError> {
         unsafe {
-            use crate::alloc::AllocErr;
-
             // NOTE: we don't early branch on ZSTs here because we want this
             // to actually catch "asking for more than usize::MAX" in that case.
             // If we make it past the first branch then we are guaranteed to
@@ -672,12 +670,16 @@
                 None => self.a.alloc(new_layout),
             };
 
-            match (&res, fallibility) {
+            let ptr = match (res, fallibility) {
                 (Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
-                _ => {}
-            }
+                (Err(AllocErr), Fallible) => return Err(TryReserveError::AllocError {
+                    layout: new_layout,
+                    non_exhaustive: (),
+                }),
+                (Ok(ptr), _) => ptr,
+            };
 
-            self.ptr = res?.cast().into();
+            self.ptr = ptr.cast().into();
             self.cap = new_cap;
 
             Ok(())
@@ -737,7 +739,7 @@
 // all 4GB in user-space. e.g., PAE or x32
 
 #[inline]
-fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
+fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
     if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize {
         Err(CapacityOverflow)
     } else {
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index eca726c..b65f191 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -56,7 +56,7 @@
 use core::str::{pattern::Pattern, lossy};
 
 use crate::borrow::{Cow, ToOwned};
-use crate::collections::CollectionAllocErr;
+use crate::collections::TryReserveError;
 use crate::boxed::Box;
 use crate::str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars};
 use crate::vec::Vec;
@@ -937,9 +937,9 @@
     ///
     /// ```
     /// #![feature(try_reserve)]
-    /// use std::collections::CollectionAllocErr;
+    /// use std::collections::TryReserveError;
     ///
-    /// fn process_data(data: &str) -> Result<String, CollectionAllocErr> {
+    /// fn process_data(data: &str) -> Result<String, TryReserveError> {
     ///     let mut output = String::new();
     ///
     ///     // Pre-reserve the memory, exiting if we can't
@@ -953,7 +953,7 @@
     /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
     /// ```
     #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.vec.try_reserve(additional)
     }
 
@@ -975,9 +975,9 @@
     ///
     /// ```
     /// #![feature(try_reserve)]
-    /// use std::collections::CollectionAllocErr;
+    /// use std::collections::TryReserveError;
     ///
-    /// fn process_data(data: &str) -> Result<String, CollectionAllocErr> {
+    /// fn process_data(data: &str) -> Result<String, TryReserveError> {
     ///     let mut output = String::new();
     ///
     ///     // Pre-reserve the memory, exiting if we can't
@@ -991,7 +991,7 @@
     /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
     /// ```
     #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr>  {
+    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError>  {
         self.vec.try_reserve_exact(additional)
     }
 
diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs
index 765210e..55edf56 100644
--- a/src/liballoc/tests/string.rs
+++ b/src/liballoc/tests/string.rs
@@ -1,5 +1,5 @@
 use std::borrow::Cow;
-use std::collections::CollectionAllocErr::*;
+use std::collections::TryReserveError::*;
 use std::mem::size_of;
 use std::{usize, isize};
 
@@ -566,11 +566,11 @@
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
             // Check isize::MAX + 1 is an OOM
-            if let Err(AllocErr) = empty_string.try_reserve(MAX_CAP + 1) {
+            if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
             // Check usize::MAX is an OOM
-            if let Err(AllocErr) = empty_string.try_reserve(MAX_USIZE) {
+            if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -590,7 +590,7 @@
             if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
+            if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should always overflow in the add-to-len
@@ -629,10 +629,10 @@
             if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
-            if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_CAP + 1) {
+            if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
-            if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_USIZE) {
+            if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -651,7 +651,7 @@
             if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
+            if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 6e8ffe1..29a22aa 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -2,7 +2,7 @@
 use std::mem::size_of;
 use std::{usize, isize};
 use std::vec::{Drain, IntoIter};
-use std::collections::CollectionAllocErr::*;
+use std::collections::TryReserveError::*;
 
 struct DropCounter<'a> {
     count: &'a mut u32,
@@ -1121,11 +1121,11 @@
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
             // Check isize::MAX + 1 is an OOM
-            if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) {
+            if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
             // Check usize::MAX is an OOM
-            if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) {
+            if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -1145,7 +1145,7 @@
             if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
+            if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should always overflow in the add-to-len
@@ -1168,7 +1168,7 @@
             if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
+            if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should fail in the mul-by-size
@@ -1209,10 +1209,10 @@
             if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
-            if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
+            if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
-            if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) {
+            if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -1231,7 +1231,7 @@
             if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
+            if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
@@ -1252,7 +1252,7 @@
             if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
+            if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs
index 1bbcca9..d49b553 100644
--- a/src/liballoc/tests/vec_deque.rs
+++ b/src/liballoc/tests/vec_deque.rs
@@ -1,6 +1,6 @@
 use std::fmt::Debug;
 use std::collections::{VecDeque, vec_deque::Drain};
-use std::collections::CollectionAllocErr::*;
+use std::collections::TryReserveError::*;
 use std::mem::size_of;
 use std::{usize, isize};
 
@@ -1168,7 +1168,7 @@
             // VecDeque starts with capacity 7, always adds 1 to the capacity
             // and also rounds the number to next power of 2 so this is the
             // furthest we can go without triggering CapacityOverflow
-            if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP) {
+            if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
     }
@@ -1188,7 +1188,7 @@
             if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
+            if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should always overflow in the add-to-len
@@ -1211,7 +1211,7 @@
             if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
+            if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should fail in the mul-by-size
@@ -1256,7 +1256,7 @@
             // VecDeque starts with capacity 7, always adds 1 to the capacity
             // and also rounds the number to next power of 2 so this is the
             // furthest we can go without triggering CapacityOverflow
-            if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP) {
+            if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
     }
@@ -1275,7 +1275,7 @@
             if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
+            if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
@@ -1296,7 +1296,7 @@
             if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
+            if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index dac04e4..d279895 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -70,7 +70,7 @@
 use core::slice::{self, SliceIndex};
 
 use crate::borrow::{ToOwned, Cow};
-use crate::collections::CollectionAllocErr;
+use crate::collections::TryReserveError;
 use crate::boxed::Box;
 use crate::raw_vec::RawVec;
 
@@ -498,9 +498,9 @@
     ///
     /// ```
     /// #![feature(try_reserve)]
-    /// use std::collections::CollectionAllocErr;
+    /// use std::collections::TryReserveError;
     ///
-    /// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> {
+    /// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
     ///     let mut output = Vec::new();
     ///
     ///     // Pre-reserve the memory, exiting if we can't
@@ -516,7 +516,7 @@
     /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
     /// ```
     #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.buf.try_reserve(self.len, additional)
     }
 
@@ -538,9 +538,9 @@
     ///
     /// ```
     /// #![feature(try_reserve)]
-    /// use std::collections::CollectionAllocErr;
+    /// use std::collections::TryReserveError;
     ///
-    /// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> {
+    /// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
     ///     let mut output = Vec::new();
     ///
     ///     // Pre-reserve the memory, exiting if we can't
@@ -556,7 +556,7 @@
     /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
     /// ```
     #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr>  {
+    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError>  {
         self.buf.try_reserve_exact(self.len, additional)
     }
 
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 078091a..e8a0a88 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -470,10 +470,5 @@
 #[stable(feature = "type_name", since = "1.38.0")]
 #[rustc_const_unstable(feature = "const_type_name")]
 pub const fn type_name<T: ?Sized>() -> &'static str {
-    #[cfg(bootstrap)]
-    unsafe {
-        intrinsics::type_name::<T>()
-    }
-    #[cfg(not(bootstrap))]
     intrinsics::type_name::<T>()
 }
diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs
index e6a6fdd..4087333 100644
--- a/src/libcore/ascii.rs
+++ b/src/libcore/ascii.rs
@@ -14,6 +14,7 @@
 use crate::fmt;
 use crate::ops::Range;
 use crate::iter::FusedIterator;
+use crate::str::from_utf8_unchecked;
 
 /// An iterator over the escaped version of a byte.
 ///
@@ -22,6 +23,7 @@
 ///
 /// [`escape_default`]: fn.escape_default.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
 pub struct EscapeDefault {
     range: Range<usize>,
     data: [u8; 4],
@@ -130,6 +132,13 @@
 #[stable(feature = "fused", since = "1.26.0")]
 impl FusedIterator for EscapeDefault {}
 
+#[stable(feature = "ascii_escape_display", since = "1.39.0")]
+impl fmt::Display for EscapeDefault {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
+    }
+}
+
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for EscapeDefault {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index aa834db..e91bf53 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -553,12 +553,7 @@
     /// `XID_Start` is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to `ID_Start` but modified for closure under `NFKx`.
-    #[cfg_attr(bootstrap,
-               unstable(feature = "rustc_private",
-                        reason = "mainly needed for compiler internals",
-                        issue = "27812"))]
-    #[cfg_attr(not(bootstrap),
-               unstable(feature = "unicode_internals", issue = "0"))]
+    #[unstable(feature = "unicode_internals", issue = "0")]
     pub fn is_xid_start(self) -> bool {
         derived_property::XID_Start(self)
     }
@@ -569,12 +564,7 @@
     /// `XID_Continue` is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to `ID_Continue` but modified for closure under NFKx.
-    #[cfg_attr(bootstrap,
-               unstable(feature = "rustc_private",
-                        reason = "mainly needed for compiler internals",
-                        issue = "27812"))]
-    #[cfg_attr(not(bootstrap),
-               unstable(feature = "unicode_internals", issue = "0"))]
+    #[unstable(feature = "unicode_internals", issue = "0")]
     #[inline]
     pub fn is_xid_continue(self) -> bool {
         derived_property::XID_Continue(self)
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 0c99356..ec22a7c 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -134,7 +134,6 @@
 }
 
 /// Derive macro generating an impl of the trait `Clone`.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 38a52d9..b802216 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -201,7 +201,6 @@
 }
 
 /// Derive macro generating an impl of the trait `PartialEq`.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
@@ -265,7 +264,6 @@
 }
 
 /// Derive macro generating an impl of the trait `Eq`.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
@@ -617,7 +615,6 @@
 }
 
 /// Derive macro generating an impl of the trait `Ord`.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
@@ -867,7 +864,6 @@
 }
 
 /// Derive macro generating an impl of the trait `PartialOrd`.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
diff --git a/src/libcore/default.rs b/src/libcore/default.rs
index 8d95e9d..9b1616c 100644
--- a/src/libcore/default.rs
+++ b/src/libcore/default.rs
@@ -116,7 +116,6 @@
 }
 
 /// Derive macro generating an impl of the trait `Default`.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 0ea01d4..d5fae9e 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -546,7 +546,6 @@
 }
 
 // Separate module to reexport the macro `Debug` from prelude without the trait `Debug`.
-#[cfg(not(bootstrap))]
 pub(crate) mod macros {
     /// Derive macro generating an impl of the trait `Debug`.
     #[rustc_builtin_macro]
@@ -555,7 +554,6 @@
     #[allow_internal_unstable(core_intrinsics)]
     pub macro Debug($item:item) { /* compiler built-in */ }
 }
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[doc(inline)]
 pub use macros::Debug;
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index c4cbf40..b397119 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -199,7 +199,6 @@
 }
 
 // Separate module to reexport the macro `Hash` from prelude without the trait `Hash`.
-#[cfg(not(bootstrap))]
 pub(crate) mod macros {
     /// Derive macro generating an impl of the trait `Hash`.
     #[rustc_builtin_macro]
@@ -208,7 +207,6 @@
     #[allow_internal_unstable(core_intrinsics)]
     pub macro Hash($item:item) { /* compiler built-in */ }
 }
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[doc(inline)]
 pub use macros::Hash;
@@ -553,8 +551,6 @@
 #[stable(since = "1.29.0", feature = "build_hasher_eq")]
 impl<H> Eq for BuildHasherDefault<H> {}
 
-//////////////////////////////////////////////////////////////////////////////
-
 mod impls {
     use crate::mem;
     use crate::slice;
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index ceaa870..d145f22 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1293,18 +1293,40 @@
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
     /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
+    #[cfg(boostrap_stdarch_ignore_this)]
     pub fn overflowing_add<T>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_sub` method. For example,
     /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
+    #[cfg(boostrap_stdarch_ignore_this)]
     pub fn overflowing_sub<T>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_mul` method. For example,
     /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
+    #[cfg(boostrap_stdarch_ignore_this)]
     pub fn overflowing_mul<T>(a: T, b: T) -> T;
 
+    /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `wrapping_add` method. For example,
+    /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
+    #[cfg(not(boostrap_stdarch_ignore_this))]
+    pub fn wrapping_add<T>(a: T, b: T) -> T;
+    /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `wrapping_sub` method. For example,
+    /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
+    #[cfg(not(boostrap_stdarch_ignore_this))]
+    pub fn wrapping_sub<T>(a: T, b: T) -> T;
+    /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `wrapping_mul` method. For example,
+    /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
+    #[cfg(not(boostrap_stdarch_ignore_this))]
+    pub fn wrapping_mul<T>(a: T, b: T) -> T;
+
     /// Computes `a + b`, while saturating at numeric bounds.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs
index 76239eb..0b9f7f6 100644
--- a/src/libcore/iter/adapters/chain.rs
+++ b/src/libcore/iter/adapters/chain.rs
@@ -207,6 +207,29 @@
         }
     }
 
+    #[inline]
+    fn nth_back(&mut self, mut n: usize) -> Option<A::Item> {
+        match self.state {
+            ChainState::Both | ChainState::Back => {
+                for x in self.b.by_ref().rev() {
+                    if n == 0 {
+                        return Some(x)
+                    }
+                    n -= 1;
+                }
+                if let ChainState::Both = self.state {
+                    self.state = ChainState::Front;
+                }
+            }
+            ChainState::Front => {}
+        }
+        if let ChainState::Front = self.state {
+            self.a.nth_back(n)
+        } else {
+            None
+        }
+    }
+
     fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
         Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs
index d8d41a2..a45173f 100644
--- a/src/libcore/iter/adapters/flatten.rs
+++ b/src/libcore/iter/adapters/flatten.rs
@@ -72,8 +72,7 @@
 impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
 where
     F: FnMut(I::Item) -> U,
-    U: IntoIterator,
-    U::IntoIter: DoubleEndedIterator,
+    U: IntoIterator<IntoIter: DoubleEndedIterator>,
 {
     #[inline]
     fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
@@ -107,10 +106,7 @@
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "iterator_flatten", since = "1.29.0")]
-pub struct Flatten<I: Iterator>
-where
-    I::Item: IntoIterator,
-{
+pub struct Flatten<I: Iterator<Item: IntoIterator>> {
     inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
 }
 
@@ -229,7 +225,7 @@
                 if let elt@Some(_) = inner.next() { return elt }
             }
             match self.iter.next() {
-                None => return self.backiter.as_mut().and_then(|it| it.next()),
+                None => return self.backiter.as_mut()?.next(),
                 Some(inner) => self.frontiter = Some(inner.into_iter()),
             }
         }
@@ -237,8 +233,8 @@
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
-        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
+        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
+        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
         let lo = flo.saturating_add(blo);
         match (self.iter.size_hint(), fhi, bhi) {
             ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
@@ -250,20 +246,25 @@
     fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
+        #[inline]
+        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
+            frontiter: &'a mut Option<T::IntoIter>,
+            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
+        ) -> impl FnMut(Acc, T) -> R + 'a {
+            move |acc, x| {
+                let mut mid = x.into_iter();
+                let r = mid.try_fold(acc, &mut *fold);
+                *frontiter = Some(mid);
+                r
+            }
+        }
+
         if let Some(ref mut front) = self.frontiter {
             init = front.try_fold(init, &mut fold)?;
         }
         self.frontiter = None;
 
-        {
-            let frontiter = &mut self.frontiter;
-            init = self.iter.try_fold(init, |acc, x| {
-                let mut mid = x.into_iter();
-                let r = mid.try_fold(acc, &mut fold);
-                *frontiter = Some(mid);
-                r
-            })?;
-        }
+        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
         self.frontiter = None;
 
         if let Some(ref mut back) = self.backiter {
@@ -275,13 +276,20 @@
     }
 
     #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
+        #[inline]
+        fn flatten<U: Iterator, Acc>(
+            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
+        ) -> impl FnMut(Acc, U) -> Acc + '_ {
+            move |acc, iter| iter.fold(acc, &mut *fold)
+        }
+
         self.frontiter.into_iter()
             .chain(self.iter.map(IntoIterator::into_iter))
             .chain(self.backiter)
-            .fold(init, |acc, iter| iter.fold(acc, &mut fold))
+            .fold(init, flatten(fold))
     }
 }
 
@@ -297,7 +305,7 @@
                 if let elt@Some(_) = inner.next_back() { return elt }
             }
             match self.iter.next_back() {
-                None => return self.frontiter.as_mut().and_then(|it| it.next_back()),
+                None => return self.frontiter.as_mut()?.next_back(),
                 next => self.backiter = next.map(IntoIterator::into_iter),
             }
         }
@@ -307,20 +315,27 @@
     fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
+        #[inline]
+        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
+            backiter: &'a mut Option<T::IntoIter>,
+            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
+        ) -> impl FnMut(Acc, T) -> R + 'a where
+            T::IntoIter: DoubleEndedIterator,
+        {
+            move |acc, x| {
+                let mut mid = x.into_iter();
+                let r = mid.try_rfold(acc, &mut *fold);
+                *backiter = Some(mid);
+                r
+            }
+        }
+
         if let Some(ref mut back) = self.backiter {
             init = back.try_rfold(init, &mut fold)?;
         }
         self.backiter = None;
 
-        {
-            let backiter = &mut self.backiter;
-            init = self.iter.try_rfold(init, |acc, x| {
-                let mut mid = x.into_iter();
-                let r = mid.try_rfold(acc, &mut fold);
-                *backiter = Some(mid);
-                r
-            })?;
-        }
+        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
         self.backiter = None;
 
         if let Some(ref mut front) = self.frontiter {
@@ -332,12 +347,19 @@
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
+        #[inline]
+        fn flatten<U: DoubleEndedIterator, Acc>(
+            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
+        ) -> impl FnMut(Acc, U) -> Acc + '_ {
+            move |acc, iter| iter.rfold(acc, &mut *fold)
+        }
+
         self.frontiter.into_iter()
             .chain(self.iter.map(IntoIterator::into_iter))
             .chain(self.backiter)
-            .rfold(init, |acc, iter| iter.rfold(acc, &mut fold))
+            .rfold(init, flatten(fold))
     }
 }
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index b270290..a63434a 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -1,6 +1,6 @@
 use crate::cmp;
 use crate::fmt;
-use crate::ops::Try;
+use crate::ops::{Add, AddAssign, Try};
 use crate::usize;
 use crate::intrinsics;
 
@@ -143,6 +143,18 @@
     }
 }
 
+fn copy_fold<T: Copy, Acc>(
+    mut f: impl FnMut(Acc, T) -> Acc,
+) -> impl FnMut(Acc, &T) -> Acc {
+    move |acc, &elt| f(acc, elt)
+}
+
+fn copy_try_fold<T: Copy, Acc, R>(
+    mut f: impl FnMut(Acc, T) -> R,
+) -> impl FnMut(Acc, &T) -> R {
+    move |acc, &elt| f(acc, elt)
+}
+
 #[stable(feature = "iter_copied", since = "1.36.0")]
 impl<'a, I, T: 'a> Iterator for Copied<I>
     where I: Iterator<Item=&'a T>, T: Copy
@@ -157,16 +169,16 @@
         self.it.size_hint()
     }
 
-    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
+    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where
         Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
     {
-        self.it.try_fold(init, move |acc, &elt| f(acc, elt))
+        self.it.try_fold(init, copy_try_fold(f))
     }
 
-    fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
         where F: FnMut(Acc, Self::Item) -> Acc,
     {
-        self.it.fold(init, move |acc, &elt| f(acc, elt))
+        self.it.fold(init, copy_fold(f))
     }
 }
 
@@ -178,16 +190,16 @@
         self.it.next_back().copied()
     }
 
-    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
+    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where
         Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
     {
-        self.it.try_rfold(init, move |acc, &elt| f(acc, elt))
+        self.it.try_rfold(init, copy_try_fold(f))
     }
 
-    fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
         where F: FnMut(Acc, Self::Item) -> Acc,
     {
-        self.it.rfold(init, move |acc, &elt| f(acc, elt))
+        self.it.rfold(init, copy_fold(f))
     }
 }
 
@@ -248,6 +260,12 @@
     }
 }
 
+fn clone_try_fold<T: Clone, Acc, R>(
+    mut f: impl FnMut(Acc, T) -> R,
+) -> impl FnMut(Acc, &T) -> R {
+    move |acc, elt| f(acc, elt.clone())
+}
+
 #[stable(feature = "iter_cloned", since = "1.1.0")]
 impl<'a, I, T: 'a> Iterator for Cloned<I>
     where I: Iterator<Item=&'a T>, T: Clone
@@ -262,16 +280,16 @@
         self.it.size_hint()
     }
 
-    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
+    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where
         Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
     {
-        self.it.try_fold(init, move |acc, elt| f(acc, elt.clone()))
+        self.it.try_fold(init, clone_try_fold(f))
     }
 
-    fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
         where F: FnMut(Acc, Self::Item) -> Acc,
     {
-        self.it.fold(init, move |acc, elt| f(acc, elt.clone()))
+        self.it.map(T::clone).fold(init, f)
     }
 }
 
@@ -283,16 +301,16 @@
         self.it.next_back().cloned()
     }
 
-    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
+    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where
         Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
     {
-        self.it.try_rfold(init, move |acc, elt| f(acc, elt.clone()))
+        self.it.try_rfold(init, clone_try_fold(f))
     }
 
-    fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
         where F: FnMut(Acc, Self::Item) -> Acc,
     {
-        self.it.rfold(init, move |acc, elt| f(acc, elt.clone()))
+        self.it.map(T::clone).rfold(init, f)
     }
 }
 
@@ -387,6 +405,36 @@
             _ => (usize::MAX, None)
         }
     }
+
+    #[inline]
+    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
+    where
+        F: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        // fully iterate the current iterator. this is necessary because
+        // `self.iter` may be empty even when `self.orig` isn't
+        acc = self.iter.try_fold(acc, &mut f)?;
+        self.iter = self.orig.clone();
+
+        // complete a full cycle, keeping track of whether the cycled
+        // iterator is empty or not. we need to return early in case
+        // of an empty iterator to prevent an infinite loop
+        let mut is_empty = true;
+        acc = self.iter.try_fold(acc, |acc, x| {
+            is_empty = false;
+            f(acc, x)
+        })?;
+
+        if is_empty {
+            return Try::from_ok(acc);
+        }
+
+        loop {
+            self.iter = self.orig.clone();
+            acc = self.iter.try_fold(acc, &mut f)?;
+        }
+    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
@@ -430,14 +478,24 @@
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let inner_hint = self.iter.size_hint();
+        #[inline]
+        fn first_size(step: usize) -> impl Fn(usize) -> usize {
+            move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) }
+        }
+
+        #[inline]
+        fn other_size(step: usize) -> impl Fn(usize) -> usize {
+            move |n| n / (step + 1)
+        }
+
+        let (low, high) = self.iter.size_hint();
 
         if self.first_take {
-            let f = |n| if n == 0 { 0 } else { 1 + (n-1)/(self.step+1) };
-            (f(inner_hint.0), inner_hint.1.map(f))
+            let f = first_size(self.step);
+            (f(low), high.map(f))
         } else {
-            let f = |n| n / (self.step+1);
-            (f(inner_hint.0), inner_hint.1.map(f))
+            let f = other_size(self.step);
+            (f(low), high.map(f))
         }
     }
 
@@ -594,6 +652,20 @@
     }
 }
 
+fn map_fold<T, B, Acc>(
+    mut f: impl FnMut(T) -> B,
+    mut g: impl FnMut(Acc, B) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, elt| g(acc, f(elt))
+}
+
+fn map_try_fold<'a, T, B, Acc, R>(
+    f: &'a mut impl FnMut(T) -> B,
+    mut g: impl FnMut(Acc, B) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, elt| g(acc, f(elt))
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
     type Item = B;
@@ -608,18 +680,16 @@
         self.iter.size_hint()
     }
 
-    fn try_fold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
+    fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
         Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let f = &mut self.f;
-        self.iter.try_fold(init, move |acc, elt| g(acc, f(elt)))
+        self.iter.try_fold(init, map_try_fold(&mut self.f, g))
     }
 
-    fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc
+    fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
         where G: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut f = self.f;
-        self.iter.fold(init, move |acc, elt| g(acc, f(elt)))
+        self.iter.fold(init, map_fold(self.f, g))
     }
 }
 
@@ -632,18 +702,16 @@
         self.iter.next_back().map(&mut self.f)
     }
 
-    fn try_rfold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
+    fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
         Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let f = &mut self.f;
-        self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt)))
+        self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
     }
 
-    fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc
+    fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
         where G: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut f = self.f;
-        self.iter.rfold(init, move |acc, elt| g(acc, f(elt)))
+        self.iter.rfold(init, map_fold(self.f, g))
     }
 }
 
@@ -710,13 +778,27 @@
     }
 }
 
+fn filter_fold<T, Acc>(
+    mut predicate: impl FnMut(&T) -> bool,
+    mut fold: impl FnMut(Acc, T) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
+}
+
+fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>(
+    predicate: &'a mut impl FnMut(&T) -> bool,
+    mut fold: impl FnMut(Acc, T) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, item| if predicate(&item) { fold(acc, item) } else { R::from_ok(acc) }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {
     type Item = I::Item;
 
     #[inline]
     fn next(&mut self) -> Option<I::Item> {
-        self.try_for_each(Err).err()
+        self.iter.find(&mut self.predicate)
     }
 
     #[inline]
@@ -738,32 +820,26 @@
     // leaving more budget for LLVM optimizations.
     #[inline]
     fn count(self) -> usize {
-        let mut predicate = self.predicate;
-        self.iter.map(|x| predicate(&x) as usize).sum()
+        #[inline]
+        fn to_usize<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize {
+            move |x| predicate(&x) as usize
+        }
+
+        self.iter.map(to_usize(self.predicate)).sum()
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let predicate = &mut self.predicate;
-        self.iter.try_fold(init, move |acc, item| if predicate(&item) {
-            fold(acc, item)
-        } else {
-            Try::from_ok(acc)
-        })
+        self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold))
     }
 
     #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut predicate = self.predicate;
-        self.iter.fold(init, move |acc, item| if predicate(&item) {
-            fold(acc, item)
-        } else {
-            acc
-        })
+        self.iter.fold(init, filter_fold(self.predicate, fold))
     }
 }
 
@@ -773,31 +849,21 @@
 {
     #[inline]
     fn next_back(&mut self) -> Option<I::Item> {
-        self.try_rfold((), |_, x| Err(x)).err()
+        self.iter.rfind(&mut self.predicate)
     }
 
     #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let predicate = &mut self.predicate;
-        self.iter.try_rfold(init, move |acc, item| if predicate(&item) {
-            fold(acc, item)
-        } else {
-            Try::from_ok(acc)
-        })
+        self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold))
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut predicate = self.predicate;
-        self.iter.rfold(init, move |acc, item| if predicate(&item) {
-            fold(acc, item)
-        } else {
-            acc
-        })
+        self.iter.rfold(init, filter_fold(self.predicate, fold))
     }
 }
 
@@ -834,6 +900,26 @@
     }
 }
 
+fn filter_map_fold<T, B, Acc>(
+    mut f: impl FnMut(T) -> Option<B>,
+    mut fold: impl FnMut(Acc, B) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| match f(item) {
+        Some(x) => fold(acc, x),
+        None => acc,
+    }
+}
+
+fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>(
+    f: &'a mut impl FnMut(T) -> Option<B>,
+    mut fold: impl FnMut(Acc, B) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, item| match f(item) {
+        Some(x) => fold(acc, x),
+        None => R::from_ok(acc),
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
     where F: FnMut(I::Item) -> Option<B>,
@@ -842,7 +928,7 @@
 
     #[inline]
     fn next(&mut self) -> Option<B> {
-        self.try_for_each(Err).err()
+        self.iter.find_map(&mut self.f)
     }
 
     #[inline]
@@ -852,25 +938,17 @@
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let f = &mut self.f;
-        self.iter.try_fold(init, move |acc, item| match f(item) {
-            Some(x) => fold(acc, x),
-            None => Try::from_ok(acc),
-        })
+        self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold))
     }
 
     #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut f = self.f;
-        self.iter.fold(init, move |acc, item| match f(item) {
-            Some(x) => fold(acc, x),
-            None => acc,
-        })
+        self.iter.fold(init, filter_map_fold(self.f, fold))
     }
 }
 
@@ -880,29 +958,31 @@
 {
     #[inline]
     fn next_back(&mut self) -> Option<B> {
-        self.try_rfold((), |_, x| Err(x)).err()
+        #[inline]
+        fn find<T, B>(
+            f: &mut impl FnMut(T) -> Option<B>
+        ) -> impl FnMut((), T) -> LoopState<(), B> + '_ {
+            move |(), x| match f(x) {
+                Some(x) => LoopState::Break(x),
+                None => LoopState::Continue(()),
+            }
+        }
+
+        self.iter.try_rfold((), find(&mut self.f)).break_value()
     }
 
     #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let f = &mut self.f;
-        self.iter.try_rfold(init, move |acc, item| match f(item) {
-            Some(x) => fold(acc, x),
-            None => Try::from_ok(acc),
-        })
+        self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold))
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut f = self.f;
-        self.iter.rfold(init, move |acc, item| match f(item) {
-            Some(x) => fold(acc, x),
-            None => acc,
-        })
+        self.iter.rfold(init, filter_map_fold(self.f, fold))
     }
 }
 
@@ -944,14 +1024,12 @@
     ///
     /// Might panic if the index of the element overflows a `usize`.
     #[inline]
-    #[rustc_inherit_overflow_checks]
     fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
-        self.iter.next().map(|a| {
-            let ret = (self.count, a);
-            // Possible undefined overflow.
-            self.count += 1;
-            ret
-        })
+        let a = self.iter.next()?;
+        let i = self.count;
+        // Possible undefined overflow.
+        AddAssign::add_assign(&mut self.count, 1);
+        Some((i, a))
     }
 
     #[inline]
@@ -960,13 +1038,12 @@
     }
 
     #[inline]
-    #[rustc_inherit_overflow_checks]
     fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
-        self.iter.nth(n).map(|a| {
-            let i = self.count + n;
-            self.count = i + 1;
-            (i, a)
-        })
+        let a = self.iter.nth(n)?;
+        // Possible undefined overflow.
+        let i = Add::add(self.count, n);
+        self.count = Add::add(i, 1);
+        Some((i, a))
     }
 
     #[inline]
@@ -975,29 +1052,43 @@
     }
 
     #[inline]
-    #[rustc_inherit_overflow_checks]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let count = &mut self.count;
-        self.iter.try_fold(init, move |acc, item| {
-            let acc = fold(acc, (*count, item));
-            *count += 1;
-            acc
-        })
+        #[inline]
+        fn enumerate<'a, T, Acc, R>(
+            count: &'a mut usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> R + 'a {
+            move |acc, item| {
+                let acc = fold(acc, (*count, item));
+                // Possible undefined overflow.
+                AddAssign::add_assign(count, 1);
+                acc
+            }
+        }
+
+        self.iter.try_fold(init, enumerate(&mut self.count, fold))
     }
 
     #[inline]
-    #[rustc_inherit_overflow_checks]
-    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut count = self.count;
-        self.iter.fold(init, move |acc, item| {
-            let acc = fold(acc, (count, item));
-            count += 1;
-            acc
-        })
+        #[inline]
+        fn enumerate<T, Acc>(
+            mut count: usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
+        ) -> impl FnMut(Acc, T) -> Acc {
+            move |acc, item| {
+                let acc = fold(acc, (count, item));
+                // Possible undefined overflow.
+                AddAssign::add_assign(&mut count, 1);
+                acc
+            }
+        }
+
+        self.iter.fold(init, enumerate(self.count, fold))
     }
 }
 
@@ -1007,48 +1098,60 @@
 {
     #[inline]
     fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
-        self.iter.next_back().map(|a| {
-            let len = self.iter.len();
-            // Can safely add, `ExactSizeIterator` promises that the number of
-            // elements fits into a `usize`.
-            (self.count + len, a)
-        })
+        let a = self.iter.next_back()?;
+        let len = self.iter.len();
+        // Can safely add, `ExactSizeIterator` promises that the number of
+        // elements fits into a `usize`.
+        Some((self.count + len, a))
     }
 
     #[inline]
     fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> {
-        self.iter.nth_back(n).map(|a| {
-            let len = self.iter.len();
-            // Can safely add, `ExactSizeIterator` promises that the number of
-            // elements fits into a `usize`.
-            (self.count + len, a)
-        })
+        let a = self.iter.nth_back(n)?;
+        let len = self.iter.len();
+        // Can safely add, `ExactSizeIterator` promises that the number of
+        // elements fits into a `usize`.
+        Some((self.count + len, a))
     }
 
     #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
         // Can safely add and subtract the count, as `ExactSizeIterator` promises
         // that the number of elements fits into a `usize`.
-        let mut count = self.count + self.iter.len();
-        self.iter.try_rfold(init, move |acc, item| {
-            count -= 1;
-            fold(acc, (count, item))
-        })
+        fn enumerate<T, Acc, R>(
+            mut count: usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> R,
+        ) -> impl FnMut(Acc, T) -> R {
+            move |acc, item| {
+                count -= 1;
+                fold(acc, (count, item))
+            }
+        }
+
+        let count = self.count + self.iter.len();
+        self.iter.try_rfold(init, enumerate(count, fold))
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
         // Can safely add and subtract the count, as `ExactSizeIterator` promises
         // that the number of elements fits into a `usize`.
-        let mut count = self.count + self.iter.len();
-        self.iter.rfold(init, move |acc, item| {
-            count -= 1;
-            fold(acc, (count, item))
-        })
+        fn enumerate<T, Acc>(
+            mut count: usize,
+            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
+        ) -> impl FnMut(Acc, T) -> Acc {
+            move |acc, item| {
+                count -= 1;
+                fold(acc, (count, item))
+            }
+        }
+
+        let count = self.count + self.iter.len();
+        self.iter.rfold(init, enumerate(count, fold))
     }
 }
 
@@ -1162,7 +1265,10 @@
         };
         let (lo, hi) = self.iter.size_hint();
         let lo = lo.saturating_add(peek_len);
-        let hi = hi.and_then(|x| x.checked_add(peek_len));
+        let hi = match hi {
+            Some(x) => x.checked_add(peek_len),
+            None => None,
+        };
         (lo, hi)
     }
 
@@ -1321,16 +1427,23 @@
 
     #[inline]
     fn next(&mut self) -> Option<I::Item> {
+        fn check<'a, T>(
+            flag: &'a mut bool,
+            pred: &'a mut impl FnMut(&T) -> bool,
+        ) -> impl FnMut(&T) -> bool + 'a {
+            move |x| {
+                if *flag || !pred(x) {
+                    *flag = true;
+                    true
+                } else {
+                    false
+                }
+            }
+        }
+
         let flag = &mut self.flag;
         let pred = &mut self.predicate;
-        self.iter.find(move |x| {
-            if *flag || !pred(x) {
-                *flag = true;
-                true
-            } else {
-                false
-            }
-        })
+        self.iter.find(check(flag, pred))
     }
 
     #[inline]
@@ -1412,14 +1525,13 @@
         if self.flag {
             None
         } else {
-            self.iter.next().and_then(|x| {
-                if (self.predicate)(&x) {
-                    Some(x)
-                } else {
-                    self.flag = true;
-                    None
-                }
-            })
+            let x = self.iter.next()?;
+            if (self.predicate)(&x) {
+                Some(x)
+            } else {
+                self.flag = true;
+                None
+            }
         }
     }
 
@@ -1434,22 +1546,30 @@
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        if self.flag {
-            Try::from_ok(init)
-        } else {
-            let flag = &mut self.flag;
-            let p = &mut self.predicate;
-            self.iter.try_fold(init, move |acc, x|{
+        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
+            flag: &'a mut bool,
+            p: &'a mut impl FnMut(&T) -> bool,
+            mut fold: impl FnMut(Acc, T) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
+            move |acc, x| {
                 if p(&x) {
                     LoopState::from_try(fold(acc, x))
                 } else {
                     *flag = true;
                     LoopState::Break(Try::from_ok(acc))
                 }
-            }).into_try()
+            }
+        }
+
+        if self.flag {
+            Try::from_ok(init)
+        } else {
+            let flag = &mut self.flag;
+            let p = &mut self.predicate;
+            self.iter.try_fold(init, check(flag, p, fold)).into_try()
         }
     }
 }
@@ -1534,7 +1654,10 @@
         let (lower, upper) = self.iter.size_hint();
 
         let lower = lower.saturating_sub(self.n);
-        let upper = upper.map(|x| x.saturating_sub(self.n));
+        let upper = match upper {
+            Some(x) => Some(x.saturating_sub(self.n)),
+            None => None,
+        };
 
         (lower, upper)
     }
@@ -1595,19 +1718,26 @@
         }
     }
 
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let mut n = self.len();
-        if n == 0 {
-            Try::from_ok(init)
-        } else {
-            self.iter.try_rfold(init, move |acc, x| {
+        fn check<T, Acc, R: Try<Ok = Acc>>(
+            mut n: usize,
+            mut fold: impl FnMut(Acc, T) -> R,
+        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> {
+            move |acc, x| {
                 n -= 1;
                 let r = fold(acc, x);
                 if n == 0 { LoopState::Break(r) }
                 else { LoopState::from_try(r) }
-            }).into_try()
+            }
+        }
+
+        let n = self.len();
+        if n == 0 {
+            Try::from_ok(init)
+        } else {
+            self.iter.try_rfold(init, check(n, fold)).into_try()
         }
     }
 }
@@ -1682,19 +1812,26 @@
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        if self.n == 0 {
-            Try::from_ok(init)
-        } else {
-            let n = &mut self.n;
-            self.iter.try_fold(init, move |acc, x| {
+        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
+            n: &'a mut usize,
+            mut fold: impl FnMut(Acc, T) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
+            move |acc, x| {
                 *n -= 1;
                 let r = fold(acc, x);
                 if *n == 0 { LoopState::Break(r) }
                 else { LoopState::from_try(r) }
-            }).into_try()
+            }
+        }
+
+        if self.n == 0 {
+            Try::from_ok(init)
+        } else {
+            let n = &mut self.n;
+            self.iter.try_fold(init, check(n, fold)).into_try()
         }
     }
 }
@@ -1793,7 +1930,8 @@
 
     #[inline]
     fn next(&mut self) -> Option<B> {
-        self.iter.next().and_then(|a| (self.f)(&mut self.state, a))
+        let a = self.iter.next()?;
+        (self.f)(&mut self.state, a)
     }
 
     #[inline]
@@ -1803,17 +1941,25 @@
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
+        fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>(
+            state: &'a mut St,
+            f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
+            mut fold: impl FnMut(Acc, B) -> R + 'a,
+        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
+            move |acc, x| {
+                match f(state, x) {
+                    None => LoopState::Break(Try::from_ok(acc)),
+                    Some(x) => LoopState::from_try(fold(acc, x)),
+                }
+            }
+        }
+
         let state = &mut self.state;
         let f = &mut self.f;
-        self.iter.try_fold(init, move |acc, x| {
-            match f(state, x) {
-                None => LoopState::Break(Try::from_ok(acc)),
-                Some(x) => LoopState::from_try(fold(acc, x)),
-            }
-        }).into_try()
+        self.iter.try_fold(init, scan(state, f, fold)).into_try()
     }
 }
 
@@ -2104,6 +2250,20 @@
     }
 }
 
+fn inspect_fold<T, Acc>(
+    mut f: impl FnMut(&T),
+    mut fold: impl FnMut(Acc, T) -> Acc,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| { f(&item); fold(acc, item) }
+}
+
+fn inspect_try_fold<'a, T, Acc, R>(
+    f: &'a mut impl FnMut(&T),
+    mut fold: impl FnMut(Acc, T) -> R + 'a,
+) -> impl FnMut(Acc, T) -> R + 'a {
+    move |acc, item| { f(&item); fold(acc, item) }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) {
     type Item = I::Item;
@@ -2120,19 +2280,17 @@
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let f = &mut self.f;
-        self.iter.try_fold(init, move |acc, item| { f(&item); fold(acc, item) })
+        self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
     }
 
     #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut f = self.f;
-        self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) })
+        self.iter.fold(init, inspect_fold(self.f, fold))
     }
 }
 
@@ -2147,19 +2305,17 @@
     }
 
     #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
-        let f = &mut self.f;
-        self.iter.try_rfold(init, move |acc, item| { f(&item); fold(acc, item) })
+        self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
-        let mut f = self.f;
-        self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) })
+        self.iter.rfold(init, inspect_fold(self.f, fold))
     }
 }
 
diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs
index 06f047d..430ceac 100644
--- a/src/libcore/iter/adapters/zip.rs
+++ b/src/libcore/iter/adapters/zip.rs
@@ -94,11 +94,9 @@
 
     #[inline]
     default fn next(&mut self) -> Option<(A::Item, B::Item)> {
-        self.a.next().and_then(|x| {
-            self.b.next().and_then(|y| {
-                Some((x, y))
-            })
-        })
+        let x = self.a.next()?;
+        let y = self.b.next()?;
+        Some((x, y))
     }
 
     #[inline]
diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs
index 70a3b70..1831760 100644
--- a/src/libcore/iter/sources.rs
+++ b/src/libcore/iter/sources.rs
@@ -394,7 +394,8 @@
 
     #[inline]
     fn next(&mut self) -> Option<A> {
-        self.gen.take().map(|f| f())
+        let f = self.gen.take()?;
+        Some(f())
     }
 
     #[inline]
@@ -608,10 +609,9 @@
 
     #[inline]
     fn next(&mut self) -> Option<Self::Item> {
-        self.next.take().map(|item| {
-            self.next = (self.succ)(&item);
-            item
-        })
+        let item = self.next.take()?;
+        self.next = (self.succ)(&item);
+        Some(item)
     }
 
     #[inline]
diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs
index 812463e..818f033 100644
--- a/src/libcore/iter/traits/accum.rs
+++ b/src/libcore/iter/traits/accum.rs
@@ -85,28 +85,28 @@
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl Sum for $a {
             fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
-                iter.fold(0.0, |a, b| a + b)
+                iter.fold(0.0, Add::add)
             }
         }
 
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl Product for $a {
             fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
-                iter.fold(1.0, |a, b| a * b)
+                iter.fold(1.0, Mul::mul)
             }
         }
 
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl<'a> Sum<&'a $a> for $a {
             fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
-                iter.fold(0.0, |a, b| a + *b)
+                iter.fold(0.0, Add::add)
             }
         }
 
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl<'a> Product<&'a $a> for $a {
             fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
-                iter.fold(1.0, |a, b| a * *b)
+                iter.fold(1.0, Mul::mul)
             }
         }
     )*)
diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs
index 2c1aeb5..006b243 100644
--- a/src/libcore/iter/traits/double_ended.rs
+++ b/src/libcore/iter/traits/double_ended.rs
@@ -69,7 +69,7 @@
     /// Returns the `n`th element from the end of the iterator.
     ///
     /// This is essentially the reversed version of [`nth`]. Although like most indexing
-    /// operations, the count starts from zero, so `nth_back(0)` returns the first value fro
+    /// operations, the count starts from zero, so `nth_back(0)` returns the first value from
     /// the end, `nth_back(1)` the second, and so on.
     ///
     /// Note that all elements between the end and the returned element will be
@@ -219,12 +219,17 @@
     /// ```
     #[inline]
     #[stable(feature = "iter_rfold", since = "1.27.0")]
-    fn rfold<B, F>(mut self, accum: B, mut f: F) -> B
+    fn rfold<B, F>(mut self, accum: B, f: F) -> B
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> B,
     {
-        self.try_rfold(accum, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
+        #[inline]
+        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
+            move |acc, x| Ok(f(acc, x))
+        }
+
+        self.try_rfold(accum, ok(f)).unwrap()
     }
 
     /// Searches for an element of an iterator from the back that satisfies a predicate.
@@ -271,15 +276,21 @@
     /// ```
     #[inline]
     #[stable(feature = "iter_rfind", since = "1.27.0")]
-    fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
+    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
         Self: Sized,
         P: FnMut(&Self::Item) -> bool
     {
-        self.try_rfold((), move |(), x| {
-            if predicate(&x) { LoopState::Break(x) }
-            else { LoopState::Continue(()) }
-        }).break_value()
+        #[inline]
+        fn check<T>(
+            mut predicate: impl FnMut(&T) -> bool,
+        ) -> impl FnMut((), T) -> LoopState<(), T> {
+            move |(), x| {
+                if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
+            }
+        }
+
+        self.try_rfold((), check(predicate)).break_value()
     }
 }
 
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index 7e94126..d644787 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -1,5 +1,5 @@
 use crate::cmp::Ordering;
-use crate::ops::Try;
+use crate::ops::{Add, Try};
 
 use super::super::LoopState;
 use super::super::{Chain, Cycle, Copied, Cloned, Enumerate, Filter, FilterMap, Fuse};
@@ -234,11 +234,15 @@
     /// assert_eq!(a.iter().count(), 5);
     /// ```
     #[inline]
-    #[rustc_inherit_overflow_checks]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn count(self) -> usize where Self: Sized {
-        // Might overflow.
-        self.fold(0, |cnt, _| cnt + 1)
+        #[inline]
+        fn add1<T>(count: usize, _: T) -> usize {
+            // Might overflow.
+            Add::add(count, 1)
+        }
+
+        self.fold(0, add1)
     }
 
     /// Consumes the iterator, returning the last element.
@@ -263,7 +267,12 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn last(self) -> Option<Self::Item> where Self: Sized {
-        self.fold(None, |_, x| Some(x))
+        #[inline]
+        fn some<T>(_: Option<T>, x: T) -> Option<T> {
+            Some(x)
+        }
+
+        self.fold(None, some)
     }
 
     /// Returns the `n`th element of the iterator.
@@ -596,10 +605,15 @@
     /// ```
     #[inline]
     #[stable(feature = "iterator_for_each", since = "1.21.0")]
-    fn for_each<F>(self, mut f: F) where
+    fn for_each<F>(self, f: F) where
         Self: Sized, F: FnMut(Self::Item),
     {
-        self.fold((), move |(), item| f(item));
+        #[inline]
+        fn call<T>(mut f: impl FnMut(T)) -> impl FnMut((), T) {
+            move |(), item| f(item)
+        }
+
+        self.fold((), call(f));
     }
 
     /// Creates an iterator which uses a closure to determine if an element
@@ -1490,21 +1504,30 @@
     /// assert_eq!(odd, vec![1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn partition<B, F>(self, mut f: F) -> (B, B) where
+    fn partition<B, F>(self, f: F) -> (B, B) where
         Self: Sized,
         B: Default + Extend<Self::Item>,
         F: FnMut(&Self::Item) -> bool
     {
+        #[inline]
+        fn extend<'a, T, B: Extend<T>>(
+            mut f: impl FnMut(&T) -> bool + 'a,
+            left: &'a mut B,
+            right: &'a mut B,
+        ) -> impl FnMut(T) + 'a {
+            move |x| {
+                if f(&x) {
+                    left.extend(Some(x));
+                } else {
+                    right.extend(Some(x));
+                }
+            }
+        }
+
         let mut left: B = Default::default();
         let mut right: B = Default::default();
 
-        self.for_each(|x| {
-            if f(&x) {
-                left.extend(Some(x))
-            } else {
-                right.extend(Some(x))
-            }
-        });
+        self.for_each(extend(f, &mut left, &mut right));
 
         (left, right)
     }
@@ -1702,10 +1725,15 @@
     /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
-    fn try_for_each<F, R>(&mut self, mut f: F) -> R where
+    fn try_for_each<F, R>(&mut self, f: F) -> R where
         Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Ok=()>
     {
-        self.try_fold((), move |(), x| f(x))
+        #[inline]
+        fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R {
+            move |(), x| f(x)
+        }
+
+        self.try_fold((), call(f))
     }
 
     /// An iterator method that applies a function, producing a single, final value.
@@ -1777,10 +1805,15 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fold<B, F>(mut self, init: B, mut f: F) -> B where
+    fn fold<B, F>(mut self, init: B, f: F) -> B where
         Self: Sized, F: FnMut(B, Self::Item) -> B,
     {
-        self.try_fold(init, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
+        #[inline]
+        fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
+            move |acc, x| Ok(f(acc, x))
+        }
+
+        self.try_fold(init, ok(f)).unwrap()
     }
 
     /// Tests if every element of the iterator matches a predicate.
@@ -1822,13 +1855,18 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn all<F>(&mut self, mut f: F) -> bool where
+    fn all<F>(&mut self, f: F) -> bool where
         Self: Sized, F: FnMut(Self::Item) -> bool
     {
-        self.try_for_each(move |x| {
-            if f(x) { LoopState::Continue(()) }
-            else { LoopState::Break(()) }
-        }) == LoopState::Continue(())
+        #[inline]
+        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
+            move |x| {
+                if f(x) { LoopState::Continue(()) }
+                else { LoopState::Break(()) }
+            }
+        }
+
+        self.try_for_each(check(f)) == LoopState::Continue(())
     }
 
     /// Tests if any element of the iterator matches a predicate.
@@ -1870,14 +1908,19 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn any<F>(&mut self, mut f: F) -> bool where
+    fn any<F>(&mut self, f: F) -> bool where
         Self: Sized,
         F: FnMut(Self::Item) -> bool
     {
-        self.try_for_each(move |x| {
-            if f(x) { LoopState::Break(()) }
-            else { LoopState::Continue(()) }
-        }) == LoopState::Break(())
+        #[inline]
+        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
+            move |x| {
+                if f(x) { LoopState::Break(()) }
+                else { LoopState::Continue(()) }
+            }
+        }
+
+        self.try_for_each(check(f)) == LoopState::Break(())
     }
 
     /// Searches for an element of an iterator that satisfies a predicate.
@@ -1924,14 +1967,19 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
+    fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where
         Self: Sized,
         P: FnMut(&Self::Item) -> bool,
     {
-        self.try_for_each(move |x| {
-            if predicate(&x) { LoopState::Break(x) }
-            else { LoopState::Continue(()) }
-        }).break_value()
+        #[inline]
+        fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> {
+            move |x| {
+                if predicate(&x) { LoopState::Break(x) }
+                else { LoopState::Continue(()) }
+            }
+        }
+
+        self.try_for_each(check(predicate)).break_value()
     }
 
     /// Applies function to the elements of iterator and returns
@@ -1951,16 +1999,19 @@
     /// ```
     #[inline]
     #[stable(feature = "iterator_find_map", since = "1.30.0")]
-    fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
+    fn find_map<B, F>(&mut self, f: F) -> Option<B> where
         Self: Sized,
         F: FnMut(Self::Item) -> Option<B>,
     {
-        self.try_for_each(move |x| {
-            match f(x) {
+        #[inline]
+        fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut(T) -> LoopState<(), B> {
+            move |x| match f(x) {
                 Some(x) => LoopState::Break(x),
                 None => LoopState::Continue(()),
             }
-        }).break_value()
+        }
+
+        self.try_for_each(check(f)).break_value()
     }
 
     /// Searches for an element in an iterator, returning its index.
@@ -2018,17 +2069,23 @@
     ///
     /// ```
     #[inline]
-    #[rustc_inherit_overflow_checks]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
+    fn position<P>(&mut self, predicate: P) -> Option<usize> where
         Self: Sized,
         P: FnMut(Self::Item) -> bool,
     {
-        // The addition might panic on overflow
-        self.try_fold(0, move |i, x| {
-            if predicate(x) { LoopState::Break(i) }
-            else { LoopState::Continue(i + 1) }
-        }).break_value()
+        #[inline]
+        fn check<T>(
+            mut predicate: impl FnMut(T) -> bool,
+        ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+            // The addition might panic on overflow
+            move |i, x| {
+                if predicate(x) { LoopState::Break(i) }
+                else { LoopState::Continue(Add::add(i, 1)) }
+            }
+        }
+
+        self.try_fold(0, check(predicate)).break_value()
     }
 
     /// Searches for an element in an iterator from the right, returning its
@@ -2071,18 +2128,25 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
+    fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
         P: FnMut(Self::Item) -> bool,
         Self: Sized + ExactSizeIterator + DoubleEndedIterator
     {
         // No need for an overflow check here, because `ExactSizeIterator`
         // implies that the number of elements fits into a `usize`.
+        #[inline]
+        fn check<T>(
+            mut predicate: impl FnMut(T) -> bool,
+        ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+            move |i, x| {
+                let i = i - 1;
+                if predicate(x) { LoopState::Break(i) }
+                else { LoopState::Continue(i) }
+            }
+        }
+
         let n = self.len();
-        self.try_rfold(n, move |i, x| {
-            let i = i - 1;
-            if predicate(x) { LoopState::Break(i) }
-            else { LoopState::Continue(i) }
-        }).break_value()
+        self.try_rfold(n, check(predicate)).break_value()
     }
 
     /// Returns the maximum element of an iterator.
@@ -2151,11 +2215,22 @@
     /// ```
     #[inline]
     #[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
-    fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
+    fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item) -> B,
     {
+        #[inline]
+        fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
+            move |x| (f(&x), x)
+        }
+
         // switch to y even if it is only equal, to preserve stability.
-        select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x)
+        #[inline]
+        fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
+            x_p <= y_p
+        }
+
+        let (_, x) = select_fold1(self.map(key(f)), select)?;
+        Some(x)
     }
 
     /// Returns the element that gives the maximum value with respect to the
@@ -2174,11 +2249,16 @@
     /// ```
     #[inline]
     #[stable(feature = "iter_max_by", since = "1.15.0")]
-    fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
+    fn max_by<F>(self, compare: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
     {
         // switch to y even if it is only equal, to preserve stability.
-        select_fold1(self, |x, y| compare(x, y) != Ordering::Greater)
+        #[inline]
+        fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
+            move |x, y| compare(x, y) != Ordering::Greater
+        }
+
+        select_fold1(self, select(compare))
     }
 
     /// Returns the element that gives the minimum value from the
@@ -2195,12 +2275,24 @@
     /// let a = [-3_i32, 0, 1, 5, -10];
     /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0);
     /// ```
+    #[inline]
     #[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
-    fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
+    fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item) -> B,
     {
+        #[inline]
+        fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
+            move |x| (f(&x), x)
+        }
+
         // only switch to y if it is strictly smaller, to preserve stability.
-        select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x)
+        #[inline]
+        fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
+            x_p > y_p
+        }
+
+        let (_, x) = select_fold1(self.map(key(f)), select)?;
+        Some(x)
     }
 
     /// Returns the element that gives the minimum value with respect to the
@@ -2219,11 +2311,16 @@
     /// ```
     #[inline]
     #[stable(feature = "iter_min_by", since = "1.15.0")]
-    fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
+    fn min_by<F>(self, compare: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
     {
         // only switch to y if it is strictly smaller, to preserve stability.
-        select_fold1(self, |x, y| compare(x, y) == Ordering::Greater)
+        #[inline]
+        fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
+            move |x, y| compare(x, y) == Ordering::Greater
+        }
+
+        select_fold1(self, select(compare))
     }
 
 
@@ -2284,13 +2381,20 @@
         FromB: Default + Extend<B>,
         Self: Sized + Iterator<Item=(A, B)>,
     {
+        fn extend<'a, A, B>(
+            ts: &'a mut impl Extend<A>,
+            us: &'a mut impl Extend<B>,
+        ) -> impl FnMut((A, B)) + 'a {
+            move |(t, u)| {
+                ts.extend(Some(t));
+                us.extend(Some(u));
+            }
+        }
+
         let mut ts: FromA = Default::default();
         let mut us: FromB = Default::default();
 
-        self.for_each(|(t, u)| {
-            ts.extend(Some(t));
-            us.extend(Some(u));
-        });
+        self.for_each(extend(&mut ts, &mut us));
 
         (ts, us)
     }
@@ -2617,7 +2721,7 @@
         Self: Sized,
         Self::Item: PartialOrd,
     {
-        self.is_sorted_by(|a, b| a.partial_cmp(b))
+        self.is_sorted_by(PartialOrd::partial_cmp)
     }
 
     /// Checks if the elements of this iterator are sorted using the given comparator function.
@@ -2639,10 +2743,7 @@
         };
 
         while let Some(curr) = self.next() {
-            if compare(&last, &curr)
-                .map(|o| o == Ordering::Greater)
-                .unwrap_or(true)
-            {
+            if let Some(Ordering::Greater) | None = compare(&last, &curr) {
                 return false;
             }
             last = curr;
@@ -2687,17 +2788,21 @@
 /// commonalities of {max,min}{,_by}. In particular, this avoids
 /// having to implement optimizations several times.
 #[inline]
-fn select_fold1<I, F>(mut it: I, mut f: F) -> Option<I::Item>
+fn select_fold1<I, F>(mut it: I, f: F) -> Option<I::Item>
     where
         I: Iterator,
         F: FnMut(&I::Item, &I::Item) -> bool,
 {
+    #[inline]
+    fn select<T>(mut f: impl FnMut(&T, &T) -> bool) -> impl FnMut(T, T) -> T {
+        move |sel, x| if f(&sel, &x) { x } else { sel }
+    }
+
     // start with the first element as our selection. This avoids
     // having to use `Option`s inside the loop, translating to a
     // sizeable performance gain (6x in one case).
-    it.next().map(|first| {
-        it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel })
-    })
+    let first = it.next()?;
+    Some(it.fold(first, select(f)))
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 678ff76..c168d5c 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -63,7 +63,7 @@
 #![warn(missing_debug_implementations)]
 #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
 #![allow(explicit_outlives_requirements)]
-#![cfg_attr(not(bootstrap), allow(incomplete_features))]
+#![allow(incomplete_features)]
 
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
@@ -129,7 +129,7 @@
 #![feature(structural_match)]
 #![feature(abi_unadjusted)]
 #![feature(adx_target_feature)]
-#![feature(maybe_uninit_slice, maybe_uninit_array)]
+#![feature(maybe_uninit_slice)]
 #![feature(external_doc)]
 #![feature(mem_take)]
 #![feature(associated_type_bounds)]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index f9dc538..e114f3a 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -2,21 +2,21 @@
 ///
 /// For details, see `std::macros`.
 #[macro_export]
-#[allow_internal_unstable(core_panic, __rust_unstable_column)]
+#[allow_internal_unstable(core_panic)]
 #[stable(feature = "core", since = "1.6.0")]
 macro_rules! panic {
     () => (
         $crate::panic!("explicit panic")
     );
     ($msg:expr) => ({
-        $crate::panicking::panic(&($msg, file!(), line!(), __rust_unstable_column!()))
+        $crate::panicking::panic(&($msg, $crate::file!(), $crate::line!(), $crate::column!()))
     });
     ($msg:expr,) => (
         $crate::panic!($msg)
     );
     ($fmt:expr, $($arg:tt)+) => ({
-        $crate::panicking::panic_fmt(format_args!($fmt, $($arg)+),
-                                     &(file!(), line!(), __rust_unstable_column!()))
+        $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+),
+                                     &($crate::file!(), $crate::line!(), $crate::column!()))
     });
 }
 
@@ -70,7 +70,7 @@
                     panic!(r#"assertion failed: `(left == right)`
   left: `{:?}`,
  right: `{:?}`: {}"#, &*left_val, &*right_val,
-                           format_args!($($arg)+))
+                           $crate::format_args!($($arg)+))
                 }
             }
         }
@@ -127,7 +127,7 @@
                     panic!(r#"assertion failed: `(left != right)`
   left: `{:?}`,
  right: `{:?}`: {}"#, &*left_val, &*right_val,
-                           format_args!($($arg)+))
+                           $crate::format_args!($($arg)+))
                 }
             }
         }
@@ -181,7 +181,7 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! debug_assert {
-    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
+    ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); })
 }
 
 /// Asserts that two expressions are equal to each other.
@@ -208,7 +208,7 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! debug_assert_eq {
-    ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
+    ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
 }
 
 /// Asserts that two expressions are not equal to each other.
@@ -235,7 +235,7 @@
 #[macro_export]
 #[stable(feature = "assert_ne", since = "1.13.0")]
 macro_rules! debug_assert_ne {
-    ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
+    ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
 }
 
 /// Unwraps a result or propagates its error.
@@ -386,7 +386,7 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! write {
-    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
+    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*)))
 }
 
 /// Write formatted data into a buffer, with a newline appended.
@@ -446,7 +446,7 @@
         $crate::writeln!($dst)
     );
     ($dst:expr, $($arg:tt)*) => (
-        $dst.write_fmt(format_args_nl!($($arg)*))
+        $dst.write_fmt($crate::format_args_nl!($($arg)*))
     );
 }
 
@@ -515,7 +515,7 @@
         $crate::unreachable!($msg)
     });
     ($fmt:expr, $($arg:tt)*) => ({
-        panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
+        panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
     });
 }
 
@@ -573,7 +573,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! unimplemented {
     () => (panic!("not yet implemented"));
-    ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+)));
+    ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
 }
 
 /// Indicates unfinished code.
@@ -632,41 +632,7 @@
 #[unstable(feature = "todo_macro", issue = "59277")]
 macro_rules! todo {
     () => (panic!("not yet implemented"));
-    ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+)));
-}
-
-/// Creates an array of [`MaybeUninit`].
-///
-/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`.
-/// It exists solely because bootstrap does not yet support const array-init expressions.
-///
-/// [`MaybeUninit`]: mem/union.MaybeUninit.html
-// FIXME: Remove both versions of this macro once bootstrap is 1.38.
-#[macro_export]
-#[unstable(feature = "maybe_uninit_array", issue = "53491")]
-#[cfg(bootstrap)]
-macro_rules! uninit_array {
-    // This `assume_init` is safe because an array of `MaybeUninit` does not
-    // require initialization.
-    ($t:ty; $size:expr) => (unsafe {
-        MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init()
-    });
-}
-
-/// Creates an array of [`MaybeUninit`].
-///
-/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`.
-/// It exists solely because bootstrap does not yet support const array-init expressions.
-///
-/// [`MaybeUninit`]: mem/union.MaybeUninit.html
-// FIXME: Just inline this version of the macro once bootstrap is 1.38.
-#[macro_export]
-#[unstable(feature = "maybe_uninit_array", issue = "53491")]
-#[cfg(not(bootstrap))]
-macro_rules! uninit_array {
-    ($t:ty; $size:expr) => (
-        [MaybeUninit::<$t>::UNINIT; $size]
-    );
+    ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
 }
 
 /// Definitions of built-in macros.
@@ -674,7 +640,6 @@
 /// Most of the macro properties (stability, visibility, etc.) are taken from the source code here,
 /// with exception of expansion functions transforming macro inputs into outputs,
 /// those functions are provided by the compiler.
-#[cfg(not(bootstrap))]
 pub(crate) mod builtin {
 
     /// Causes compilation to fail with the given error message when encountered.
@@ -962,13 +927,6 @@
     #[macro_export]
     macro_rules! column { () => { /* compiler built-in */ } }
 
-    /// Same as `column`, but less likely to be shadowed.
-    #[unstable(feature = "__rust_unstable_column", issue = "0",
-               reason = "internal implementation detail of the `panic` macro")]
-    #[rustc_builtin_macro]
-    #[macro_export]
-    macro_rules! __rust_unstable_column { () => { /* compiler built-in */ } }
-
     /// Expands to the file name in which it was invoked.
     ///
     /// With [`line!`] and [`column!`], these macros provide debugging information for
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 78a2736..3befd42 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -289,7 +289,6 @@
 }
 
 /// Derive macro generating an impl of the trait `Copy`.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs
index 1bbea02..9e9e901 100644
--- a/src/libcore/mem/maybe_uninit.rs
+++ b/src/libcore/mem/maybe_uninit.rs
@@ -213,7 +213,7 @@
 #[allow(missing_debug_implementations)]
 #[stable(feature = "maybe_uninit", since = "1.36.0")]
 // Lang item so we can wrap other types in it. This is useful for generators.
-#[cfg_attr(not(bootstrap), lang = "maybe_uninit")]
+#[lang = "maybe_uninit"]
 #[derive(Copy)]
 #[repr(transparent)]
 pub union MaybeUninit<T> {
@@ -312,7 +312,7 @@
     /// without dropping it, so be careful not to use this twice unless you want to
     /// skip running the destructor. For your convenience, this also returns a mutable
     /// reference to the (now safely initialized) contents of `self`.
-    #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
     #[inline(always)]
     pub fn write(&mut self, val: T) -> &mut T {
         unsafe {
@@ -502,7 +502,7 @@
     /// // We now created two copies of the same vector, leading to a double-free when
     /// // they both get dropped!
     /// ```
-    #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
     #[inline(always)]
     pub unsafe fn read(&self) -> T {
         intrinsics::panic_if_uninhabited::<T>();
@@ -516,7 +516,7 @@
     /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
     /// state. Calling this when the content is not yet fully initialized causes undefined
     /// behavior.
-    #[unstable(feature = "maybe_uninit_ref", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
     #[inline(always)]
     pub unsafe fn get_ref(&self) -> &T {
         &*self.value
@@ -532,21 +532,21 @@
     // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
     // to uninitialized data (e.g., in `libcore/fmt/float.rs`).  We should make
     // a final decision about the rules before stabilization.
-    #[unstable(feature = "maybe_uninit_ref", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
     #[inline(always)]
     pub unsafe fn get_mut(&mut self) -> &mut T {
         &mut *self.value
     }
 
     /// Gets a pointer to the first element of the array.
-    #[unstable(feature = "maybe_uninit_slice", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
     #[inline(always)]
     pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
         this as *const [MaybeUninit<T>] as *const T
     }
 
     /// Gets a mutable pointer to the first element of the array.
-    #[unstable(feature = "maybe_uninit_slice", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
     #[inline(always)]
     pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T {
         this as *mut [MaybeUninit<T>] as *mut T
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 2534400..87ec05a 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -453,7 +453,7 @@
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(bootstrap, allow(deprecated_in_future))]
+#[allow(deprecated_in_future)]
 #[allow(deprecated)]
 pub unsafe fn zeroed<T>() -> T {
     intrinsics::panic_if_uninhabited::<T>();
@@ -481,7 +481,7 @@
 #[inline]
 #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(bootstrap, allow(deprecated_in_future))]
+#[allow(deprecated_in_future)]
 #[allow(deprecated)]
 pub unsafe fn uninitialized<T>() -> T {
     intrinsics::panic_if_uninhabited::<T>();
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 67e30e7..b46e06f 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1112,7 +1112,13 @@
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_add(self, rhs: Self) -> Self {
-                intrinsics::overflowing_add(self, rhs)
+                #[cfg(boostrap_stdarch_ignore_this)] {
+                    intrinsics::overflowing_add(self, rhs)
+                }
+
+                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                    intrinsics::wrapping_add(self, rhs)
+                }
             }
         }
 
@@ -1135,7 +1141,13 @@
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                intrinsics::overflowing_sub(self, rhs)
+                #[cfg(boostrap_stdarch_ignore_this)] {
+                    intrinsics::overflowing_sub(self, rhs)
+                }
+
+                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                    intrinsics::wrapping_sub(self, rhs)
+                }
             }
         }
 
@@ -1157,7 +1169,13 @@
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_mul(self, rhs: Self) -> Self {
-                intrinsics::overflowing_mul(self, rhs)
+                #[cfg(boostrap_stdarch_ignore_this)] {
+                    intrinsics::overflowing_mul(self, rhs)
+                }
+
+                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                    intrinsics::wrapping_mul(self, rhs)
+                }
             }
         }
 
@@ -3031,7 +3049,13 @@
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_add(self, rhs: Self) -> Self {
-                intrinsics::overflowing_add(self, rhs)
+                #[cfg(boostrap_stdarch_ignore_this)] {
+                    intrinsics::overflowing_add(self, rhs)
+                }
+
+                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                    intrinsics::wrapping_add(self, rhs)
+                }
             }
         }
 
@@ -3053,7 +3077,13 @@
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                intrinsics::overflowing_sub(self, rhs)
+                #[cfg(boostrap_stdarch_ignore_this)] {
+                    intrinsics::overflowing_sub(self, rhs)
+                }
+
+                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                    intrinsics::wrapping_sub(self, rhs)
+                }
             }
         }
 
@@ -3076,7 +3106,13 @@
                           without modifying the original"]
         #[inline]
         pub const fn wrapping_mul(self, rhs: Self) -> Self {
-            intrinsics::overflowing_mul(self, rhs)
+            #[cfg(boostrap_stdarch_ignore_this)] {
+                intrinsics::overflowing_mul(self, rhs)
+            }
+
+            #[cfg(not(boostrap_stdarch_ignore_this))] {
+                intrinsics::wrapping_mul(self, rhs)
+            }
         }
 
         doc_comment! {
diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs
index 84cf85f..7cc279a 100644
--- a/src/libcore/prelude/v1.rs
+++ b/src/libcore/prelude/v1.rs
@@ -46,20 +46,16 @@
 pub use crate::result::Result::{self, Ok, Err};
 
 // Re-exported built-in macros
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[doc(no_inline)]
 pub use crate::fmt::macros::Debug;
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[doc(no_inline)]
 pub use crate::hash::macros::Hash;
 
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[doc(no_inline)]
 pub use crate::{
-    __rust_unstable_column,
     asm,
     assert,
     cfg,
@@ -83,7 +79,6 @@
     trace_macros,
 };
 
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
 #[doc(no_inline)]
diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs
index 3db70d5..fec17c4 100644
--- a/src/libcore/task/poll.rs
+++ b/src/libcore/task/poll.rs
@@ -81,6 +81,34 @@
     }
 }
 
+impl<T, E> Poll<Option<Result<T, E>>> {
+    /// Changes the success value of this `Poll` with the closure provided.
+    #[unstable(feature = "poll_map", issue = "63514")]
+    pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
+        where F: FnOnce(T) -> U
+    {
+        match self {
+            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
+            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
+            Poll::Ready(None) => Poll::Ready(None),
+            Poll::Pending => Poll::Pending,
+        }
+    }
+
+    /// Changes the error value of this `Poll` with the closure provided.
+    #[unstable(feature = "poll_map", issue = "63514")]
+    pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
+        where F: FnOnce(E) -> U
+    {
+        match self {
+            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
+            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
+            Poll::Ready(None) => Poll::Ready(None),
+            Poll::Pending => Poll::Pending,
+        }
+    }
+}
+
 #[stable(feature = "futures_api", since = "1.36.0")]
 impl<T> From<T> for Poll<T> {
     fn from(t: T) -> Poll<T> {
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 3615fab..a1a27e1 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -104,6 +104,22 @@
 }
 
 #[test]
+fn test_iterator_chain_nth_back() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let zs = [];
+    let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+    for (i, x) in expected.iter().rev().enumerate() {
+        assert_eq!(Some(x), xs.iter().chain(&ys).nth_back(i));
+    }
+    assert_eq!(zs.iter().chain(&xs).nth_back(0), Some(&5));
+
+    let mut it = xs.iter().chain(&zs);
+    assert_eq!(it.nth_back(5), Some(&0));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
 fn test_iterator_chain_last() {
     let xs = [0, 1, 2, 3, 4, 5];
     let ys = [30, 40, 50, 60];
@@ -1136,6 +1152,18 @@
     assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0);
 
     assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4);
+
+    assert_eq!((0..10).cycle().take(5).sum::<i32>(), 10);
+    assert_eq!((0..10).cycle().take(15).sum::<i32>(), 55);
+    assert_eq!((0..10).cycle().take(25).sum::<i32>(), 100);
+
+    let mut iter = (0..10).cycle();
+    iter.nth(14);
+    assert_eq!(iter.take(8).sum::<i32>(), 38);
+
+    let mut iter = (0..10).cycle();
+    iter.nth(9);
+    assert_eq!(iter.take(3).sum::<i32>(), 3);
 }
 
 #[test]
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index ca852fe..7ada56c 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -136,7 +136,7 @@
             }
 
             PatKind::Struct(_, ref subpats, _) => {
-                let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
+                let pats_exit = self.pats_all(subpats.iter().map(|f| &f.pat), pred);
                 self.add_ast_node(pat.hir_id.local_id, &[pats_exit])
             }
 
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 22124d4..eae956c 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -336,7 +336,7 @@
 fn is_c_like_enum(item: &hir::Item) -> bool {
     if let hir::ItemKind::Enum(ref def, _) = item.node {
         for variant in &def.variants {
-            match variant.node.data {
+            match variant.data {
                 hir::VariantData::Unit(..) => { /* continue */ }
                 _ => { return false; }
             }
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index b5c760b..99fe9f1 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -577,15 +577,15 @@
                                         variant: &'v Variant,
                                         generics: &'v Generics,
                                         parent_item_id: HirId) {
-    visitor.visit_ident(variant.node.ident);
-    visitor.visit_id(variant.node.id);
-    visitor.visit_variant_data(&variant.node.data,
-                               variant.node.ident.name,
+    visitor.visit_ident(variant.ident);
+    visitor.visit_id(variant.id);
+    visitor.visit_variant_data(&variant.data,
+                               variant.ident.name,
                                generics,
                                parent_item_id,
                                variant.span);
-    walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
-    walk_list!(visitor, visit_attribute, &variant.node.attrs);
+    walk_list!(visitor, visit_anon_const, &variant.disr_expr);
+    walk_list!(visitor, visit_attribute, &variant.attrs);
 }
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
@@ -704,9 +704,9 @@
         PatKind::Struct(ref qpath, ref fields, _) => {
             visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
             for field in fields {
-                visitor.visit_id(field.node.hir_id);
-                visitor.visit_ident(field.node.ident);
-                visitor.visit_pat(&field.node.pat)
+                visitor.visit_id(field.hir_id);
+                visitor.visit_ident(field.ident);
+                visitor.visit_pat(&field.pat)
             }
         }
         PatKind::Tuple(ref tuple_elements, _) => {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index fe69c9e..0f6e834 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -67,7 +67,7 @@
 use syntax::ext::base::SpecialDerives;
 use syntax::ext::hygiene::ExpnId;
 use syntax::print::pprust;
-use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
+use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::parse::token::{self, Token};
@@ -136,7 +136,10 @@
     /// When `is_collectin_in_band_lifetimes` is true, each lifetime is checked
     /// against this list to see if it is already in-scope, or if a definition
     /// needs to be created for it.
-    in_scope_lifetimes: Vec<Ident>,
+    ///
+    /// We always store a `modern()` version of the param-name in this
+    /// vector.
+    in_scope_lifetimes: Vec<ParamName>,
 
     current_module: NodeId,
 
@@ -337,49 +340,6 @@
 
     /// Pass responsibility to `resolve_lifetime` code for all cases.
     PassThrough,
-
-    /// Used in the return types of `async fn` where there exists
-    /// exactly one argument-position elided lifetime.
-    ///
-    /// In `async fn`, we lower the arguments types using the `CreateParameter`
-    /// mode, meaning that non-`dyn` elided lifetimes are assigned a fresh name.
-    /// If any corresponding elided lifetimes appear in the output, we need to
-    /// replace them with references to the fresh name assigned to the corresponding
-    /// elided lifetime in the arguments.
-    ///
-    /// For **Modern cases**, replace the anonymous parameter with a
-    /// reference to a specific freshly-named lifetime that was
-    /// introduced in argument
-    ///
-    /// For **Dyn Bound** cases, pass responsibility to
-    /// `resole_lifetime` code.
-    Replace(LtReplacement),
-}
-
-/// The type of elided lifetime replacement to perform on `async fn` return types.
-#[derive(Copy, Clone)]
-enum LtReplacement {
-    /// Fresh name introduced by the single non-dyn elided lifetime
-    /// in the arguments of the async fn.
-    Some(ParamName),
-
-    /// There is no single non-dyn elided lifetime because no lifetimes
-    /// appeared in the arguments.
-    NoLifetimes,
-
-    /// There is no single non-dyn elided lifetime because multiple
-    /// lifetimes appeared in the arguments.
-    MultipleLifetimes,
-}
-
-/// Calculates the `LtReplacement` to use for elided lifetimes in the return
-/// type based on the fresh elided lifetimes introduced in argument position.
-fn get_elided_lt_replacement(arg_position_lifetimes: &[(Span, ParamName)]) -> LtReplacement {
-    match arg_position_lifetimes {
-        [] => LtReplacement::NoLifetimes,
-        [(_span, param)] => LtReplacement::Some(*param),
-        _ => LtReplacement::MultipleLifetimes,
-    }
 }
 
 struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[NodeId; 1]> }
@@ -744,10 +704,9 @@
         span: Span,
         allow_internal_unstable: Option<Lrc<[Symbol]>>,
     ) -> Span {
-        span.fresh_expansion(ExpnId::root(), ExpnInfo {
-            def_site: span,
+        span.fresh_expansion(ExpnData {
             allow_internal_unstable,
-            ..ExpnInfo::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
+            ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
         })
     }
 
@@ -865,7 +824,7 @@
             return;
         }
 
-        if self.in_scope_lifetimes.contains(&ident.modern()) {
+        if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) {
             return;
         }
 
@@ -899,7 +858,7 @@
     {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
-            GenericParamKind::Lifetime { .. } => Some(param.ident.modern()),
+            GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())),
             _ => None,
         });
         self.in_scope_lifetimes.extend(lt_def_names);
@@ -1264,7 +1223,7 @@
                     P(hir::Path {
                         res,
                         segments: hir_vec![hir::PathSegment::from_ident(
-                            Ident::with_empty_ctxt(kw::SelfUpper)
+                            Ident::with_dummy_span(kw::SelfUpper)
                         )],
                         span: t.span,
                     }),
@@ -1598,7 +1557,7 @@
 
                     let (name, kind) = match name {
                         hir::LifetimeName::Underscore => (
-                            hir::ParamName::Plain(Ident::with_empty_ctxt(kw::UnderscoreLifetime)),
+                            hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)),
                             hir::LifetimeParamKind::Elided,
                         ),
                         hir::LifetimeName::Param(param_name) => (
@@ -1953,8 +1912,7 @@
                         err.emit();
                     }
                     AnonymousLifetimeMode::PassThrough |
-                    AnonymousLifetimeMode::ReportError |
-                    AnonymousLifetimeMode::Replace(_) => {
+                    AnonymousLifetimeMode::ReportError => {
                         self.sess.buffer_lint_with_diagnostic(
                             ELIDED_LIFETIMES_IN_PATHS,
                             CRATE_NODE_ID,
@@ -2043,7 +2001,7 @@
                         bindings: hir_vec![
                             hir::TypeBinding {
                                 hir_id: this.next_id(),
-                                ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
+                                ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
                                 kind: hir::TypeBindingKind::Equality {
                                     ty: output
                                         .as_ref()
@@ -2141,7 +2099,6 @@
 
         // Remember how many lifetimes were already around so that we can
         // only look at the lifetime parameters introduced by the arguments.
-        let lifetime_count_before_args = self.lifetimes_to_define.len();
         let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| {
             decl.inputs
                 .iter()
@@ -2156,16 +2113,10 @@
         });
 
         let output = if let Some(ret_id) = make_ret_async {
-            // Calculate the `LtReplacement` to use for any return-position elided
-            // lifetimes based on the elided lifetime parameters introduced in the args.
-            let lt_replacement = get_elided_lt_replacement(
-                &self.lifetimes_to_define[lifetime_count_before_args..]
-            );
             self.lower_async_fn_ret_ty(
                 &decl.output,
                 in_band_ty_params.expect("`make_ret_async` but no `fn_def_id`").0,
                 ret_id,
-                lt_replacement,
             )
         } else {
             match decl.output {
@@ -2230,7 +2181,6 @@
         output: &FunctionRetTy,
         fn_def_id: DefId,
         opaque_ty_node_id: NodeId,
-        elided_lt_replacement: LtReplacement,
     ) -> hir::FunctionRetTy {
         let span = output.span();
 
@@ -2248,9 +2198,65 @@
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
+        // When we create the opaque type for this async fn, it is going to have
+        // to capture all the lifetimes involved in the signature (including in the
+        // return type). This is done by introducing lifetime parameters for:
+        //
+        // - all the explicitly declared lifetimes from the impl and function itself;
+        // - all the elided lifetimes in the fn arguments;
+        // - all the elided lifetimes in the return type.
+        //
+        // So for example in this snippet:
+        //
+        // ```rust
+        // impl<'a> Foo<'a> {
+        //   async fn bar<'b>(&self, x: &'b Vec<f64>, y: &str) -> &u32 {
+        //   //               ^ '0                       ^ '1     ^ '2
+        //   // elided lifetimes used below
+        //   }
+        // }
+        // ```
+        //
+        // we would create an opaque type like:
+        //
+        // ```
+        // type Bar<'a, 'b, '0, '1, '2> = impl Future<Output = &'2 u32>;
+        // ```
+        //
+        // and we would then desugar `bar` to the equivalent of:
+        //
+        // ```rust
+        // impl<'a> Foo<'a> {
+        //   fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_>
+        // }
+        // ```
+        //
+        // Note that the final parameter to `Bar` is `'_`, not `'2` --
+        // this is because the elided lifetimes from the return type
+        // should be figured out using the ordinary elision rules, and
+        // this desugaring achieves that.
+        //
+        // The variable `input_lifetimes_count` tracks the number of
+        // lifetime parameters to the opaque type *not counting* those
+        // lifetimes elided in the return type. This includes those
+        // that are explicitly declared (`in_scope_lifetimes`) and
+        // those elided lifetimes we found in the arguments (current
+        // content of `lifetimes_to_define`). Next, we will process
+        // the return type, which will cause `lifetimes_to_define` to
+        // grow.
+        let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
+
         let (opaque_ty_id, lifetime_params) = self.with_hir_id_owner(opaque_ty_node_id, |this| {
+            // We have to be careful to get elision right here. The
+            // idea is that we create a lifetime parameter for each
+            // lifetime in the return type.  So, given a return type
+            // like `async fn foo(..) -> &[&u32]`, we lower to `impl
+            // Future<Output = &'1 [ &'2 u32 ]>`.
+            //
+            // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
+            // hence the elision takes place at the fn site.
             let future_bound = this.with_anonymous_lifetime_mode(
-                AnonymousLifetimeMode::Replace(elided_lt_replacement),
+                AnonymousLifetimeMode::CreateParameter,
                 |this| this.lower_async_fn_output_type_to_future_bound(
                     output,
                     fn_def_id,
@@ -2267,10 +2273,14 @@
             let lifetime_params: Vec<(Span, ParamName)> =
                 this.in_scope_lifetimes
                     .iter().cloned()
-                    .map(|ident| (ident.span, ParamName::Plain(ident)))
+                    .map(|name| (name.ident().span, name))
                     .chain(this.lifetimes_to_define.iter().cloned())
                     .collect();
 
+            debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes);
+            debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
+            debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
+
             let generic_params =
                 lifetime_params
                     .iter().cloned()
@@ -2304,19 +2314,52 @@
             (opaque_ty_id, lifetime_params)
         });
 
-        let generic_args =
-            lifetime_params
-                .iter().cloned()
-                .map(|(span, hir_name)| {
-                    GenericArg::Lifetime(hir::Lifetime {
-                        hir_id: self.next_id(),
-                        span,
-                        name: hir::LifetimeName::Param(hir_name),
-                    })
+        // As documented above on the variable
+        // `input_lifetimes_count`, we need to create the lifetime
+        // arguments to our opaque type. Continuing with our example,
+        // we're creating the type arguments for the return type:
+        //
+        // ```
+        // Bar<'a, 'b, '0, '1, '_>
+        // ```
+        //
+        // For the "input" lifetime parameters, we wish to create
+        // references to the parameters themselves, including the
+        // "implicit" ones created from parameter types (`'a`, `'b`,
+        // '`0`, `'1`).
+        //
+        // For the "output" lifetime parameters, we just want to
+        // generate `'_`.
+        let mut generic_args: Vec<_> =
+            lifetime_params[..input_lifetimes_count]
+            .iter()
+            .map(|&(span, hir_name)| {
+                // Input lifetime like `'a` or `'1`:
+                GenericArg::Lifetime(hir::Lifetime {
+                    hir_id: self.next_id(),
+                    span,
+                    name: hir::LifetimeName::Param(hir_name),
                 })
-                .collect();
+            })
+            .collect();
+        generic_args.extend(
+            lifetime_params[input_lifetimes_count..]
+            .iter()
+            .map(|&(span, _)| {
+                // Output lifetime like `'_`.
+                GenericArg::Lifetime(hir::Lifetime {
+                    hir_id: self.next_id(),
+                    span,
+                    name: hir::LifetimeName::Implicit,
+                })
+            })
+        );
 
-        let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args);
+        // Create the `Foo<...>` refernece itself. Note that the `type
+        // Foo = impl Trait` is, internally, created as a child of the
+        // async fn, so the *type parameters* are inherited.  It's
+        // only the lifetime parameters that we must supply.
+        let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into());
 
         hir::FunctionRetTy::Return(P(hir::Ty {
             node: opaque_ty_ref,
@@ -2350,7 +2393,7 @@
         let future_params = P(hir::GenericArgs {
             args: hir_vec![],
             bindings: hir_vec![hir::TypeBinding {
-                ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
+                ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
                 kind: hir::TypeBindingKind::Equality {
                     ty: output_ty,
                 },
@@ -2412,11 +2455,6 @@
                     }
 
                     AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
-
-                    AnonymousLifetimeMode::Replace(replacement) => {
-                        let hir_id = self.lower_node_id(l.id);
-                        self.replace_elided_lifetime(hir_id, span, replacement)
-                    }
                 },
             ident => {
                 self.maybe_collect_in_band_lifetime(ident);
@@ -2439,39 +2477,6 @@
         }
     }
 
-    /// Replace a return-position elided lifetime with the elided lifetime
-    /// from the arguments.
-    fn replace_elided_lifetime(
-        &mut self,
-        hir_id: hir::HirId,
-        span: Span,
-        replacement: LtReplacement,
-    ) -> hir::Lifetime {
-        let multiple_or_none = match replacement {
-            LtReplacement::Some(name) => {
-                return hir::Lifetime {
-                    hir_id,
-                    span,
-                    name: hir::LifetimeName::Param(name),
-                };
-            }
-            LtReplacement::MultipleLifetimes => "multiple",
-            LtReplacement::NoLifetimes => "none",
-        };
-
-        let mut err = crate::middle::resolve_lifetime::report_missing_lifetime_specifiers(
-            self.sess,
-            span,
-            1,
-        );
-        err.note(&format!(
-            "return-position elided lifetimes require exactly one \
-             input-position elided lifetime, found {}.", multiple_or_none));
-        err.emit();
-
-        hir::Lifetime { hir_id, span, name: hir::LifetimeName::Error }
-    }
-
     fn lower_generic_params(
         &mut self,
         params: &[GenericParam],
@@ -2685,16 +2690,12 @@
 
                 let fs = fields
                     .iter()
-                    .map(|f| {
-                        Spanned {
-                            span: f.span,
-                            node: hir::FieldPat {
-                                hir_id: self.next_id(),
-                                ident: f.node.ident,
-                                pat: self.lower_pat(&f.node.pat),
-                                is_shorthand: f.node.is_shorthand,
-                            },
-                        }
+                    .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,
                     })
                     .collect();
                 hir::PatKind::Struct(qpath, fs, etc)
@@ -3174,10 +3175,6 @@
             AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
 
             AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
-
-            AnonymousLifetimeMode::Replace(replacement) => {
-                self.new_replacement_lifetime(replacement, span)
-            }
         }
     }
 
@@ -3231,10 +3228,6 @@
             // This is the normal case.
             AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
 
-            AnonymousLifetimeMode::Replace(replacement) => {
-                self.new_replacement_lifetime(replacement, span)
-            }
-
             AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
         }
     }
@@ -3266,25 +3259,11 @@
 
             // This is the normal case.
             AnonymousLifetimeMode::PassThrough => {}
-
-            // We don't need to do any replacement here as this lifetime
-            // doesn't refer to an elided lifetime elsewhere in the function
-            // signature.
-            AnonymousLifetimeMode::Replace(_) => {}
         }
 
         self.new_implicit_lifetime(span)
     }
 
-    fn new_replacement_lifetime(
-        &mut self,
-        replacement: LtReplacement,
-        span: Span,
-    ) -> hir::Lifetime {
-        let hir_id = self.next_id();
-        self.replace_elided_lifetime(hir_id, span, replacement)
-    }
-
     fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
         hir::Lifetime {
             hir_id: self.next_id(),
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index d273006..4ba61e9 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -552,7 +552,7 @@
 
         // let mut pinned = <expr>;
         let expr = P(self.lower_expr(expr));
-        let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
+        let pinned_ident = Ident::with_dummy_span(sym::pinned);
         let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
             span,
             pinned_ident,
@@ -593,7 +593,7 @@
         let loop_node_id = self.sess.next_node_id();
         let loop_hir_id = self.lower_node_id(loop_node_id);
         let ready_arm = {
-            let x_ident = Ident::with_empty_ctxt(sym::result);
+            let x_ident = Ident::with_dummy_span(sym::result);
             let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
             let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
             let ready_pat = self.pat_std_enum(
@@ -677,6 +677,7 @@
         let fn_decl = self.lower_fn_decl(decl, None, false, None);
 
         self.with_new_scopes(|this| {
+            let prev = this.current_item;
             this.current_item = Some(fn_decl_span);
             let mut generator_kind = None;
             let body_id = this.lower_fn_body(decl, |this| {
@@ -690,8 +691,10 @@
                 generator_kind,
                 movability,
             );
+            let capture_clause = this.lower_capture_clause(capture_clause);
+            this.current_item = prev;
             hir::ExprKind::Closure(
-                this.lower_capture_clause(capture_clause),
+                capture_clause,
                 fn_decl,
                 body_id,
                 fn_decl_span,
@@ -1067,9 +1070,9 @@
         );
         head.span = desugared_span;
 
-        let iter = Ident::with_empty_ctxt(sym::iter);
+        let iter = Ident::with_dummy_span(sym::iter);
 
-        let next_ident = Ident::with_empty_ctxt(sym::__next);
+        let next_ident = Ident::with_dummy_span(sym::__next);
         let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
             desugared_span,
             next_ident,
@@ -1078,7 +1081,7 @@
 
         // `::std::option::Option::Some(val) => __next = val`
         let pat_arm = {
-            let val_ident = Ident::with_empty_ctxt(sym::val);
+            let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
             let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
             let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
@@ -1244,7 +1247,7 @@
 
         // `Ok(val) => #[allow(unreachable_code)] val,`
         let ok_arm = {
-            let val_ident = Ident::with_empty_ctxt(sym::val);
+            let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
             let val_expr = P(self.expr_ident_with_attrs(
                 span,
@@ -1260,7 +1263,7 @@
         // `Err(err) => #[allow(unreachable_code)]
         //              return Try::from_error(From::from(err)),`
         let err_arm = {
-            let err_ident = Ident::with_empty_ctxt(sym::err);
+            let err_ident = Ident::with_dummy_span(sym::err);
             let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
             let from_expr = {
                 let from_path = &[sym::convert, sym::From, sym::from];
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 6b717e7..51a0c41 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -60,10 +60,12 @@
     fn visit_item(&mut self, item: &'tcx Item) {
         let mut item_hir_id = None;
         self.lctx.with_hir_id_owner(item.id, |lctx| {
-            if let Some(hir_item) = lctx.lower_item(item) {
-                item_hir_id = Some(hir_item.hir_id);
-                lctx.insert_item(hir_item);
-            }
+            lctx.without_in_scope_lifetime_defs(|lctx| {
+                if let Some(hir_item) = lctx.lower_item(item) {
+                    item_hir_id = Some(hir_item.hir_id);
+                    lctx.insert_item(hir_item);
+                }
+            })
         });
 
         if let Some(hir_id) = item_hir_id {
@@ -123,7 +125,7 @@
             _ => &[],
         };
         let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()),
+            hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()),
             _ => None,
         });
         self.in_scope_lifetimes.extend(lt_def_names);
@@ -134,6 +136,28 @@
         res
     }
 
+    // Clears (and restores) the `in_scope_lifetimes` field. Used when
+    // visiting nested items, which never inherit in-scope lifetimes
+    // from their surrounding environment.
+    fn without_in_scope_lifetime_defs<T>(
+        &mut self,
+        f: impl FnOnce(&mut LoweringContext<'_>) -> T,
+    ) -> T {
+        let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]);
+
+        // this vector is only used when walking over impl headers,
+        // input types, and the like, and should not be non-empty in
+        // between items
+        assert!(self.lifetimes_to_define.is_empty());
+
+        let res = f(self);
+
+        assert!(self.in_scope_lifetimes.is_empty());
+        self.in_scope_lifetimes = old_in_scope_lifetimes;
+
+        res
+    }
+
     pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
         hir::Mod {
             inner: m.inner,
@@ -733,14 +757,12 @@
     }
 
     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
-        Spanned {
-            node: hir::VariantKind {
-                ident: v.node.ident,
-                id: self.lower_node_id(v.node.id),
-                attrs: self.lower_attrs(&v.node.attrs),
-                data: self.lower_variant_data(&v.node.data),
-                disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
-            },
+        hir::Variant {
+            attrs: self.lower_attrs(&v.attrs),
+            data: self.lower_variant_data(&v.data),
+            disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
+            id: self.lower_node_id(v.id),
+            ident: v.ident,
             span: v.span,
         }
     }
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index b6807f7..effe2c0 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -544,11 +544,11 @@
     }
 
     fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
-        self.insert(v.span, v.node.id, Node::Variant(v));
-        self.with_parent(v.node.id, |this| {
+        self.insert(v.span, v.id, Node::Variant(v));
+        self.with_parent(v.id, |this| {
             // Register the constructor of this variant.
-            if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() {
-                this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data));
+            if let Some(ctor_hir_id) = v.data.ctor_hir_id() {
+                this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data));
             }
             intravisit::walk_variant(this, v, g, item_id);
         });
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 2964b13..df9bd3a 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -155,11 +155,11 @@
     }
 
     fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
-        let def = self.create_def(v.node.id,
-                                  DefPathData::TypeNs(v.node.ident.as_interned_str()),
+        let def = self.create_def(v.id,
+                                  DefPathData::TypeNs(v.ident.as_interned_str()),
                                   v.span);
         self.with_parent(def, |this| {
-            if let Some(ctor_hir_id) = v.node.data.ctor_id() {
+            if let Some(ctor_hir_id) = v.data.ctor_id() {
                 this.create_def(ctor_hir_id, DefPathData::Ctor, v.span);
             }
             visit::walk_variant(this, v, g, item_id)
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index b85738d..7292428 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -649,12 +649,34 @@
         }
     }
 
-    pub fn is_const_scope(&self, hir_id: HirId) -> bool {
-        self.walk_parent_nodes(hir_id, |node| match *node {
-            Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true,
-            Node::Item(Item { node: ItemKind::Fn(_, header, _, _), .. }) => header.is_const(),
+    /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
+    /// Used exclusively for diagnostics, to avoid suggestion function calls.
+    pub fn is_const_context(&self, hir_id: HirId) -> bool {
+        let parent_id = self.get_parent_item(hir_id);
+        match self.get(parent_id) {
+            Node::Item(&Item {
+                node: ItemKind::Const(..),
+                ..
+            })
+            | Node::TraitItem(&TraitItem {
+                node: TraitItemKind::Const(..),
+                ..
+            })
+            | Node::ImplItem(&ImplItem {
+                node: ImplItemKind::Const(..),
+                ..
+            })
+            | Node::AnonConst(_)
+            | Node::Item(&Item {
+                node: ItemKind::Static(..),
+                ..
+            }) => true,
+            Node::Item(&Item {
+                node: ItemKind::Fn(_, header, ..),
+                ..
+            }) => header.constness == Constness::Const,
             _ => false,
-        }, |_| false).map(|id| id != CRATE_HIR_ID).unwrap_or(false)
+        }
     }
 
     /// If there is some error when walking the parents (e.g., a node does not
@@ -885,7 +907,7 @@
                     _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id))
                 }
             }
-            Some(Node::Variant(variant)) => &variant.node.data,
+            Some(Node::Variant(variant)) => &variant.data,
             Some(Node::Ctor(data)) => data,
             _ => bug!("expected struct or variant, found {}", self.node_to_string(id))
         }
@@ -918,7 +940,7 @@
             Node::ForeignItem(fi) => fi.ident.name,
             Node::ImplItem(ii) => ii.ident.name,
             Node::TraitItem(ti) => ti.ident.name,
-            Node::Variant(v) => v.node.ident.name,
+            Node::Variant(v) => v.ident.name,
             Node::Field(f) => f.ident.name,
             Node::Lifetime(lt) => lt.name.ident().name,
             Node::GenericParam(param) => param.name.ident().name,
@@ -939,7 +961,7 @@
             Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
             Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]),
             Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]),
-            Some(Node::Variant(ref v)) => Some(&v.node.attrs[..]),
+            Some(Node::Variant(ref v)) => Some(&v.attrs[..]),
             Some(Node::Field(ref f)) => Some(&f.attrs[..]),
             Some(Node::Expr(ref e)) => Some(&*e.attrs),
             Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
@@ -1133,7 +1155,7 @@
 
 impl Named for Item { fn name(&self) -> Name { self.ident.name } }
 impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
-impl Named for VariantKind { fn name(&self) -> Name { self.ident.name } }
+impl Named for Variant { fn name(&self) -> Name { self.ident.name } }
 impl Named for StructField { fn name(&self) -> Name { self.ident.name } }
 impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
 impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
@@ -1310,7 +1332,7 @@
         }
         Some(Node::Variant(ref variant)) => {
             format!("variant {} in {}{}",
-                    variant.node.ident,
+                    variant.ident,
                     path_str(), id_str)
         }
         Some(Node::Field(ref field)) => {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 3d049fe..57fd0be 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -202,7 +202,7 @@
         match *self {
             ParamName::Plain(ident) => ident,
             ParamName::Fresh(_) |
-            ParamName::Error => Ident::with_empty_ctxt(kw::UnderscoreLifetime),
+            ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime),
         }
     }
 
@@ -237,8 +237,8 @@
     pub fn ident(&self) -> Ident {
         match *self {
             LifetimeName::Implicit | LifetimeName::Error => Ident::invalid(),
-            LifetimeName::Underscore => Ident::with_empty_ctxt(kw::UnderscoreLifetime),
-            LifetimeName::Static => Ident::with_empty_ctxt(kw::StaticLifetime),
+            LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
+            LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
             LifetimeName::Param(param_name) => param_name.ident(),
         }
     }
@@ -877,7 +877,7 @@
         match self.node {
             PatKind::Binding(.., Some(ref p)) => p.walk_(it),
             PatKind::Struct(_, ref fields, _) => {
-                fields.iter().all(|field| field.node.pat.walk_(it))
+                fields.iter().all(|field| field.pat.walk_(it))
             }
             PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
                 s.iter().all(|p| p.walk_(it))
@@ -923,6 +923,7 @@
     /// The pattern the field is destructured to.
     pub pat: P<Pat>,
     pub is_shorthand: bool,
+    pub span: Span,
 }
 
 /// Explicit binding annotations given in the HIR for a binding. Note
@@ -968,7 +969,7 @@
 
     /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
     /// The `bool` is `true` in the presence of a `..`.
-    Struct(QPath, HirVec<Spanned<FieldPat>>, bool),
+    Struct(QPath, HirVec<FieldPat>, bool),
 
     /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@@ -1541,7 +1542,7 @@
     Match(P<Expr>, HirVec<Arm>, MatchSource),
     /// A closure (e.g., `move |a, b, c| {a + b + c}`).
     ///
-    /// The final span is the span of the argument block `|...|`.
+    /// The `Span` is the argument block `|...|`.
     ///
     /// This may also be a generator literal or an `async block` as indicated by the
     /// `Option<GeneratorMovability>`.
@@ -2193,7 +2194,7 @@
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct VariantKind {
+pub struct Variant {
     /// Name of the variant.
     #[stable_hasher(project(name))]
     pub ident: Ident,
@@ -2205,10 +2206,10 @@
     pub data: VariantData,
     /// Explicit discriminant (e.g., `Foo = 1`).
     pub disr_expr: Option<AnonConst>,
+    /// Span
+    pub span: Span
 }
 
-pub type Variant = Spanned<VariantKind>;
-
 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum UseKind {
     /// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 11ba512..2fd683e 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -737,7 +737,7 @@
         for v in variants {
             self.space_if_not_bol();
             self.maybe_print_comment(v.span.lo());
-            self.print_outer_attributes(&v.node.attrs);
+            self.print_outer_attributes(&v.attrs);
             self.ibox(INDENT_UNIT);
             self.print_variant(v);
             self.s.word(",");
@@ -829,8 +829,8 @@
     pub fn print_variant(&mut self, v: &hir::Variant) {
         self.head("");
         let generics = hir::Generics::empty();
-        self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false);
-        if let Some(ref d) = v.node.disr_expr {
+        self.print_struct(&v.data, &generics, v.ident.name, v.span, false);
+        if let Some(ref d) = v.disr_expr {
             self.s.space();
             self.word_space("=");
             self.print_anon_const(d);
@@ -1457,7 +1457,7 @@
     }
 
     pub fn print_name(&mut self, name: ast::Name) {
-        self.print_ident(ast::Ident::with_empty_ctxt(name))
+        self.print_ident(ast::Ident::with_dummy_span(name))
     }
 
     pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) {
@@ -1670,14 +1670,14 @@
                                    &fields[..],
                                    |s, f| {
                                        s.cbox(INDENT_UNIT);
-                                       if !f.node.is_shorthand {
-                                           s.print_ident(f.node.ident);
+                                       if !f.is_shorthand {
+                                           s.print_ident(f.ident);
                                            s.word_nbsp(":");
                                        }
-                                       s.print_pat(&f.node.pat);
+                                       s.print_pat(&f.pat);
                                        s.end()
                                    },
-                                   |f| f.node.pat.span);
+                                   |f| f.pat.span);
                 if etc {
                     if !fields.is_empty() {
                         self.word_space(",");
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index ae7d82c..e77faea 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -350,7 +350,7 @@
         let line_col_len = col | line | len;
         std_hash::Hash::hash(&line_col_len, hasher);
 
-        if span.ctxt == SyntaxContext::empty() {
+        if span.ctxt == SyntaxContext::root() {
             TAG_NO_EXPANSION.hash_stable(hcx, hasher);
         } else {
             TAG_EXPANSION.hash_stable(hcx, hasher);
@@ -370,7 +370,7 @@
                 }
 
                 let mut hasher = StableHasher::new();
-                expn_id.expn_info().hash_stable(hcx, &mut hasher);
+                expn_id.expn_data().hash_stable(hcx, &mut hasher);
                 let sub_hash: Fingerprint = hasher.finish();
                 let sub_hash = sub_hash.to_smaller_hash();
                 cache.borrow_mut().insert(expn_id, sub_hash);
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 30d76f2..60b3380 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -153,8 +153,6 @@
     }
 }
 
-impl_stable_hash_for_spanned!(hir::FieldPat);
-
 impl_stable_hash_for_spanned!(hir::BinOpKind);
 
 impl_stable_hash_for!(struct hir::Stmt {
@@ -187,8 +185,6 @@
 
 impl_stable_hash_for_spanned!(usize);
 
-impl_stable_hash_for_spanned!(ast::Ident);
-
 impl_stable_hash_for!(struct ast::Ident {
     name,
     span,
@@ -304,7 +300,7 @@
     }
 }
 
-impl_stable_hash_for_spanned!(hir::VariantKind);
+impl_stable_hash_for_spanned!(hir::Variant);
 
 
 impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 5cc8324..7003f71 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -397,9 +397,10 @@
     Opaque,
 });
 
-impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
-    call_site,
+impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
     kind,
+    parent -> _,
+    call_site,
     def_site,
     default_transparency,
     allow_internal_unstable,
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 770d515..3267505 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -1,5 +1,5 @@
 use crate::hir::def::Namespace;
-use crate::hir::{self, Local, Pat, Body, HirId};
+use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat};
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::infer::InferCtxt;
 use crate::infer::type_variable::TypeVariableOriginKind;
@@ -7,7 +7,7 @@
 use crate::ty::print::Print;
 use syntax::source_map::DesugaringKind;
 use syntax_pos::Span;
-use errors::DiagnosticBuilder;
+use errors::{Applicability, DiagnosticBuilder};
 
 struct FindLocalByTypeVisitor<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
@@ -16,9 +16,26 @@
     found_local_pattern: Option<&'tcx Pat>,
     found_arg_pattern: Option<&'tcx Pat>,
     found_ty: Option<Ty<'tcx>>,
+    found_closure: Option<&'tcx ExprKind>,
 }
 
 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 {
+        Self {
+            infcx,
+            target_ty,
+            hir_map,
+            found_local_pattern: None,
+            found_arg_pattern: None,
+            found_ty: None,
+            found_closure: None,
+        }
+    }
+
     fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
         let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
             tables.borrow().node_type_opt(hir_id)
@@ -72,6 +89,60 @@
         }
         intravisit::walk_body(self, body);
     }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr) {
+        if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = (
+            &expr.node,
+            self.node_matches_type(expr.hir_id),
+        ) {
+            self.found_closure = Some(&expr.node);
+        }
+        intravisit::walk_expr(self, expr);
+    }
+}
+
+/// Suggest giving an appropriate return type to a closure expression.
+fn closure_return_type_suggestion(
+    span: Span,
+    err: &mut DiagnosticBuilder<'_>,
+    output: &FunctionRetTy,
+    body: &Body,
+    name: &str,
+    ret: &str,
+) {
+    let (arrow, post) = match output {
+        FunctionRetTy::DefaultReturn(_) => ("-> ", " "),
+        _ => ("", ""),
+    };
+    let suggestion = match body.value.node {
+        ExprKind::Block(..) => {
+            vec![(output.span(), format!("{}{}{}", arrow, ret, post))]
+        }
+        _ => {
+            vec![
+                (output.span(), format!("{}{}{}{{ ", arrow, ret, post)),
+                (body.value.span.shrink_to_hi(), " }".to_string()),
+            ]
+        }
+    };
+    err.multipart_suggestion(
+        "give this closure an explicit return type without `_` placeholders",
+        suggestion,
+        Applicability::HasPlaceholders,
+    );
+    err.span_label(span, InferCtxt::missing_type_msg(&name));
+}
+
+/// Given a closure signature, return a `String` containing a list of all its argument types.
+fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
+    fn_sig.inputs()
+        .skip_binder()
+        .iter()
+        .next()
+        .map(|args| args.tuple_fields()
+            .map(|arg| arg.to_string())
+            .collect::<Vec<_>>().join(", "))
+        .unwrap_or_default()
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
@@ -106,16 +177,7 @@
         let ty = self.resolve_vars_if_possible(&ty);
         let name = self.extract_type_name(&ty, None);
 
-        let mut err_span = span;
-
-        let mut local_visitor = FindLocalByTypeVisitor {
-            infcx: &self,
-            target_ty: ty,
-            hir_map: &self.tcx.hir(),
-            found_local_pattern: None,
-            found_arg_pattern: None,
-            found_ty: None,
-        };
+        let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir());
         let ty_to_string = |ty: Ty<'tcx>| -> String {
             let mut s = String::new();
             let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
@@ -136,6 +198,31 @@
             let expr = self.tcx.hir().expect_expr(body_id.hir_id);
             local_visitor.visit_expr(expr);
         }
+        let err_span = if let Some(pattern) = local_visitor.found_arg_pattern {
+            pattern.span
+        } else {
+            span
+        };
+
+        let is_named_and_not_impl_trait = |ty: Ty<'_>| {
+            &ty.to_string() != "_" &&
+                // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527
+                (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings)
+        };
+
+        let ty_msg = match local_visitor.found_ty {
+            Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => {
+                let fn_sig = substs.closure_sig(*def_id, self.tcx);
+                let args = closure_args(&fn_sig);
+                let ret = fn_sig.output().skip_binder().to_string();
+                format!(" for the closure `fn({}) -> {}`", args, ret)
+            }
+            Some(ty) if is_named_and_not_impl_trait(ty) => {
+                let ty = ty_to_string(ty);
+                format!(" for `{}`", ty)
+            }
+            _ => String::new(),
+        };
 
         // When `name` corresponds to a type argument, show the path of the full type we're
         // trying to infer. In the following example, `ty_msg` contains
@@ -150,27 +237,58 @@
         //   |         consider giving `b` the explicit type `std::result::Result<i32, E>`, where
         //   |         the type parameter `E` is specified
         // ```
-        let (ty_msg, suffix) = match &local_visitor.found_ty {
-            Some(ty) if &ty.to_string() != "_" && name == "_" => {
-                let ty = ty_to_string(ty);
-                (format!(" for `{}`", ty),
-                 format!("the explicit type `{}`, with the type parameters specified", ty))
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            err_span,
+            E0282,
+            "type annotations needed{}",
+            ty_msg,
+        );
+
+        let suffix = match local_visitor.found_ty {
+            Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => {
+                let fn_sig = substs.closure_sig(*def_id, self.tcx);
+                let ret = fn_sig.output().skip_binder().to_string();
+
+                if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure {
+                    if let Some(body) = self.tcx.hir().krate().bodies.get(body_id) {
+                        closure_return_type_suggestion(
+                            span,
+                            &mut err,
+                            &decl.output,
+                            &body,
+                            &name,
+                            &ret,
+                        );
+                        // We don't want to give the other suggestions when the problem is the
+                        // closure return type.
+                        return err;
+                    }
+                }
+
+                // This shouldn't be reachable, but just in case we leave a reasonable fallback.
+                let args = closure_args(&fn_sig);
+                // This suggestion is incomplete, as the user will get further type inference
+                // errors due to the `_` placeholders and the introduction of `Box`, but it does
+                // nudge them in the right direction.
+                format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret)
             }
-            Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
+            Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => {
                 let ty = ty_to_string(ty);
-                (format!(" for `{}`", ty),
-                 format!(
-                     "the explicit type `{}`, where the type parameter `{}` is specified",
+                format!("the explicit type `{}`, with the type parameters specified", ty)
+            }
+            Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => {
+                let ty = ty_to_string(ty);
+                format!(
+                    "the explicit type `{}`, where the type parameter `{}` is specified",
                     ty,
                     name,
-                 ))
+                )
             }
-            _ => (String::new(), "a type".to_owned()),
+            _ => "a type".to_string(),
         };
-        let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
 
         if let Some(pattern) = local_visitor.found_arg_pattern {
-            err_span = pattern.span;
             // We don't want to show the default label for closures.
             //
             // So, before clearing, the output would look something like this:
@@ -187,39 +305,31 @@
             //          ^ consider giving this closure parameter the type `[_; 0]`
             //            with the type parameter `_` specified
             // ```
-            labels.clear();
-            labels.push((
+            err.span_label(
                 pattern.span,
                 format!("consider giving this closure parameter {}", suffix),
-            ));
+            );
         } else if let Some(pattern) = local_visitor.found_local_pattern {
-            if let Some(simple_ident) = pattern.simple_ident() {
+            let msg = if let Some(simple_ident) = pattern.simple_ident() {
                 match pattern.span.desugaring_kind() {
-                    None => labels.push((
-                        pattern.span,
-                        format!("consider giving `{}` {}", simple_ident, suffix),
-                    )),
-                    Some(DesugaringKind::ForLoop) => labels.push((
-                        pattern.span,
-                        "the element type for this iterator is not specified".to_owned(),
-                    )),
-                    _ => {}
+                    None => {
+                        format!("consider giving `{}` {}", simple_ident, suffix)
+                    }
+                    Some(DesugaringKind::ForLoop) => {
+                        "the element type for this iterator is not specified".to_string()
+                    }
+                    _ => format!("this needs {}", suffix),
                 }
             } else {
-                labels.push((pattern.span, format!("consider giving this pattern {}", suffix)));
-            }
-        };
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            err_span,
-            E0282,
-            "type annotations needed{}",
-            ty_msg,
-        );
-
-        for (target_span, label_message) in labels {
-            err.span_label(target_span, label_message);
+                format!("consider giving this pattern {}", suffix)
+            };
+            err.span_label(pattern.span, msg);
+        }
+        if !err.span.span_labels().iter().any(|span_label| {
+                span_label.label.is_some() && span_label.span == span
+            }) && local_visitor.found_arg_pattern.is_none()
+        { // Avoid multiple labels pointing at `span`.
+            err.span_label(span, InferCtxt::missing_type_msg(&name));
         }
 
         err
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index de81241..6801fa8 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -1060,7 +1060,7 @@
                      v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
-        self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| {
+        self.with_lint_attrs(v.id, &v.attrs, |cx| {
             lint_callback!(cx, check_variant, v, g);
             hir_visit::walk_variant(cx, v, g, item_id);
             lint_callback!(cx, check_variant_post, v, g);
@@ -1236,7 +1236,7 @@
     }
 
     fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) {
-        self.with_lint_attrs(item_id, &v.node.attrs, |cx| {
+        self.with_lint_attrs(item_id, &v.attrs, |cx| {
             run_early_pass!(cx, check_variant, v, g);
             ast_visit::walk_variant(cx, v, g, item_id);
             run_early_pass!(cx, check_variant_post, v, g);
@@ -1345,7 +1345,7 @@
         // part of `walk_mac`, and (b) we should be calling
         // `visit_path`, *but* that would require a `NodeId`, and I
         // want to get #53686 fixed quickly. -nmatsakis
-        ast_visit::walk_path(self, &mac.node.path);
+        ast_visit::walk_path(self, &mac.path);
 
         run_early_pass!(self, check_mac, mac);
     }
@@ -1355,7 +1355,7 @@
     lints: &'a mut [LateLintPassObject],
 }
 
-#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))]
+#[allow(rustc::lint_pass_impl_without_macro)]
 impl LintPass for LateLintPassObjects<'_> {
     fn name(&self) -> &'static str {
         panic!()
@@ -1525,7 +1525,7 @@
     lints: &'a mut [EarlyLintPassObject],
 }
 
-#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))]
+#[allow(rustc::lint_pass_impl_without_macro)]
 impl LintPass for EarlyLintPassObjects<'_> {
     fn name(&self) -> &'static str {
         panic!()
diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs
index 0b514f5..be73b30 100644
--- a/src/librustc/lint/internal.rs
+++ b/src/librustc/lint/internal.rs
@@ -9,7 +9,6 @@
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast::{Ident, Item, ItemKind};
 use syntax::symbol::{sym, Symbol};
-use syntax_pos::ExpnInfo;
 
 declare_tool_lint! {
     pub rustc::DEFAULT_HASH_TYPES,
@@ -23,7 +22,7 @@
 
 impl DefaultHashTypes {
     // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself
-    #[cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
+    #[allow(rustc::default_hash_types)]
     pub fn new() -> Self {
         let mut map = FxHashMap::default();
         map.insert(sym::HashMap, sym::FxHashMap);
@@ -108,7 +107,7 @@
                             .help("try using `Ty` instead")
                             .emit();
                         } else {
-                            if ty.span.ctxt().outer_expn_info().is_some() {
+                            if ty.span.from_expansion() {
                                 return;
                             }
                             if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
@@ -228,30 +227,20 @@
         if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node {
             if let Some(last) = lint_pass.path.segments.last() {
                 if last.ident.name == sym::LintPass {
-                    match &lint_pass.path.span.ctxt().outer_expn_info() {
-                        Some(info) if is_lint_pass_expansion(info) => {}
-                        _ => {
-                            cx.struct_span_lint(
-                                LINT_PASS_IMPL_WITHOUT_MACRO,
-                                lint_pass.path.span,
-                                "implementing `LintPass` by hand",
-                            )
-                            .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
-                            .emit();
-                        }
+                    let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
+                    let call_site = expn_data.call_site;
+                    if expn_data.kind.descr() != sym::impl_lint_pass &&
+                       call_site.ctxt().outer_expn_data().kind.descr() != sym::declare_lint_pass {
+                        cx.struct_span_lint(
+                            LINT_PASS_IMPL_WITHOUT_MACRO,
+                            lint_pass.path.span,
+                            "implementing `LintPass` by hand",
+                        )
+                        .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
+                        .emit();
                     }
                 }
             }
         }
     }
 }
-
-fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool {
-    if expn_info.kind.descr() == sym::impl_lint_pass {
-        true
-    } else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() {
-        info.kind.descr() == sym::declare_lint_pass
-    } else {
-        false
-    }
-}
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 8ddf460..2b58627 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -846,7 +846,7 @@
                      v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
-        self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| {
+        self.with_lint_attrs(v.id, &v.attrs, |builder| {
             intravisit::walk_variant(builder, v, g, item_id);
         })
     }
@@ -885,21 +885,16 @@
 /// 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 info = match span.ctxt().outer_expn_info() {
-        Some(info) => info,
-        // no ExpnInfo means this span doesn't come from a macro
-        None => return false,
-    };
-
-    match info.kind {
+    let expn_data = span.ctxt().outer_expn_data();
+    match expn_data.kind {
         ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
         ExpnKind::Desugaring(_) => true, // well, it's "external"
         ExpnKind::Macro(MacroKind::Bang, _) => {
-            if info.def_site.is_dummy() {
+            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(info.def_site) {
+            match sess.source_map().span_to_snippet(expn_data.def_site) {
                 Ok(code) => !code.starts_with("macro_rules"),
                 // no snippet = external macro or compiler-builtin expansion
                 Err(_) => true,
@@ -911,10 +906,8 @@
 
 /// Returns whether `span` originates in a derive macro's expansion
 pub fn in_derive_expansion(span: Span) -> bool {
-    if let Some(info) = span.ctxt().outer_expn_info() {
-        if let ExpnKind::Macro(MacroKind::Derive, _) = info.kind {
-            return true;
-        }
+    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 d37b236..de84fcd 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -178,8 +178,7 @@
                           -> Result<MetadataRef, String>;
 }
 
-/// A store of Rust crates, through with their metadata
-/// can be accessed.
+/// A store of Rust crates, through which their metadata can be accessed.
 ///
 /// Note that this trait should probably not be expanding today. All new
 /// functionality should be driven through queries instead!
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 55fa261..8ce8bb5 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -17,8 +17,7 @@
 
 use rustc_data_structures::fx::FxHashMap;
 
-use syntax::{ast, source_map};
-use syntax::attr;
+use syntax::{ast, attr};
 use syntax::symbol::sym;
 use syntax_pos;
 
@@ -119,17 +118,16 @@
         }
     }
 
-    fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res,
-                                  pats: &[source_map::Spanned<hir::FieldPat>]) {
+    fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res, pats: &[hir::FieldPat]) {
         let variant = match self.tables.node_type(lhs.hir_id).sty {
             ty::Adt(adt, _) => adt.variant_of_res(res),
             _ => span_bug!(lhs.span, "non-ADT in struct pattern")
         };
         for pat in pats {
-            if let PatKind::Wild = pat.node.pat.node {
+            if let PatKind::Wild = pat.pat.node {
                 continue;
             }
-            let index = self.tcx.field_index(pat.node.hir_id, self.tables);
+            let index = self.tcx.field_index(pat.hir_id, self.tables);
             self.insert_def_id(variant.fields[index].did);
         }
     }
@@ -366,12 +364,12 @@
         match item.node {
             hir::ItemKind::Enum(ref enum_def, _) => {
                 if allow_dead_code {
-                    self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
+                    self.worklist.extend(enum_def.variants.iter().map(|variant| variant.id));
                 }
 
                 for variant in &enum_def.variants {
-                    if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
-                        self.struct_constructors.insert(ctor_hir_id, variant.node.id);
+                    if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
+                        self.struct_constructors.insert(ctor_hir_id, variant.id);
                     }
                 }
             }
@@ -497,7 +495,7 @@
             && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs)
     }
 
-    fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
+    fn should_warn_about_variant(&mut self, variant: &hir::Variant) -> bool {
         !self.symbol_is_live(variant.id)
             && !has_allow_dead_code_or_lang_attr(self.tcx,
                                                  variant.id,
@@ -596,8 +594,8 @@
                      variant: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      id: hir::HirId) {
-        if self.should_warn_about_variant(&variant.node) {
-            self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name,
+        if self.should_warn_about_variant(&variant) {
+            self.warn_dead_code(variant.id, variant.span, variant.ident.name,
                                 "variant", "constructed");
         } else {
             intravisit::walk_variant(self, variant, g, id);
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index daf0d81..9c9e8c0 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -418,8 +418,8 @@
             }
             Struct(_, ref fields, _) => {
                 for field in fields {
-                    if field.node.is_shorthand {
-                        shorthand_field_ids.insert(field.node.pat.hir_id);
+                    if field.is_shorthand {
+                        shorthand_field_ids.insert(field.pat.hir_id);
                     }
                 }
             }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 77d6f39..a55803e 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1282,11 +1282,11 @@
                 };
 
                 for fp in field_pats {
-                    let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2)
-                    let f_index = self.tcx.field_index(fp.node.hir_id, self.tables);
+                    let field_ty = self.pat_ty_adjusted(&fp.pat)?; // see (*2)
+                    let f_index = self.tcx.field_index(fp.hir_id, self.tables);
                     let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index,
-                                                           fp.node.ident, field_ty));
-                    self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
+                                                           fp.ident, field_ty));
+                    self.cat_pattern_(cmt_field, &fp.pat, op)?;
                 }
             }
 
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 76d8a67..c2bcd46 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -33,6 +33,9 @@
     }
 
     match item.node {
+        hir::ItemKind::Fn(_, header, ..) if header.is_const() => {
+            return true;
+        }
         hir::ItemKind::Impl(..) |
         hir::ItemKind::Fn(..) => {
             let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
@@ -52,6 +55,11 @@
     if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
         return true
     }
+    if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.node {
+        if method_sig.header.is_const() {
+            return true
+        }
+    }
     if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_src) {
         match tcx.hir().find(impl_hir_id) {
             Some(Node::Item(item)) =>
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 88c1971..3d100d2 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -1207,7 +1207,7 @@
             PatKind::Binding(hir::BindingAnnotation::RefMut, ..) => true,
 
             PatKind::Struct(_, ref field_pats, _) => {
-                field_pats.iter().any(|fp| is_binding_pat(&fp.node.pat))
+                field_pats.iter().any(|fp| is_binding_pat(&fp.pat))
             }
 
             PatKind::Slice(ref pats1, ref pats2, ref pats3) => {
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 5ab762a..d02259b 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -290,10 +290,10 @@
     }
 
     fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
-        self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required,
+        self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required,
             |v| {
-                if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() {
-                    v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required,
+                if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
+                    v.annotate(ctor_hir_id, &var.attrs, var.span, AnnotationKind::Required,
                                |_| {});
                 }
 
@@ -372,7 +372,7 @@
     }
 
     fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
-        self.check_missing_stability(var.node.id, var.span, "variant");
+        self.check_missing_stability(var.id, var.span, "variant");
         intravisit::walk_variant(self, var, g, item_id);
     }
 
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs
index 0a99851..b55e6bc 100644
--- a/src/librustc/mir/interpret/pointer.rs
+++ b/src/librustc/mir/interpret/pointer.rs
@@ -189,8 +189,11 @@
         Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
     }
 
+    /// Test if the pointer is "inbounds" of an allocation of the given size.
+    /// A pointer is "inbounds" even if its offset is equal to the size; this is
+    /// a "one-past-the-end" pointer.
     #[inline(always)]
-    pub fn check_in_alloc(
+    pub fn check_inbounds_alloc(
         self,
         allocation_size: Size,
         msg: CheckInAllocMsg,
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 1e2ec08..11701a6 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2197,7 +2197,6 @@
         let ty = tcx.type_of(def_id).subst(tcx, substs);
         Operand::Constant(box Constant {
             span,
-            ty,
             user_ty: None,
             literal: ty::Const::zero_sized(tcx, ty),
         })
@@ -2476,7 +2475,6 @@
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
 pub struct Constant<'tcx> {
     pub span: Span,
-    pub ty: Ty<'tcx>,
 
     /// Optional user-given type: for something like
     /// `collect::<Vec<_>>`, this would be present and would
@@ -3385,12 +3383,11 @@
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         Constant {
             span: self.span.clone(),
-            ty: self.ty.fold_with(folder),
             user_ty: self.user_ty.fold_with(folder),
             literal: self.literal.fold_with(folder),
         }
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
+        self.literal.visit_with(visitor)
     }
 }
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index f888938..e9f7636 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -252,7 +252,7 @@
         match self {
             &Operand::Copy(ref l) |
             &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
-            &Operand::Constant(ref c) => c.ty,
+            &Operand::Constant(ref c) => c.literal.ty,
         }
     }
 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index ee4ecb6..2d16e7b 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -782,13 +782,11 @@
                               location: Location) {
                 let Constant {
                     span,
-                    ty,
                     user_ty,
                     literal,
                 } = constant;
 
                 self.visit_span(span);
-                self.visit_ty(ty, TyContext::Location(location));
                 drop(user_ty); // no visit method for this
                 self.visit_const(literal, location);
             }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 3536b2a..8e3b910 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -395,7 +395,7 @@
         output_types: OutputTypes [TRACKED],
         search_paths: Vec<SearchPath> [UNTRACKED],
         libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
-        maybe_sysroot: Option<PathBuf> [TRACKED],
+        maybe_sysroot: Option<PathBuf> [UNTRACKED],
 
         target_triple: TargetTriple [TRACKED],
 
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 83bd5c5..ba92e85 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -36,7 +36,7 @@
 use std::fmt;
 use syntax::ast;
 use syntax::symbol::sym;
-use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnKind};
+use syntax_pos::{DUMMY_SP, Span, ExpnKind};
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn report_fulfillment_errors(&self,
@@ -61,9 +61,9 @@
             // We want to ignore desugarings here: spans are equivalent even
             // if one is the result of a desugaring and the other is not.
             let mut span = error.obligation.cause.span;
-            if let Some(ExpnInfo { kind: ExpnKind::Desugaring(_), def_site, .. })
-                    = span.ctxt().outer_expn_info() {
-                span = def_site;
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(_) = expn_data.kind {
+                span = expn_data.call_site;
             }
 
             error_map.entry(span).or_default().push(
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 38263f2..72df45d 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1417,7 +1417,7 @@
                 projection_ty: ty::ProjectionTy::from_ref_and_name(
                     tcx,
                     trait_ref,
-                    Ident::with_empty_ctxt(FN_OUTPUT_NAME),
+                    Ident::with_dummy_span(FN_OUTPUT_NAME),
                 ),
                 ty: ret_type
             }
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index e3c6eca..1ddc678 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -27,7 +27,7 @@
     fn variant(&self) -> &Self::Variant;
 }
 
-#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+#[allow(rustc::usage_of_ty_tykind)]
 impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
     type Variant = ty::TyKind<'tcx>;
     fn variant(&self) -> &Self::Variant {
@@ -160,7 +160,7 @@
     Ok(decoder.map_encoded_cnum_to_current(cnum))
 }
 
-#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+#[allow(rustc::usage_of_ty_tykind)]
 #[inline]
 pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
 where
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index ef74d9e..d504ba4 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -130,7 +130,7 @@
     }
 
     /// Intern a type
-    #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+    #[allow(rustc::usage_of_ty_tykind)]
     #[inline(never)]
     fn intern_ty(&self,
         st: TyKind<'tcx>
@@ -2076,7 +2076,7 @@
     }
 }
 
-#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+#[allow(rustc::usage_of_ty_tykind)]
 impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> {
     fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> {
         &self.0.sty
@@ -2291,7 +2291,7 @@
         self.mk_fn_ptr(converted_sig)
     }
 
-    #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+    #[allow(rustc::usage_of_ty_tykind)]
     #[inline]
     pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> {
         self.interners.intern_ty(st)
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 411b18e..9119505 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -18,7 +18,7 @@
         }
     }
 
-    #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+    #[allow(rustc::usage_of_ty_tykind)]
     pub fn for_sty(st: &ty::TyKind<'_>) -> FlagComputation {
         let mut result = FlagComputation::new();
         result.add_sty(st);
@@ -62,7 +62,7 @@
         } // otherwise, this binder captures nothing
     }
 
-    #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+    #[allow(rustc::usage_of_ty_tykind)]
     fn add_sty(&mut self, st: &ty::TyKind<'_>) {
         match st {
             &ty::Bool |
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 9d563e2..a8ff36a 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -483,7 +483,7 @@
     }
 }
 
-#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+#[allow(rustc::usage_of_ty_tykind)]
 pub struct TyS<'tcx> {
     pub sty: TyKind<'tcx>,
     pub flags: TypeFlags,
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 00871a1cb..8bf0197 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -23,16 +23,16 @@
 use syntax::ast::NodeId;
 use syntax::source_map::{SourceMap, StableSourceFileId};
 use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile};
-use syntax_pos::hygiene::{ExpnId, SyntaxContext, ExpnInfo};
+use syntax_pos::hygiene::{ExpnId, SyntaxContext, ExpnData};
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 
 const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
 const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
 
-const TAG_NO_EXPANSION_INFO: u8 = 0;
-const TAG_EXPANSION_INFO_SHORTHAND: u8 = 1;
-const TAG_EXPANSION_INFO_INLINE: u8 = 2;
+const TAG_NO_EXPN_DATA: u8 = 0;
+const TAG_EXPN_DATA_SHORTHAND: u8 = 1;
+const TAG_EXPN_DATA_INLINE: u8 = 2;
 
 const TAG_VALID_SPAN: u8 = 0;
 const TAG_INVALID_SPAN: u8 = 1;
@@ -58,7 +58,7 @@
 
     // These two fields caches that are populated lazily during decoding.
     file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
-    synthetic_expansion_infos: Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
+    synthetic_syntax_contexts: Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
 
     // A map from dep-node to the position of the cached query result in
     // `serialized_data`.
@@ -135,7 +135,7 @@
             current_diagnostics: Default::default(),
             query_result_index: footer.query_result_index.into_iter().collect(),
             prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
-            synthetic_expansion_infos: Default::default(),
+            synthetic_syntax_contexts: Default::default(),
             alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
         }
     }
@@ -151,7 +151,7 @@
             current_diagnostics: Default::default(),
             query_result_index: Default::default(),
             prev_diagnostics_index: Default::default(),
-            synthetic_expansion_infos: Default::default(),
+            synthetic_syntax_contexts: Default::default(),
             alloc_decoding_state: AllocDecodingState::new(Vec::new()),
         }
     }
@@ -185,7 +185,7 @@
                 encoder,
                 type_shorthands: Default::default(),
                 predicate_shorthands: Default::default(),
-                expn_info_shorthands: Default::default(),
+                expn_data_shorthands: Default::default(),
                 interpret_allocs: Default::default(),
                 interpret_allocs_inverse: Vec::new(),
                 source_map: CachingSourceMapView::new(tcx.sess.source_map()),
@@ -383,7 +383,7 @@
             cnum_map: self.cnum_map.get(),
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
-            synthetic_expansion_infos: &self.synthetic_expansion_infos,
+            synthetic_syntax_contexts: &self.synthetic_syntax_contexts,
             alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
         };
 
@@ -440,7 +440,7 @@
     opaque: opaque::Decoder<'a>,
     source_map: &'a SourceMap,
     cnum_map: &'a IndexVec<CrateNum, Option<CrateNum>>,
-    synthetic_expansion_infos: &'a Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
+    synthetic_syntax_contexts: &'a Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
     file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
     file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, StableSourceFileId>,
     alloc_decoding_session: AllocDecodingSession<'a>,
@@ -586,37 +586,37 @@
         let lo = file_lo.lines[line_lo - 1] + col_lo;
         let hi = lo + len;
 
-        let expn_info_tag = u8::decode(self)?;
+        let expn_data_tag = u8::decode(self)?;
 
-        // FIXME(mw): This method does not restore `InternalExpnData::parent` or
+        // FIXME(mw): This method does not restore `ExpnData::parent` or
         // `SyntaxContextData::prev_ctxt` or `SyntaxContextData::opaque`. These things
         // don't seem to be used after HIR lowering, so everything should be fine
         // as long as incremental compilation does not kick in before that.
-        let location = || Span::new(lo, hi, SyntaxContext::empty());
-        let recover_from_expn_info = |this: &Self, expn_info, pos| {
-            let span = location().fresh_expansion(ExpnId::root(), expn_info);
-            this.synthetic_expansion_infos.borrow_mut().insert(pos, span.ctxt());
+        let location = || Span::with_root_ctxt(lo, hi);
+        let recover_from_expn_data = |this: &Self, expn_data, pos| {
+            let span = location().fresh_expansion(expn_data);
+            this.synthetic_syntax_contexts.borrow_mut().insert(pos, span.ctxt());
             span
         };
-        Ok(match expn_info_tag {
-            TAG_NO_EXPANSION_INFO => {
+        Ok(match expn_data_tag {
+            TAG_NO_EXPN_DATA => {
                 location()
             }
-            TAG_EXPANSION_INFO_INLINE => {
-                let expn_info = Decodable::decode(self)?;
-                recover_from_expn_info(
-                    self, expn_info, AbsoluteBytePos::new(self.opaque.position())
+            TAG_EXPN_DATA_INLINE => {
+                let expn_data = Decodable::decode(self)?;
+                recover_from_expn_data(
+                    self, expn_data, AbsoluteBytePos::new(self.opaque.position())
                 )
             }
-            TAG_EXPANSION_INFO_SHORTHAND => {
+            TAG_EXPN_DATA_SHORTHAND => {
                 let pos = AbsoluteBytePos::decode(self)?;
-                let cached_ctxt = self.synthetic_expansion_infos.borrow().get(&pos).cloned();
+                let cached_ctxt = self.synthetic_syntax_contexts.borrow().get(&pos).cloned();
                 if let Some(ctxt) = cached_ctxt {
                     Span::new(lo, hi, ctxt)
                 } else {
-                    let expn_info =
-                        self.with_position(pos.to_usize(), |this| ExpnInfo::decode(this))?;
-                    recover_from_expn_info(self, expn_info, pos)
+                    let expn_data =
+                        self.with_position(pos.to_usize(), |this| ExpnData::decode(this))?;
+                    recover_from_expn_data(self, expn_data, pos)
                 }
             }
             _ => {
@@ -725,7 +725,7 @@
     encoder: &'a mut E,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
-    expn_info_shorthands: FxHashMap<ExpnId, AbsoluteBytePos>,
+    expn_data_shorthands: FxHashMap<ExpnId, AbsoluteBytePos>,
     interpret_allocs: FxHashMap<interpret::AllocId, usize>,
     interpret_allocs_inverse: Vec<interpret::AllocId>,
     source_map: CachingSourceMapView<'tcx>,
@@ -816,22 +816,18 @@
         col_lo.encode(self)?;
         len.encode(self)?;
 
-        if span_data.ctxt == SyntaxContext::empty() {
-            TAG_NO_EXPANSION_INFO.encode(self)
+        if span_data.ctxt == SyntaxContext::root() {
+            TAG_NO_EXPN_DATA.encode(self)
         } else {
-            let (expn_id, expn_info) = span_data.ctxt.outer_expn_with_info();
-            if let Some(expn_info) = expn_info {
-                if let Some(pos) = self.expn_info_shorthands.get(&expn_id).cloned() {
-                    TAG_EXPANSION_INFO_SHORTHAND.encode(self)?;
-                    pos.encode(self)
-                } else {
-                    TAG_EXPANSION_INFO_INLINE.encode(self)?;
-                    let pos = AbsoluteBytePos::new(self.position());
-                    self.expn_info_shorthands.insert(expn_id, pos);
-                    expn_info.encode(self)
-                }
+            let (expn_id, expn_data) = span_data.ctxt.outer_expn_with_data();
+            if let Some(pos) = self.expn_data_shorthands.get(&expn_id).cloned() {
+                TAG_EXPN_DATA_SHORTHAND.encode(self)?;
+                pos.encode(self)
             } else {
-                TAG_NO_EXPANSION_INFO.encode(self)
+                TAG_EXPN_DATA_INLINE.encode(self)?;
+                let pos = AbsoluteBytePos::new(self.position());
+                self.expn_data_shorthands.insert(expn_id, pos);
+                expn_data.encode(self)
             }
         }
     }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 129ea9b..42390c2 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1,6 +1,6 @@
 //! This module contains `TyKind` and its major components.
 
-#![cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+#![allow(rustc::usage_of_ty_tykind)]
 
 use crate::hir;
 use crate::hir::def_id::DefId;
@@ -2068,6 +2068,9 @@
             Error => {  // ignore errors (#54954)
                 ty::Binder::dummy(FnSig::fake())
             }
+            Closure(..) => bug!(
+                "to get the signature of a closure, use `closure_sig()` not `fn_sig()`",
+            ),
             _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
         }
     }
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index a9b8962..9483ffc 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -328,7 +328,7 @@
             },
             "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
             "bitreverse" | "add_with_overflow" | "sub_with_overflow" |
-            "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
+            "mul_with_overflow" | "wrapping_add" | "wrapping_sub" | "wrapping_mul" |
             "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" |
             "unchecked_add" | "unchecked_sub" | "unchecked_mul" | "exact_div" |
             "rotate_left" | "rotate_right" | "saturating_add" | "saturating_sub" => {
@@ -398,9 +398,9 @@
 
                                 return;
                             },
-                            "overflowing_add" => self.add(args[0].immediate(), args[1].immediate()),
-                            "overflowing_sub" => self.sub(args[0].immediate(), args[1].immediate()),
-                            "overflowing_mul" => self.mul(args[0].immediate(), args[1].immediate()),
+                            "wrapping_add" => self.add(args[0].immediate(), args[1].immediate()),
+                            "wrapping_sub" => self.sub(args[0].immediate(), args[1].immediate()),
+                            "wrapping_mul" => self.mul(args[0].immediate(), args[1].immediate()),
                             "exact_div" =>
                                 if signed {
                                     self.exactsdiv(args[0].immediate(), args[1].immediate())
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 8fb0828..8603d61 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -32,6 +32,7 @@
 use std::process::{Output, Stdio, ExitStatus};
 use std::str;
 use std::env;
+use std::ffi::OsString;
 
 pub use rustc_codegen_utils::link::*;
 
@@ -158,6 +159,36 @@
         }
     };
 
+    // UWP apps have API restrictions enforced during Store submissions.
+    // To comply with the Windows App Certification Kit,
+    // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
+    let t = &sess.target.target;
+    if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" {
+        if let Some(ref tool) = msvc_tool {
+            let original_path = tool.path();
+            if let Some(ref root_lib_path) = original_path.ancestors().skip(4).next() {
+                let arch = match t.arch.as_str() {
+                    "x86_64" => Some("x64".to_string()),
+                    "x86" => Some("x86".to_string()),
+                    "aarch64" => Some("arm64".to_string()),
+                    _ => None,
+                };
+                if let Some(ref a) = arch {
+                    let mut arg = OsString::from("/LIBPATH:");
+                    arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a.to_string()));
+                    cmd.arg(&arg);
+                }
+                else {
+                    warn!("arch is not supported");
+                }
+            } else {
+                warn!("MSVC root path lib location not found");
+            }
+        } else {
+            warn!("link.exe not found");
+        }
+    }
+
     // The compiler's sysroot often has some bundled tools, so add it to the
     // PATH for the child.
     let mut new_path = sess.host_filesearch(PathKind::All)
@@ -1027,6 +1058,7 @@
     let t = &sess.target.target;
 
     cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
+
     for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
         cmd.add_object(obj);
     }
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index c9e4663..eec0984 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1775,10 +1775,7 @@
                     }
                 }
                 Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => {
-                    match ExpnId::from_u32(cookie).expn_info() {
-                        Some(ei) => sess.span_err(ei.call_site, &msg),
-                        None     => sess.err(&msg),
-                    }
+                    sess.span_err(ExpnId::from_u32(cookie).expn_data().call_site, &msg)
                 }
                 Ok(SharedEmitterMessage::AbortIfErrors) => {
                     sess.abort_if_errors();
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index cc0c733..e63f1b9 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -221,7 +221,7 @@
             mir::TerminatorKind::Call {
                 func: mir::Operand::Constant(ref c),
                 ref args, ..
-            } => match c.ty.sty {
+            } => match c.literal.ty.sty {
                 ty::FnDef(did, _) => Some((did, args)),
                 _ => None,
             },
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index ce98979..dbce5ce 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -651,7 +651,7 @@
                             let (llval, ty) = self.simd_shuffle_indices(
                                 &bx,
                                 constant.span,
-                                constant.ty,
+                                constant.literal.ty,
                                 c,
                             );
                             return OperandRef {
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index e7517d6..32bcdeb 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -8,7 +8,7 @@
 use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext};
 use crate::traits::*;
 
-use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
+use syntax_pos::{DUMMY_SP, BytePos, Span};
 use syntax::symbol::kw;
 
 use std::iter;
@@ -120,7 +120,7 @@
         // In order to have a good line stepping behavior in debugger, we overwrite debug
         // locations of macro expansions with that of the outermost expansion site
         // (unless the crate is being compiled with `-Z debug-macros`).
-        if source_info.span.ctxt() == NO_EXPANSION ||
+        if !source_info.span.from_expansion() ||
            self.cx.sess().opts.debugging_opts.debug_macros {
             let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
             (scope, source_info.span)
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 5e5804b..254b73d 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -466,7 +466,6 @@
             }
 
             mir::Operand::Constant(ref constant) => {
-                let ty = self.monomorphize(&constant.ty);
                 self.eval_mir_constant(constant)
                     .map(|c| OperandRef::from_const(bx, c))
                     .unwrap_or_else(|err| {
@@ -481,6 +480,7 @@
                         // the above error (or silence it under some conditions) will not cause UB
                         bx.abort();
                         // We've errored, so we don't have to produce working code.
+                        let ty = self.monomorphize(&constant.literal.ty);
                         let layout = bx.cx().layout_of(ty);
                         bx.load_operand(PlaceRef::new_sized(
                             bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))),
diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml
index d93589e..89b50c5 100644
--- a/src/librustc_codegen_utils/Cargo.toml
+++ b/src/librustc_codegen_utils/Cargo.toml
@@ -13,7 +13,7 @@
 flate2 = "1.0"
 log = "0.4"
 punycode = "0.4.0"
-rustc-demangle = "0.1.15"
+rustc-demangle = "0.1.16"
 
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs
index 47601da..8d6a1d7 100644
--- a/src/librustc_codegen_utils/symbol_names/v0.rs
+++ b/src/librustc_codegen_utils/symbol_names/v0.rs
@@ -198,10 +198,14 @@
 
         let lifetimes = regions.into_iter().map(|br| {
             match br {
-                ty::BrAnon(i) => i + 1,
+                ty::BrAnon(i) => {
+                    // FIXME(eddyb) for some reason, `anonymize_late_bound_regions` starts at `1`.
+                    assert_ne!(i, 0);
+                    i - 1
+                },
                 _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
             }
-        }).max().unwrap_or(0);
+        }).max().map_or(0, |max| max + 1);
 
         self.push_opt_integer_62("G", lifetimes as u64);
         lifetime_depths.end += lifetimes;
@@ -297,6 +301,10 @@
             // Late-bound lifetimes use indices starting at 1,
             // see `BinderLevel` for more details.
             ty::ReLateBound(debruijn, ty::BrAnon(i)) => {
+                // FIXME(eddyb) for some reason, `anonymize_late_bound_regions` starts at `1`.
+                assert_ne!(i, 0);
+                let i = i - 1;
+
                 let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
                 let depth = binder.lifetime_depths.start + i;
 
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 9f10343..f759350 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -27,7 +27,7 @@
 
 #![cfg_attr(unix, feature(libc))]
 
-#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
+#![allow(rustc::default_hash_types)]
 
 #[macro_use]
 extern crate log;
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index e9d85a5..fdd0773 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -678,7 +678,7 @@
 
                     let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| {
                         let gated_cfg = GatedCfg::gate(&ast::MetaItem {
-                            path: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)),
+                            path: ast::Path::from_ident(ast::Ident::with_dummy_span(name)),
                             node: ast::MetaItemKind::Word,
                             span: DUMMY_SP,
                         });
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index 96a9b6c..255af31 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -148,7 +148,7 @@
     /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
     fn annotation_type_for_level(level: Level) -> AnnotationType {
         match level {
-            Level::Bug | Level::Fatal | Level::PhaseFatal | Level::Error => AnnotationType::Error,
+            Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
             Level::Warning => AnnotationType::Warning,
             Level::Note => AnnotationType::Note,
             Level::Help => AnnotationType::Help,
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 424d7c0..3f1b912 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -94,7 +94,6 @@
         match self.level {
             Level::Bug |
             Level::Fatal |
-            Level::PhaseFatal |
             Level::Error |
             Level::FailureNote => {
                 true
@@ -120,6 +119,9 @@
     }
 
     /// Adds a span/label to be included in the resulting snippet.
+    /// This label will be shown together with the original span/label used when creating the
+    /// diagnostic, *not* a span added by one of the `span_*` methods.
+    ///
     /// This is pushed onto the `MultiSpan` that was created when the
     /// diagnostic was first built. If you don't call this function at
     /// all, and you just supplied a `Span` to create the diagnostic,
@@ -196,6 +198,7 @@
         self
     }
 
+    /// Prints the span with a note above it.
     pub fn span_note<S: Into<MultiSpan>>(&mut self,
                                          sp: S,
                                          msg: &str)
@@ -209,6 +212,7 @@
         self
     }
 
+    /// Prints the span with a warn above it.
     pub fn span_warn<S: Into<MultiSpan>>(&mut self,
                                          sp: S,
                                          msg: &str)
@@ -222,6 +226,7 @@
         self
     }
 
+    /// Prints the span with some help above it.
     pub fn span_help<S: Into<MultiSpan>>(&mut self,
                                          sp: S,
                                          msg: &str)
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 3b6a6a8..4018a66 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -43,8 +43,7 @@
                  SourceFile,
                  FileName,
                  MultiSpan,
-                 Span,
-                 NO_EXPANSION};
+                 Span};
 
 /// Indicates the confidence in the correctness of a suggestion.
 ///
@@ -189,7 +188,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 bounding_span = Span::new(lo, hi, NO_EXPANSION);
+            let bounding_span = Span::with_root_ctxt(lo, hi);
             let lines = cm.span_to_lines(bounding_span).unwrap();
             assert!(!lines.lines.is_empty());
 
@@ -787,9 +786,6 @@
 pub enum Level {
     Bug,
     Fatal,
-    // An error which while not immediately fatal, should stop the compiler
-    // progressing beyond the current phase.
-    PhaseFatal,
     Error,
     Warning,
     Note,
@@ -808,7 +804,7 @@
     fn color(self) -> ColorSpec {
         let mut spec = ColorSpec::new();
         match self {
-            Bug | Fatal | PhaseFatal | Error => {
+            Bug | Fatal | Error => {
                 spec.set_fg(Some(Color::Red))
                     .set_intense(true);
             }
@@ -833,7 +829,7 @@
     pub fn to_str(self) -> &'static str {
         match self {
             Bug => "error: internal compiler error",
-            Fatal | PhaseFatal | Error => "error",
+            Fatal | Error => "error",
             Warning => "warning",
             Note => "note",
             Help => "help",
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 13ec27a..8216008 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -21,6 +21,8 @@
 //! 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 rustc::hir::def::{Res, DefKind};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx};
@@ -40,7 +42,7 @@
 use syntax::edition::Edition;
 use syntax::feature_gate::{self, AttributeGate, AttributeType};
 use syntax::feature_gate::{Stability, deprecated_attributes};
-use syntax_pos::{BytePos, Span, SyntaxContext};
+use syntax_pos::{BytePos, Span};
 use syntax::symbol::{Symbol, kw, sym};
 use syntax::errors::{Applicability, DiagnosticBuilder};
 use syntax::print::pprust::expr_to_string;
@@ -76,7 +78,7 @@
         if let ast::ExprKind::While(cond, ..) = &e.node {
             if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).node {
                 if let ast::LitKind::Bool(true) = lit.node {
-                    if lit.span.ctxt() == SyntaxContext::empty() {
+                    if !lit.span.from_expansion() {
                         let msg = "denote infinite loops with `loop { ... }`";
                         let condition_span = cx.sess.source_map().def_span(e.span);
                         cx.struct_span_lint(WHILE_TRUE, condition_span, msg)
@@ -162,18 +164,18 @@
                                    .expect("struct pattern type is not an ADT")
                                    .variant_of_res(cx.tables.qpath_res(qpath, pat.hir_id));
             for fieldpat in field_pats {
-                if fieldpat.node.is_shorthand {
+                if fieldpat.is_shorthand {
                     continue;
                 }
-                if fieldpat.span.ctxt().outer_expn_info().is_some() {
+                if fieldpat.span.from_expansion() {
                     // Don't lint if this is a macro expansion: macro authors
                     // shouldn't have to worry about this kind of style issue
                     // (Issue #49588)
                     continue;
                 }
-                if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
+                if let PatKind::Binding(_, _, ident, None) = fieldpat.pat.node {
                     if cx.tcx.find_field_index(ident, &variant) ==
-                       Some(cx.tcx.field_index(fieldpat.node.hir_id, cx.tables)) {
+                       Some(cx.tcx.field_index(fieldpat.hir_id, cx.tables)) {
                         let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
                                      fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant", ident));
@@ -482,8 +484,8 @@
 
     fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) {
         self.check_missing_docs_attrs(cx,
-                                      Some(v.node.id),
-                                      &v.node.attrs,
+                                      Some(v.id),
+                                      &v.attrs,
                                       v.span,
                                       "a variant");
     }
@@ -1010,7 +1012,7 @@
         let mut applicability = Applicability::MachineApplicable;
         match vis.node {
             hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => {
-                if span.ctxt().outer_expn_info().is_some() {
+                if span.from_expansion() {
                     applicability = Applicability::MaybeIncorrect;
                 }
                 let def_span = cx.tcx.sess.source_map().def_span(span);
@@ -1491,7 +1493,7 @@
         self.check_tokens(cx, mac_def.stream());
     }
     fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
-        self.check_tokens(cx, mac.node.tts.clone().into());
+        self.check_tokens(cx, mac.tts.clone().into());
     }
     fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
         self.check_ident_token(cx, UnderMacro(false), ident);
@@ -1877,41 +1879,57 @@
         const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed];
         const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized];
 
-        /// Return `false` only if we are sure this type does *not*
+        /// Information about why a type cannot be initialized this way.
+        /// Contains an error message and optionally a span to point at.
+        type InitError = (String, Option<Span>);
+
+        /// Return `Some` only if we are sure this type does *not*
         /// allow zero initialization.
-        fn ty_maybe_allows_zero_init<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
+        fn ty_find_init_error<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<InitError> {
             use rustc::ty::TyKind::*;
             match ty.sty {
                 // Primitive types that don't like 0 as a value.
-                Ref(..) | FnPtr(..) | Never => false,
-                Adt(..) if ty.is_box() => false,
+                Ref(..) => Some((format!("References must be non-null"), None)),
+                Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)),
+                FnPtr(..) => Some((format!("Function pointers must be non-null"), None)),
+                Never => Some((format!("The never type (`!`) has no valid value"), None)),
                 // Recurse for some compound types.
                 Adt(adt_def, substs) if !adt_def.is_union() => {
                     match adt_def.variants.len() {
-                        0 => false, // Uninhabited enum!
+                        0 => Some((format!("0-variant enums have no valid value"), None)),
                         1 => {
                             // Struct, or enum with exactly one variant.
                             // Proceed recursively, check all fields.
                             let variant = &adt_def.variants[VariantIdx::from_u32(0)];
-                            variant.fields.iter().all(|field| {
-                                ty_maybe_allows_zero_init(
+                            variant.fields.iter().find_map(|field| {
+                                ty_find_init_error(
                                     tcx,
                                     field.ty(tcx, substs),
-                                )
+                                ).map(|(mut msg, span)| if span.is_none() {
+                                    // Point to this field, should be helpful for figuring
+                                    // out where the source of the error is.
+                                    let span = tcx.def_span(field.did);
+                                    write!(&mut msg, " (in this {} field)", adt_def.descr())
+                                        .unwrap();
+                                    (msg, Some(span))
+                                } else {
+                                    // Just forward.
+                                    (msg, span)
+                                })
                             })
                         }
-                        _ => true, // Conservative fallback for multi-variant enum.
+                        _ => None, // Conservative fallback for multi-variant enum.
                     }
                 }
                 Tuple(..) => {
                     // Proceed recursively, check all fields.
-                    ty.tuple_fields().all(|field| ty_maybe_allows_zero_init(tcx, field))
+                    ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field))
                 }
                 // FIXME: Would be nice to also warn for `NonNull`/`NonZero*`.
                 // FIXME: *Only for `mem::uninitialized`*, we could also warn for `bool`,
                 //        `char`, and any multivariant enum.
                 // Conservative fallback.
-                _ => true,
+                _ => None,
             }
         }
 
@@ -1925,9 +1943,8 @@
                         // using zeroed or uninitialized memory.
                         // We are extremely conservative with what we warn about.
                         let conjured_ty = cx.tables.expr_ty(expr);
-
-                        if !ty_maybe_allows_zero_init(cx.tcx, conjured_ty) {
-                            cx.struct_span_lint(
+                        if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty) {
+                            let mut err = cx.struct_span_lint(
                                 INVALID_VALUE,
                                 expr.span,
                                 &format!(
@@ -1939,11 +1956,16 @@
                                         "being left uninitialized"
                                     }
                                 ),
-                            )
-                            .note("this means that this code causes undefined behavior \
-                                when executed")
-                            .help("use `MaybeUninit` instead")
-                            .emit();
+                            );
+                            err.span_label(expr.span,
+                                "this code causes undefined behavior when executed");
+                            err.span_label(expr.span, "help: use `MaybeUninit<T>` instead");
+                            if let Some(span) = span {
+                                err.span_note(span, &msg);
+                            } else {
+                                err.note(&msg);
+                            }
+                            err.emit();
                         }
                     }
                 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 3a540fd..fc416be 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -24,6 +24,7 @@
 
 mod error_codes;
 mod nonstandard_style;
+mod redundant_semicolon;
 pub mod builtin;
 mod types;
 mod unused;
@@ -55,6 +56,7 @@
 use lint::LintId;
 use lint::FutureIncompatibleInfo;
 
+use redundant_semicolon::*;
 use nonstandard_style::*;
 use builtin::*;
 use types::*;
@@ -98,6 +100,7 @@
             WhileTrue: WhileTrue,
             NonAsciiIdents: NonAsciiIdents,
             IncompleteFeatures: IncompleteFeatures,
+            RedundantSemicolon: RedundantSemicolon,
         ]);
     )
 }
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 8f7fe66..acd17f7 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -147,7 +147,7 @@
     }
 
     fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant, _: &ast::Generics) {
-        self.check_case(cx, "variant", &v.node.ident);
+        self.check_case(cx, "variant", &v.ident);
     }
 
     fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) {
diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs
new file mode 100644
index 0000000..7c9df35
--- /dev/null
+++ b/src/librustc_lint/redundant_semicolon.rs
@@ -0,0 +1,52 @@
+use crate::lint::{EarlyLintPass, LintPass, EarlyContext, LintArray, LintContext};
+use syntax::ast::{Stmt, StmtKind, ExprKind};
+use syntax::errors::Applicability;
+
+declare_lint! {
+    pub REDUNDANT_SEMICOLON,
+    Warn,
+    "detects unnecessary trailing semicolons"
+}
+
+declare_lint_pass!(RedundantSemicolon => [REDUNDANT_SEMICOLON]);
+
+impl EarlyLintPass for RedundantSemicolon {
+    fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) {
+        if let StmtKind::Semi(expr) = &stmt.node {
+            if let ExprKind::Tup(ref v) = &expr.node {
+                if v.is_empty() {
+                    // Strings of excess semicolons are encoded as empty tuple expressions
+                    // during the parsing stage, so we check for empty tuple expressions
+                    // which span only semicolons
+                    if let Ok(source_str) = cx.sess().source_map().span_to_snippet(stmt.span) {
+                        if source_str.chars().all(|c| c == ';') {
+                            let multiple = (stmt.span.hi() - stmt.span.lo()).0 > 1;
+                            let msg = if multiple {
+                                "unnecessary trailing semicolons"
+                            } else {
+                                "unnecessary trailing semicolon"
+                            };
+                            let mut err = cx.struct_span_lint(
+                                REDUNDANT_SEMICOLON,
+                                stmt.span,
+                                &msg
+                            );
+                            let suggest_msg = if multiple {
+                                "remove these semicolons"
+                            } else {
+                                "remove this semicolon"
+                            };
+                            err.span_suggestion(
+                                stmt.span,
+                                &suggest_msg,
+                                String::new(),
+                                Applicability::MaybeIncorrect
+                            );
+                            err.emit();
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index e862304..217e10a 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -976,7 +976,7 @@
                     let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
 
                     debug!("- variant `{}` is {} bytes large",
-                           variant.node.ident,
+                           variant.ident,
                            bytes);
                     bytes
                 })
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 6a3dfdb..90e4677 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -517,9 +517,8 @@
                 // trigger in situations that macro authors shouldn't have to care about, e.g.,
                 // when a parenthesized token tree matched in one macro expansion is matched as
                 // an expression in another and used as a fn/method argument (Issue #47775)
-                if e.span.ctxt().outer_expn_info()
-                    .map_or(false, |info| info.call_site.ctxt().outer_expn_info().is_some()) {
-                        return;
+                if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
+                    return;
                 }
                 let msg = format!("{} argument", call_kind);
                 for arg in args_to_check {
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index c84ec4e..40ddd65 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -254,8 +254,11 @@
     let llvm_use_libcxx = env::var_os("LLVM_USE_LIBCXX");
 
     let stdcppname = if target.contains("openbsd") {
-        // llvm-config on OpenBSD doesn't mention stdlib=libc++
-        "c++"
+        if target.contains("sparc64") {
+            "estdc++"
+        } else {
+            "c++"
+        }
     } else if target.contains("freebsd") {
         "c++"
     } else if target.contains("darwin") {
diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs
index 85e2247..3d3a020 100644
--- a/src/librustc_macros/src/lib.rs
+++ b/src/librustc_macros/src/lib.rs
@@ -1,5 +1,5 @@
 #![feature(proc_macro_hygiene)]
-#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
+#![allow(rustc::default_hash_types)]
 
 #![recursion_limit="128"]
 
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 5d8fabc..4ac0a5b9 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -70,7 +70,7 @@
     // whichever `TyCtxt` is being used to decode those values.
     pub root: schema::CrateRoot<'static>,
 
-    /// For each public item in this crate, we encode a key. When the
+    /// For each definition in this crate, we encode a key. When the
     /// crate is loaded, we read all the keys and put them in this
     /// hashmap, which gives the reverse mapping. This allows us to
     /// quickly retrace a `DefPath`, which is needed for incremental
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index ee1175e..b46758a 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -35,7 +35,7 @@
 use syntax::parse::source_file_to_stream;
 use syntax::parse::parser::emit_unclosed_delims;
 use syntax::symbol::{Symbol, sym};
-use syntax_pos::{Span, NO_EXPANSION, FileName};
+use syntax_pos::{Span, FileName};
 use rustc_data_structures::bit_set::BitSet;
 
 macro_rules! provide {
@@ -443,7 +443,7 @@
         let source_name = FileName::Macros(macro_full_name);
 
         let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);
-        let local_span = Span::new(source_file.start_pos, source_file.end_pos, NO_EXPANSION);
+        let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos);
         let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None);
         emit_unclosed_delims(&mut errors, &sess.diagnostic());
 
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 935187d..0bec31d 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -32,7 +32,7 @@
 use syntax::symbol::{Symbol, sym};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::hygiene::ExpnId;
-use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
+use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
 use log::debug;
 
 pub struct DecodeContext<'a, 'tcx> {
@@ -344,7 +344,7 @@
         let hi = (hi + source_file.translated_source_file.start_pos)
                  - source_file.original_start_pos;
 
-        Ok(Span::new(lo, hi, NO_EXPANSION))
+        Ok(Span::with_root_ctxt(lo, hi))
     }
 }
 
@@ -569,7 +569,7 @@
 
         ty::VariantDef::new(
             tcx,
-            Ident::with_empty_ctxt(self.item_name(index)),
+            Ident::with_dummy_span(self.item_name(index)),
             variant_did,
             ctor_did,
             data.discr,
@@ -577,7 +577,7 @@
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
-                    ident: Ident::with_empty_ctxt(self.item_name(index)),
+                    ident: Ident::with_dummy_span(self.item_name(index)),
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
@@ -741,7 +741,7 @@
                         DefKind::Macro(ext.macro_kind()),
                         self.local_def_id(DefIndex::from_proc_macro_index(id)),
                     );
-                    let ident = Ident::with_empty_ctxt(name);
+                    let ident = Ident::with_dummy_span(name);
                     callback(def::Export {
                         ident: ident,
                         res: res,
@@ -783,7 +783,7 @@
                             if let Some(kind) = self.def_kind(child_index) {
                                 callback(def::Export {
                                     res: Res::Def(kind, self.local_def_id(child_index)),
-                                    ident: Ident::with_empty_ctxt(self.item_name(child_index)),
+                                    ident: Ident::with_dummy_span(self.item_name(child_index)),
                                     vis: self.get_visibility(child_index),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                 });
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index d73a496..fb675d7 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1676,7 +1676,7 @@
                      id: hir::HirId) {
         intravisit::walk_variant(self, v, g, id);
 
-        if let Some(ref discr) = v.node.disr_expr {
+        if let Some(ref discr) = v.disr_expr {
             let def_id = self.tcx.hir().local_def_id(discr.hir_id);
             self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
         }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 70d6c15..9ff0c6c 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -272,12 +272,11 @@
 
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
-        self.sanitize_constant(constant, location);
-        self.sanitize_type(constant, constant.ty);
+        self.sanitize_type(constant, constant.literal.ty);
 
         if let Some(annotation_index) = constant.user_ty {
             if let Err(terr) = self.cx.relate_type_and_user_type(
-                constant.ty,
+                constant.literal.ty,
                 ty::Variance::Invariant,
                 &UserTypeProjection { base: annotation_index, projs: vec![], },
                 location.to_locations(),
@@ -289,7 +288,7 @@
                     constant,
                     "bad constant user type {:?} vs {:?}: {:?}",
                     annotation,
-                    constant.ty,
+                    constant.literal.ty,
                     terr,
                 );
             }
@@ -299,7 +298,7 @@
                     location.to_locations(),
                     ConstraintCategory::Boring,
                     self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
-                        constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
+                        constant.literal.ty, def_id, UserSubsts { substs, user_self_ty: None },
                     )),
                 ) {
                     span_mirbug!(
@@ -403,41 +402,6 @@
         }
     }
 
-    /// Checks that the constant's `ty` field matches up with what would be
-    /// expected from its literal. Unevaluated constants and well-formed
-    /// constraints are checked by `visit_constant`.
-    fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
-        debug!(
-            "sanitize_constant(constant={:?}, location={:?})",
-            constant, location
-        );
-
-        let literal = constant.literal;
-
-        if let ConstValue::Unevaluated(..) = literal.val {
-            return;
-        }
-
-        debug!("sanitize_constant: expected_ty={:?}", literal.ty);
-
-        if let Err(terr) = self.cx.eq_types(
-            literal.ty,
-            constant.ty,
-            location.to_locations(),
-            ConstraintCategory::Boring,
-        ) {
-            span_mirbug!(
-                self,
-                constant,
-                "constant {:?} should have type {:?} but has {:?} ({:?})",
-                constant,
-                literal.ty,
-                constant.ty,
-                terr,
-            );
-        }
-    }
-
     /// Checks that the types internal to the `place` match up with
     /// what would be expected.
     fn sanitize_place(
diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs
index 5197981..39bdc87 100644
--- a/src/librustc_mir/build/expr/as_constant.rs
+++ b/src/librustc_mir/build/expr/as_constant.rs
@@ -38,9 +38,9 @@
                         inferred_ty: ty,
                     })
                 });
+                assert_eq!(literal.ty, ty);
                 Constant {
                     span,
-                    ty,
                     user_ty,
                     literal,
                 }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index ec061e7..1a186fa 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -591,7 +591,7 @@
         let n = (!0u128) >> (128 - bits);
         let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty);
 
-        self.literal_operand(span, ty, literal)
+        self.literal_operand(span, literal)
     }
 
     // Helper to get the minimum value of the appropriate type
@@ -602,6 +602,6 @@
         let n = 1 << (bits - 1);
         let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty);
 
-        self.literal_operand(span, ty, literal)
+        self.literal_operand(span, literal)
     }
 }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 02ab53f..889861b 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -114,7 +114,6 @@
                     destination,
                     Constant {
                         span: expr_span,
-                        ty: this.hir.bool_ty(),
                         user_ty: None,
                         literal: this.hir.true_literal(),
                     },
@@ -126,7 +125,6 @@
                     destination,
                     Constant {
                         span: expr_span,
-                        ty: this.hir.bool_ty(),
                         user_ty: None,
                         literal: this.hir.false_literal(),
                     },
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index d9b748f..3473155 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -108,8 +108,8 @@
                 Err(match_pair)
             }
 
-            PatternKind::Range(PatternRange { lo, hi, ty, end }) => {
-                let (range, bias) = match ty.sty {
+            PatternKind::Range(PatternRange { lo, hi, end }) => {
+                let (range, bias) = match lo.ty.sty {
                     ty::Char => {
                         (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
                     }
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 1c93abd..65e92d4 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -63,7 +63,8 @@
             }
 
             PatternKind::Range(range) => {
-                assert!(range.ty == match_pair.pattern.ty);
+                assert_eq!(range.lo.ty, match_pair.pattern.ty);
+                assert_eq!(range.hi.ty, match_pair.pattern.ty);
                 Test {
                     span: match_pair.pattern.span,
                     kind: TestKind::Range(range),
@@ -270,8 +271,9 @@
                     );
                 } else {
                     if let [success, fail] = *make_target_blocks(self) {
+                        assert_eq!(value.ty, ty);
+                        let expect = self.literal_operand(test.span, value);
                         let val = Operand::Copy(place.clone());
-                        let expect = self.literal_operand(test.span, ty, value);
                         self.compare(block, success, fail, source_info, BinOp::Eq, expect, val);
                     } else {
                         bug!("`TestKind::Eq` should have two target blocks");
@@ -279,13 +281,13 @@
                 }
             }
 
-            TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => {
+            TestKind::Range(PatternRange { ref lo, ref hi, ref end }) => {
                 let lower_bound_success = self.cfg.start_new_block();
                 let target_blocks = make_target_blocks(self);
 
                 // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
-                let lo = self.literal_operand(test.span, ty, lo);
-                let hi = self.literal_operand(test.span, ty, hi);
+                let lo = self.literal_operand(test.span, lo);
+                let hi = self.literal_operand(test.span, hi);
                 let val = Operand::Copy(place.clone());
 
                 if let [success, fail] = *target_blocks {
@@ -387,7 +389,7 @@
     ) {
         use rustc::middle::lang_items::EqTraitLangItem;
 
-        let mut expect = self.literal_operand(source_info.span, value.ty, value);
+        let mut expect = self.literal_operand(source_info.span, value);
         let mut val = Operand::Copy(place.clone());
 
         // If we're using `b"..."` as a pattern, we need to insert an
@@ -440,7 +442,7 @@
         };
 
         let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem);
-        let (mty, method) = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]);
+        let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]);
 
         let bool_ty = self.hir.bool_ty();
         let eq_result = self.temp(bool_ty, source_info.span);
@@ -449,7 +451,6 @@
         self.cfg.terminate(block, source_info, TerminatorKind::Call {
             func: Operand::Constant(box Constant {
                 span: source_info.span,
-                ty: mty,
 
                 // FIXME(#54571): This constant comes from user input (a
                 // constant in a pattern).  Are there forms where users can add
@@ -656,8 +657,9 @@
 
                     let tcx = self.hir.tcx();
 
-                    let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test.ty)?;
-                    let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test.ty)?;
+                    let test_ty = test.lo.ty;
+                    let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test_ty)?;
+                    let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test_ty)?;
 
                     match (test.end, pat.end, lo, hi) {
                         // pat < test
@@ -774,8 +776,8 @@
 
         let tcx = self.hir.tcx();
 
-        let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.ty)?;
-        let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.ty)?;
+        let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.lo.ty)?;
+        let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.lo.ty)?;
 
         match (b, range.end) {
             (Less, _) |
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 56025ee..d038310 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -26,12 +26,10 @@
     /// without any user type annotation.
     pub fn literal_operand(&mut self,
                            span: Span,
-                           ty: Ty<'tcx>,
                            literal: &'tcx ty::Const<'tcx>)
                            -> Operand<'tcx> {
         let constant = box Constant {
             span,
-            ty,
             user_ty: None,
             literal,
         };
@@ -47,7 +45,7 @@
     pub 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, ty, literal)
+        self.literal_operand(span, literal)
     }
 
     pub fn push_usize(&mut self,
@@ -61,7 +59,6 @@
             block, source_info, &temp,
             Constant {
                 span: source_info.span,
-                ty: self.hir.usize_ty(),
                 user_ty: None,
                 literal: self.hir.usize_literal(value),
             });
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 36d80d0..52225ea 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -540,6 +540,12 @@
     ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
 }
 
+pub fn note_on_undefined_behavior_error() -> &'static str {
+    "The rules on what exactly is undefined behavior aren't clear, \
+    so this check might be overzealous. Please open an issue on the rust compiler \
+    repository if you believe it should not be considered undefined behavior"
+}
+
 fn validate_and_turn_into_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     constant: RawConst<'tcx>,
@@ -579,10 +585,7 @@
         let err = error_to_const_error(&ecx, error);
         match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") {
             Ok(mut diag) => {
-                diag.note("The rules on what exactly is undefined behavior aren't clear, \
-                    so this check might be overzealous. Please open an issue on the rust compiler \
-                    repository if you believe it should not be considered undefined behavior",
-                );
+                diag.note(note_on_undefined_behavior_error());
                 diag.emit();
                 ErrorHandled::Reported
             }
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 1c6a743..a33d720 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -927,7 +927,7 @@
             ExprKind::Literal {
                 literal: cx.tcx.mk_const(ty::Const {
                     val: ConstValue::Unevaluated(def_id, substs),
-                    ty: cx.tcx.type_of(def_id),
+                    ty: cx.tables().node_type(expr.hir_id),
                 }),
                 user_ty,
             }
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 3d9349d..740dc20 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -170,13 +170,13 @@
                         method_name: Symbol,
                         self_ty: Ty<'tcx>,
                         params: &[Kind<'tcx>])
-                        -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) {
+                        -> &'tcx ty::Const<'tcx> {
         let substs = self.tcx.mk_substs_trait(self_ty, params);
         for item in self.tcx.associated_items(trait_def_id) {
             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);
-                return (method_ty, ty::Const::zero_sized(self.tcx, method_ty));
+                return ty::Const::zero_sized(self.tcx, method_ty);
             }
         }
 
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 8a3d904..1833ee3 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -609,7 +609,6 @@
                         ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange {
                             lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)),
                             hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
-                            ty,
                             end,
                         }),
                         _ => PatternKind::Wild,
@@ -880,10 +879,10 @@
         let range = loop {
             match pat.kind {
                 box PatternKind::Constant { value } => break ConstantValue(value),
-                box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange(
-                    lo.eval_bits(tcx, param_env, ty),
-                    hi.eval_bits(tcx, param_env, ty),
-                    ty,
+                box PatternKind::Range(PatternRange { lo, hi, end }) => break ConstantRange(
+                    lo.eval_bits(tcx, param_env, lo.ty),
+                    hi.eval_bits(tcx, param_env, hi.ty),
+                    lo.ty,
                     end,
                 ),
                 box PatternKind::AscribeUserType { ref subpattern, .. } => {
@@ -1339,11 +1338,11 @@
             Some(vec![Variant(adt_def.variants[variant_index].def_id)])
         }
         PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
-        PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
+        PatternKind::Range(PatternRange { lo, hi, end }) =>
             Some(vec![ConstantRange(
-                lo.eval_bits(cx.tcx, cx.param_env, ty),
-                hi.eval_bits(cx.tcx, cx.param_env, ty),
-                ty,
+                lo.eval_bits(cx.tcx, cx.param_env, lo.ty),
+                hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
+                lo.ty,
                 end,
             )]),
         PatternKind::Array { .. } => match pcx.ty.sty {
@@ -1656,7 +1655,7 @@
 ) -> Result<bool, ErrorReported> {
     let (from, to, end, ty) = match pat.kind {
         box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty),
-        box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty),
+        box PatternKind::Range(PatternRange { lo, hi, end }) => (lo, hi, end, lo.ty),
         _ => bug!("`constructor_covered_by_range` called with {:?}", pat),
     };
     trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 5ecfb84..bebb071 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -181,7 +181,6 @@
 pub struct PatternRange<'tcx> {
     pub lo: &'tcx ty::Const<'tcx>,
     pub hi: &'tcx ty::Const<'tcx>,
-    pub ty: Ty<'tcx>,
     pub end: RangeEnd,
 }
 
@@ -296,7 +295,7 @@
             PatternKind::Constant { value } => {
                 write!(f, "{}", value)
             }
-            PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
+            PatternKind::Range(PatternRange { lo, hi, end }) => {
                 write!(f, "{}", lo)?;
                 match end {
                     RangeEnd::Included => write!(f, "..=")?,
@@ -442,6 +441,8 @@
 
                 let mut kind = match (lo, hi) {
                     (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
+                        assert_eq!(lo.ty, ty);
+                        assert_eq!(hi.ty, ty);
                         let cmp = compare_const_vals(
                             self.tcx,
                             lo,
@@ -451,7 +452,7 @@
                         );
                         match (end, cmp) {
                             (RangeEnd::Excluded, Some(Ordering::Less)) =>
-                                PatternKind::Range(PatternRange { lo, hi, ty, end }),
+                                PatternKind::Range(PatternRange { lo, hi, end }),
                             (RangeEnd::Excluded, _) => {
                                 span_err!(
                                     self.tcx.sess,
@@ -465,7 +466,7 @@
                                 PatternKind::Constant { value: lo }
                             }
                             (RangeEnd::Included, Some(Ordering::Less)) => {
-                                PatternKind::Range(PatternRange { lo, hi, ty, end })
+                                PatternKind::Range(PatternRange { lo, hi, end })
                             }
                             (RangeEnd::Included, _) => {
                                 let mut err = struct_span_err!(
@@ -645,9 +646,9 @@
                     fields.iter()
                           .map(|field| {
                               FieldPattern {
-                                  field: Field::new(self.tcx.field_index(field.node.hir_id,
+                                  field: Field::new(self.tcx.field_index(field.hir_id,
                                                                          self.tables)),
-                                  pattern: self.lower_pattern(&field.node.pat),
+                                  pattern: self.lower_pattern(&field.pat),
                               }
                           })
                           .collect();
@@ -1416,17 +1417,7 @@
             } => PatternKind::Constant {
                 value,
             },
-            PatternKind::Range(PatternRange {
-                lo,
-                hi,
-                ty,
-                end,
-            }) => PatternKind::Range(PatternRange {
-                lo,
-                hi,
-                ty: ty.fold_with(folder),
-                end,
-            }),
+            PatternKind::Range(range) => PatternKind::Range(range),
             PatternKind::Slice {
                 ref prefix,
                 ref slice,
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 1074ab9..32ba70a 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -296,11 +296,7 @@
                 let err = crate::const_eval::error_to_const_error(&ecx, error);
                 match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") {
                     Ok(mut diag) => {
-                        diag.note("The rules on what exactly is undefined behavior aren't clear, \
-                            so this check might be overzealous. Please open an issue on the rust \
-                            compiler repository if you believe it should not be considered \
-                            undefined behavior",
-                        );
+                        diag.note(crate::const_eval::note_on_undefined_behavior_error());
                         diag.emit();
                     }
                     Err(ErrorHandled::TooGeneric) |
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 89c5be1..ee105fe 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -110,18 +110,18 @@
                 };
                 self.write_scalar(out_val, dest)?;
             }
-            | "overflowing_add"
-            | "overflowing_sub"
-            | "overflowing_mul"
+            | "wrapping_add"
+            | "wrapping_sub"
+            | "wrapping_mul"
             | "add_with_overflow"
             | "sub_with_overflow"
             | "mul_with_overflow" => {
                 let lhs = self.read_immediate(args[0])?;
                 let rhs = self.read_immediate(args[1])?;
                 let (bin_op, ignore_overflow) = match intrinsic_name {
-                    "overflowing_add" => (BinOp::Add, true),
-                    "overflowing_sub" => (BinOp::Sub, true),
-                    "overflowing_mul" => (BinOp::Mul, true),
+                    "wrapping_add" => (BinOp::Add, true),
+                    "wrapping_sub" => (BinOp::Sub, true),
+                    "wrapping_mul" => (BinOp::Mul, true),
                     "add_with_overflow" => (BinOp::Add, false),
                     "sub_with_overflow" => (BinOp::Sub, false),
                     "mul_with_overflow" => (BinOp::Mul, false),
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index aef09df..6771d76 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -368,7 +368,7 @@
                 // It is sufficient to check this for the end pointer. The addition
                 // checks for overflow.
                 let end_ptr = ptr.offset(size, self)?;
-                end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?;
+                end_ptr.check_inbounds_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?;
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
                 if let Some(align) = align {
@@ -400,7 +400,7 @@
     ) -> bool {
         let (size, _align) = self.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)
             .expect("alloc info with MaybeDead cannot fail");
-        ptr.check_in_alloc(size, CheckInAllocMsg::NullPointerTest).is_err()
+        ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err()
     }
 }
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index f778eb1..139a92c 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -246,7 +246,9 @@
             return Ok(None);
         }
 
-        let ptr = match self.check_mplace_access(mplace, None)? {
+        let ptr = match self.check_mplace_access(mplace, None)
+            .expect("places should be checked on creation")
+        {
             Some(ptr) => ptr,
             None => return Ok(Some(ImmTy { // zero-sized type
                 imm: Scalar::zst().into(),
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index f66c4ad..16686c3 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -277,6 +277,10 @@
 {
     /// Take a value, which represents a (thin or fat) reference, and make it a place.
     /// Alignment is just based on the type.  This is the inverse of `MemPlace::to_ref()`.
+    ///
+    /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not
+    /// want to ever use the place for memory access!
+    /// Generally prefer `deref_operand`.
     pub fn ref_to_mplace(
         &self,
         val: ImmTy<'tcx, M::PointerTag>,
@@ -304,7 +308,8 @@
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let val = self.read_immediate(src)?;
         trace!("deref to {} on {:?}", val.layout.ty, *val);
-        self.ref_to_mplace(val)
+        let place = self.ref_to_mplace(val)?;
+        self.mplace_access_checked(place)
     }
 
     /// Check if the given place is good for memory access with the given
@@ -327,6 +332,23 @@
         self.memory.check_ptr_access(place.ptr, size, place.align)
     }
 
+    /// Return the "access-checked" version of this `MPlace`, where for non-ZST
+    /// this is definitely a `Pointer`.
+    pub fn mplace_access_checked(
+        &self,
+        mut place: MPlaceTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        let (size, align) = self.size_and_align_of_mplace(place)?
+            .unwrap_or((place.layout.size, place.layout.align.abi));
+        assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?");
+        place.mplace.align = align; // maximally strict checking
+        // When dereferencing a pointer, it must be non-NULL, aligned, and live.
+        if let Some(ptr) = self.check_mplace_access(place, Some(size))? {
+            place.mplace.ptr = ptr.into();
+        }
+        Ok(place)
+    }
+
     /// 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(
@@ -750,7 +772,9 @@
         // to handle padding properly, which is only correct if we never look at this data with the
         // wrong type.
 
-        let ptr = match self.check_mplace_access(dest, None)? {
+        let ptr = match self.check_mplace_access(dest, None)
+            .expect("places should be checked on creation")
+        {
             Some(ptr) => ptr,
             None => return Ok(()), // zero-sized access
         };
@@ -853,8 +877,10 @@
         });
         assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances");
 
-        let src = self.check_mplace_access(src, Some(size))?;
-        let dest = self.check_mplace_access(dest, Some(size))?;
+        let src = self.check_mplace_access(src, Some(size))
+            .expect("places should be checked on creation");
+        let dest = self.check_mplace_access(dest, Some(size))
+            .expect("places should be checked on creation");
         let (src_ptr, dest_ptr) = match (src, dest) {
             (Some(src_ptr), Some(dest_ptr)) => (src_ptr, dest_ptr),
             (None, None) => return Ok(()), // zero-sized copy
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index d152e2b..e558278 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -240,8 +240,12 @@
 
             Ref(_, _, ref place) => {
                 let src = self.eval_place(place)?;
-                let val = self.force_allocation(src)?;
-                self.write_immediate(val.to_ref(), dest)?;
+                let place = self.force_allocation(src)?;
+                if place.layout.size.bytes() > 0 {
+                    // definitely not a ZST
+                    assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`");
+                }
+                self.write_immediate(place.to_ref(), dest)?;
             }
 
             NullaryOp(mir::NullOp::Box, _) => {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 33447eba..063e779 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -445,7 +445,6 @@
         let func_ty = tcx.mk_fn_def(self.def_id, substs);
         let func = Operand::Constant(box Constant {
             span: self.span,
-            ty: func_ty,
             user_ty: None,
             literal: ty::Const::zero_sized(tcx, func_ty),
         });
@@ -505,7 +504,6 @@
     fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
         box Constant {
             span: self.span,
-            ty: self.tcx.types.usize,
             user_ty: None,
             literal: ty::Const::from_usize(self.tcx, value),
         }
@@ -745,7 +743,6 @@
             let ty = tcx.type_of(def_id);
             (Operand::Constant(box Constant {
                 span,
-                ty,
                 user_ty: None,
                 literal: ty::Const::zero_sized(tcx, ty),
              }),
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index d573423..524a19e 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -42,9 +42,8 @@
     }
 }
 
-/// Determine whether this type may have a reference in it, recursing below compound types but
-/// not below references.
-fn may_have_reference<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
+/// Determine whether this type may be a reference (or box), and thus needs retagging.
+fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool {
     match ty.sty {
         // Primitive types that are not references
         ty::Bool | ty::Char |
@@ -55,15 +54,12 @@
         // References
         ty::Ref(..) => true,
         ty::Adt(..) if ty.is_box() => true,
-        // Compound types
-        ty::Array(ty, ..) | ty::Slice(ty) =>
-            may_have_reference(ty, tcx),
-        ty::Tuple(tys) =>
-            tys.iter().any(|ty| may_have_reference(ty.expect_ty(), tcx)),
-        ty::Adt(adt, substs) =>
-            adt.variants.iter().any(|v| v.fields.iter().any(|f|
-                may_have_reference(f.ty(tcx, substs), tcx)
-            )),
+        // Compound types are not references
+        ty::Array(..) |
+        ty::Slice(..) |
+        ty::Tuple(..) |
+        ty::Adt(..) =>
+            false,
         // Conservative fallback
         _ => true,
     }
@@ -80,7 +76,7 @@
             // FIXME: Instead of giving up for unstable places, we should introduce
             // a temporary and retag on that.
             is_stable(place.as_ref())
-                && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx)
+                && may_be_reference(place.ty(&*local_decls, tcx).ty)
         };
 
         // PART 1
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 38d26d0..c3c432d 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -539,7 +539,6 @@
         Operand::Constant(Box::new(
             Constant {
                 span,
-                ty,
                 user_ty: None,
                 literal: self.tcx.mk_const(*ty::Const::from_scalar(
                     self.tcx,
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 0a021d9..4480d1e 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -527,7 +527,6 @@
     fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
         Rvalue::Use(Operand::Constant(Box::new(Constant {
             span,
-            ty: self.tcx.types.bool,
             user_ty: None,
             literal: ty::Const::from_bool(self.tcx, val),
         })))
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 94bb70e..f694188 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -975,7 +975,6 @@
     let term = TerminatorKind::Assert {
         cond: Operand::Constant(box Constant {
             span: body.span,
-            ty: tcx.types.bool,
             user_ty: None,
             literal: ty::Const::from_bool(tcx, false),
         }),
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 40cb1fb..bc7bd39 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -328,7 +328,7 @@
                 }
 
                 TerminatorKind::Call {func: Operand::Constant(ref f), .. } => {
-                    if let ty::FnDef(def_id, _) = f.ty.sty {
+                    if let ty::FnDef(def_id, _) = f.literal.ty.sty {
                         // Don't give intrinsics the extra penalty for calls
                         let f = tcx.fn_sig(def_id);
                         if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 5542926..b2d063a 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -97,8 +97,7 @@
             let place_ty = place.ty(&self.body.local_decls, self.tcx).ty;
             if let ty::Array(_, len) = place_ty.sty {
                 let span = self.body.source_info(location).span;
-                let ty = self.tcx.types.usize;
-                let constant = Constant { span, ty, literal: len, user_ty: None };
+                let constant = Constant { span, literal: len, user_ty: None };
                 self.optimizations.arrays_lengths.insert(location, constant);
             }
         }
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index dcfc809..649cccc 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -249,7 +249,7 @@
                 if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
                     // 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.ty).unwrap_or(false)
+                        Self::in_any_value_of_ty(cx, constant.literal.ty).unwrap_or(false)
                     } else {
                         let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id);
 
@@ -258,7 +258,7 @@
                         // Just in case the type is more specific than
                         // the definition, e.g., impl associated const
                         // with type parameters, take it into account.
-                        qualif && Self::mask_for_ty(cx, constant.ty)
+                        qualif && Self::mask_for_ty(cx, constant.literal.ty)
                     }
                 } else {
                     false
@@ -537,9 +537,9 @@
                             | "cttz_nonzero"
                             | "ctlz"
                             | "ctlz_nonzero"
-                            | "overflowing_add"
-                            | "overflowing_sub"
-                            | "overflowing_mul"
+                            | "wrapping_add"
+                            | "wrapping_sub"
+                            | "wrapping_mul"
                             | "unchecked_shl"
                             | "unchecked_shr"
                             | "rotate_left"
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index b84bc31..334d0ce 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -379,9 +379,9 @@
         | "add_with_overflow" // ~> .overflowing_add
         | "sub_with_overflow" // ~> .overflowing_sub
         | "mul_with_overflow" // ~> .overflowing_mul
-        | "overflowing_add" // ~> .wrapping_add
-        | "overflowing_sub" // ~> .wrapping_sub
-        | "overflowing_mul" // ~> .wrapping_mul
+        | "wrapping_add" // ~> .wrapping_add
+        | "wrapping_sub" // ~> .wrapping_sub
+        | "wrapping_mul" // ~> .wrapping_mul
         | "saturating_add" // ~> .saturating_add
         | "saturating_sub" // ~> .saturating_sub
         | "unchecked_shl" // ~> .wrapping_shl
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 7fe8480..598de3a 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -224,7 +224,7 @@
     if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator {
         if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind {
             if let mir::Operand::Constant(ref func) = *oper {
-                if let ty::FnDef(def_id, _) = func.ty.sty {
+                if let ty::FnDef(def_id, _) = func.literal.ty.sty {
                     let abi = tcx.fn_sig(def_id).abi();
                     let name = tcx.item_name(def_id);
                     if abi == Abi::RustIntrinsic && name == sym::rustc_peek {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 52fd645..c5561a1 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -970,7 +970,6 @@
     fn constant_usize(&self, val: u16) -> Operand<'tcx> {
         Operand::Constant(box Constant {
             span: self.source_info.span,
-            ty: self.tcx().types.usize,
             user_ty: None,
             literal: ty::Const::from_usize(self.tcx(), val.into()),
         })
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 68880fc..ac27019 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -397,10 +397,9 @@
 impl Visitor<'tcx> for ExtraComments<'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
-        let Constant { span, ty, user_ty, literal } = constant;
+        let Constant { span, user_ty, literal } = constant;
         self.push("mir::Constant");
         self.push(&format!("+ span: {:?}", span));
-        self.push(&format!("+ ty: {:?}", ty));
         if let Some(user_ty) = user_ty {
             self.push(&format!("+ user_ty: {:?}", user_ty));
         }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 3c31bce..bd46ca4 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -602,7 +602,7 @@
             }
             ItemKind::Enum(ref def, _) => {
                 for variant in &def.variants {
-                    for field in variant.node.data.fields() {
+                    for field in variant.data.fields() {
                         self.invalid_visibility(&field.vis, None);
                     }
                 }
@@ -824,7 +824,7 @@
             |this| visit::walk_enum_def(this, enum_definition, generics, item_id))
     }
 
-    fn visit_mac(&mut self, mac: &Spanned<Mac_>) {
+    fn visit_mac(&mut self, mac: &Mac) {
         // when a new macro kind is added but the author forgets to set it up for expansion
         // because that's the only part that won't cause a compiler error
         self.session.diagnostic()
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 673762e..bca7762 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -687,11 +687,11 @@
         match item.node {
             hir::ItemKind::Enum(ref def, _) => {
                 for variant in &def.variants {
-                    let variant_level = self.update(variant.node.id, item_level);
-                    if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+                    let variant_level = self.update(variant.id, item_level);
+                    if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
                         self.update(ctor_hir_id, item_level);
                     }
-                    for field in variant.node.data.fields() {
+                    for field in variant.data.fields() {
                         self.update(field.hir_id, variant_level);
                     }
                 }
@@ -810,9 +810,9 @@
                     self.reach(item.hir_id, item_level).generics().predicates();
                 }
                 for variant in &def.variants {
-                    let variant_level = self.get(variant.node.id);
+                    let variant_level = self.get(variant.id);
                     if variant_level.is_some() {
-                        for field in variant.node.data.fields() {
+                        for field in variant.data.fields() {
                             self.reach(field.hir_id, variant_level).ty();
                         }
                         // Corner case: if the variant is reachable, but its
@@ -1075,8 +1075,8 @@
                 let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap();
                 let variant = adt.variant_of_res(res);
                 for field in fields {
-                    let use_ctxt = field.node.ident.span;
-                    let index = self.tcx.field_index(field.node.hir_id, self.tables);
+                    let use_ctxt = field.ident.span;
+                    let index = self.tcx.field_index(field.hir_id, self.tables);
                     self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
                 }
             }
@@ -1647,7 +1647,7 @@
                      v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
-        if self.access_levels.is_reachable(v.node.id) {
+        if self.access_levels.is_reachable(v.id) {
             self.in_variant = true;
             intravisit::walk_variant(self, v, g, item_id);
             self.in_variant = false;
@@ -1898,7 +1898,7 @@
                 self.check(item.hir_id, item_visibility).generics().predicates();
 
                 for variant in &def.variants {
-                    for field in variant.node.data.fields() {
+                    for field in variant.data.fields() {
                         self.check(field.hir_id, item_visibility).ty();
                     }
                 }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 5dd7bc3..1510d74 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -1,9 +1,11 @@
-//! Reduced graph building.
+//! After we obtain a fresh AST fragment from a macro, code in this module helps to integrate
+//! that fragment into the module structures that are already partially built.
 //!
-//! Here we build the "reduced graph": the graph of the module tree without
-//! any imports resolved.
+//! Items from the fragment are placed into modules,
+//! unexpanded macros in the fragment are visited and registered.
+//! Imports are also considered items and placed into modules here, but not resolved yet.
 
-use crate::macros::{InvocationData, LegacyBinding, LegacyScope};
+use crate::macros::{LegacyBinding, LegacyScope};
 use crate::resolve_imports::ImportDirective;
 use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
 use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
@@ -14,6 +16,7 @@
 use rustc::bug;
 use rustc::hir::def::{self, *};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
+use rustc::hir::map::DefCollector;
 use rustc::ty;
 use rustc::middle::cstore::CrateStore;
 use rustc_metadata::cstore::LoadedMacro;
@@ -30,6 +33,7 @@
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
 use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
+use syntax::ext::expand::AstFragment;
 use syntax::ext::hygiene::ExpnId;
 use syntax::feature_gate::is_builtin_attr;
 use syntax::parse::token::{self, Token};
@@ -67,7 +71,7 @@
     }
 }
 
-pub(crate) struct IsMacroExport;
+struct IsMacroExport;
 
 impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport) {
     fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
@@ -84,7 +88,7 @@
 impl<'a> Resolver<'a> {
     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
     /// otherwise, reports an error.
-    pub fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
+    crate fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
         where T: ToNameBinding<'a>,
     {
         let binding = def.to_name_binding(self.arenas);
@@ -93,7 +97,7 @@
         }
     }
 
-    pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
+    crate fn get_module(&mut self, def_id: DefId) -> Module<'a> {
         if def_id.krate == LOCAL_CRATE {
             return self.module_map[&def_id]
         }
@@ -119,7 +123,7 @@
         module
     }
 
-    pub fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
+    crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
         let def_id = match self.macro_defs.get(&expn_id) {
             Some(def_id) => *def_id,
             None => return self.graph_root,
@@ -141,7 +145,7 @@
         }
     }
 
-    crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
+    fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
         if let Some(ext) = self.macro_map.get(&def_id) {
             return Some(ext.clone());
         }
@@ -156,23 +160,32 @@
         Some(ext)
     }
 
-    /// Ensures that the reduced graph rooted at the given external module
-    /// is built, building it if it is not.
-    pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
-        if module.populated.get() { return }
-        let def_id = module.def_id().unwrap();
+    crate fn build_reduced_graph(
+        &mut self, fragment: &AstFragment, parent_scope: ParentScope<'a>
+    ) -> LegacyScope<'a> {
+        fragment.visit_with(&mut DefCollector::new(&mut self.definitions, parent_scope.expansion));
+        let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
+        fragment.visit_with(&mut visitor);
+        visitor.parent_scope.legacy
+    }
+
+    crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
+        let def_id = module.def_id().expect("unpopulated module without a def-id");
         for child in self.cstore.item_children_untracked(def_id, self.session) {
             let child = child.map_id(|_| panic!("unexpected id"));
-            BuildReducedGraphVisitor { parent_scope: self.dummy_parent_scope(), r: self }
-                .build_reduced_graph_for_external_crate_res(module, child);
+            BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) }
+                .build_reduced_graph_for_external_crate_res(child);
         }
-        module.populated.set(true)
     }
 }
 
-pub struct BuildReducedGraphVisitor<'a, 'b> {
-    pub r: &'b mut Resolver<'a>,
-    pub parent_scope: ParentScope<'a>,
+struct BuildReducedGraphVisitor<'a, 'b> {
+    r: &'b mut Resolver<'a>,
+    parent_scope: ParentScope<'a>,
+}
+
+impl<'a> AsMut<Resolver<'a>> for BuildReducedGraphVisitor<'a, '_> {
+    fn as_mut(&mut self) -> &mut Resolver<'a> { self.r }
 }
 
 impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
@@ -300,10 +313,9 @@
         root_id: NodeId,
         vis: ty::Visibility,
     ) {
-        let parent_scope = &self.parent_scope;
-        let current_module = parent_scope.module;
+        let current_module = self.parent_scope.module;
         let directive = self.r.arenas.alloc_import_directive(ImportDirective {
-            parent_scope: parent_scope.clone(),
+            parent_scope: self.parent_scope,
             module_path,
             imported_module: Cell::new(None),
             subclass,
@@ -593,15 +605,13 @@
                     self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
                 };
 
-                self.r.populate_module_if_necessary(module);
-
                 let used = self.process_legacy_macro_imports(item, module);
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
                 let directive = self.r.arenas.alloc_import_directive(ImportDirective {
                     root_id: item.id,
                     id: item.id,
-                    parent_scope: self.parent_scope.clone(),
+                    parent_scope: self.parent_scope,
                     imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
                     subclass: ImportDirectiveSubclass::ExternCrate {
                         source: orig_name,
@@ -706,7 +716,7 @@
                 self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
 
                 for variant in &(*enum_definition).variants {
-                    self.build_reduced_graph_for_variant(variant, module, vis, expansion);
+                    self.build_reduced_graph_for_variant(variant, module, vis);
                 }
             }
 
@@ -797,19 +807,19 @@
     fn build_reduced_graph_for_variant(&mut self,
                                        variant: &Variant,
                                        parent: Module<'a>,
-                                       vis: ty::Visibility,
-                                       expn_id: ExpnId) {
-        let ident = variant.node.ident;
+                                       vis: ty::Visibility) {
+        let expn_id = self.parent_scope.expansion;
+        let ident = variant.ident;
 
         // Define a name in the type namespace.
-        let def_id = self.r.definitions.local_def_id(variant.node.id);
+        let def_id = self.r.definitions.local_def_id(variant.id);
         let res = Res::Def(DefKind::Variant, def_id);
         self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id));
 
         // If the variant is marked as non_exhaustive then lower the visibility to within the
         // crate.
         let mut ctor_vis = vis;
-        let has_non_exhaustive = attr::contains_name(&variant.node.attrs, sym::non_exhaustive);
+        let has_non_exhaustive = attr::contains_name(&variant.attrs, sym::non_exhaustive);
         if has_non_exhaustive && vis == ty::Visibility::Public {
             ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
         }
@@ -819,9 +829,9 @@
         // value namespace, they are reserved for possible future use.
         // It's ok to use the variant's id as a ctor id since an
         // error will be reported on any use of such resolution anyway.
-        let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.id);
+        let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id);
         let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id);
-        let ctor_kind = CtorKind::from_ast(&variant.node.data);
+        let ctor_kind = CtorKind::from_ast(&variant.data);
         let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
         self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
     }
@@ -861,20 +871,19 @@
     }
 
     /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_res(
-        &mut self,
-        parent: Module<'a>,
-        child: Export<ast::NodeId>,
-    ) {
+    fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<ast::NodeId>) {
+        let parent = self.parent_scope.module;
         let Export { ident, res, vis, span } = child;
         // FIXME: We shouldn't create the gensym here, it should come from metadata,
         // but metadata cannot encode gensyms currently, so we create it here.
         // This is only a guess, two equivalent idents may incorrectly get different gensyms here.
         let ident = ident.gensym_if_underscore();
         let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene
+        // Record primary definitions.
         match res {
             Res::Def(kind @ DefKind::Mod, def_id)
-            | Res::Def(kind @ DefKind::Enum, def_id) => {
+            | Res::Def(kind @ DefKind::Enum, def_id)
+            | Res::Def(kind @ DefKind::Trait, def_id) => {
                 let module = self.r.new_module(parent,
                                              ModuleKind::Def(kind, def_id, ident.name),
                                              def_id,
@@ -882,70 +891,55 @@
                                              span);
                 self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
             }
-            Res::Def(DefKind::Variant, _)
+            Res::Def(DefKind::Struct, _)
+            | Res::Def(DefKind::Union, _)
+            | Res::Def(DefKind::Variant, _)
             | Res::Def(DefKind::TyAlias, _)
             | Res::Def(DefKind::ForeignTy, _)
             | Res::Def(DefKind::OpaqueTy, _)
             | Res::Def(DefKind::TraitAlias, _)
+            | Res::Def(DefKind::AssocTy, _)
+            | Res::Def(DefKind::AssocOpaqueTy, _)
             | Res::PrimTy(..)
-            | Res::ToolMod => {
-                self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
-            }
+            | Res::ToolMod =>
+                self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)),
             Res::Def(DefKind::Fn, _)
+            | Res::Def(DefKind::Method, _)
             | Res::Def(DefKind::Static, _)
             | Res::Def(DefKind::Const, _)
-            | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => {
-                self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
-            }
-            Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
-                self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
-
-                if let Some(struct_def_id) =
-                        self.r.cstore.def_key(def_id).parent
-                            .map(|index| DefId { krate: def_id.krate, index: index }) {
-                    self.r.struct_constructors.insert(struct_def_id, (res, vis));
-                }
-            }
-            Res::Def(DefKind::Trait, def_id) => {
-                let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name);
-                let module = self.r.new_module(parent,
-                                             module_kind,
-                                             parent.normal_ancestor_id,
-                                             expansion,
-                                             span);
-                self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
-
-                for child in self.r.cstore.item_children_untracked(def_id, self.r.session) {
-                    let res = child.res.map_id(|_| panic!("unexpected id"));
-                    let ns = if let Res::Def(DefKind::AssocTy, _) = res {
-                        TypeNS
-                    } else { ValueNS };
-                    self.r.define(module, child.ident, ns,
-                                (res, ty::Visibility::Public, DUMMY_SP, expansion));
-
-                    if self.r.cstore.associated_item_cloned_untracked(child.res.def_id())
-                           .method_has_self_argument {
-                        self.r.has_self.insert(res.def_id());
-                    }
-                }
-                module.populated.set(true);
-            }
+            | Res::Def(DefKind::AssocConst, _)
+            | Res::Def(DefKind::Ctor(..), _) =>
+                self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)),
+            Res::Def(DefKind::Macro(..), _)
+            | Res::NonMacroAttr(..) =>
+                self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)),
+            Res::Def(DefKind::TyParam, _) | Res::Def(DefKind::ConstParam, _)
+            | Res::Local(..) | Res::SelfTy(..) | Res::SelfCtor(..) | Res::Err =>
+                bug!("unexpected resolution: {:?}", res)
+        }
+        // Record some extra data for better diagnostics.
+        match res {
             Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
-                self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
-
-                // Record field names for error reporting.
                 let field_names = self.r.cstore.struct_field_names_untracked(def_id);
                 self.insert_field_names(def_id, field_names);
             }
-            Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
-                self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion));
+            Res::Def(DefKind::Method, def_id) => {
+                if self.r.cstore.associated_item_cloned_untracked(def_id).method_has_self_argument {
+                    self.r.has_self.insert(def_id);
+                }
             }
-            _ => bug!("unexpected resolution: {:?}", res)
+            Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
+                let parent = self.r.cstore.def_key(def_id).parent;
+                if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) {
+                    self.r.struct_constructors.insert(struct_def_id, (res, vis));
+                }
+            }
+            _ => {}
         }
     }
 
     fn legacy_import_macro(&mut self,
-                           name: Name,
+                           name: ast::Name,
                            binding: &'a NameBinding<'a>,
                            span: Span,
                            allow_shadowing: bool) {
@@ -997,7 +991,7 @@
                 |this: &Self, span| this.r.arenas.alloc_import_directive(ImportDirective {
             root_id: item.id,
             id: item.id,
-            parent_scope: this.parent_scope.clone(),
+            parent_scope: this.parent_scope,
             imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
             subclass: ImportDirectiveSubclass::MacroUse,
             use_span_with_attributes: item.span_with_attributes(),
@@ -1014,9 +1008,9 @@
         if let Some(span) = import_all {
             let directive = macro_use_directive(self, span);
             self.r.potentially_unused_imports.push(directive);
-            module.for_each_child(|ident, ns, binding| if ns == MacroNS {
-                let imported_binding = self.r.import(binding, directive);
-                self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
+            module.for_each_child(self, |this, ident, ns, binding| if ns == MacroNS {
+                let imported_binding = this.r.import(binding, directive);
+                this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
             });
         } else {
             for ident in single_imports.iter().cloned() {
@@ -1066,20 +1060,15 @@
         false
     }
 
-    fn visit_invoc(&mut self, id: ast::NodeId) -> &'a InvocationData<'a> {
+    fn visit_invoc(&mut self, id: ast::NodeId) -> LegacyScope<'a> {
         let invoc_id = id.placeholder_to_expn_id();
 
         self.parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id);
 
-        let invocation_data = self.r.arenas.alloc_invocation_data(InvocationData {
-            module: self.parent_scope.module,
-            parent_legacy_scope: self.parent_scope.legacy,
-            output_legacy_scope: Cell::new(None),
-        });
-        let old_invocation_data = self.r.invocations.insert(invoc_id, invocation_data);
-        assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation");
+        let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
+        assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
 
-        invocation_data
+        LegacyScope::Invocation(invoc_id)
     }
 
     fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
@@ -1180,7 +1169,7 @@
                 return
             }
             ItemKind::Mac(..) => {
-                self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(item.id));
+                self.parent_scope.legacy = self.visit_invoc(item.id);
                 return
             }
             ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
@@ -1199,7 +1188,7 @@
 
     fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
         if let ast::StmtKind::Mac(..) = stmt.node {
-            self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(stmt.id));
+            self.parent_scope.legacy = self.visit_invoc(stmt.id);
         } else {
             visit::walk_stmt(self, stmt);
         }
@@ -1267,9 +1256,7 @@
 
     fn visit_attribute(&mut self, attr: &'b ast::Attribute) {
         if !attr.is_sugared_doc && is_builtin_attr(attr) {
-            self.parent_scope.module.builtin_attrs.borrow_mut().push((
-                attr.path.segments[0].ident, self.parent_scope.clone()
-            ));
+            self.r.builtin_attrs.push((attr.path.segments[0].ident, self.parent_scope));
         }
         visit::walk_attribute(self, attr);
     }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 1de67ed..afdcec1 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -73,20 +73,23 @@
     false
 }
 
-crate fn add_module_candidates(
-    module: Module<'_>, names: &mut Vec<TypoSuggestion>, filter_fn: &impl Fn(Res) -> bool
-) {
-    for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
-        if let Some(binding) = resolution.borrow().binding {
-            let res = binding.res();
-            if filter_fn(res) {
-                names.push(TypoSuggestion::from_res(ident.name, res));
+impl<'a> Resolver<'a> {
+    crate fn add_module_candidates(
+        &mut self,
+        module: Module<'a>,
+        names: &mut Vec<TypoSuggestion>,
+        filter_fn: &impl Fn(Res) -> bool,
+    ) {
+        for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() {
+            if let Some(binding) = resolution.borrow().binding {
+                let res = binding.res();
+                if filter_fn(res) {
+                    names.push(TypoSuggestion::from_res(ident.name, res));
+                }
             }
         }
     }
-}
 
-impl<'a> Resolver<'a> {
     /// Combines an error with provided span and emits it.
     ///
     /// This takes the error provided, combines it with the span and any additional spans inside the
@@ -376,9 +379,9 @@
                 Scope::DeriveHelpers => {
                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
                     if filter_fn(res) {
-                        for derive in &parent_scope.derives {
+                        for derive in parent_scope.derives {
                             let parent_scope =
-                                &ParentScope { derives: Vec::new(), ..*parent_scope };
+                                &ParentScope { derives: &[], ..*parent_scope };
                             if let Ok((Some(ext), _)) = this.resolve_macro_path(
                                 derive, Some(MacroKind::Derive), parent_scope, false, false
                             ) {
@@ -402,10 +405,10 @@
                 Scope::CrateRoot => {
                     let root_ident = Ident::new(kw::PathRoot, ident.span);
                     let root_module = this.resolve_crate_root(root_ident);
-                    add_module_candidates(root_module, &mut suggestions, filter_fn);
+                    this.add_module_candidates(root_module, &mut suggestions, filter_fn);
                 }
                 Scope::Module(module) => {
-                    add_module_candidates(module, &mut suggestions, filter_fn);
+                    this.add_module_candidates(module, &mut suggestions, filter_fn);
                 }
                 Scope::MacroUsePrelude => {
                     suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
@@ -453,9 +456,9 @@
                 Scope::StdLibPrelude => {
                     if let Some(prelude) = this.prelude {
                         let mut tmp_suggestions = Vec::new();
-                        add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
+                        this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
                         suggestions.extend(tmp_suggestions.into_iter().filter(|s| {
-                            use_prelude || this.is_builtin_macro(s.res.opt_def_id())
+                            use_prelude || this.is_builtin_macro(s.res)
                         }));
                     }
                 }
@@ -509,11 +512,9 @@
         while let Some((in_module,
                         path_segments,
                         in_module_is_extern)) = worklist.pop() {
-            self.populate_module_if_necessary(in_module);
-
             // We have to visit module children in deterministic order to avoid
             // instabilities in reported imports (#43552).
-            in_module.for_each_child_stable(|ident, ns, name_binding| {
+            in_module.for_each_child_stable(self, |this, ident, ns, name_binding| {
                 // avoid imports entirely
                 if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
                 // avoid non-importable candidates as well
@@ -547,7 +548,7 @@
                         // outside crate private modules => no need to check this)
                         if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
                             let did = match res {
-                                Res::Def(DefKind::Ctor(..), did) => self.parent(did),
+                                Res::Def(DefKind::Ctor(..), did) => this.parent(did),
                                 _ => res.opt_def_id(),
                             };
                             candidates.push(ImportSuggestion { did, path });
@@ -595,7 +596,7 @@
         where FilterFn: Fn(Res) -> bool
     {
         let mut suggestions = self.lookup_import_candidates_from_module(
-            lookup_ident, namespace, self.graph_root, Ident::with_empty_ctxt(kw::Crate), &filter_fn
+            lookup_ident, namespace, self.graph_root, Ident::with_dummy_span(kw::Crate), &filter_fn
         );
 
         if lookup_ident.span.rust_2018() {
@@ -607,8 +608,6 @@
                         krate: crate_id,
                         index: CRATE_DEF_INDEX,
                     });
-                    self.populate_module_if_necessary(&crate_root);
-
                     suggestions.extend(self.lookup_import_candidates_from_module(
                         lookup_ident, namespace, crate_root, ident, &filter_fn));
                 }
@@ -805,7 +804,7 @@
     ///            at the root of the crate instead of the module where it is defined
     /// ```
     pub(crate) fn check_for_module_export_macro(
-        &self,
+        &mut self,
         directive: &'b ImportDirective<'b>,
         module: ModuleOrUniformRoot<'b>,
         ident: Ident,
@@ -826,7 +825,7 @@
             return None;
         }
 
-        let resolutions = crate_module.resolutions.borrow();
+        let resolutions = self.r.resolutions(crate_module).borrow();
         let resolution = resolutions.get(&(ident, MacroNS))?;
         let binding = resolution.borrow().binding()?;
         if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 358eaae..d8bd866 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -1,3 +1,10 @@
+//! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros.
+//! It runs when the crate is fully expanded and its module structure is fully built.
+//! So it just walks through the crate and resolves all the expressions, types, etc.
+//!
+//! If you wonder why there's no `early.rs`, that's because it's split into three files -
+//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`.
+
 use GenericParameters::*;
 use RibKind::*;
 
@@ -352,7 +359,7 @@
                 self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
             }
             TyKind::ImplicitSelf => {
-                let self_ty = Ident::with_empty_ctxt(kw::SelfUpper);
+                let self_ty = Ident::with_dummy_span(kw::SelfUpper);
                 let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span)
                               .map_or(Res::Err, |d| d.res());
                 self.r.record_partial_res(ty.id, PartialRes::new(res));
@@ -442,7 +449,7 @@
                 GenericParamKind::Type { ref default, .. } => {
                     found_default |= default.is_some();
                     if found_default {
-                        Some((Ident::with_empty_ctxt(param.ident.name), Res::Err))
+                        Some((Ident::with_dummy_span(param.ident.name), Res::Err))
                     } else {
                         None
                     }
@@ -459,7 +466,7 @@
                     false
                 }
             })
-            .map(|param| (Ident::with_empty_ctxt(param.ident.name), Res::Err)));
+            .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err)));
 
         for param in &generics.params {
             match param.kind {
@@ -476,7 +483,7 @@
                     }
 
                     // Allow all following defaults to refer to this type parameter.
-                    default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
+                    default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
                 }
                 GenericParamKind::Const { ref ty } => {
                     self.ribs[TypeNS].push(const_ty_param_ban_rib);
@@ -501,8 +508,8 @@
     fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> {
         // During late resolution we only track the module component of the parent scope,
         // although it may be useful to track other components as well for diagnostics.
-        let parent_scope = resolver.dummy_parent_scope();
         let graph_root = resolver.graph_root;
+        let parent_scope = ParentScope::module(graph_root);
         LateResolutionVisitor {
             r: resolver,
             parent_scope,
@@ -574,7 +581,6 @@
             self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
 
-            self.r.finalize_current_module_macro_resolutions(module);
             let ret = f(self);
 
             self.parent_scope.module = orig_module;
@@ -965,7 +971,7 @@
         let mut self_type_rib = Rib::new(NormalRibKind);
 
         // Plain insert (no renaming, since types are not currently hygienic)
-        self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
+        self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
         self.ribs[TypeNS].push(self_type_rib);
         f(self);
         self.ribs[TypeNS].pop();
@@ -976,7 +982,7 @@
     {
         let self_res = Res::SelfCtor(impl_id);
         let mut self_type_rib = Rib::new(NormalRibKind);
-        self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
+        self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
         self.ribs[ValueNS].push(self_type_rib);
         f(self);
         self.ribs[ValueNS].pop();
@@ -1227,7 +1233,6 @@
             self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
             self.parent_scope.module = anonymous_module;
-            self.r.finalize_current_module_macro_resolutions(anonymous_module);
         } else {
             self.ribs[ValueNS].push(Rib::new(NormalRibKind));
         }
@@ -1476,7 +1481,7 @@
                     self.r.trait_map.insert(id, traits);
                 }
 
-                let mut std_path = vec![Segment::from_ident(Ident::with_empty_ctxt(sym::std))];
+                let mut std_path = vec![Segment::from_ident(Ident::with_dummy_span(sym::std))];
                 std_path.extend(path);
                 if self.r.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) {
                     let cl = CrateLint::No;
@@ -1507,7 +1512,7 @@
 
     fn self_type_is_available(&mut self, span: Span) -> bool {
         let binding = self.resolve_ident_in_lexical_scope(
-            Ident::with_empty_ctxt(kw::SelfUpper),
+            Ident::with_dummy_span(kw::SelfUpper),
             TypeNS,
             None,
             span,
@@ -1924,7 +1929,7 @@
         let mut traits = module.traits.borrow_mut();
         if traits.is_none() {
             let mut collected_traits = Vec::new();
-            module.for_each_child(|name, ns, binding| {
+            module.for_each_child(self.r, |_, name, ns, binding| {
                 if ns != TypeNS { return }
                 match binding.res() {
                     Res::Def(DefKind::Trait, _) |
@@ -1984,7 +1989,6 @@
 
 impl<'a> Resolver<'a> {
     pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
-        self.finalize_current_module_macro_resolutions(self.graph_root);
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
         visit::walk_crate(&mut late_resolution_visitor, krate);
         for (id, span) in late_resolution_visitor.unused_labels.iter() {
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 68f9c16..a822fa0 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -1,8 +1,7 @@
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 use crate::path_names_to_string;
-use crate::diagnostics::{add_typo_suggestion, add_module_candidates};
-use crate::diagnostics::{ImportSuggestion, TypoSuggestion};
+use crate::diagnostics::{add_typo_suggestion, ImportSuggestion, TypoSuggestion};
 use crate::late::{LateResolutionVisitor, RibKind};
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
@@ -548,7 +547,7 @@
                 // Items in scope
                 if let RibKind::ModuleRibKind(module) = rib.kind {
                     // Items from this module
-                    add_module_candidates(module, &mut names, &filter_fn);
+                    self.r.add_module_candidates(module, &mut names, &filter_fn);
 
                     if let ModuleKind::Block(..) = module.kind {
                         // We can see through blocks
@@ -577,7 +576,7 @@
                             }));
 
                             if let Some(prelude) = self.r.prelude {
-                                add_module_candidates(prelude, &mut names, &filter_fn);
+                                self.r.add_module_candidates(prelude, &mut names, &filter_fn);
                             }
                         }
                         break;
@@ -599,7 +598,7 @@
                 mod_path, Some(TypeNS), false, span, CrateLint::No
             ) {
                 if let ModuleOrUniformRoot::Module(module) = module {
-                    add_module_candidates(module, &mut names, &filter_fn);
+                    self.r.add_module_candidates(module, &mut names, &filter_fn);
                 }
             }
         }
@@ -717,9 +716,7 @@
             // abort if the module is already found
             if result.is_some() { break; }
 
-            self.r.populate_module_if_necessary(in_module);
-
-            in_module.for_each_child_stable(|ident, _, name_binding| {
+            in_module.for_each_child_stable(self.r, |_, ident, _, name_binding| {
                 // abort if the module is already found or if name_binding is private external
                 if result.is_some() || !name_binding.vis.is_visible_locally() {
                     return
@@ -750,10 +747,8 @@
 
     fn collect_enum_variants(&mut self, def_id: DefId) -> Option<Vec<Path>> {
         self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
-            self.r.populate_module_if_necessary(enum_module);
-
             let mut variants = Vec::new();
-            enum_module.for_each_child_stable(|ident, _, name_binding| {
+            enum_module.for_each_child_stable(self.r, |_, ident, _, name_binding| {
                 if let Res::Def(DefKind::Variant, _) = name_binding.res() {
                     let mut segms = enum_import_suggestion.path.segments.clone();
                     segms.push(ast::PathSegment::from_ident(ident));
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 8a4a60c..12c4f5b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1,3 +1,12 @@
+//! This crate is responsible for the part of name resolution that doesn't require type checker.
+//!
+//! Module structure of the crate is built here.
+//! Paths in macros, imports, expressions, types, patterns are resolved here.
+//! Label names are resolved here as well.
+//!
+//! Type-relative name resolution (methods, fields, associated items) happens in `librustc_typeck`.
+//! Lifetime names are resolved in `librustc/middle/resolve_lifetime.rs`.
+
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(crate_visibility_modifier)]
@@ -54,7 +63,7 @@
 use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
 use late::{PathSource, Rib, RibKind::*};
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
-use macros::{InvocationData, LegacyBinding, LegacyScope};
+use macros::{LegacyBinding, LegacyScope};
 
 type Res = def::Res<NodeId>;
 
@@ -122,12 +131,25 @@
 /// Serves as a starting point for the scope visitor.
 /// This struct is currently used only for early resolution (imports and macros),
 /// but not for late resolution yet.
-#[derive(Clone, Debug)]
+#[derive(Clone, Copy, Debug)]
 pub struct ParentScope<'a> {
     module: Module<'a>,
     expansion: ExpnId,
     legacy: LegacyScope<'a>,
-    derives: Vec<ast::Path>,
+    derives: &'a [ast::Path],
+}
+
+impl<'a> ParentScope<'a> {
+    /// Creates a parent scope with the passed argument used as the module scope component,
+    /// and other scope components set to default empty values.
+    pub fn module(module: Module<'a>) -> ParentScope<'a> {
+        ParentScope {
+            module,
+            expansion: ExpnId::root(),
+            legacy: LegacyScope::Empty,
+            derives: &[],
+        }
+    }
 }
 
 #[derive(Eq)]
@@ -274,7 +296,7 @@
                 ItemKind::Use(..) => {
                     // don't suggest placing a use before the prelude
                     // import or other generated ones
-                    if item.span.ctxt().outer_expn_info().is_none() {
+                    if !item.span.from_expansion() {
                         self.span = Some(item.span.shrink_to_lo());
                         self.found_use = true;
                         return;
@@ -284,7 +306,7 @@
                 ItemKind::ExternCrate(_) => {}
                 // but place them before the first other item
                 _ => if self.span.map_or(true, |span| item.span < span ) {
-                    if item.span.ctxt().outer_expn_info().is_none() {
+                    if !item.span.from_expansion() {
                         // don't insert between attributes and an item
                         if item.attrs.is_empty() {
                             self.span = Some(item.span.shrink_to_lo());
@@ -409,6 +431,8 @@
     }
 }
 
+type Resolutions<'a> = RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>;
+
 /// One node in the tree of modules.
 pub struct ModuleData<'a> {
     parent: Option<Module<'a>>,
@@ -417,12 +441,11 @@
     // The def id of the closest normal module (`mod`) ancestor (including this module).
     normal_ancestor_id: DefId,
 
-    resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
-    single_segment_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
-                                                   Option<&'a NameBinding<'a>>)>>,
-    multi_segment_macro_resolutions: RefCell<Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>,
-                                                  Option<Res>)>>,
-    builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>,
+    // Mapping between names and their (possibly in-progress) resolutions in this module.
+    // Resolutions in modules from other crates are not populated until accessed.
+    lazy_resolutions: Resolutions<'a>,
+    // True if this is a module from other crate that needs to be populated on access.
+    populate_on_access: Cell<bool>,
 
     // Macro invocations that can expand into items in this module.
     unresolved_invocations: RefCell<FxHashSet<ExpnId>>,
@@ -435,11 +458,6 @@
     // Used to memoize the traits in this module for faster searches through all traits in scope.
     traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
 
-    // Whether this module is populated. If not populated, any attempt to
-    // access the children must be preceded with a
-    // `populate_module_if_necessary` call.
-    populated: Cell<bool>,
-
     /// Span of the module itself. Used for error reporting.
     span: Span,
 
@@ -458,33 +476,34 @@
             parent,
             kind,
             normal_ancestor_id,
-            resolutions: Default::default(),
-            single_segment_macro_resolutions: RefCell::new(Vec::new()),
-            multi_segment_macro_resolutions: RefCell::new(Vec::new()),
-            builtin_attrs: RefCell::new(Vec::new()),
+            lazy_resolutions: Default::default(),
+            populate_on_access: Cell::new(!normal_ancestor_id.is_local()),
             unresolved_invocations: Default::default(),
             no_implicit_prelude: false,
             glob_importers: RefCell::new(Vec::new()),
             globs: RefCell::new(Vec::new()),
             traits: RefCell::new(None),
-            populated: Cell::new(normal_ancestor_id.is_local()),
             span,
             expansion,
         }
     }
 
-    fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
-        for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() {
-            name_resolution.borrow().binding.map(|binding| f(ident, ns, binding));
+    fn for_each_child<R, F>(&'a self, resolver: &mut R, mut f: F)
+        where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>)
+    {
+        for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
+            name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
         }
     }
 
-    fn for_each_child_stable<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
-        let resolutions = self.resolutions.borrow();
+    fn for_each_child_stable<R, F>(&'a self, resolver: &mut R, mut f: F)
+        where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>)
+    {
+        let resolutions = resolver.as_mut().resolutions(self).borrow();
         let mut resolutions = resolutions.iter().collect::<Vec<_>>();
         resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns));
         for &(&(ident, ns), &resolution) in resolutions.iter() {
-            resolution.borrow().binding.map(|binding| f(ident, ns, binding));
+            resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
         }
     }
 
@@ -807,7 +826,7 @@
 
     pub definitions: Definitions,
 
-    graph_root: Module<'a>,
+    pub graph_root: Module<'a>,
 
     prelude: Option<Module<'a>>,
     pub extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
@@ -896,15 +915,24 @@
     local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
     unused_macros: NodeMap<Span>,
     proc_macro_stubs: NodeSet,
+    /// Traces collected during macro resolution and validated when it's complete.
+    single_segment_macro_resolutions: Vec<(Ident, MacroKind, ParentScope<'a>,
+                                           Option<&'a NameBinding<'a>>)>,
+    multi_segment_macro_resolutions: Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>,
+                                          Option<Res>)>,
+    builtin_attrs: Vec<(Ident, ParentScope<'a>)>,
     /// Some built-in derives mark items they are applied to so they are treated specially later.
     /// Derive macros cannot modify the item themselves and have to store the markers in the global
     /// context, so they attach the markers to derive container IDs using this resolver table.
     /// FIXME: Find a way for `PartialEq` and `Eq` to emulate `#[structural_match]`
     /// by marking the produced impls rather than the original items.
     special_derives: FxHashMap<ExpnId, SpecialDerives>,
-
-    /// Maps the `ExpnId` of an expansion to its containing module or block.
-    invocations: FxHashMap<ExpnId, &'a InvocationData<'a>>,
+    /// Parent scopes in which the macros were invoked.
+    /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
+    invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
+    /// Legacy scopes *produced* by expanding the macro invocations,
+    /// include all the `macro_rules` items and other invocations generated by them.
+    output_legacy_scopes: FxHashMap<ExpnId, LegacyScope<'a>>,
 
     /// Avoid duplicated errors for "name already defined".
     name_already_seen: FxHashMap<Name, Span>,
@@ -927,8 +955,8 @@
     name_bindings: arena::TypedArena<NameBinding<'a>>,
     import_directives: arena::TypedArena<ImportDirective<'a>>,
     name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
-    invocation_data: arena::TypedArena<InvocationData<'a>>,
     legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
+    ast_paths: arena::TypedArena<ast::Path>,
 }
 
 impl<'a> ResolverArenas<'a> {
@@ -952,13 +980,16 @@
     fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
         self.name_resolutions.alloc(Default::default())
     }
-    fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>)
-                             -> &'a InvocationData<'a> {
-        self.invocation_data.alloc(expansion_data)
-    }
     fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> {
         self.legacy_bindings.alloc(binding)
     }
+    fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] {
+        self.ast_paths.alloc_from_iter(paths.iter().cloned())
+    }
+}
+
+impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
+    fn as_mut(&mut self) -> &mut Resolver<'a> { self }
 }
 
 impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> {
@@ -985,11 +1016,11 @@
         } else {
             kw::Crate
         };
-        let segments = iter::once(Ident::with_empty_ctxt(root))
+        let segments = iter::once(Ident::with_dummy_span(root))
             .chain(
                 crate_root.into_iter()
                     .chain(components.iter().cloned())
-                    .map(Ident::with_empty_ctxt)
+                    .map(Ident::with_dummy_span)
             ).map(|i| self.new_ast_path_segment(i)).collect::<Vec<_>>();
 
         let path = ast::Path {
@@ -997,7 +1028,7 @@
             segments,
         };
 
-        let parent_scope = &self.dummy_parent_scope();
+        let parent_scope = &ParentScope::module(self.graph_root);
         let res = match self.resolve_ast_path(&path, ns, parent_scope) {
             Ok(res) => res,
             Err((span, error)) => {
@@ -1060,18 +1091,17 @@
                                        .collect();
 
         if !attr::contains_name(&krate.attrs, sym::no_core) {
-            extern_prelude.insert(Ident::with_empty_ctxt(sym::core), Default::default());
+            extern_prelude.insert(Ident::with_dummy_span(sym::core), Default::default());
             if !attr::contains_name(&krate.attrs, sym::no_std) {
-                extern_prelude.insert(Ident::with_empty_ctxt(sym::std), Default::default());
+                extern_prelude.insert(Ident::with_dummy_span(sym::std), Default::default());
                 if session.rust_2018() {
-                    extern_prelude.insert(Ident::with_empty_ctxt(sym::meta), Default::default());
+                    extern_prelude.insert(Ident::with_dummy_span(sym::meta), Default::default());
                 }
             }
         }
 
-        let mut invocations = FxHashMap::default();
-        invocations.insert(ExpnId::root(),
-                           arenas.alloc_invocation_data(InvocationData::root(graph_root)));
+        let mut invocation_parent_scopes = FxHashMap::default();
+        invocation_parent_scopes.insert(ExpnId::root(), ParentScope::module(graph_root));
 
         let mut macro_defs = FxHashMap::default();
         macro_defs.insert(ExpnId::root(), root_def_id);
@@ -1143,7 +1173,8 @@
             dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())),
             dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
             non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
-            invocations,
+            invocation_parent_scopes,
+            output_legacy_scopes: Default::default(),
             macro_defs,
             local_macro_def_scopes: FxHashMap::default(),
             name_already_seen: FxHashMap::default(),
@@ -1151,6 +1182,9 @@
             struct_constructors: Default::default(),
             unused_macros: Default::default(),
             proc_macro_stubs: Default::default(),
+            single_segment_macro_resolutions: Default::default(),
+            multi_segment_macro_resolutions: Default::default(),
+            builtin_attrs: Default::default(),
             special_derives: Default::default(),
             active_features:
                 features.declared_lib_features.iter().map(|(feat, ..)| *feat)
@@ -1182,9 +1216,8 @@
         f(self, MacroNS);
     }
 
-    fn is_builtin_macro(&mut self, def_id: Option<DefId>) -> bool {
-        def_id.and_then(|def_id| self.get_macro_by_def_id(def_id))
-              .map_or(false, |ext| ext.is_builtin)
+    fn is_builtin_macro(&mut self, res: Res) -> bool {
+        self.get_macro(res).map_or(false, |ext| ext.is_builtin)
     }
 
     fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
@@ -1203,6 +1236,7 @@
     /// Entry point to crate resolution.
     pub fn resolve_crate(&mut self, krate: &Crate) {
         ImportResolver { r: self }.finalize_imports();
+        self.finalize_macro_resolutions();
 
         self.late_resolve_crate(krate);
 
@@ -1223,6 +1257,20 @@
         self.arenas.alloc_module(module)
     }
 
+    fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> {
+        if module.populate_on_access.get() {
+            module.populate_on_access.set(false);
+            self.build_reduced_graph_external(module);
+        }
+        &module.lazy_resolutions
+    }
+
+    fn resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace)
+                  -> &'a RefCell<NameResolution<'a>> {
+        *self.resolutions(module).borrow_mut().entry((ident.modern(), ns))
+               .or_insert_with(|| self.arenas.alloc_name_resolution())
+    }
+
     fn record_use(&mut self, ident: Ident, ns: Namespace,
                   used_binding: &'a NameBinding<'a>, is_lexical_scope: bool) {
         if let Some((b2, kind)) = used_binding.ambiguity {
@@ -1319,13 +1367,15 @@
             ScopeSet::AbsolutePath(ns) => (ns, true),
             ScopeSet::Macro(_) => (MacroNS, false),
         };
+        // Jump out of trait or enum modules, they do not act as scopes.
+        let module = parent_scope.module.nearest_item_scope();
         let mut scope = match ns {
             _ if is_absolute_path => Scope::CrateRoot,
-            TypeNS | ValueNS => Scope::Module(parent_scope.module),
+            TypeNS | ValueNS => Scope::Module(module),
             MacroNS => Scope::DeriveHelpers,
         };
         let mut ident = ident.modern();
-        let mut use_prelude = !parent_scope.module.no_implicit_prelude;
+        let mut use_prelude = !module.no_implicit_prelude;
 
         loop {
             let visit = match scope {
@@ -1355,10 +1405,11 @@
                     LegacyScope::Binding(binding) => Scope::MacroRules(
                         binding.parent_legacy_scope
                     ),
-                    LegacyScope::Invocation(invoc) => Scope::MacroRules(
-                        invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
+                    LegacyScope::Invocation(invoc_id) => Scope::MacroRules(
+                        self.output_legacy_scopes.get(&invoc_id).cloned()
+                            .unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy)
                     ),
-                    LegacyScope::Empty => Scope::Module(parent_scope.module),
+                    LegacyScope::Empty => Scope::Module(module),
                 }
                 Scope::CrateRoot => match ns {
                     TypeNS => {
@@ -1430,7 +1481,7 @@
         }
         let (general_span, modern_span) = if ident.name == kw::SelfUpper {
             // FIXME(jseyfried) improve `Self` hygiene
-            let empty_span = ident.span.with_ctxt(SyntaxContext::empty());
+            let empty_span = ident.span.with_ctxt(SyntaxContext::root());
             (empty_span, empty_span)
         } else if ns == TypeNS {
             let modern_span = ident.span.modern();
@@ -1501,7 +1552,7 @@
                 self.hygienic_lexical_parent(module, &mut ident.span)
             };
             module = unwrap_or!(opt_module, break);
-            let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() };
+            let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
             let result = self.resolve_ident_in_module_unadjusted(
                 ModuleOrUniformRoot::Module(module),
                 ident,
@@ -1637,7 +1688,7 @@
             ModuleOrUniformRoot::Module(m) => {
                 if let Some(def) = ident.span.modernize_and_adjust(m.expansion) {
                     tmp_parent_scope =
-                        ParentScope { module: self.macro_def_scope(def), ..parent_scope.clone() };
+                        ParentScope { module: self.macro_def_scope(def), ..*parent_scope };
                     adjusted_parent_scope = &tmp_parent_scope;
                 }
             }
@@ -2606,7 +2657,6 @@
                     return None;
                 };
                 let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
-                self.populate_module_if_necessary(&crate_root);
                 Some((crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root())
                     .to_name_binding(self.arenas))
             }
@@ -2624,7 +2674,7 @@
         let path = if path_str.starts_with("::") {
             ast::Path {
                 span,
-                segments: iter::once(Ident::with_empty_ctxt(kw::PathRoot))
+                segments: iter::once(Ident::with_dummy_span(kw::PathRoot))
                     .chain({
                         path_str.split("::").skip(1).map(Ident::from_str)
                     })
@@ -2645,7 +2695,7 @@
             let def_id = self.definitions.local_def_id(module_id);
             self.module_map.get(&def_id).copied().unwrap_or(self.graph_root)
         });
-        let parent_scope = &ParentScope { module, ..self.dummy_parent_scope() };
+        let parent_scope = &ParentScope::module(module);
         let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?;
         Ok((path, res))
     }
@@ -2713,7 +2763,7 @@
     fn collect_mod(names: &mut Vec<Ident>, module: Module<'_>) {
         if let ModuleKind::Def(.., name) = module.kind {
             if let Some(parent) = module.parent {
-                names.push(Ident::with_empty_ctxt(name));
+                names.push(Ident::with_dummy_span(name));
                 collect_mod(names, parent);
             }
         } else {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 8e9e138..6f49377 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -1,12 +1,13 @@
+//! A bunch of methods and structures more or less related to resolving macros and
+//! interface provided by `Resolver` to macro expander.
+
 use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
 use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak};
-use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
+use crate::{ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
 use crate::{ModuleOrUniformRoot, KNOWN_TOOLS};
 use crate::Namespace::*;
-use crate::build_reduced_graph::BuildReducedGraphVisitor;
 use crate::resolve_imports::ImportResolver;
 use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc::hir::map::DefCollector;
 use rustc::middle::stability;
 use rustc::{ty, lint, span_bug};
 use syntax::ast::{self, Ident};
@@ -15,43 +16,18 @@
 use syntax::ext::base::{self, Indeterminate, SpecialDerives};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
-use syntax::ext::hygiene::{self, ExpnId, ExpnInfo, ExpnKind};
+use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
 use syntax::feature_gate::GateIssue;
 use syntax::symbol::{Symbol, kw, sym};
 use syntax_pos::{Span, DUMMY_SP};
 
-use std::cell::Cell;
 use std::{mem, ptr};
 use rustc_data_structures::sync::Lrc;
 
 type Res = def::Res<ast::NodeId>;
 
-// FIXME: Merge this with `ParentScope`.
-#[derive(Clone, Debug)]
-pub struct InvocationData<'a> {
-    /// The module in which the macro was invoked.
-    crate module: Module<'a>,
-    /// The legacy scope in which the macro was invoked.
-    /// The invocation path is resolved in this scope.
-    crate parent_legacy_scope: LegacyScope<'a>,
-    /// The legacy scope *produced* by expanding this macro invocation,
-    /// includes all the macro_rules items, other invocations, etc generated by it.
-    /// `None` if the macro is not expanded yet.
-    crate output_legacy_scope: Cell<Option<LegacyScope<'a>>>,
-}
-
-impl<'a> InvocationData<'a> {
-    pub fn root(graph_root: Module<'a>) -> Self {
-        InvocationData {
-            module: graph_root,
-            parent_legacy_scope: LegacyScope::Empty,
-            output_legacy_scope: Cell::new(None),
-        }
-    }
-}
-
 /// Binding produced by a `macro_rules` item.
 /// Not modularized, can shadow previous legacy bindings, etc.
 #[derive(Debug)]
@@ -75,7 +51,7 @@
     Binding(&'a LegacyBinding<'a>),
     /// The scope introduced by a macro invocation that can potentially
     /// create a `macro_rules!` macro definition.
-    Invocation(&'a InvocationData<'a>),
+    Invocation(ExpnId),
 }
 
 // Macro namespace is separated into two sub-namespaces, one for bang macros and
@@ -120,17 +96,12 @@
     }
 
     fn get_module_scope(&mut self, id: ast::NodeId) -> ExpnId {
-        let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::default(
+        let expn_id = ExpnId::fresh(Some(ExpnData::default(
             ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition()
-        ));
-        let expn_id = span.ctxt().outer_expn();
+        )));
         let module = self.module_map[&self.definitions.local_def_id(id)];
+        self.invocation_parent_scopes.insert(expn_id, ParentScope::module(module));
         self.definitions.set_invocation_parent(expn_id, module.def_id().unwrap().index);
-        self.invocations.insert(expn_id, self.arenas.alloc_invocation_data(InvocationData {
-            module,
-            parent_legacy_scope: LegacyScope::Empty,
-            output_legacy_scope: Cell::new(None),
-        }));
         expn_id
     }
 
@@ -144,29 +115,23 @@
         });
     }
 
-    fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment,
-                                            derives: &[ExpnId]) {
-        fragment.visit_with(&mut DefCollector::new(&mut self.definitions, expn_id));
-
-        let invocation = self.invocations[&expn_id];
-        invocation.module.unresolved_invocations.borrow_mut().remove(&expn_id);
-        invocation.module.unresolved_invocations.borrow_mut().extend(derives);
-        let parent_def = self.definitions.invocation_parent(expn_id);
+    fn visit_ast_fragment_with_placeholders(
+        &mut self, expansion: ExpnId, fragment: &AstFragment, derives: &[ExpnId]
+    ) {
+        // Fill in some data for derives if the fragment is from a derive container.
+        // We are inside the `expansion` now, but other parent scope components are still the same.
+        let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
+        let parent_def = self.definitions.invocation_parent(expansion);
+        self.invocation_parent_scopes.extend(derives.iter().map(|&derive| (derive, parent_scope)));
         for &derive_invoc_id in derives {
             self.definitions.set_invocation_parent(derive_invoc_id, parent_def);
         }
-        self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
-        let mut visitor = BuildReducedGraphVisitor {
-            r: self,
-            parent_scope: ParentScope {
-                module: invocation.module,
-                expansion: expn_id,
-                legacy: invocation.parent_legacy_scope,
-                derives: Vec::new(),
-            },
-        };
-        fragment.visit_with(&mut visitor);
-        invocation.output_legacy_scope.set(Some(visitor.parent_scope.legacy));
+        parent_scope.module.unresolved_invocations.borrow_mut().remove(&expansion);
+        parent_scope.module.unresolved_invocations.borrow_mut().extend(derives);
+
+        // Integrate the new AST fragment into all the definition and module structures.
+        let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope);
+        self.output_legacy_scopes.insert(expansion, output_legacy_scope);
     }
 
     fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) {
@@ -182,13 +147,14 @@
 
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool)
                                 -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
-        let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
+        let parent_scope = self.invocation_parent_scopes[&invoc_id];
+        let (path, kind, derives, after_derive) = match invoc.kind {
             InvocationKind::Attr { ref attr, ref derives, after_derive, .. } =>
-                (&attr.path, MacroKind::Attr, derives.clone(), after_derive),
+                (&attr.path, MacroKind::Attr, self.arenas.alloc_ast_paths(derives), after_derive),
             InvocationKind::Bang { ref mac, .. } =>
-                (&mac.node.path, MacroKind::Bang, Vec::new(), false),
+                (&mac.path, MacroKind::Bang, &[][..], false),
             InvocationKind::Derive { ref path, .. } =>
-                (path, MacroKind::Derive, Vec::new(), false),
+                (path, MacroKind::Derive, &[][..], false),
             InvocationKind::DeriveContainer { ref derives, .. } => {
                 // Block expansion of derives in the container until we know whether one of them
                 // is a built-in `Copy`. Skip the resolution if there's only one derive - either
@@ -196,10 +162,9 @@
                 // will automatically knows about itself.
                 let mut result = Ok(None);
                 if derives.len() > 1 {
-                    let parent_scope = &self.invoc_parent_scope(invoc_id, Vec::new());
                     for path in derives {
                         match self.resolve_macro_path(path, Some(MacroKind::Derive),
-                                                      parent_scope, true, force) {
+                                                      &parent_scope, true, force) {
                             Ok((Some(ref ext), _)) if ext.is_derive_copy => {
                                 self.add_derives(invoc.expansion_data.id, SpecialDerives::COPY);
                                 return Ok(None);
@@ -213,11 +178,14 @@
             }
         };
 
-        let parent_scope = &self.invoc_parent_scope(invoc_id, derives_in_scope);
+        // Derives are not included when `invocations` are collected, so we have to add them here.
+        let parent_scope = &ParentScope { derives, ..parent_scope };
         let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;
 
         let span = invoc.span();
-        invoc.expansion_data.id.set_expn_info(ext.expn_info(span, fast_print_path(path)));
+        invoc.expansion_data.id.set_expn_data(
+            ext.expn_data(parent_scope.expansion, span, fast_print_path(path))
+        );
 
         if let Res::Def(_, def_id) = res {
             if after_derive {
@@ -251,20 +219,6 @@
 }
 
 impl<'a> Resolver<'a> {
-    pub fn dummy_parent_scope(&self) -> ParentScope<'a> {
-        self.invoc_parent_scope(ExpnId::root(), Vec::new())
-    }
-
-    fn invoc_parent_scope(&self, invoc_id: ExpnId, derives: Vec<ast::Path>) -> ParentScope<'a> {
-        let invoc = self.invocations[&invoc_id];
-        ParentScope {
-            module: invoc.module.nearest_item_scope(),
-            expansion: invoc_id.parent(),
-            legacy: invoc.parent_legacy_scope,
-            derives,
-        }
-    }
-
     /// Resolve macro path with error reporting and recovery.
     fn smart_resolve_macro_path(
         &mut self,
@@ -346,8 +300,7 @@
 
         // Possibly apply the macro helper hack
         if kind == Some(MacroKind::Bang) && path.len() == 1 &&
-           path[0].ident.span.ctxt().outer_expn_info()
-               .map_or(false, |info| info.local_inner_macros) {
+           path[0].ident.span.ctxt().outer_expn_data().local_inner_macros {
             let root = Ident::new(kw::DollarCrate, path[0].ident.span);
             path.insert(0, Segment::from_ident(root));
         }
@@ -367,8 +320,8 @@
 
             if trace {
                 let kind = kind.expect("macro kind must be specified if tracing is enabled");
-                parent_scope.module.multi_segment_macro_resolutions.borrow_mut()
-                    .push((path, path_span, kind, parent_scope.clone(), res.ok()));
+                self.multi_segment_macro_resolutions
+                    .push((path, path_span, kind, *parent_scope, res.ok()));
             }
 
             self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
@@ -384,8 +337,8 @@
 
             if trace {
                 let kind = kind.expect("macro kind must be specified if tracing is enabled");
-                parent_scope.module.single_segment_macro_resolutions.borrow_mut()
-                    .push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
+                self.single_segment_macro_resolutions
+                    .push((path[0].ident, kind, *parent_scope, binding.ok()));
             }
 
             let res = binding.map(|binding| binding.res());
@@ -454,8 +407,8 @@
             let result = match scope {
                 Scope::DeriveHelpers => {
                     let mut result = Err(Determinacy::Determined);
-                    for derive in &parent_scope.derives {
-                        let parent_scope = &ParentScope { derives: Vec::new(), ..*parent_scope };
+                    for derive in parent_scope.derives {
+                        let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
                         match this.resolve_macro_path(derive, Some(MacroKind::Derive),
                                                       parent_scope, true, force) {
                             Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
@@ -475,8 +428,9 @@
                 Scope::MacroRules(legacy_scope) => match legacy_scope {
                     LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
                         Ok((legacy_binding.binding, Flags::MACRO_RULES)),
-                    LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() =>
-                        Err(Determinacy::Undetermined),
+                    LegacyScope::Invocation(invoc_id)
+                        if !this.output_legacy_scopes.contains_key(&invoc_id) =>
+                            Err(Determinacy::Undetermined),
                     _ => Err(Determinacy::Determined),
                 }
                 Scope::CrateRoot => {
@@ -500,7 +454,7 @@
                     }
                 }
                 Scope::Module(module) => {
-                    let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() };
+                    let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
                     let binding = this.resolve_ident_in_module_unadjusted_ext(
                         ModuleOrUniformRoot::Module(module),
                         ident,
@@ -575,7 +529,7 @@
                             false,
                             path_span,
                         ) {
-                            if use_prelude || this.is_builtin_macro(binding.res().opt_def_id()) {
+                            if use_prelude || this.is_builtin_macro(binding.res()) {
                                 result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
                             }
                         }
@@ -694,7 +648,7 @@
         }
     }
 
-    pub fn finalize_current_module_macro_resolutions(&mut self, module: Module<'a>) {
+    crate fn finalize_macro_resolutions(&mut self) {
         let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind,
                                  initial_res: Option<Res>, res: Res| {
             if let Some(initial_res) = initial_res {
@@ -730,8 +684,7 @@
             }
         };
 
-        let macro_resolutions =
-            mem::take(&mut *module.multi_segment_macro_resolutions.borrow_mut());
+        let macro_resolutions = mem::take(&mut self.multi_segment_macro_resolutions);
         for (mut path, path_span, kind, parent_scope, initial_res) in macro_resolutions {
             // FIXME: Path resolution will ICE if segment IDs present.
             for seg in &mut path { seg.id = None; }
@@ -758,8 +711,7 @@
             }
         }
 
-        let macro_resolutions =
-            mem::take(&mut *module.single_segment_macro_resolutions.borrow_mut());
+        let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions);
         for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
             match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
                                                             &parent_scope, true, true, ident.span) {
@@ -784,7 +736,7 @@
             }
         }
 
-        let builtin_attrs = mem::take(&mut *module.builtin_attrs.borrow_mut());
+        let builtin_attrs = mem::take(&mut self.builtin_attrs);
         for (ident, parent_scope) in builtin_attrs {
             let _ = self.early_resolve_ident_in_lexical_scope(
                 ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 00e89f0fda..b49f186 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1,3 +1,5 @@
+//! A bunch of methods and structures more or less related to resolving imports.
+
 use ImportDirectiveSubclass::*;
 
 use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
@@ -5,9 +7,8 @@
 use crate::Determinacy::{self, *};
 use crate::Namespace::{self, TypeNS, MacroNS};
 use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
-use crate::{Resolver, ResolutionError, Segment};
+use crate::{Resolver, ResolutionError, Segment, ModuleKind};
 use crate::{names_to_string, module_to_string};
-use crate::ModuleKind;
 use crate::diagnostics::Suggestion;
 
 use errors::Applicability;
@@ -35,7 +36,7 @@
 
 use log::*;
 
-use std::cell::{Cell, RefCell};
+use std::cell::Cell;
 use std::{mem, ptr};
 
 type Res = def::Res<NodeId>;
@@ -159,12 +160,6 @@
 }
 
 impl<'a> Resolver<'a> {
-    crate fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
-                  -> &'a RefCell<NameResolution<'a>> {
-        *module.resolutions.borrow_mut().entry((ident.modern(), ns))
-               .or_insert_with(|| self.arenas.alloc_name_resolution())
-    }
-
     crate fn resolve_ident_in_module_unadjusted(
         &mut self,
         module: ModuleOrUniformRoot<'a>,
@@ -240,8 +235,6 @@
             }
         };
 
-        self.populate_module_if_necessary(module);
-
         let resolution = self.resolution(module, ident, ns)
             .try_borrow_mut()
             .map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
@@ -394,7 +387,7 @@
             match ident.span.glob_adjust(module.expansion, glob_import.span) {
                 Some(Some(def)) => {
                     tmp_parent_scope =
-                        ParentScope { module: self.macro_def_scope(def), ..parent_scope.clone() };
+                        ParentScope { module: self.macro_def_scope(def), ..*parent_scope };
                     adjusted_parent_scope = &tmp_parent_scope;
                 }
                 Some(None) => {}
@@ -848,7 +841,7 @@
         directive.vis.set(orig_vis);
         let module = match path_res {
             PathResult::Module(module) => {
-                // Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
+                // Consistency checks, analogous to `finalize_macro_resolutions`.
                 if let Some(initial_module) = directive.imported_module.get() {
                     if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity {
                         span_bug!(directive.span, "inconsistent resolution for an import");
@@ -973,7 +966,7 @@
 
             match binding {
                 Ok(binding) => {
-                    // Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
+                    // Consistency checks, analogous to `finalize_macro_resolutions`.
                     let initial_res = source_bindings[ns].get().map(|initial_binding| {
                         all_ns_err = false;
                         if let Some(target_binding) = target_bindings[ns].get() {
@@ -1025,7 +1018,8 @@
 
             return if all_ns_failed {
                 let resolutions = match module {
-                    ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()),
+                    ModuleOrUniformRoot::Module(module) =>
+                        Some(self.r.resolutions(module).borrow()),
                     _ => None,
                 };
                 let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
@@ -1263,8 +1257,6 @@
             }
         };
 
-        self.r.populate_module_if_necessary(module);
-
         if module.is_trait() {
             self.r.session.span_err(directive.span, "items in traits are not importable.");
             return;
@@ -1280,8 +1272,8 @@
 
         // Ensure that `resolutions` isn't borrowed during `try_define`,
         // since it might get updated via a glob cycle.
-        let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| {
-            resolution.borrow().binding().map(|binding| (ident, binding))
+        let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(ident, resolution)| {
+            resolution.borrow().binding().map(|binding| (*ident, binding))
         }).collect::<Vec<_>>();
         for ((mut ident, ns), binding) in bindings {
             let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
@@ -1308,7 +1300,7 @@
 
         let mut reexports = Vec::new();
 
-        for (&(ident, ns), resolution) in module.resolutions.borrow().iter() {
+        for (&(ident, ns), resolution) in self.r.resolutions(module).borrow().iter() {
             let resolution = &mut *resolution.borrow_mut();
             let binding = match resolution.binding {
                 Some(binding) => binding,
@@ -1367,8 +1359,8 @@
                             Some(ModuleOrUniformRoot::Module(module)) => module,
                             _ => bug!("module should exist"),
                         };
-                        let resolutions = imported_module.parent.expect("parent should exist")
-                            .resolutions.borrow();
+                        let parent_module = imported_module.parent.expect("parent should exist");
+                        let resolutions = self.r.resolutions(parent_module).borrow();
                         let enum_path_segment_index = directive.module_path.len() - 1;
                         let enum_ident = directive.module_path[enum_path_segment_index].ident;
 
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index c32d488..9068605 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -32,7 +32,7 @@
     ty_to_string
 };
 use syntax::ptr::P;
-use syntax::source_map::{Spanned, DUMMY_SP, respan};
+use syntax::source_map::{DUMMY_SP, respan};
 use syntax::walk_list;
 use syntax_pos::*;
 
@@ -557,11 +557,11 @@
         let access = access_from!(self.save_ctxt, item, hir_id);
 
         for variant in &enum_definition.variants {
-            let name = variant.node.ident.name.to_string();
+            let name = variant.ident.name.to_string();
             let qualname = format!("{}::{}", enum_data.qualname, name);
-            let name_span = variant.node.ident.span;
+            let name_span = variant.ident.span;
 
-            match variant.node.data {
+            match variant.data {
                 ast::VariantData::Struct(ref fields, ..) => {
                     let fields_str = fields
                         .iter()
@@ -574,7 +574,7 @@
                     let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
-                        let id = id_from_node_id(variant.node.id, &self.save_ctxt);
+                        let id = id_from_node_id(variant.id, &self.save_ctxt);
                         let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
 
                         self.dumper.dump_def(
@@ -589,10 +589,10 @@
                                 parent,
                                 children: vec![],
                                 decl_id: None,
-                                docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
+                                docs: self.save_ctxt.docs_for_attrs(&variant.attrs),
                                 sig: sig::variant_signature(variant, &self.save_ctxt),
                                 attributes: lower_attributes(
-                                    variant.node.attrs.clone(),
+                                    variant.attrs.clone(),
                                     &self.save_ctxt,
                                 ),
                             },
@@ -612,7 +612,7 @@
                     }
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
-                        let id = id_from_node_id(variant.node.id, &self.save_ctxt);
+                        let id = id_from_node_id(variant.id, &self.save_ctxt);
                         let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
 
                         self.dumper.dump_def(
@@ -627,10 +627,10 @@
                                 parent,
                                 children: vec![],
                                 decl_id: None,
-                                docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
+                                docs: self.save_ctxt.docs_for_attrs(&variant.attrs),
                                 sig: sig::variant_signature(variant, &self.save_ctxt),
                                 attributes: lower_attributes(
-                                    variant.node.attrs.clone(),
+                                    variant.attrs.clone(),
                                     &self.save_ctxt,
                                 ),
                             },
@@ -640,8 +640,8 @@
             }
 
 
-            for field in variant.node.data.fields() {
-                self.process_struct_field_def(field, variant.node.id);
+            for field in variant.data.fields() {
+                self.process_struct_field_def(field, variant.id);
                 self.visit_ty(&field.ty);
             }
         }
@@ -879,7 +879,7 @@
                 };
                 let variant = adt.variant_of_res(self.save_ctxt.get_path_res(p.id));
 
-                for &Spanned { node: ref field, .. } in fields {
+                for field in fields {
                     if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
                         if !self.span.filter_generated(field.ident.span) {
                             let span = self.span_from_span(field.ident.span);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index c699a88..0bbbbb8 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -277,7 +277,7 @@
                 filter!(self.span_utils, item.ident.span);
                 let variants_str = def.variants
                     .iter()
-                    .map(|v| v.node.ident.to_string())
+                    .map(|v| v.ident.to_string())
                     .collect::<Vec<_>>()
                     .join(", ");
                 let value = format!("{}::{{{}}}", name, variants_str);
@@ -291,7 +291,7 @@
                     parent: None,
                     children: def.variants
                         .iter()
-                        .map(|v| id_from_node_id(v.node.id, self))
+                        .map(|v| id_from_node_id(v.id, self))
                         .collect(),
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
@@ -1156,7 +1156,7 @@
 // Helper function to determine if a span came from a
 // macro expansion or syntax extension.
 fn generated_code(span: Span) -> bool {
-    span.ctxt() != NO_EXPANSION || span.is_dummy()
+    span.from_expansion() || span.is_dummy()
 }
 
 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index c212cda..b34506a 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -65,7 +65,7 @@
     if !scx.config.signatures {
         return None;
     }
-    variant.node.make(0, None, scx).ok()
+    variant.make(0, None, scx).ok()
 }
 
 pub fn method_signature(
@@ -699,7 +699,7 @@
 }
 
 
-impl Sig for ast::Variant_ {
+impl Sig for ast::Variant {
     fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
         let mut text = self.ident.to_string();
         match self.data {
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index dd7ae74..dafa866 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -114,26 +114,20 @@
                 [p] if p.starts_with("P") => {
                     dl.instruction_address_space = parse_address_space(&p[1..], "P")?
                 }
-                // FIXME: Ping cfg(bootstrap) -- Use `ref a @ ..` with new bootstrap compiler.
-                ["a", ..] => {
-                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                ["a", ref a @ ..] => {
                     dl.aggregate_align = align(a, "a")?
                 }
-                ["f32", ..] => {
-                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                ["f32", ref a @ ..] => {
                     dl.f32_align = align(a, "f32")?
                 }
-                ["f64", ..] => {
-                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                ["f64", ref a @ ..] => {
                     dl.f64_align = align(a, "f64")?
                 }
-                [p @ "p", s, ..] | [p @ "p0", s, ..] => {
-                    let a = &spec_parts[2..]; // FIXME inline into pattern.
+                [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
                     dl.pointer_size = size(s, p)?;
                     dl.pointer_align = align(a, p)?;
                 }
-                [s, ..] if s.starts_with("i") => {
-                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                [s, ref a @ ..] if s.starts_with("i") => {
                     let bits = match s[1..].parse::<u64>() {
                         Ok(bits) => bits,
                         Err(_) => {
@@ -157,8 +151,7 @@
                         dl.i128_align = a;
                     }
                 }
-                [s, ..] if s.starts_with("v") => {
-                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                [s, ref a @ ..] if s.starts_with("v") => {
                     let v_size = size(&s[1..], "v")?;
                     let a = align(a, s)?;
                     if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
diff --git a/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs b/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs
new file mode 100644
index 0000000..5d8b829
--- /dev/null
+++ b/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, Target, TargetResult, PanicStrategy};
+
+pub fn target() -> TargetResult {
+    let mut base = super::windows_uwp_msvc_base::opts();
+    base.max_atomic_width = Some(64);
+    base.has_elf_tls = true;
+
+    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
+    base.panic_strategy = PanicStrategy::Abort;
+
+    Ok(Target {
+        llvm_target: "aarch64-pc-windows-msvc".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        target_os: "windows".to_string(),
+        target_env: "msvc".to_string(),
+        target_vendor: "uwp".to_string(),
+        linker_flavor: LinkerFlavor::Msvc,
+        options: base,
+    })
+}
diff --git a/src/librustc_target/spec/aarch64_wrs_vxworks.rs b/src/librustc_target/spec/aarch64_wrs_vxworks.rs
index 6ad6632..65caeac 100644
--- a/src/librustc_target/spec/aarch64_wrs_vxworks.rs
+++ b/src/librustc_target/spec/aarch64_wrs_vxworks.rs
@@ -9,15 +9,14 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        target_env: "gnu".to_string(),
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
         target_os: "vxworks".to_string(),
-        target_vendor: "unknown".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "wrs".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
-            target_mcount: "\u{1}_mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs
index f46ad06..6d3900c 100644
--- a/src/librustc_target/spec/apple_ios_base.rs
+++ b/src/librustc_target/spec/apple_ios_base.rs
@@ -13,7 +13,8 @@
     Armv7s,
     Arm64,
     I386,
-    X86_64
+    X86_64,
+    X86_64_macabi,
 }
 
 impl Arch {
@@ -23,7 +24,8 @@
             Armv7s => "armv7s",
             Arm64 => "arm64",
             I386 => "i386",
-            X86_64 => "x86_64"
+            X86_64 => "x86_64",
+            X86_64_macabi => "x86_64"
         }
     }
 }
@@ -67,7 +69,8 @@
 fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
     let sdk_name = match arch {
         Armv7 | Armv7s | Arm64 => "iphoneos",
-        I386 | X86_64 => "iphonesimulator"
+        I386 | X86_64 => "iphonesimulator",
+        X86_64_macabi => "macosx10.15",
     };
 
     let arch_name = arch.to_string();
@@ -93,6 +96,7 @@
         Arm64 => "cyclone",
         I386 => "yonah",
         X86_64 => "core2",
+        X86_64_macabi => "core2",
     }.to_string()
 }
 
diff --git a/src/librustc_target/spec/arm_wrs_vxworks_sf.rs b/src/librustc_target/spec/arm_wrs_vxworks_sf.rs
deleted file mode 100644
index bde903d..0000000
--- a/src/librustc_target/spec/arm_wrs_vxworks_sf.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
-
-pub fn target() -> TargetResult {
-    let mut base = super::vxworks_base::opts();
-    base.max_atomic_width = Some(64);
-    Ok(Target {
-        llvm_target: "arm-unknown-linux-gnueabi".to_string(),
-        target_endian: "little".to_string(),
-        target_pointer_width: "32".to_string(),
-        target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
-        target_os: "vxworks".to_string(),
-        target_env: "gnu".to_string(),
-        target_vendor: "unknown".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
-
-        options: TargetOptions {
-            features: "+strict-align,+v6".to_string(),
-            abi_blacklist: super::arm_base::abi_blacklist(),
-            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            .. base
-        },
-    })
-}
diff --git a/src/librustc_target/spec/armv7_wrs_vxworks.rs b/src/librustc_target/spec/armv7_wrs_vxworks.rs
deleted file mode 100644
index 06c51ae..0000000
--- a/src/librustc_target/spec/armv7_wrs_vxworks.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
-
-// This target is for glibc Linux on ARMv7 without NEON or
-// thumb-mode. See the thumbv7neon variant for enabling both.
-
-pub fn target() -> TargetResult {
-    let base = super::vxworks_base::opts();
-    Ok(Target {
-        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
-        target_endian: "little".to_string(),
-        target_pointer_width: "32".to_string(),
-        target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
-        target_os: "vxworks".to_string(),
-        target_env: "gnu".to_string(),
-        target_vendor: "unknown".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
-
-        options: TargetOptions {
-            // Info about features at https://wiki.debian.org/ArmHardFloatPort
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
-            cpu: "generic".to_string(),
-            max_atomic_width: Some(64),
-            abi_blacklist: super::arm_base::abi_blacklist(),
-            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            position_independent_executables: false,
-            .. base
-        }
-    })
-}
diff --git a/src/librustc_target/spec/arm_wrs_vxworks.rs b/src/librustc_target/spec/armv7_wrs_vxworks_eabihf.rs
similarity index 77%
rename from src/librustc_target/spec/arm_wrs_vxworks.rs
rename to src/librustc_target/spec/armv7_wrs_vxworks_eabihf.rs
index 06c51ae..9e3b24d 100644
--- a/src/librustc_target/spec/arm_wrs_vxworks.rs
+++ b/src/librustc_target/spec/armv7_wrs_vxworks_eabihf.rs
@@ -1,8 +1,5 @@
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
-// This target is for glibc Linux on ARMv7 without NEON or
-// thumb-mode. See the thumbv7neon variant for enabling both.
-
 pub fn target() -> TargetResult {
     let base = super::vxworks_base::opts();
     Ok(Target {
@@ -14,17 +11,14 @@
         arch: "arm".to_string(),
         target_os: "vxworks".to_string(),
         target_env: "gnu".to_string(),
-        target_vendor: "unknown".to_string(),
+        target_vendor: "wrs".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-
         options: TargetOptions {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
             features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
-            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
-            position_independent_executables: false,
             .. base
         }
     })
diff --git a/src/librustc_target/spec/i586_wrs_vxworks.rs b/src/librustc_target/spec/i586_wrs_vxworks.rs
deleted file mode 100644
index 355250e..0000000
--- a/src/librustc_target/spec/i586_wrs_vxworks.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use crate::spec::TargetResult;
-
-pub fn target() -> TargetResult {
-    let mut base = super::i686_wrs_vxworks::target()?;
-    base.options.cpu = "pentium".to_string();
-    base.llvm_target = "i586-unknown-linux-gnu".to_string();
-    Ok(base)
-}
diff --git a/src/librustc_target/spec/i686_uwp_windows_msvc.rs b/src/librustc_target/spec/i686_uwp_windows_msvc.rs
new file mode 100644
index 0000000..5e8e8c2
--- /dev/null
+++ b/src/librustc_target/spec/i686_uwp_windows_msvc.rs
@@ -0,0 +1,22 @@
+use crate::spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::windows_uwp_msvc_base::opts();
+    base.cpu = "pentium4".to_string();
+    base.max_atomic_width = Some(64);
+    base.has_elf_tls = true;
+
+    Ok(Target {
+        llvm_target: "i686-pc-windows-msvc".to_string(),
+        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(),
+        arch: "x86".to_string(),
+        target_os: "windows".to_string(),
+        target_env: "msvc".to_string(),
+        target_vendor: "uwp".to_string(),
+        linker_flavor: LinkerFlavor::Msvc,
+        options: base,
+    })
+}
diff --git a/src/librustc_target/spec/i686_wrs_vxworks.rs b/src/librustc_target/spec/i686_wrs_vxworks.rs
index 4b1ff5c..c5f9583 100644
--- a/src/librustc_target/spec/i686_wrs_vxworks.rs
+++ b/src/librustc_target/spec/i686_wrs_vxworks.rs
@@ -16,7 +16,7 @@
         arch: "x86".to_string(),
         target_os: "vxworks".to_string(),
         target_env: "gnu".to_string(),
-        target_vendor: "unknown".to_string(),
+        target_vendor: "wrs".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: base,
     })
diff --git a/src/librustc_target/spec/i686_wrs_vxworks_gnu.rs b/src/librustc_target/spec/i686_wrs_vxworks_gnu.rs
deleted file mode 100644
index 4b1ff5c..0000000
--- a/src/librustc_target/spec/i686_wrs_vxworks_gnu.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
-
-pub fn target() -> TargetResult {
-    let mut base = super::vxworks_base::opts();
-    base.cpu = "pentium4".to_string();
-    base.max_atomic_width = Some(64);
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
-    base.stack_probes = true;
-
-    Ok(Target {
-        llvm_target: "i686-unknown-linux-gnu".to_string(),
-        target_endian: "little".to_string(),
-        target_pointer_width: "32".to_string(),
-        target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
-        arch: "x86".to_string(),
-        target_os: "vxworks".to_string(),
-        target_env: "gnu".to_string(),
-        target_vendor: "unknown".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
-        options: base,
-    })
-}
diff --git a/src/librustc_target/spec/mips64_unknown_linux_muslabi64.rs b/src/librustc_target/spec/mips64_unknown_linux_muslabi64.rs
new file mode 100644
index 0000000..75f3efa
--- /dev/null
+++ b/src/librustc_target/spec/mips64_unknown_linux_muslabi64.rs
@@ -0,0 +1,25 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+    base.cpu = "mips64r2".to_string();
+    base.features = "+mips64r2".to_string();
+    base.max_atomic_width = Some(64);
+    Ok(Target {
+        // LLVM doesn't recognize "muslabi64" yet.
+        llvm_target: "mips64-unknown-linux-musl".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
+        arch: "mips64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mips64el_unknown_linux_muslabi64.rs b/src/librustc_target/spec/mips64el_unknown_linux_muslabi64.rs
new file mode 100644
index 0000000..a6aad3d
--- /dev/null
+++ b/src/librustc_target/spec/mips64el_unknown_linux_muslabi64.rs
@@ -0,0 +1,25 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+    base.cpu = "mips64r2".to_string();
+    base.features = "+mips64r2".to_string();
+    base.max_atomic_width = Some(64);
+    Ok(Target {
+        // LLVM doesn't recognize "muslabi64" yet.
+        llvm_target: "mips64el-unknown-linux-musl".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
+        arch: "mips64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index ec72c00..539e28f 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -61,6 +61,7 @@
 mod windows_base;
 mod windows_msvc_base;
 mod windows_uwp_base;
+mod windows_uwp_msvc_base;
 mod thumb_base;
 mod l4re_base;
 mod fuchsia_base;
@@ -371,6 +372,8 @@
     ("i586-unknown-linux-musl", i586_unknown_linux_musl),
     ("mips-unknown-linux-musl", mips_unknown_linux_musl),
     ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
+    ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
+    ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
     ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
 
     ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
@@ -395,6 +398,7 @@
 
     ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
     ("i686-unknown-openbsd", i686_unknown_openbsd),
+    ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
     ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
 
     ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
@@ -425,6 +429,7 @@
     ("aarch64-apple-ios", aarch64_apple_ios),
     ("armv7-apple-ios", armv7_apple_ios),
     ("armv7s-apple-ios", armv7s_apple_ios),
+    ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
 
     ("armebv7r-none-eabi", armebv7r_none_eabi),
     ("armebv7r-none-eabihf", armebv7r_none_eabihf),
@@ -442,8 +447,11 @@
     ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
 
     ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
+    ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
     ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
+    ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
     ("i686-pc-windows-msvc", i686_pc_windows_msvc),
+    ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
     ("i586-pc-windows-msvc", i586_pc_windows_msvc),
     ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
 
@@ -485,10 +493,9 @@
 
     ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
 
-    ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
     ("i686-wrs-vxworks", i686_wrs_vxworks),
-    ("i586-wrs-vxworks", i586_wrs_vxworks),
-    ("armv7-wrs-vxworks", armv7_wrs_vxworks),
+    ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
+    ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
     ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
     ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
     ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
diff --git a/src/librustc_target/spec/powerpc64_wrs_vxworks.rs b/src/librustc_target/spec/powerpc64_wrs_vxworks.rs
index a952070..27a84b9 100644
--- a/src/librustc_target/spec/powerpc64_wrs_vxworks.rs
+++ b/src/librustc_target/spec/powerpc64_wrs_vxworks.rs
@@ -15,10 +15,9 @@
         arch: "powerpc64".to_string(),
         target_os: "vxworks".to_string(),
         target_env: "gnu".to_string(),
-        target_vendor: "unknown".to_string(),
+        target_vendor: "wrs".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
-            target_mcount: "_mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/powerpc64_wrs_vxworks_gnusf.rs b/src/librustc_target/spec/powerpc64_wrs_vxworks_gnusf.rs
deleted file mode 100644
index c2dae85..0000000
--- a/src/librustc_target/spec/powerpc64_wrs_vxworks_gnusf.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
-
-pub fn target() -> TargetResult {
-    let mut base = super::vxworks_base::opts();
-    base.cpu = "ppc64".to_string();
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
-    base.max_atomic_width = Some(64);
-
-    Ok(Target {
-        llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
-        target_endian: "big".to_string(),
-        target_pointer_width: "64".to_string(),
-        target_c_int_width: "32".to_string(),
-        data_layout: "E-m:e-i64:64-n32:64".to_string(),
-        arch: "powerpc64".to_string(),
-        target_os: "vxworks".to_string(),
-        target_env: "gnu".to_string(),
-        target_vendor: "unknown".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
-        options: TargetOptions {
-            features: "-hard-float".to_string(),
-            target_mcount: "_mcount".to_string(),
-            .. base
-        },
-    })
-}
diff --git a/src/librustc_target/spec/powerpc_wrs_vxworks.rs b/src/librustc_target/spec/powerpc_wrs_vxworks.rs
index 2e833ee..a4d2897 100644
--- a/src/librustc_target/spec/powerpc_wrs_vxworks.rs
+++ b/src/librustc_target/spec/powerpc_wrs_vxworks.rs
@@ -19,7 +19,6 @@
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             features: "+secure-plt".to_string(),
-            target_mcount: "_mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/powerpc_wrs_vxworks_gnusf.rs b/src/librustc_target/spec/powerpc_wrs_vxworks_gnusf.rs
deleted file mode 100644
index 43723ea..0000000
--- a/src/librustc_target/spec/powerpc_wrs_vxworks_gnusf.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
-
-pub fn target() -> TargetResult {
-    let mut base = super::vxworks_base::opts();
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("--secure-plt".to_string());
-    base.max_atomic_width = Some(32);
-
-    Ok(Target {
-        llvm_target: "powerpc-unknown-linux-gnu".to_string(),
-        target_endian: "big".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-n32".to_string(),
-        arch: "powerpc".to_string(),
-        target_os: "vxworks".to_string(),
-        target_env: "gnu".to_string(),
-        target_vendor: "wrs".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
-        options: TargetOptions {
-            features: "+secure-plt,-hard-float".to_string(),
-            target_mcount: "_mcount".to_string(),
-            .. base
-        },
-    })
-}
diff --git a/src/librustc_target/spec/powerpc_wrs_vxworks_gnuspesf.rs b/src/librustc_target/spec/powerpc_wrs_vxworks_gnuspesf.rs
deleted file mode 100644
index 8f23623..0000000
--- a/src/librustc_target/spec/powerpc_wrs_vxworks_gnuspesf.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
-
-pub fn target() -> TargetResult {
-    let mut base = super::vxworks_base::opts();
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string());
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("--secure-plt".to_string());
-    base.max_atomic_width = Some(32);
-
-    Ok(Target {
-        llvm_target: "powerpc-unknown-linux-gnuspe".to_string(),
-        target_endian: "big".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-n32".to_string(),
-        arch: "powerpc".to_string(),
-        target_os: "vxworks".to_string(),
-        target_env: "gnu".to_string(),
-        target_vendor: "wrs".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
-        options: TargetOptions {
-            // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
-            features: "+secure-plt,+msync,-hard-float".to_string(),
-            target_mcount: "_mcount".to_string(),
-            .. base
-        },
-    })
-}
diff --git a/src/librustc_target/spec/powerpc_wrs_vxworks_spe.rs b/src/librustc_target/spec/powerpc_wrs_vxworks_spe.rs
index 2305b4b..90118a14 100644
--- a/src/librustc_target/spec/powerpc_wrs_vxworks_spe.rs
+++ b/src/librustc_target/spec/powerpc_wrs_vxworks_spe.rs
@@ -20,7 +20,6 @@
         options: TargetOptions {
             // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
             features: "+secure-plt,+msync".to_string(),
-            target_mcount: "_mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/sparc64_unknown_openbsd.rs b/src/librustc_target/spec/sparc64_unknown_openbsd.rs
new file mode 100644
index 0000000..229e062
--- /dev/null
+++ b/src/librustc_target/spec/sparc64_unknown_openbsd.rs
@@ -0,0 +1,22 @@
+use crate::spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::openbsd_base::opts();
+    base.cpu = "v9".to_string();
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+    base.max_atomic_width = Some(64);
+
+    Ok(Target {
+        llvm_target: "sparc64-unknown-openbsd".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
+        arch: "sparc64".to_string(),
+        target_os: "openbsd".to_string(),
+        target_env: String::new(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_target/spec/vxworks_base.rs b/src/librustc_target/spec/vxworks_base.rs
index 6db56c5..16acd41 100644
--- a/src/librustc_target/spec/vxworks_base.rs
+++ b/src/librustc_target/spec/vxworks_base.rs
@@ -1,7 +1,11 @@
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions, RelroLevel};
+use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    let mut args_crt = LinkArgs::new();
+    args_crt.insert(LinkerFlavor::Gcc, vec![
+        "--static-crt".to_string(),
+    ]);
     let mut args = LinkArgs::new();
     args.insert(LinkerFlavor::Gcc, vec![
         // We want to be able to strip as much executable code as possible
@@ -12,30 +16,25 @@
         // following libraries so we're sure to pass it as one of the first
         // arguments.
         "-Wl,--as-needed".to_string(),
-
-        // Always enable NX protection when it is available
-        "-Wl,-z,noexecstack".to_string(),
-    ]);
-
-    let mut late_lk_args = LinkArgs::new();
-    late_lk_args.insert(LinkerFlavor::Gcc, vec![
-        "-lnet".to_string(),
-        "-lunix".to_string(),
     ]);
 
     TargetOptions {
-        linker: Some("vx-cxx".to_string()),
+        linker: Some("wr-c++".to_string()),
         exe_suffix: ".vxe".to_string(),
-        late_link_args: late_lk_args,
         dynamic_linking: true,
         executables: true,
         target_family: Some("unix".to_string()),
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: args,
-        position_independent_executables: true,
-        relro_level: RelroLevel::Full,
+        position_independent_executables: false,
         has_elf_tls: true,
+        pre_link_args_crt: args_crt,
+        crt_static_default: true,
+        crt_static_respected: true,
+        crt_static_allows_dylibs: true,
+        // VxWorks needs to implement this to support profiling
+        target_mcount: "_mcount".to_string(),
         .. Default::default()
     }
 }
diff --git a/src/librustc_target/spec/windows_uwp_msvc_base.rs b/src/librustc_target/spec/windows_uwp_msvc_base.rs
new file mode 100644
index 0000000..1121916
--- /dev/null
+++ b/src/librustc_target/spec/windows_uwp_msvc_base.rs
@@ -0,0 +1,33 @@
+use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Msvc,
+                vec!["/NOLOGO".to_string(),
+                     "/NXCOMPAT".to_string(),
+                     "/APPCONTAINER".to_string(),
+                     "mincore.lib".to_string()]);
+
+    TargetOptions {
+        function_sections: true,
+        dynamic_linking: true,
+        executables: true,
+        dll_prefix: String::new(),
+        dll_suffix: ".dll".to_string(),
+        exe_suffix: ".exe".to_string(),
+        staticlib_prefix: String::new(),
+        staticlib_suffix: ".lib".to_string(),
+        target_family: Some("windows".to_string()),
+        is_like_windows: true,
+        is_like_msvc: true,
+        pre_link_args: args,
+        crt_static_allows_dylibs: true,
+        crt_static_respected: true,
+        abi_return_struct_as_int: true,
+        emit_debug_gdb_scripts: false,
+        requires_uwtable: true,
+
+        .. Default::default()
+    }
+}
diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
new file mode 100644
index 0000000..2ce7728
--- /dev/null
+++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
@@ -0,0 +1,23 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+use super::apple_ios_base::{opts, Arch};
+
+pub fn target() -> TargetResult {
+    let base = opts(Arch::X86_64_macabi)?;
+    Ok(Target {
+        llvm_target: "x86_64-apple-ios13.0-macabi".to_string(),
+        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(),
+        arch: "x86_64".to_string(),
+        target_os: "ios".to_string(),
+        target_env: String::new(),
+        target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            max_atomic_width: Some(64),
+            stack_probes: true,
+            .. base
+        }
+    })
+}
diff --git a/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
new file mode 100644
index 0000000..40dd52c
--- /dev/null
+++ b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
@@ -0,0 +1,22 @@
+use crate::spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::windows_uwp_msvc_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.max_atomic_width = Some(64);
+    base.has_elf_tls = true;
+
+    Ok(Target {
+        llvm_target: "x86_64-pc-windows-msvc".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "windows".to_string(),
+        target_env: "msvc".to_string(),
+        target_vendor: "uwp".to_string(),
+        linker_flavor: LinkerFlavor::Msvc,
+        options: base,
+    })
+}
diff --git a/src/librustc_target/spec/x86_64_wrs_vxworks.rs b/src/librustc_target/spec/x86_64_wrs_vxworks.rs
index eac7cd7..1ab2f3a 100644
--- a/src/librustc_target/spec/x86_64_wrs_vxworks.rs
+++ b/src/librustc_target/spec/x86_64_wrs_vxworks.rs
@@ -6,6 +6,7 @@
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.stack_probes = true;
+    base.disable_redzone = true;
 
     Ok(Target {
         llvm_target: "x86_64-unknown-linux-gnu".to_string(),
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 3a43e76..99ae777 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -12,7 +12,6 @@
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::subst::Kind;
 use syntax::ast;
-use syntax::source_map::Spanned;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
 use syntax_pos::hygiene::DesugaringKind;
@@ -1036,7 +1035,7 @@
         &self,
         pat: &'tcx hir::Pat,
         qpath: &hir::QPath,
-        fields: &'tcx [Spanned<hir::FieldPat>],
+        fields: &'tcx [hir::FieldPat],
         etc: bool,
         expected: Ty<'tcx>,
         def_bm: ty::BindingMode,
@@ -1048,7 +1047,7 @@
             variant_ty
         } else {
             for field in fields {
-                self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span);
+                self.check_pat_walk(&field.pat, self.tcx.types.err, def_bm, discrim_span);
             }
             return self.tcx.types.err;
         };
@@ -1206,7 +1205,7 @@
         pat_id: hir::HirId,
         span: Span,
         variant: &'tcx ty::VariantDef,
-        fields: &'tcx [Spanned<hir::FieldPat>],
+        fields: &'tcx [hir::FieldPat],
         etc: bool,
         def_bm: ty::BindingMode,
     ) -> bool {
@@ -1231,7 +1230,8 @@
 
         let mut inexistent_fields = vec![];
         // Typecheck each field.
-        for &Spanned { node: ref field, span } in fields {
+        for field in fields {
+            let span = field.span;
             let ident = tcx.adjust_ident(field.ident, variant.def_id);
             let field_ty = match used_fields.entry(ident) {
                 Occupied(occupied) => {
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 3229d49..de5ba8b 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -127,6 +127,7 @@
 
         self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
         self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
+        self.suggest_boxing_when_appropriate(&mut err, expr, expected, expr_ty);
         self.suggest_missing_await(&mut err, expr, expected, expr_ty);
 
         (expected, Some(err))
@@ -346,9 +347,9 @@
             sp,
         );
 
-        // Check the `expn_info()` to see if this is a macro; if so, it's hard to
-        // extract the text and make a good suggestion, so don't bother.
-        let is_macro = sp.ctxt().outer_expn_info().is_some();
+        // If the span is from a macro, then it's hard to extract the text
+        // and make a good suggestion, so don't bother.
+        let is_macro = sp.from_expansion();
 
         match (&expr.node, &expected.sty, &checked_ty.sty) {
             (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) {
@@ -548,11 +549,15 @@
         checked_ty: Ty<'tcx>,
         expected_ty: Ty<'tcx>,
     ) -> bool {
-        if self.tcx.hir().is_const_scope(expr.hir_id) {
+        if self.tcx.hir().is_const_context(expr.hir_id) {
             // Shouldn't suggest `.into()` on `const`s.
             // FIXME(estebank): modify once we decide to suggest `as` casts
             return false;
         }
+        if !self.tcx.sess.source_map().span_to_filename(expr.span).is_real() {
+            // Ignore if span is from within a macro.
+            return false;
+        }
 
         // If casting this expression to a given numeric type would be appropriate in case of a type
         // mismatch.
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 9680f61..d139cd4 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -24,6 +24,7 @@
 use syntax::util::lev_distance::find_best_match_for_name;
 use rustc::hir;
 use rustc::hir::{ExprKind, QPath};
+use rustc::hir::def_id::DefId;
 use rustc::hir::def::{CtorKind, Res, DefKind};
 use rustc::hir::ptr::P;
 use rustc::infer;
@@ -1336,114 +1337,180 @@
         autoderef.unambiguous_final_ty(self);
 
         if let Some((did, field_ty)) = private_candidate {
-            let struct_path = self.tcx().def_path_str(did);
-            let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616,
-                                           "field `{}` of struct `{}` is private",
-                                           field, struct_path);
-            // Also check if an accessible method exists, which is often what is meant.
-            if self.method_exists(field, expr_t, expr.hir_id, false)
-                && !self.expr_in_place(expr.hir_id)
-            {
-                self.suggest_method_call(
-                    &mut err,
-                    &format!("a method `{}` also exists, call it with parentheses", field),
-                    field,
-                    expr_t,
-                    expr.hir_id,
-                );
-            }
-            err.emit();
-            field_ty
-        } else if field.name == kw::Invalid {
-            self.tcx().types.err
-        } else if self.method_exists(field, expr_t, expr.hir_id, true) {
-            let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0615,
-                               "attempted to take value of method `{}` on type `{}`",
-                               field, expr_t);
-
-            if !self.expr_in_place(expr.hir_id) {
-                self.suggest_method_call(
-                    &mut err,
-                    "use parentheses to call the method",
-                    field,
-                    expr_t,
-                    expr.hir_id
-                );
-            } else {
-                err.help("methods are immutable and cannot be assigned to");
-            }
-
-            err.emit();
-            self.tcx().types.err
-        } else {
-            if !expr_t.is_primitive_ty() {
-                let mut err = self.no_such_field_err(field.span, field, expr_t);
-
-                match expr_t.sty {
-                    ty::Adt(def, _) if !def.is_enum() => {
-                        if let Some(suggested_field_name) =
-                            Self::suggest_field_name(def.non_enum_variant(),
-                                                     &field.as_str(), vec![]) {
-                                err.span_suggestion(
-                                    field.span,
-                                    "a field with a similar name exists",
-                                    suggested_field_name.to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else {
-                                err.span_label(field.span, "unknown field");
-                                let struct_variant_def = def.non_enum_variant();
-                                let field_names = self.available_field_names(struct_variant_def);
-                                if !field_names.is_empty() {
-                                    err.note(&format!("available fields are: {}",
-                                                      self.name_series_display(field_names)));
-                                }
-                            };
-                    }
-                    ty::Array(_, len) => {
-                        if let (Some(len), Ok(user_index)) = (
-                            len.try_eval_usize(self.tcx, self.param_env),
-                            field.as_str().parse::<u64>()
-                        ) {
-                            let base = self.tcx.sess.source_map()
-                                .span_to_snippet(base.span)
-                                .unwrap_or_else(|_|
-                                    self.tcx.hir().hir_to_pretty_string(base.hir_id));
-                            let help = "instead of using tuple indexing, use array indexing";
-                            let suggestion = format!("{}[{}]", base, field);
-                            let applicability = if len < user_index {
-                                Applicability::MachineApplicable
-                            } else {
-                                Applicability::MaybeIncorrect
-                            };
-                            err.span_suggestion(
-                                expr.span, help, suggestion, applicability
-                            );
-                        }
-                    }
-                    ty::RawPtr(..) => {
-                        let base = self.tcx.sess.source_map()
-                            .span_to_snippet(base.span)
-                            .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id));
-                        let msg = format!("`{}` is a raw pointer; try dereferencing it", base);
-                        let suggestion = format!("(*{}).{}", base, field);
-                        err.span_suggestion(
-                            expr.span,
-                            &msg,
-                            suggestion,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    _ => {}
-                }
-                err
-            } else {
-                type_error_struct!(self.tcx().sess, field.span, expr_t, E0610,
-                                   "`{}` is a primitive type and therefore doesn't have fields",
-                                   expr_t)
-            }.emit();
-            self.tcx().types.err
+            self.ban_private_field_access(expr, expr_t, field, did);
+            return field_ty;
         }
+
+        if field.name == kw::Invalid {
+        } else if self.method_exists(field, expr_t, expr.hir_id, true) {
+            self.ban_take_value_of_method(expr, expr_t, field);
+        } else if !expr_t.is_primitive_ty() {
+            let mut err = self.no_such_field_err(field.span, field, expr_t);
+
+            match expr_t.sty {
+                ty::Adt(def, _) if !def.is_enum() => {
+                    self.suggest_fields_on_recordish(&mut err, def, field);
+                }
+                ty::Array(_, len) => {
+                    self.maybe_suggest_array_indexing(&mut err, expr, base, field, len);
+                }
+                ty::RawPtr(..) => {
+                    self.suggest_first_deref_field(&mut err, expr, base, field);
+                }
+                _ => {}
+            }
+
+            if field.name == kw::Await {
+                // We know by construction that `<expr>.await` is either on Rust 2015
+                // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
+                err.note("to `.await` a `Future`, switch to Rust 2018");
+                err.help("set `edition = \"2018\"` in `Cargo.toml`");
+                err.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
+            }
+
+            err.emit();
+        } else {
+            type_error_struct!(
+                self.tcx().sess,
+                field.span,
+                expr_t,
+                E0610,
+                "`{}` is a primitive type and therefore doesn't have fields",
+                expr_t
+            )
+            .emit();
+        }
+
+        self.tcx().types.err
+    }
+
+    fn ban_private_field_access(
+        &self,
+        expr: &hir::Expr,
+        expr_t: Ty<'tcx>,
+        field: ast::Ident,
+        base_did: DefId,
+    ) {
+        let struct_path = self.tcx().def_path_str(base_did);
+        let mut err = struct_span_err!(
+            self.tcx().sess,
+            expr.span,
+            E0616,
+            "field `{}` of struct `{}` is private",
+            field,
+            struct_path
+        );
+        // Also check if an accessible method exists, which is often what is meant.
+        if self.method_exists(field, expr_t, expr.hir_id, false)
+            && !self.expr_in_place(expr.hir_id)
+        {
+            self.suggest_method_call(
+                &mut err,
+                &format!("a method `{}` also exists, call it with parentheses", field),
+                field,
+                expr_t,
+                expr.hir_id,
+            );
+        }
+        err.emit();
+    }
+
+    fn ban_take_value_of_method(&self, expr: &hir::Expr, expr_t: Ty<'tcx>, field: ast::Ident) {
+        let mut err = type_error_struct!(
+            self.tcx().sess,
+            field.span,
+            expr_t,
+            E0615,
+            "attempted to take value of method `{}` on type `{}`",
+            field,
+            expr_t
+        );
+
+        if !self.expr_in_place(expr.hir_id) {
+            self.suggest_method_call(
+                &mut err,
+                "use parentheses to call the method",
+                field,
+                expr_t,
+                expr.hir_id
+            );
+        } else {
+            err.help("methods are immutable and cannot be assigned to");
+        }
+
+        err.emit();
+    }
+
+    fn suggest_fields_on_recordish(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def: &'tcx ty::AdtDef,
+        field: ast::Ident,
+    ) {
+        if let Some(suggested_field_name) =
+            Self::suggest_field_name(def.non_enum_variant(), &field.as_str(), vec![])
+        {
+            err.span_suggestion(
+                field.span,
+                "a field with a similar name exists",
+                suggested_field_name.to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            err.span_label(field.span, "unknown field");
+            let struct_variant_def = def.non_enum_variant();
+            let field_names = self.available_field_names(struct_variant_def);
+            if !field_names.is_empty() {
+                err.note(&format!("available fields are: {}",
+                                    self.name_series_display(field_names)));
+            }
+        }
+    }
+
+    fn maybe_suggest_array_indexing(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr,
+        base: &hir::Expr,
+        field: ast::Ident,
+        len: &ty::Const<'tcx>,
+    ) {
+        if let (Some(len), Ok(user_index)) = (
+            len.try_eval_usize(self.tcx, self.param_env),
+            field.as_str().parse::<u64>()
+        ) {
+            let base = self.tcx.sess.source_map()
+                .span_to_snippet(base.span)
+                .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id));
+            let help = "instead of using tuple indexing, use array indexing";
+            let suggestion = format!("{}[{}]", base, field);
+            let applicability = if len < user_index {
+                Applicability::MachineApplicable
+            } else {
+                Applicability::MaybeIncorrect
+            };
+            err.span_suggestion(expr.span, help, suggestion, applicability);
+        }
+    }
+
+    fn suggest_first_deref_field(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr,
+        base: &hir::Expr,
+        field: ast::Ident,
+    ) {
+        let base = self.tcx.sess.source_map()
+            .span_to_snippet(base.span)
+            .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id));
+        let msg = format!("`{}` is a raw pointer; try dereferencing it", base);
+        let suggestion = format!("(*{}).{}", base, field);
+        err.span_suggestion(
+            expr.span,
+            &msg,
+            suggestion,
+            Applicability::MaybeIncorrect,
+        );
     }
 
     fn no_such_field_err<T: Display>(&self, span: Span, field: T, expr_t: &ty::TyS<'_>)
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 8bb24ee..dfbf8bc 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -67,7 +67,7 @@
     match intrinsic {
         "size_of" | "min_align_of" | "needs_drop" |
         "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
-        "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
+        "wrapping_add" | "wrapping_sub" | "wrapping_mul" |
         "saturating_add" | "saturating_sub" |
         "rotate_left" | "rotate_right" |
         "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" |
@@ -314,7 +314,7 @@
                 (1, vec![param(0), param(0)], param(0)),
             "unchecked_add" | "unchecked_sub" | "unchecked_mul" =>
                 (1, vec![param(0), param(0)], param(0)),
-            "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
+            "wrapping_add" | "wrapping_sub" | "wrapping_mul" =>
                 (1, vec![param(0), param(0)], param(0)),
             "saturating_add" | "saturating_sub" =>
                 (1, vec![param(0), param(0)], param(0)),
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 4a5eba1..53024d9 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -985,7 +985,7 @@
                 hir::ItemKind::Use(..) => {
                     // Don't suggest placing a `use` before the prelude
                     // import or other generated ones.
-                    if item.span.ctxt().outer_expn_info().is_none() {
+                    if !item.span.from_expansion() {
                         self.span = Some(item.span.shrink_to_lo());
                         self.found_use = true;
                         return;
@@ -995,7 +995,7 @@
                 hir::ItemKind::ExternCrate(_) => {}
                 // ...but do place them before the first other item.
                 _ => if self.span.map_or(true, |span| item.span < span ) {
-                    if item.span.ctxt().outer_expn_info().is_none() {
+                    if !item.span.from_expansion() {
                         // Don't insert between attributes and an item.
                         if item.attrs.is_empty() {
                             self.span = Some(item.span.shrink_to_lo());
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4fb28db..fc1ee64 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1325,12 +1325,94 @@
     check_packed(tcx, span, def_id);
 }
 
+/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
+/// projections that would result in "inheriting lifetimes".
 fn check_opaque<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     substs: SubstsRef<'tcx>,
     span: Span,
-    origin: &hir::OpaqueTyOrigin
+    origin: &hir::OpaqueTyOrigin,
+) {
+    check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
+    check_opaque_for_cycles(tcx, def_id, substs, span, origin);
+}
+
+/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
+/// in "inheriting lifetimes".
+fn check_opaque_for_inheriting_lifetimes(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    span: Span,
+) {
+    let item = tcx.hir().expect_item(
+        tcx.hir().as_local_hir_id(def_id).expect("opaque type is not local"));
+    debug!("check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
+           def_id, span, item);
+
+    #[derive(Debug)]
+    struct ProhibitOpaqueVisitor<'tcx> {
+        opaque_identity_ty: Ty<'tcx>,
+        generics: &'tcx ty::Generics,
+    };
+
+    impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+            debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
+            if t == self.opaque_identity_ty { false } else { t.super_visit_with(self) }
+        }
+
+        fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+            debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
+            if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
+                return *index < self.generics.parent_count as u32;
+            }
+
+            r.super_visit_with(self)
+        }
+    }
+
+    let prohibit_opaque = match item.node {
+        ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn, .. }) |
+        ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn, .. }) => {
+            let mut visitor = ProhibitOpaqueVisitor {
+                opaque_identity_ty: tcx.mk_opaque(
+                    def_id, InternalSubsts::identity_for_item(tcx, def_id)),
+                generics: tcx.generics_of(def_id),
+            };
+            debug!("check_opaque_for_inheriting_lifetimes: visitor={:?}", visitor);
+
+            tcx.predicates_of(def_id).predicates.iter().any(
+                |(predicate, _)| predicate.visit_with(&mut visitor))
+        },
+        _ => false,
+    };
+
+    debug!("check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}", prohibit_opaque);
+    if prohibit_opaque {
+        let is_async = match item.node {
+            ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => match origin {
+                hir::OpaqueTyOrigin::AsyncFn => true,
+                _ => false,
+            },
+            _ => unreachable!(),
+        };
+
+        tcx.sess.span_err(span, &format!(
+            "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
+             a parent scope",
+            if is_async { "async fn" } else { "impl Trait" },
+        ));
+    }
+}
+
+/// Checks that an opaque type does not contain cycles.
+fn check_opaque_for_cycles<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    substs: SubstsRef<'tcx>,
+    span: Span,
+    origin: &hir::OpaqueTyOrigin,
 ) {
     if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) {
         if let hir::OpaqueTyOrigin::AsyncFn = origin {
@@ -1834,9 +1916,7 @@
     );
     let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
     err.span_label(sp, &msg);
-    if let &[.., ref end] = &variant_spans[..] {
-        // FIXME: Ping cfg(bootstrap) -- Use `ref start @ ..` with new bootstrap compiler.
-        let start = &variant_spans[..variant_spans.len() - 1];
+    if let &[ref start @ .., ref end] = &variant_spans[..] {
         for variant_span in start {
             err.span_label(*variant_span, "");
         }
@@ -1968,19 +2048,19 @@
     }
 
     for v in vs {
-        if let Some(ref e) = v.node.disr_expr {
+        if let Some(ref e) = v.disr_expr {
             tcx.typeck_tables_of(tcx.hir().local_def_id(e.hir_id));
         }
     }
 
     if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
         let is_unit =
-            |var: &hir::Variant| match var.node.data {
+            |var: &hir::Variant| match var.data {
                 hir::VariantData::Unit(..) => true,
                 _ => false
             };
 
-        let has_disr = |var: &hir::Variant| var.node.disr_expr.is_some();
+        let has_disr = |var: &hir::Variant| var.disr_expr.is_some();
         let has_non_units = vs.iter().any(|var| !is_unit(var));
         let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var));
         let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var));
@@ -1999,11 +2079,11 @@
             let variant_did = def.variants[VariantIdx::new(i)].def_id;
             let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did).unwrap();
             let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
-            let i_span = match variant_i.node.disr_expr {
+            let i_span = match variant_i.disr_expr {
                 Some(ref expr) => tcx.hir().span(expr.hir_id),
                 None => tcx.hir().span(variant_i_hir_id)
             };
-            let span = match v.node.disr_expr {
+            let span = match v.disr_expr {
                 Some(ref expr) => tcx.hir().span(expr.hir_id),
                 None => v.span
             };
@@ -2863,7 +2943,7 @@
             (PlaceOp::Index, false) => (self.tcx.lang_items().index_trait(), sym::index),
             (PlaceOp::Index, true) => (self.tcx.lang_items().index_mut_trait(), sym::index_mut),
         };
-        (tr, ast::Ident::with_empty_ctxt(name))
+        (tr, ast::Ident::with_dummy_span(name))
     }
 
     fn try_overloaded_place_op(&self,
@@ -3820,6 +3900,7 @@
                 err, &fn_decl, expected, found, can_suggest);
         }
         self.suggest_ref_or_into(err, expression, expected, found);
+        self.suggest_boxing_when_appropriate(err, expression, expected, found);
         pointing_at_return_type
     }
 
@@ -3980,6 +4061,41 @@
         }
     }
 
+    /// When encountering the expected boxed value allocated in the stack, suggest allocating it
+    /// in the heap by calling `Box::new()`.
+    fn suggest_boxing_when_appropriate(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        expr: &hir::Expr,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) {
+        if self.tcx.hir().is_const_context(expr.hir_id) {
+            // Do not suggest `Box::new` in const context.
+            return;
+        }
+        if !expected.is_box() || found.is_box() {
+            return;
+        }
+        let boxed_found = self.tcx.mk_box(found);
+        if let (true, Ok(snippet)) = (
+            self.can_coerce(boxed_found, expected),
+            self.sess().source_map().span_to_snippet(expr.span),
+        ) {
+            err.span_suggestion(
+                expr.span,
+                "store this in the heap by calling `Box::new`",
+                format!("Box::new({})", snippet),
+                Applicability::MachineApplicable,
+            );
+            err.note("for more on the distinction between the stack and the \
+                        heap, read https://doc.rust-lang.org/book/ch15-01-box.html, \
+                        https://doc.rust-lang.org/rust-by-example/std/box.html, and \
+                        https://doc.rust-lang.org/std/boxed/index.html");
+        }
+    }
+
+
     /// A common error is to forget to add a semicolon at the end of a block, e.g.,
     ///
     /// ```
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index c1d8fde..b2c0e34 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -1119,7 +1119,7 @@
 
     fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> {
         enum_def.variants.iter()
-            .map(|variant| self.non_enum_variant(&variant.node.data))
+            .map(|variant| self.non_enum_variant(&variant.data))
             .collect()
     }
 
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 67a8eca..a88e32e 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -283,7 +283,7 @@
             }
             hir::PatKind::Struct(_, ref fields, _) => {
                 for field in fields {
-                    self.visit_field_id(field.node.hir_id);
+                    self.visit_field_id(field.hir_id);
                 }
             }
             _ => {}
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 0f05689..5ff6422 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -35,7 +35,6 @@
 use syntax::ast;
 use syntax::ast::{Ident, MetaItemKind};
 use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used};
-use syntax::source_map::Spanned;
 use syntax::feature_gate;
 use syntax::symbol::{InternedString, kw, Symbol, sym};
 use syntax_pos::{Span, DUMMY_SP};
@@ -520,7 +519,11 @@
     tcx.predicates_of(def_id);
 }
 
-fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: &[hir::Variant]) {
+fn convert_enum_variant_types<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    variants: &[hir::Variant]
+) {
     let def = tcx.adt_def(def_id);
     let repr_type = def.repr.discr_type();
     let initial = repr_type.initial_discriminant(tcx);
@@ -530,7 +533,7 @@
     for variant in variants {
         let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
         prev_discr = Some(
-            if let Some(ref e) = variant.node.disr_expr {
+            if let Some(ref e) = variant.disr_expr {
                 let expr_did = tcx.hir().local_def_id(e.hir_id);
                 def.eval_explicit_discr(tcx, expr_did)
             } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
@@ -546,14 +549,14 @@
                     format!("overflowed on value after {}", prev_discr.unwrap()),
                 ).note(&format!(
                     "explicitly set `{} = {}` if that is desired outcome",
-                    variant.node.ident, wrapped_discr
+                    variant.ident, wrapped_discr
                 ))
                 .emit();
                 None
             }.unwrap_or(wrapped_discr),
         );
 
-        for f in variant.node.data.fields() {
+        for f in variant.data.fields() {
             let def_id = tcx.hir().local_def_id(f.hir_id);
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
@@ -562,7 +565,7 @@
 
         // Convert the ctor, if any. This also registers the variant as
         // an item.
-        if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+        if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
             convert_variant_ctor(tcx, ctor_hir_id);
         }
     }
@@ -641,11 +644,11 @@
             let variants = def.variants
                 .iter()
                 .map(|v| {
-                    let variant_did = Some(tcx.hir().local_def_id(v.node.id));
-                    let ctor_did = v.node.data.ctor_hir_id()
+                    let variant_did = Some(tcx.hir().local_def_id(v.id));
+                    let ctor_did = v.data.ctor_hir_id()
                         .map(|hir_id| tcx.hir().local_def_id(hir_id));
 
-                    let discr = if let Some(ref e) = v.node.disr_expr {
+                    let discr = if let Some(ref e) = v.disr_expr {
                         distance_from_explicit = 0;
                         ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.hir_id))
                     } else {
@@ -653,8 +656,8 @@
                     };
                     distance_from_explicit += 1;
 
-                    convert_variant(tcx, variant_did, ctor_did, v.node.ident, discr,
-                                    &v.node.data, AdtKind::Enum, def_id)
+                    convert_variant(tcx, variant_did, ctor_did, v.ident, discr,
+                                    &v.data, AdtKind::Enum, def_id)
                 })
                 .collect();
 
@@ -1314,10 +1317,9 @@
             ForeignItemKind::Type => tcx.mk_foreign(def_id),
         },
 
-        Node::Ctor(&ref def) | Node::Variant(&Spanned {
-            node: hir::VariantKind { data: ref def, .. },
-            ..
-        }) => match *def {
+        Node::Ctor(&ref def) | Node::Variant(
+            hir::Variant { data: ref def, .. }
+        ) => match *def {
             VariantData::Unit(..) | VariantData::Struct(..) => {
                 tcx.type_of(tcx.hir().get_parent_did(hir_id))
             }
@@ -1363,12 +1365,8 @@
                     tcx.types.usize
                 }
 
-                Node::Variant(&Spanned {
-                    node:
-                        VariantKind {
-                            disr_expr: Some(ref e),
-                            ..
-                        },
+                Node::Variant(Variant {
+                    disr_expr: Some(ref e),
                     ..
                 }) if e.hir_id == hir_id =>
                 {
@@ -1809,10 +1807,9 @@
             compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
         }
 
-        Ctor(data) | Variant(Spanned {
-            node: hir::VariantKind { data, ..  },
-            ..
-        }) if data.ctor_hir_id().is_some() => {
+        Ctor(data) | Variant(
+            hir::Variant { data, ..  }
+        ) if data.ctor_hir_id().is_some() => {
             let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id));
             let inputs = data.fields()
                 .iter()
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index b75a091..7ed9d66 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -82,8 +82,8 @@
                 self.visit_node_helper(item.hir_id);
 
                 for variant in &enum_def.variants {
-                    if let hir::VariantData::Tuple(..) = variant.node.data {
-                        self.visit_node_helper(variant.node.data.ctor_hir_id().unwrap());
+                    if let hir::VariantData::Tuple(..) = variant.data {
+                        self.visit_node_helper(variant.data.ctor_hir_id().unwrap());
                     }
                 }
             }
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 7af7c79..e10837e 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -145,8 +145,8 @@
                 self.add_inferreds_for_item(item.hir_id);
 
                 for variant in &enum_def.variants {
-                    if let hir::VariantData::Tuple(..) = variant.node.data {
-                        self.add_inferreds_for_item(variant.node.data.ctor_hir_id().unwrap());
+                    if let hir::VariantData::Tuple(..) = variant.data {
+                        self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap());
                     }
                 }
             }
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 405144b..ec5d86b 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -3,7 +3,6 @@
 use syntax_pos::DUMMY_SP;
 use syntax::ast::*;
 use syntax::attr;
-use syntax::source_map::dummy_spanned;
 use syntax::symbol::Symbol;
 use syntax::with_default_globals;
 
@@ -181,7 +180,8 @@
 
         let mi = attr::mk_name_value_item_str(
             Ident::from_str("all"),
-            dummy_spanned(Symbol::intern("done"))
+            Symbol::intern("done"),
+            DUMMY_SP,
         );
         assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b281505..fede9e9 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -29,7 +29,7 @@
 use syntax::ast::{self, AttrStyle, Ident};
 use syntax::attr;
 use syntax::ext::base::MacroKind;
-use syntax::source_map::{dummy_spanned, Spanned};
+use syntax::source_map::DUMMY_SP;
 use syntax::symbol::{Symbol, kw, sym};
 use syntax::symbol::InternedString;
 use syntax_pos::{self, Pos, FileName};
@@ -930,8 +930,8 @@
             if attr.check_name(sym::enable) {
                 if let Some(feat) = attr.value_str() {
                     let meta = attr::mk_name_value_item_str(
-                        Ident::with_empty_ctxt(sym::target_feature),
-                        dummy_spanned(feat));
+                        Ident::with_dummy_span(sym::target_feature), feat, DUMMY_SP
+                    );
                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
                         cfg &= feat_cfg;
                     }
@@ -4102,8 +4102,7 @@
         PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
         PatKind::Struct(ref name, ref fields, etc) => {
             format!("{} {{ {}{} }}", qpath_to_string(name),
-                fields.iter().map(|&Spanned { node: ref fp, .. }|
-                                  format!("{}: {}", fp.ident, name_from_pat(&*fp.pat)))
+                fields.iter().map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat)))
                              .collect::<Vec<String>>().join(", "),
                 if etc { ", .." } else { "" }
             )
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 5c9fac7..c73c464 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -4,6 +4,7 @@
 use rustc::hir;
 use rustc::lint as lint;
 use rustc::ty;
+use rustc_resolve::ParentScope;
 use syntax;
 use syntax::ast::{self, Ident};
 use syntax::ext::base::SyntaxExtensionKind;
@@ -431,7 +432,7 @@
     let path = ast::Path::from_ident(Ident::from_str(path_str));
     cx.enter_resolver(|resolver| {
         if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
-            &path, None, &resolver.dummy_parent_scope(), false, false
+            &path, None, &ParentScope::module(resolver.graph_root), false, false
         ) {
             if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
                 return Some(res.map_id(|_| panic!("unexpected id")));
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 462e21b..83a8d3f 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -951,7 +951,7 @@
                      v: &'hir hir::Variant,
                      g: &'hir hir::Generics,
                      item_id: hir::HirId) {
-        self.visit_testable(v.node.ident.to_string(), &v.node.attrs, |this| {
+        self.visit_testable(v.ident.to_string(), &v.attrs, |this| {
             intravisit::walk_variant(this, v, g, item_id);
         });
     }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 35b6d99..903ed3a 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -130,10 +130,10 @@
         Enum {
             name,
             variants: def.variants.iter().map(|v| Variant {
-                name: v.node.ident.name,
-                id: v.node.id,
-                attrs: &v.node.attrs,
-                def: &v.node.data,
+                name: v.ident.name,
+                id: v.id,
+                attrs: &v.attrs,
+                def: &v.data,
                 whence: v.span,
             }).collect(),
             vis: &it.vis,
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 5334c4d..3288d0b 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -23,7 +23,7 @@
 compiler_builtins = { version = "0.1.16" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
-hashbrown = { version = "0.4.0", features = ['rustc-dep-of-std'] }
+hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] }
 
 [dependencies.backtrace]
 version = "0.3.34"
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 1e28ee8..a053898 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -6,7 +6,7 @@
 
 use crate::borrow::Borrow;
 use crate::cell::Cell;
-use crate::collections::CollectionAllocErr;
+use crate::collections::TryReserveError;
 use crate::fmt::{self, Debug};
 #[allow(deprecated)]
 use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13};
@@ -588,7 +588,7 @@
     /// ```
     #[inline]
     #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.base
             .try_reserve(additional)
             .map_err(map_collection_alloc_err)
@@ -2542,10 +2542,13 @@
 }
 
 #[inline]
-fn map_collection_alloc_err(err: hashbrown::CollectionAllocErr) -> CollectionAllocErr {
+fn map_collection_alloc_err(err: hashbrown::CollectionAllocErr) -> TryReserveError {
     match err {
-        hashbrown::CollectionAllocErr::CapacityOverflow => CollectionAllocErr::CapacityOverflow,
-        hashbrown::CollectionAllocErr::AllocErr => CollectionAllocErr::AllocErr,
+        hashbrown::CollectionAllocErr::CapacityOverflow => TryReserveError::CapacityOverflow,
+        hashbrown::CollectionAllocErr::AllocErr { layout } => TryReserveError::AllocError {
+            layout,
+            non_exhaustive: (),
+        },
     }
 }
 
@@ -2605,7 +2608,7 @@
     use super::RandomState;
     use crate::cell::RefCell;
     use rand::{thread_rng, Rng};
-    use realstd::collections::CollectionAllocErr::*;
+    use realstd::collections::TryReserveError::*;
     use realstd::usize;
 
     // https://github.com/rust-lang/rust/issues/62301
@@ -3405,7 +3408,7 @@
             panic!("usize::MAX should trigger an overflow!");
         }
 
-        if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE / 8) {
+        if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 8) {
         } else {
             panic!("usize::MAX / 8 should trigger an OOM!")
         }
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index d243412..26db651 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -1,5 +1,5 @@
 use crate::borrow::Borrow;
-use crate::collections::CollectionAllocErr;
+use crate::collections::TryReserveError;
 use crate::fmt;
 use crate::hash::{Hash, BuildHasher};
 use crate::iter::{Chain, FromIterator, FusedIterator};
@@ -383,7 +383,7 @@
     /// ```
     #[inline]
     #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.map.try_reserve(additional)
     }
 
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 15c2532..f595746 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -427,7 +427,7 @@
 pub use self::hash_set::HashSet;
 
 #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-pub use alloc_crate::collections::CollectionAllocErr;
+pub use alloc_crate::collections::TryReserveError;
 
 mod hash;
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index ba80d1b..c3882ba 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -228,7 +228,6 @@
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
 // NB: the following list is sorted to minimize merge conflicts.
-#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))]
 #![feature(alloc_error_handler)]
 #![feature(alloc_layout_extra)]
 #![feature(allocator_api)]
@@ -251,6 +250,7 @@
 #![feature(concat_idents)]
 #![feature(const_cstr_unchecked)]
 #![feature(const_raw_ptr_deref)]
+#![feature(container_error_extra)]
 #![feature(core_intrinsics)]
 #![feature(custom_test_frameworks)]
 #![feature(doc_alias)]
@@ -513,7 +513,7 @@
 
 // Re-export macros defined in libcore.
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated_in_future)]
+#[allow(deprecated, deprecated_in_future)]
 pub use core::{
     // Stable
     assert_eq,
@@ -531,7 +531,6 @@
 };
 
 // Re-export built-in macros defined through libcore.
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 pub use core::{
     // Stable
@@ -551,7 +550,6 @@
     option_env,
     stringify,
     // Unstable
-    __rust_unstable_column,
     asm,
     concat_idents,
     format_args_nl,
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index f200093..cbeaf20 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -53,20 +53,20 @@
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow_internal_unstable(__rust_unstable_column, libstd_sys_internals)]
+#[allow_internal_unstable(libstd_sys_internals)]
 macro_rules! panic {
     () => ({
         $crate::panic!("explicit panic")
     });
     ($msg:expr) => ({
-        $crate::rt::begin_panic($msg, &(file!(), line!(), __rust_unstable_column!()))
+        $crate::rt::begin_panic($msg, &($crate::file!(), $crate::line!(), $crate::column!()))
     });
     ($msg:expr,) => ({
         $crate::panic!($msg)
     });
     ($fmt:expr, $($arg:tt)+) => ({
-        $crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+),
-                                    &(file!(), line!(), __rust_unstable_column!()))
+        $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+),
+                                    &($crate::file!(), $crate::line!(), $crate::column!()))
     });
 }
 
@@ -113,7 +113,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(print_internals)]
 macro_rules! print {
-    ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
+    ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
 }
 
 /// Prints to the standard output, with a newline.
@@ -147,7 +147,7 @@
 macro_rules! println {
     () => ($crate::print!("\n"));
     ($($arg:tt)*) => ({
-        $crate::io::_print(format_args_nl!($($arg)*));
+        $crate::io::_print($crate::format_args_nl!($($arg)*));
     })
 }
 
@@ -176,7 +176,7 @@
 #[stable(feature = "eprint", since = "1.19.0")]
 #[allow_internal_unstable(print_internals)]
 macro_rules! eprint {
-    ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
+    ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
 }
 
 /// Prints to the standard error, with a newline.
@@ -206,7 +206,7 @@
 macro_rules! eprintln {
     () => ($crate::eprint!("\n"));
     ($($arg:tt)*) => ({
-        $crate::io::_eprint(format_args_nl!($($arg)*));
+        $crate::io::_eprint($crate::format_args_nl!($($arg)*));
     })
 }
 
@@ -337,7 +337,7 @@
 #[stable(feature = "dbg_macro", since = "1.32.0")]
 macro_rules! dbg {
     () => {
-        $crate::eprintln!("[{}:{}]", file!(), line!());
+        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
     };
     ($val:expr) => {
         // Use of `match` here is intentional because it affects the lifetimes
@@ -345,7 +345,7 @@
         match $val {
             tmp => {
                 $crate::eprintln!("[{}:{}] {} = {:#?}",
-                    file!(), line!(), stringify!($val), &tmp);
+                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                 tmp
             }
         }
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index 0761c50..611a170 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -8,8 +8,7 @@
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
-#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
+#[doc(include = "char.md")]
 #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "hexagon",
@@ -33,8 +32,7 @@
                                          target_arch = "powerpc")),
           all(target_os = "fuchsia", target_arch = "aarch64")))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
-#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
+#[doc(include = "char.md")]
 #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "hexagon",
@@ -58,51 +56,37 @@
                                              target_arch = "powerpc")),
               all(target_os = "fuchsia", target_arch = "aarch64"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
-#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "schar.md"))]
+#[doc(include = "schar.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
-#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))]
+#[doc(include = "uchar.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
-#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "short.md"))]
+#[doc(include = "short.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
-#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))]
+#[doc(include = "ushort.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
-#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "int.md"))]
+#[doc(include = "int.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
-#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "uint.md"))]
+#[doc(include = "uint.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
-#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
+#[doc(include = "long.md")]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
-#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
+#[doc(include = "ulong.md")]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
-#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
+#[doc(include = "long.md")]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
-#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
+#[doc(include = "ulong.md")]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
-#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))]
+#[doc(include = "longlong.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
-#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))]
+#[doc(include = "ulonglong.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
-#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "float.md"))]
+#[doc(include = "float.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
-#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))]
-#[cfg_attr(not(bootstrap), doc(include = "double.md"))]
+#[doc(include = "double.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;
 
 #[stable(feature = "raw_os", since = "1.1.0")]
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index 1c61f21..3e4cf91 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -7,10 +7,6 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 // Re-exported core operators
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)]
-pub use crate::marker::Copy;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::marker::{Send, Sized, Sync, Unpin};
@@ -24,21 +20,9 @@
 pub use crate::mem::drop;
 
 // Re-exported types and traits
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)]
-pub use crate::clone::Clone;
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)]
-pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::convert::{AsRef, AsMut, Into, From};
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)]
-pub use crate::default::Default;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::iter::{Iterator, Extend, IntoIterator};
@@ -53,11 +37,9 @@
 pub use crate::result::Result::{self, Ok, Err};
 
 // Re-exported built-in macros
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[doc(no_inline)]
 pub use core::prelude::v1::{
-    __rust_unstable_column,
     asm,
     assert,
     cfg,
@@ -83,7 +65,6 @@
 
 // FIXME: Attribute and derive macros are not documented because for them rustdoc generates
 // dead links which fail link checker testing.
-#[cfg(not(bootstrap))]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
 #[doc(hidden)]
diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs
index e29faf1..fd6e46f 100644
--- a/src/libstd/sync/mod.rs
+++ b/src/libstd/sync/mod.rs
@@ -163,7 +163,6 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::mutex::{Mutex, MutexGuard};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(bootstrap, allow(deprecated_in_future))]
 #[allow(deprecated)]
 pub use self::once::{Once, OnceState, ONCE_INIT};
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs
index 9addba8..38db4dd 100644
--- a/src/libstd/sys/cloudabi/abi/cloudabi.rs
+++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs
@@ -115,6 +115,7 @@
 
 #![no_std]
 #![allow(non_camel_case_types)]
+#![allow(deprecated)] // FIXME: using `mem::uninitialized()`
 
 include!("bitflags.rs");
 
diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs
index 6e14761..2fb10cc 100644
--- a/src/libstd/sys/cloudabi/mod.rs
+++ b/src/libstd/sys/cloudabi/mod.rs
@@ -1,5 +1,3 @@
-#![allow(deprecated_in_future)] // mem::uninitialized; becomes `deprecated` when nightly is 1.39
-
 use crate::io::ErrorKind;
 use crate::mem;
 
diff --git a/src/libstd/sys/cloudabi/mutex.rs b/src/libstd/sys/cloudabi/mutex.rs
index d3ff007..0e30d3a 100644
--- a/src/libstd/sys/cloudabi/mutex.rs
+++ b/src/libstd/sys/cloudabi/mutex.rs
@@ -104,10 +104,11 @@
                 },
                 ..mem::zeroed()
             };
-            let mut event: abi::event = mem::uninitialized();
-            let mut nevents: usize = mem::uninitialized();
-            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            let mut event = MaybeUninit::<abi::event>::uninit();
+            let mut nevents = MaybeUninit::<usize>::uninit();
+            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
+            let event = event.assume_init();
             assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
         }
     }
diff --git a/src/libstd/sys/cloudabi/rwlock.rs b/src/libstd/sys/cloudabi/rwlock.rs
index 6da3f38..73499d6 100644
--- a/src/libstd/sys/cloudabi/rwlock.rs
+++ b/src/libstd/sys/cloudabi/rwlock.rs
@@ -1,5 +1,6 @@
 use crate::cell::UnsafeCell;
 use crate::mem;
+use crate::mem::MaybeUninit;
 use crate::sync::atomic::{AtomicU32, Ordering};
 use crate::sys::cloudabi::abi;
 
@@ -73,10 +74,11 @@
                 },
                 ..mem::zeroed()
             };
-            let mut event: abi::event = mem::uninitialized();
-            let mut nevents: usize = mem::uninitialized();
-            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            let mut event = MaybeUninit::<abi::event>::uninit();
+            let mut nevents = MaybeUninit::<usize>::uninit();
+            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock");
+            let event = event.assume_init();
             assert_eq!(
                 event.error,
                 abi::errno::SUCCESS,
@@ -182,10 +184,11 @@
                 },
                 ..mem::zeroed()
             };
-            let mut event: abi::event = mem::uninitialized();
-            let mut nevents: usize = mem::uninitialized();
-            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            let mut event = MaybeUninit::<abi::event>::uninit();
+            let mut nevents = MaybeUninit::<usize>::uninit();
+            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock");
+            let event = event.assume_init();
             assert_eq!(
                 event.error,
                 abi::errno::SUCCESS,
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
index 7da16c4..240b6ea 100644
--- a/src/libstd/sys/cloudabi/thread.rs
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -72,10 +72,11 @@
                 },
                 ..mem::zeroed()
             };
-            let mut event: abi::event = mem::uninitialized();
-            let mut nevents: usize = mem::uninitialized();
-            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            let mut event = mem::MaybeUninit::<abi::event>::uninit();
+            let mut nevents = mem::MaybeUninit::<usize>::uninit();
+            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
             assert_eq!(ret, abi::errno::SUCCESS);
+            let event = event.assume_init();
             assert_eq!(event.error, abi::errno::SUCCESS);
         }
     }
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index f706709..b1f9d97 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -714,7 +714,7 @@
     pub struct FILE_STANDARD_INFO {
         pub AllocationSize: LARGE_INTEGER,
         pub EndOfFile: LARGE_INTEGER,
-        pub NumberOfLink: DWORD,
+        pub NumberOfLinks: DWORD,
         pub DeletePending: BOOLEAN,
         pub Directory: BOOLEAN,
     }
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 5bae6ba..204f6af 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -357,7 +357,7 @@
                                                 size as c::DWORD))?;
             attr.file_size = info.AllocationSize as u64;
             attr.number_of_links = Some(info.NumberOfLinks);
-            if attr.is_reparse_point() {
+            if attr.file_type().is_reparse_point() {
                 let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
                 if let Ok((_, buf)) = self.reparse_point(&mut b) {
                     attr.reparse_tag = buf.ReparseTag;
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 052eb55..3ae37f7 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -571,7 +571,7 @@
 
         match &self.node {
             PatKind::Ident(_, _, Some(p)) => p.walk(it),
-            PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
+            PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk(it)),
             PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => {
                 s.iter().all(|p| p.walk(it))
             }
@@ -608,6 +608,8 @@
     pub pat: P<Pat>,
     pub is_shorthand: bool,
     pub attrs: ThinVec<Attribute>,
+    pub id: NodeId,
+    pub span: Span,
 }
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
@@ -641,7 +643,7 @@
 
     /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
     /// The `bool` is `true` in the presence of a `..`.
-    Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
+    Struct(Path, Vec<FieldPat>, /* recovered */ bool),
 
     /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
     TupleStruct(Path, Vec<P<Pat>>),
@@ -925,6 +927,7 @@
     pub guard: Option<P<Expr>>,
     pub body: P<Expr>,
     pub span: Span,
+    pub id: NodeId,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -934,10 +937,9 @@
     pub span: Span,
     pub is_shorthand: bool,
     pub attrs: ThinVec<Attribute>,
+    pub id: NodeId,
 }
 
-pub type SpannedIdent = Spanned<Ident>;
-
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
 pub enum BlockCheckMode {
     Default,
@@ -1284,8 +1286,6 @@
     Movable,
 }
 
-pub type Mac = Spanned<Mac_>;
-
 /// Represents a macro invocation. The `Path` indicates which macro
 /// is being invoked, and the vector of token-trees contains the source
 /// of the macro invocation.
@@ -1293,10 +1293,11 @@
 /// N.B., the additional ident for a `macro_rules`-style macro is actually
 /// stored in the enclosing item.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct Mac_ {
+pub struct Mac {
     pub path: Path,
     pub delim: MacDelimiter,
     pub tts: TokenStream,
+    pub span: Span,
     pub prior_type_ascription: Option<(Span, bool)>,
 }
 
@@ -1307,7 +1308,7 @@
     Brace,
 }
 
-impl Mac_ {
+impl Mac {
     pub fn stream(&self) -> TokenStream {
         self.tts.clone()
     }
@@ -2038,7 +2039,7 @@
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct Variant_ {
+pub struct Variant {
     /// Name of the variant.
     pub ident: Ident,
     /// Attributes of the variant.
@@ -2049,10 +2050,10 @@
     pub data: VariantData,
     /// Explicit discriminant, e.g., `Foo = 1`.
     pub disr_expr: Option<AnonConst>,
+    /// Span
+    pub span: Span,
 }
 
-pub type Variant = Spanned<Variant_>;
-
 /// Part of `use` item to the right of its prefix.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum UseTreeKind {
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index a9d3227..bcf03b5 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -13,7 +13,7 @@
 use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem};
 use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam};
 use crate::mut_visit::visit_clobber;
-use crate::source_map::{BytePos, Spanned, dummy_spanned};
+use crate::source_map::{BytePos, Spanned, DUMMY_SP};
 use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
 use crate::parse::parser::Parser;
 use crate::parse::{self, ParseSess, PResult};
@@ -327,8 +327,10 @@
         if self.is_sugared_doc {
             let comment = self.value_str().unwrap();
             let meta = mk_name_value_item_str(
-                Ident::with_empty_ctxt(sym::doc),
-                dummy_spanned(Symbol::intern(&strip_doc_comment_decoration(&comment.as_str()))));
+                Ident::with_dummy_span(sym::doc),
+                Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())),
+                DUMMY_SP,
+            );
             f(&Attribute {
                 id: self.id,
                 style: self.style,
@@ -345,9 +347,9 @@
 
 /* Constructors */
 
-pub fn mk_name_value_item_str(ident: Ident, value: Spanned<Symbol>) -> MetaItem {
-    let lit_kind = LitKind::Str(value.node, ast::StrStyle::Cooked);
-    mk_name_value_item(ident, lit_kind, value.span)
+pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
+    let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked);
+    mk_name_value_item(ident, lit_kind, str_span)
 }
 
 pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem {
@@ -410,7 +412,7 @@
     Attribute {
         id: mk_attr_id(),
         style,
-        path: Path::from_ident(Ident::with_empty_ctxt(sym::doc).with_span_pos(span)),
+        path: Path::from_ident(Ident::with_dummy_span(sym::doc).with_span_pos(span)),
         tokens: MetaItemKind::NameValue(lit).tokens(span),
         is_sugared_doc: true,
         span,
@@ -712,7 +714,7 @@
 
 derive_has_attrs! {
     Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
-    ast::Field, ast::FieldPat, ast::Variant_, ast::Arg
+    ast::Field, ast::FieldPat, ast::Variant, ast::Arg
 }
 
 pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate {
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 1ab367f..7eeea4e 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -260,7 +260,7 @@
             ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
                 variants.flat_map_in_place(|variant| self.configure(variant));
                 for variant in variants {
-                    self.configure_variant_data(&mut variant.node.data);
+                    self.configure_variant_data(&mut variant.data);
                 }
             }
             _ => {}
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index 80591ad..9618b5a 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -172,7 +172,7 @@
             (descriptions.len(), ecx.expr_vec(span, descriptions))
         });
 
-    let static_ = ecx.lifetime(span, Ident::with_empty_ctxt(kw::StaticLifetime));
+    let static_ = ecx.lifetime(span, Ident::with_dummy_span(kw::StaticLifetime));
     let ty_str = ecx.ty_rptr(
         span,
         ecx.ty_ident(span, ecx.ident_of("str")),
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 7f4feff..fb1bf4d 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -1,6 +1,6 @@
 use crate::ast::{self, Attribute, Name, PatKind};
 use crate::attr::{HasAttrs, Stability, Deprecation};
-use crate::source_map::{SourceMap, Spanned, respan};
+use crate::source_map::SourceMap;
 use crate::edition::Edition;
 use crate::ext::expand::{self, AstFragment, Invocation};
 use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency};
@@ -15,7 +15,7 @@
 use errors::{DiagnosticBuilder, DiagnosticId};
 use smallvec::{smallvec, SmallVec};
 use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP};
-use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
+use syntax_pos::hygiene::{ExpnData, ExpnKind};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
@@ -405,7 +405,6 @@
 /// after hitting errors.
 #[derive(Copy, Clone)]
 pub struct DummyResult {
-    expr_only: bool,
     is_error: bool,
     span: Span,
 }
@@ -416,21 +415,12 @@
     /// Use this as a return value after hitting any errors and
     /// calling `span_err`.
     pub fn any(span: Span) -> Box<dyn MacResult+'static> {
-        Box::new(DummyResult { expr_only: false, is_error: true, span })
+        Box::new(DummyResult { is_error: true, span })
     }
 
     /// Same as `any`, but must be a valid fragment, not error.
     pub fn any_valid(span: Span) -> Box<dyn MacResult+'static> {
-        Box::new(DummyResult { expr_only: false, is_error: false, span })
-    }
-
-    /// Creates a default MacResult that can only be an expression.
-    ///
-    /// Use this for macros that must expand to an expression, so even
-    /// if an error is encountered internally, the user will receive
-    /// an error that they also used it in the wrong place.
-    pub fn expr(span: Span) -> Box<dyn MacResult+'static> {
-        Box::new(DummyResult { expr_only: true, is_error: true, span })
+        Box::new(DummyResult { is_error: false, span })
     }
 
     /// A plain dummy expression.
@@ -472,36 +462,19 @@
     }
 
     fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
-        // this code needs a comment... why not always just return the Some() ?
-        if self.expr_only {
-            None
-        } else {
-            Some(SmallVec::new())
-        }
+        Some(SmallVec::new())
     }
 
     fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::ImplItem; 1]>> {
-        if self.expr_only {
-            None
-        } else {
-            Some(SmallVec::new())
-        }
+        Some(SmallVec::new())
     }
 
     fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::TraitItem; 1]>> {
-        if self.expr_only {
-            None
-        } else {
-            Some(SmallVec::new())
-        }
+        Some(SmallVec::new())
     }
 
     fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[ast::ForeignItem; 1]>> {
-        if self.expr_only {
-            None
-        } else {
-            Some(SmallVec::new())
-        }
+        Some(SmallVec::new())
     }
 
     fn make_stmts(self: Box<DummyResult>) -> Option<SmallVec<[ast::Stmt; 1]>> {
@@ -667,10 +640,11 @@
         SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition)
     }
 
-    pub fn expn_info(&self, call_site: Span, descr: Symbol) -> ExpnInfo {
-        ExpnInfo {
-            call_site,
+    pub fn expn_data(&self, parent: ExpnId, call_site: Span, descr: Symbol) -> ExpnData {
+        ExpnData {
             kind: ExpnKind::Macro(self.macro_kind(), descr),
+            parent,
+            call_site,
             def_site: self.span,
             default_transparency: self.default_transparency,
             allow_internal_unstable: self.allow_internal_unstable.clone(),
@@ -734,7 +708,7 @@
 
 /// One of these is made during expansion and incrementally updated as we go;
 /// when a macro expansion occurs, the resulting nodes have the `backtrace()
-/// -> expn_info` of their expansion context stored into their span.
+/// -> expn_data` of their expansion context stored into their span.
 pub struct ExtCtxt<'a> {
     pub parse_sess: &'a parse::ParseSess,
     pub ecfg: expand::ExpansionConfig<'a>,
@@ -783,13 +757,10 @@
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
     pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config }
     pub fn call_site(&self) -> Span {
-        match self.current_expansion.id.expn_info() {
-            Some(expn_info) => expn_info.call_site,
-            None => DUMMY_SP,
-        }
+        self.current_expansion.id.expn_data().call_site
     }
     pub fn backtrace(&self) -> SyntaxContext {
-        SyntaxContext::empty().apply_mark(self.current_expansion.id)
+        SyntaxContext::root().apply_mark(self.current_expansion.id)
     }
 
     /// Returns span for the macro which originally caused the current expansion to happen.
@@ -799,17 +770,13 @@
         let mut ctxt = self.backtrace();
         let mut last_macro = None;
         loop {
-            if ctxt.outer_expn_info().map_or(None, |info| {
-                if info.kind.descr() == sym::include {
-                    // Stop going up the backtrace once include! is encountered
-                    return None;
-                }
-                ctxt = info.call_site.ctxt();
-                last_macro = Some(info.call_site);
-                Some(())
-            }).is_none() {
-                break
+            let expn_data = ctxt.outer_expn_data();
+            // Stop going up the backtrace once include! is encountered
+            if expn_data.is_root() || expn_data.kind.descr() == sym::include {
+                break;
             }
+            ctxt = expn_data.call_site.ctxt();
+            last_macro = Some(expn_data.call_site);
         }
         last_macro
     }
@@ -899,7 +866,7 @@
     pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
         let def_site = DUMMY_SP.apply_mark(self.current_expansion.id);
         iter::once(Ident::new(kw::DollarCrate, def_site))
-            .chain(components.iter().map(|&s| Ident::with_empty_ctxt(s)))
+            .chain(components.iter().map(|&s| Ident::with_dummy_span(s)))
             .collect()
     }
     pub fn name_of(&self, st: &str) -> ast::Name {
@@ -943,15 +910,17 @@
     cx: &'a mut ExtCtxt<'_>,
     mut expr: P<ast::Expr>,
     err_msg: &str,
-) -> Result<Spanned<(Symbol, ast::StrStyle)>, Option<DiagnosticBuilder<'a>>> {
+) -> Result<(Symbol, ast::StrStyle, Span), Option<DiagnosticBuilder<'a>>> {
     // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
     expr.span = expr.span.apply_mark(cx.current_expansion.id);
 
-    // we want to be able to handle e.g., `concat!("foo", "bar")`
-    cx.expander().visit_expr(&mut expr);
+    // Perform eager expansion on the expression.
+    // We want to be able to handle e.g., `concat!("foo", "bar")`.
+    let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
+
     Err(match expr.node {
         ast::ExprKind::Lit(ref l) => match l.node {
-            ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))),
+            ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
             ast::LitKind::Err(_) => None,
             _ => Some(cx.struct_span_err(l.span, err_msg))
         },
@@ -965,7 +934,7 @@
     expr_to_spanned_string(cx, expr, err_msg)
         .map_err(|err| err.map(|mut err| err.emit()))
         .ok()
-        .map(|s| s.node)
+        .map(|(symbol, style, _)| (symbol, style))
 }
 
 /// Non-fatally assert that `tts` is empty. Note that this function
@@ -1013,8 +982,12 @@
     let mut p = cx.new_parser_from_tts(tts);
     let mut es = Vec::new();
     while p.token != token::Eof {
-        let mut expr = panictry!(p.parse_expr());
-        cx.expander().visit_expr(&mut expr);
+        let expr = panictry!(p.parse_expr());
+
+        // Perform eager expansion on the expression.
+        // We want to be able to handle e.g., `concat!("foo", "bar")`.
+        let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
+
         es.push(expr);
         if p.eat(&token::Comma) {
             continue;
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 2296249..e2ac4d5 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -340,7 +340,7 @@
         self.expr_path(self.path_ident(span, id))
     }
     pub fn expr_self(&self, span: Span) -> P<ast::Expr> {
-        self.expr_ident(span, Ident::with_empty_ctxt(kw::SelfLower))
+        self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
     }
 
     pub fn expr_binary(&self, sp: Span, op: ast::BinOpKind,
@@ -403,6 +403,7 @@
             span,
             is_shorthand: false,
             attrs: ThinVec::new(),
+            id: ast::DUMMY_NODE_ID,
         }
     }
     pub fn expr_struct(
@@ -574,7 +575,7 @@
         self.pat(span, PatKind::TupleStruct(path, subpats))
     }
     pub fn pat_struct(&self, span: Span, path: ast::Path,
-                  field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
+                      field_pats: Vec<ast::FieldPat>) -> P<ast::Pat> {
         self.pat(span, PatKind::Struct(path, field_pats, false))
     }
     pub fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
@@ -612,6 +613,7 @@
             guard: None,
             body: expr,
             span,
+            id: ast::DUMMY_NODE_ID,
         }
     }
 
@@ -781,14 +783,14 @@
             ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID)
         };
 
-        respan(span,
-               ast::Variant_ {
-                   ident,
-                   id: ast::DUMMY_NODE_ID,
-                   attrs: Vec::new(),
-                   data: vdata,
-                   disr_expr: None,
-               })
+        ast::Variant {
+            attrs: Vec::new(),
+            data: vdata,
+            disr_expr: None,
+            id: ast::DUMMY_NODE_ID,
+            ident,
+            span,
+        }
     }
 
     pub fn item_enum_poly(&self, span: Span, name: Ident,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 9a3195b..dac4029 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1,11 +1,11 @@
 use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path};
 use crate::ast::{MacStmtStyle, StmtKind, ItemKind};
 use crate::attr::{self, HasAttrs};
-use crate::source_map::{dummy_spanned, respan};
+use crate::source_map::respan;
 use crate::config::StripUnconfigured;
 use crate::ext::base::*;
 use crate::ext::proc_macro::collect_derives;
-use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind};
+use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind};
 use crate::ext::tt::macro_rules::annotate_err_with_kind;
 use crate::ext::placeholders::{placeholder, PlaceholderExpander};
 use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
@@ -25,7 +25,6 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
-use std::fs;
 use std::io::ErrorKind;
 use std::{iter, mem};
 use std::ops::DerefMut;
@@ -116,18 +115,6 @@
             }
         }
 
-        impl<'a, 'b> MutVisitor for MacroExpander<'a, 'b> {
-            fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
-                self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr()
-            }
-            $($(fn $mut_visit_ast(&mut self, ast: &mut $AstTy) {
-                visit_clobber(ast, |ast| self.expand_fragment(AstFragment::$Kind(ast)).$make_ast());
-            })?)*
-            $($(fn $flat_map_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
-                self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast()
-            })?)*
-        }
-
         impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> {
             $(fn $make_ast(self: Box<crate::ext::tt::macro_rules::ParserAnyMacro<'a>>)
                            -> Option<$AstTy> {
@@ -265,7 +252,7 @@
             tokens: None,
         })]);
 
-        match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
+        match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
             Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
                 krate.attrs = attrs;
                 krate.module = module;
@@ -285,8 +272,8 @@
         krate
     }
 
-    // Fully expand all macro invocations in this AST fragment.
-    fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
+    // Recursively expand all macro invocations in this AST fragment.
+    pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
         let orig_expansion_data = self.cx.current_expansion.clone();
         self.cx.current_expansion.depth = 0;
 
@@ -365,7 +352,7 @@
                 derives.reserve(traits.len());
                 invocations.reserve(traits.len());
                 for path in traits {
-                    let expn_id = ExpnId::fresh(self.cx.current_expansion.id, None);
+                    let expn_id = ExpnId::fresh(None);
                     derives.push(expn_id);
                     invocations.push(Invocation {
                         kind: InvocationKind::Derive { path, item: item.clone() },
@@ -487,11 +474,11 @@
         }
 
         if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
-            let info = self.cx.current_expansion.id.expn_info().unwrap();
+            let expn_data = self.cx.current_expansion.id.expn_data();
             let suggested_limit = self.cx.ecfg.recursion_limit * 2;
-            let mut err = self.cx.struct_span_err(info.call_site,
+            let mut err = self.cx.struct_span_err(expn_data.call_site,
                 &format!("recursion limit reached while expanding the macro `{}`",
-                         info.kind.descr()));
+                         expn_data.kind.descr()));
             err.help(&format!(
                 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                 suggested_limit));
@@ -504,22 +491,21 @@
             InvocationKind::Bang { mac, .. } => match ext {
                 SyntaxExtensionKind::Bang(expander) => {
                     self.gate_proc_macro_expansion_kind(span, fragment_kind);
-                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                    let tok_result = expander.expand(self.cx, span, mac.stream());
                     let result =
-                        self.parse_ast_fragment(tok_result, fragment_kind, &mac.node.path, span);
+                        self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span);
                     self.gate_proc_macro_expansion(span, &result);
                     result
                 }
                 SyntaxExtensionKind::LegacyBang(expander) => {
                     let prev = self.cx.current_expansion.prior_type_ascription;
-                    self.cx.current_expansion.prior_type_ascription =
-                        mac.node.prior_type_ascription;
-                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                    self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
+                    let tok_result = expander.expand(self.cx, span, mac.stream());
                     let result = if let Some(result) = fragment_kind.make_from(tok_result) {
                         result
                     } else {
                         let msg = format!("non-{kind} macro in {kind} position: {path}",
-                                          kind = fragment_kind.name(), path = mac.node.path);
+                                          kind = fragment_kind.name(), path = mac.path);
                         self.cx.span_err(span, &msg);
                         self.cx.trace_macros_diag();
                         fragment_kind.dummy(span)
@@ -772,7 +758,7 @@
             let msg = format!("macro expansion ignores token `{}` and any following",
                               self.this_token_to_string());
             // Avoid emitting backtrace info twice.
-            let def_site_span = self.token.span.with_ctxt(SyntaxContext::empty());
+            let def_site_span = self.token.span.with_ctxt(SyntaxContext::root());
             let mut err = self.diagnostic().struct_span_err(def_site_span, &msg);
             err.span_label(span, "caused by the macro expansion here");
             let msg = format!(
@@ -809,17 +795,20 @@
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
-        // Expansion info for all the collected invocations is set upon their resolution,
+        // Expansion data for all the collected invocations is set upon their resolution,
         // with exception of the derive container case which is not resolved and can get
-        // its expansion info immediately.
-        let expn_info = match &kind {
-            InvocationKind::DeriveContainer { item, .. } => Some(ExpnInfo::default(
-                ExpnKind::Macro(MacroKind::Attr, sym::derive),
-                item.span(), self.cx.parse_sess.edition,
-            )),
+        // its expansion data immediately.
+        let expn_data = match &kind {
+            InvocationKind::DeriveContainer { item, .. } => Some(ExpnData {
+                parent: self.cx.current_expansion.id,
+                ..ExpnData::default(
+                    ExpnKind::Macro(MacroKind::Attr, sym::derive),
+                    item.span(), self.cx.parse_sess.edition,
+                )
+            }),
             _ => None,
         };
-        let expn_id = ExpnId::fresh(self.cx.current_expansion.id, expn_info);
+        let expn_id = ExpnId::fresh(expn_data);
         self.invocations.push(Invocation {
             kind,
             fragment_kind,
@@ -1251,30 +1240,30 @@
                     }
 
                     let filename = self.cx.resolve_path(&*file.as_str(), it.span());
-                    match fs::read_to_string(&filename) {
-                        Ok(src) => {
-                            let src_interned = Symbol::intern(&src);
-
-                            // Add this input file to the code map to make it available as
-                            // dependency information
-                            self.cx.source_map().new_source_file(filename.into(), src);
+                    match self.cx.source_map().load_file(&filename) {
+                        Ok(source_file) => {
+                            let src = source_file.src.as_ref()
+                                .expect("freshly loaded file should have a source");
+                            let src_interned = Symbol::intern(src.as_str());
 
                             let include_info = vec![
                                 ast::NestedMetaItem::MetaItem(
                                     attr::mk_name_value_item_str(
-                                        Ident::with_empty_ctxt(sym::file),
-                                        dummy_spanned(file),
+                                        Ident::with_dummy_span(sym::file),
+                                        file,
+                                        DUMMY_SP,
                                     ),
                                 ),
                                 ast::NestedMetaItem::MetaItem(
                                     attr::mk_name_value_item_str(
-                                        Ident::with_empty_ctxt(sym::contents),
-                                        dummy_spanned(src_interned),
+                                        Ident::with_dummy_span(sym::contents),
+                                        src_interned,
+                                        DUMMY_SP,
                                     ),
                                 ),
                             ];
 
-                            let include_ident = Ident::with_empty_ctxt(sym::include);
+                            let include_ident = Ident::with_dummy_span(sym::include);
                             let item = attr::mk_list_item(include_ident, include_info);
                             items.push(ast::NestedMetaItem::MetaItem(item));
                         }
@@ -1336,7 +1325,7 @@
                 }
             }
 
-            let meta = attr::mk_list_item(Ident::with_empty_ctxt(sym::doc), items);
+            let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
             *at = attr::Attribute {
                 span: at.span,
                 id: at.id,
diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs
index b2b17b0..2d05f8f 100644
--- a/src/libsyntax/ext/placeholders.rs
+++ b/src/libsyntax/ext/placeholders.rs
@@ -14,12 +14,13 @@
 
 pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
     fn mac_placeholder() -> ast::Mac {
-        dummy_spanned(ast::Mac_ {
+        ast::Mac {
             path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
             tts: TokenStream::empty().into(),
             delim: ast::MacDelimiter::Brace,
+            span: DUMMY_SP,
             prior_type_ascription: None,
-        })
+        }
     }
 
     let ident = ast::Ident::invalid();
diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
index 36621ce..1619fa6 100644
--- a/src/libsyntax/ext/proc_macro_server.rs
+++ b/src/libsyntax/ext/proc_macro_server.rs
@@ -362,10 +362,10 @@
 impl<'a> Rustc<'a> {
     pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
         // No way to determine def location for a proc macro right now, so use call location.
-        let location = cx.current_expansion.id.expn_info().unwrap().call_site;
+        let location = cx.current_expansion.id.expn_data().call_site;
         let to_span = |transparency| {
             location.with_ctxt(
-                SyntaxContext::empty()
+                SyntaxContext::root()
                     .apply_mark_with_transparency(cx.current_expansion.id, transparency),
             )
         };
@@ -677,7 +677,7 @@
         self.sess.source_map().lookup_char_pos(span.lo()).file
     }
     fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
-        span.ctxt().outer_expn_info().map(|i| i.call_site)
+        span.parent()
     }
     fn source(&mut self, span: Self::Span) -> Self::Span {
         span.source_callsite()
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 08a113b..1a87a90 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -30,7 +30,6 @@
 
 use errors::{Applicability, DiagnosticBuilder, Handler};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lock;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use log::debug;
@@ -1956,7 +1955,7 @@
 
             ast::ItemKind::Enum(ast::EnumDef{ref variants, ..}, ..) => {
                 for variant in variants {
-                    match (&variant.node.data, &variant.node.disr_expr) {
+                    match (&variant.data, &variant.disr_expr) {
                         (ast::VariantData::Unit(..), _) => {},
                         (_, Some(disr_expr)) =>
                             gate_feature_post!(
@@ -2088,11 +2087,6 @@
                                        "type ascription is experimental");
                 }
             }
-            ast::ExprKind::Yield(..) => {
-                gate_feature_post!(&self, generators,
-                                  e.span,
-                                  "yield syntax is experimental");
-            }
             ast::ExprKind::TryBlock(_) => {
                 gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
             }
@@ -2427,10 +2421,6 @@
     features
 }
 
-fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
-    vec.borrow().iter().for_each(f);
-}
-
 pub fn check_crate(krate: &ast::Crate,
                    sess: &ParseSess,
                    features: &Features,
@@ -2443,26 +2433,16 @@
         plugin_attributes,
     };
 
-    for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
-        &ctx,
-        param_attrs,
-        *span,
-        "attributes on function parameters are unstable"
-    ));
+    macro_rules! gate_all {
+        ($spans:ident, $gate:ident, $msg:literal) => {
+            for span in &*sess.$spans.borrow() { gate_feature!(&ctx, $gate, *span, $msg); }
+        }
+    }
 
-    for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
-        &ctx,
-        let_chains,
-        *span,
-        "`let` expressions in this position are experimental"
-    ));
-
-    for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
-        &ctx,
-        async_closure,
-        *span,
-        "async closures are unstable"
-    ));
+    gate_all!(param_attr_spans, param_attrs, "attributes on function parameters are unstable");
+    gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental");
+    gate_all!(async_closure_spans, async_closure, "async closures are unstable");
+    gate_all!(yield_spans, generators, "yield syntax is experimental");
 
     let visitor = &mut PostExpansionVisitor {
         context: &ctx,
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index be04c6a..acafe32 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -383,10 +383,11 @@
 }
 
 pub fn noop_visit_arm<T: MutVisitor>(
-    Arm { attrs, pats, guard, body, span }: &mut Arm,
+    Arm { attrs, pats, guard, body, span, id }: &mut Arm,
     vis: &mut T,
 ) {
     visit_attrs(attrs, vis);
+    vis.visit_id(id);
     visit_vec(pats, |pat| vis.visit_pat(pat));
     visit_opt(guard, |guard| vis.visit_expr(guard));
     vis.visit_expr(body);
@@ -455,7 +456,7 @@
 }
 
 pub fn noop_visit_variant<T: MutVisitor>(variant: &mut Variant, vis: &mut T) {
-    let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant;
+    let Variant { ident, attrs, id, data, disr_expr, span } = variant;
     vis.visit_ident(ident);
     visit_attrs(attrs, vis);
     vis.visit_id(id);
@@ -532,8 +533,8 @@
     vis.visit_span(span);
 }
 
-pub fn noop_visit_mac<T: MutVisitor>(Spanned { node, span }: &mut Mac, vis: &mut T) {
-    let Mac_ { path, delim: _, tts, .. } = node;
+pub fn noop_visit_mac<T: MutVisitor>(mac: &mut Mac, vis: &mut T) {
+    let Mac { path, delim: _, tts, span, prior_type_ascription: _ } = mac;
     vis.visit_path(path);
     vis.visit_tts(tts);
     vis.visit_span(span);
@@ -808,9 +809,10 @@
 }
 
 pub fn noop_visit_field<T: MutVisitor>(f: &mut Field, vis: &mut T) {
-    let Field { ident, expr, span, is_shorthand: _, attrs } = f;
+    let Field { ident, expr, span, is_shorthand: _, attrs, id } = f;
     vis.visit_ident(ident);
     vis.visit_expr(expr);
+    vis.visit_id(id);
     vis.visit_span(span);
     visit_thin_attrs(attrs, vis);
 }
@@ -1040,8 +1042,9 @@
         }
         PatKind::Struct(path, fields, _etc) => {
             vis.visit_path(path);
-            for Spanned { node: FieldPat { ident, pat, is_shorthand: _, attrs }, span } in fields {
+            for FieldPat { ident, pat, is_shorthand: _, attrs, id, span } in fields {
                 vis.visit_ident(ident);
+                vis.visit_id(id);
                 vis.visit_pat(pat);
                 visit_thin_attrs(attrs, vis);
                 vis.visit_span(span);
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index 730efb5..1fbf28f 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -8,7 +8,6 @@
 use crate::parse::token::{self, TokenKind};
 use crate::print::pprust;
 use crate::ptr::P;
-use crate::source_map::Spanned;
 use crate::symbol::{kw, sym};
 use crate::ThinVec;
 use crate::util::parser::AssocOp;
@@ -592,18 +591,18 @@
 
     crate fn maybe_report_invalid_custom_discriminants(
         sess: &ParseSess,
-        variants: &[Spanned<ast::Variant_>],
+        variants: &[ast::Variant],
     ) {
-        let has_fields = variants.iter().any(|variant| match variant.node.data {
+        let has_fields = variants.iter().any(|variant| match variant.data {
             VariantData::Tuple(..) | VariantData::Struct(..) => true,
             VariantData::Unit(..) => false,
         });
 
-        let discriminant_spans = variants.iter().filter(|variant| match variant.node.data {
+        let discriminant_spans = variants.iter().filter(|variant| match variant.data {
             VariantData::Tuple(..) | VariantData::Struct(..) => false,
             VariantData::Unit(..) => true,
         })
-        .filter_map(|variant| variant.node.disr_expr.as_ref().map(|c| c.value.span))
+        .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
         .collect::<Vec<_>>();
 
         if !discriminant_spans.is_empty() && has_fields {
@@ -618,7 +617,7 @@
                 err.span_label(sp, "disallowed custom discriminant");
             }
             for variant in variants.iter() {
-                match &variant.node.data {
+                match &variant.data {
                     VariantData::Struct(..) => {
                         err.span_label(
                             variant.span,
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index e86d4c7..17629d3 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -4,7 +4,7 @@
 use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char};
 
 use errors::{FatalError, DiagnosticBuilder};
-use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION};
+use syntax_pos::{BytePos, Pos, Span};
 use rustc_lexer::Base;
 use rustc_lexer::unescape;
 
@@ -84,7 +84,7 @@
 
 
     fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
-        self.override_span.unwrap_or_else(|| Span::new(lo, hi, NO_EXPANSION))
+        self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi))
     }
 
     /// Returns the next token, including trivia like whitespace or comments.
diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs
index fc47e4f..9457014 100644
--- a/src/libsyntax/parse/lexer/tests.rs
+++ b/src/libsyntax/parse/lexer/tests.rs
@@ -1,41 +1,17 @@
 use super::*;
 
-use crate::ast::CrateConfig;
 use crate::symbol::Symbol;
 use crate::source_map::{SourceMap, FilePathMapping};
-use crate::feature_gate::UnstableFeatures;
 use crate::parse::token;
-use crate::diagnostics::plugin::ErrorMap;
 use crate::with_default_globals;
 use std::io;
 use std::path::PathBuf;
-use syntax_pos::{BytePos, Span, NO_EXPANSION, edition::Edition};
-use rustc_data_structures::fx::{FxHashSet, FxHashMap};
-use rustc_data_structures::sync::{Lock, Once};
+use errors::{Handler, emitter::EmitterWriter};
+use syntax_pos::{BytePos, Span};
 
 fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
-    let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
-                                                        Some(sm.clone()),
-                                                        false,
-                                                        false,
-                                                        false);
-    ParseSess {
-        span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)),
-        unstable_features: UnstableFeatures::from_environment(),
-        config: CrateConfig::default(),
-        included_mod_stack: Lock::new(Vec::new()),
-        source_map: sm,
-        missing_fragment_specifiers: Lock::new(FxHashSet::default()),
-        raw_identifier_spans: Lock::new(Vec::new()),
-        registered_diagnostics: Lock::new(ErrorMap::new()),
-        buffered_lints: Lock::new(vec![]),
-        edition: Edition::from_session(),
-        ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
-        param_attr_spans: Lock::new(Vec::new()),
-        let_chains_spans: Lock::new(Vec::new()),
-        async_closure_spans: Lock::new(Vec::new()),
-        injected_crate_name: Once::new(),
-    }
+    let emitter = EmitterWriter::new(Box::new(io::sink()), Some(sm.clone()), false, false, false);
+    ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm)
 }
 
 // open a string reader for the given string
@@ -61,7 +37,7 @@
         let tok1 = string_reader.next_token();
         let tok2 = Token::new(
             mk_ident("fn"),
-            Span::new(BytePos(21), BytePos(23), NO_EXPANSION),
+            Span::with_root_ctxt(BytePos(21), BytePos(23)),
         );
         assert_eq!(tok1.kind, tok2.kind);
         assert_eq!(tok1.span, tok2.span);
@@ -71,7 +47,7 @@
         assert_eq!(string_reader.pos.clone(), BytePos(28));
         let tok4 = Token::new(
             mk_ident("main"),
-            Span::new(BytePos(24), BytePos(28), NO_EXPANSION),
+            Span::with_root_ctxt(BytePos(24), BytePos(28)),
         );
         assert_eq!(tok3.kind, tok4.kind);
         assert_eq!(tok3.span, tok4.span);
diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs
index eaa736c..525b421 100644
--- a/src/libsyntax/parse/lexer/unicode_chars.rs
+++ b/src/libsyntax/parse/lexer/unicode_chars.rs
@@ -3,7 +3,7 @@
 
 use super::StringReader;
 use errors::{Applicability, DiagnosticBuilder};
-use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION, symbol::kw};
+use syntax_pos::{BytePos, Pos, Span, symbol::kw};
 use crate::parse::token;
 
 #[rustfmt::skip] // for line breaks
@@ -343,7 +343,7 @@
         None => return None,
     };
 
-    let span = Span::new(pos, pos + Pos::from_usize(ch.len_utf8()), NO_EXPANSION);
+    let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8()));
 
     let (ascii_name, token) = match ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) {
         Some((_ascii_char, ascii_name, token)) => (ascii_name, token),
@@ -362,10 +362,9 @@
             ascii_char, ascii_name
         );
         err.span_suggestion(
-            Span::new(
+            Span::with_root_ctxt(
                 pos,
                 pos + Pos::from_usize('“'.len_utf8() + s.len() + '”'.len_utf8()),
-                NO_EXPANSION,
             ),
             &msg,
             format!("\"{}\"", s),
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 80aa7a3..9088f92 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -16,6 +16,7 @@
 use rustc_data_structures::sync::{Lrc, Lock, Once};
 use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
 use syntax_pos::edition::Edition;
+use syntax_pos::hygiene::ExpnId;
 
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use std::borrow::Cow;
@@ -62,6 +63,8 @@
     pub let_chains_spans: Lock<Vec<Span>>,
     // Places where `async || ..` exprs were used and should be feature gated.
     pub async_closure_spans: Lock<Vec<Span>>,
+    // Places where `yield e?` exprs were used and should be feature gated.
+    pub yield_spans: Lock<Vec<Span>>,
     pub injected_crate_name: Once<Symbol>,
 }
 
@@ -86,11 +89,12 @@
             included_mod_stack: Lock::new(vec![]),
             source_map,
             buffered_lints: Lock::new(vec![]),
-            edition: Edition::from_session(),
+            edition: ExpnId::root().expn_data().edition,
             ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
             param_attr_spans: Lock::new(Vec::new()),
             let_chains_spans: Lock::new(Vec::new()),
             async_closure_spans: Lock::new(Vec::new()),
+            yield_spans: Lock::new(Vec::new()),
             injected_crate_name: Once::new(),
         }
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 1c1428c..89725d8 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -13,7 +13,6 @@
 use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind};
 use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind};
 use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar};
-use crate::ext::hygiene::SyntaxContext;
 use crate::source_map::{self, respan};
 use crate::parse::{SeqSep, literal, token};
 use crate::parse::lexer::UnmatchedBrace;
@@ -1101,7 +1100,7 @@
 
     crate fn process_potential_macro_variable(&mut self) {
         self.token = match self.token.kind {
-            token::Dollar if self.token.span.ctxt() != SyntaxContext::empty() &&
+            token::Dollar if self.token.span.from_expansion() &&
                              self.look_ahead(1, |t| t.is_ident()) => {
                 self.bump();
                 let name = match self.token.kind {
@@ -1236,7 +1235,7 @@
 
         let args: Vec<_> = args.into_iter().filter_map(|x| x).collect();
 
-        if c_variadic && args.is_empty() {
+        if c_variadic && args.len() <= 1 {
             self.span_err(sp,
                           "C-variadic function must be declared with at least one named argument");
         }
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs
index 4432c13..ccc6bd150 100644
--- a/src/libsyntax/parse/parser/expr.rs
+++ b/src/libsyntax/parse/parser/expr.rs
@@ -8,13 +8,13 @@
 use crate::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm};
 use crate::ast::{Ty, TyKind, FunctionRetTy, Arg, FnDecl};
 use crate::ast::{BinOpKind, BinOp, UnOp};
-use crate::ast::{Mac_, AnonConst, Field};
+use crate::ast::{Mac, AnonConst, Field};
 
 use crate::parse::classify;
 use crate::parse::token::{self, Token};
 use crate::parse::diagnostics::{Error};
 use crate::print::pprust;
-use crate::source_map::{self, respan, Span};
+use crate::source_map::{self, Span};
 use crate::symbol::{kw, sym};
 use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
 
@@ -224,6 +224,10 @@
                 self.err_dotdotdot_syntax(self.token.span);
             }
 
+            if self.token == token::LArrow {
+                self.err_larrow_operator(self.token.span);
+            }
+
             self.bump();
             if op.is_comparison() {
                 self.check_no_chained_comparison(&lhs, &op);
@@ -993,6 +997,9 @@
                     } else {
                         ex = ExprKind::Yield(None);
                     }
+
+                    let span = lo.to(hi);
+                    self.sess.yield_spans.borrow_mut().push(span);
                 } else if self.eat_keyword(kw::Let) {
                     return self.parse_let_expr(attrs);
                 } else if is_span_rust_2018 && self.eat_keyword(kw::Await) {
@@ -1007,12 +1014,13 @@
                         // MACRO INVOCATION expression
                         let (delim, tts) = self.expect_delimited_token_tree()?;
                         hi = self.prev_span;
-                        ex = ExprKind::Mac(respan(lo.to(hi), Mac_ {
+                        ex = ExprKind::Mac(Mac {
                             path,
                             tts,
                             delim,
+                            span: lo.to(hi),
                             prior_type_ascription: self.last_type_ascription,
-                        }));
+                        });
                     } else if self.check(&token::OpenDelim(token::Brace)) {
                         if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
                             return expr;
@@ -1199,7 +1207,7 @@
         if self.eat_keyword(kw::Else) || !cond.returns() {
             let sp = self.sess.source_map().next_point(lo);
             let mut err = self.diagnostic()
-                .struct_span_err(sp, "missing condition for `if` statemement");
+                .struct_span_err(sp, "missing condition for `if` expression");
             err.span_label(sp, "expected if condition here");
             return Err(err)
         }
@@ -1444,6 +1452,7 @@
             guard,
             body: expr,
             span: lo.to(hi),
+            id: ast::DUMMY_NODE_ID,
         })
     }
 
@@ -1599,6 +1608,7 @@
                         expr: self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()),
                         is_shorthand: false,
                         attrs: ThinVec::new(),
+                        id: ast::DUMMY_NODE_ID,
                     });
                 }
             }
@@ -1684,6 +1694,7 @@
             expr,
             is_shorthand,
             attrs: attrs.into(),
+            id: ast::DUMMY_NODE_ID,
         })
     }
 
@@ -1702,6 +1713,19 @@
             .emit();
     }
 
+    fn err_larrow_operator(&self, span: Span) {
+        self.struct_span_err(
+            span,
+            "unexpected token: `<-`"
+        ).span_suggestion(
+            span,
+            "if you meant to write a comparison against a negative value, add a \
+             space in between `<` and `-`",
+            "< -".to_string(),
+            Applicability::MaybeIncorrect
+        ).emit();
+    }
+
     fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
         ExprKind::AssignOp(binop, lhs, rhs)
     }
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index e85ef9c..72819c9 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -10,7 +10,7 @@
 use crate::ast::{ForeignItem, ForeignItemKind};
 use crate::ast::{Ty, TyKind, GenericBounds, TraitRef};
 use crate::ast::{EnumDef, VariantData, StructField, AnonConst};
-use crate::ast::{Mac, Mac_, MacDelimiter};
+use crate::ast::{Mac, MacDelimiter};
 use crate::ext::base::DummyResult;
 use crate::parse::token;
 use crate::parse::parser::maybe_append;
@@ -530,12 +530,13 @@
             }
 
             let hi = self.prev_span;
-            let mac = respan(mac_lo.to(hi), Mac_ {
+            let mac = Mac {
                 path,
                 tts,
                 delim,
+                span: mac_lo.to(hi),
                 prior_type_ascription: self.last_type_ascription,
-            });
+            };
             let item =
                 self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs);
             return Ok(Some(item));
@@ -604,12 +605,13 @@
                 self.expect(&token::Semi)?;
             }
 
-            Ok(Some(respan(lo.to(self.prev_span), Mac_ {
+            Ok(Some(Mac {
                 path,
                 tts,
                 delim,
+                span: lo.to(self.prev_span),
                 prior_type_ascription: self.last_type_ascription,
-            })))
+            }))
         } else {
             Ok(None)
         }
@@ -1564,14 +1566,15 @@
                 None
             };
 
-            let vr = ast::Variant_ {
+            let vr = ast::Variant {
                 ident,
                 id: ast::DUMMY_NODE_ID,
                 attrs: variant_attrs,
                 data: struct_def,
                 disr_expr,
+                span: vlo.to(self.prev_span),
             };
-            variants.push(respan(vlo.to(self.prev_span), vr));
+            variants.push(vr);
 
             if !self.eat(&token::Comma) {
                 if self.token.is_ident() && !self.token.is_reserved_ident() {
diff --git a/src/libsyntax/parse/parser/module.rs b/src/libsyntax/parse/parser/module.rs
index 58a7ffb..3f6f87b 100644
--- a/src/libsyntax/parse/parser/module.rs
+++ b/src/libsyntax/parse/parser/module.rs
@@ -60,7 +60,7 @@
                 // Record that we fetched the mod from an external file
                 if warn {
                     let attr = attr::mk_attr_outer(
-                        attr::mk_word_item(Ident::with_empty_ctxt(sym::warn_directory_ownership)));
+                        attr::mk_word_item(Ident::with_dummy_span(sym::warn_directory_ownership)));
                     attr::mark_known(&attr);
                     attrs.push(attr);
                 }
diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs
index 5cc428a..c3079d2 100644
--- a/src/libsyntax/parse/parser/pat.rs
+++ b/src/libsyntax/parse/parser/pat.rs
@@ -2,8 +2,8 @@
 
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 use crate::ptr::P;
-use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac_};
-use crate::ast::{BindingMode, Ident, Mutability, Expr, ExprKind};
+use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac};
+use crate::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind};
 use crate::parse::token::{self};
 use crate::print::pprust;
 use crate::source_map::{respan, Span, Spanned};
@@ -108,93 +108,52 @@
         maybe_whole!(self, NtPat, |x| x);
 
         let lo = self.token.span;
-        let pat;
-        match self.token.kind {
-            token::BinOp(token::And) | token::AndAnd => {
-                // Parse &pat / &mut pat
-                self.expect_and()?;
-                let mutbl = self.parse_mutability();
-                if let token::Lifetime(name) = self.token.kind {
-                    let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name));
-                    err.span_label(self.token.span, "unexpected lifetime");
-                    return Err(err);
-                }
-                let subpat = self.parse_pat_with_range_pat(false, expected)?;
-                pat = PatKind::Ref(subpat, mutbl);
-            }
-            token::OpenDelim(token::Paren) => {
-                // Parse a tuple or parenthesis pattern.
-                let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
-
-                // Here, `(pat,)` is a tuple pattern.
-                // For backward compatibility, `(..)` is a tuple pattern as well.
-                pat = if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
-                    PatKind::Paren(fields.into_iter().nth(0).unwrap())
-                } else {
-                    PatKind::Tuple(fields)
-                };
-            }
+        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 (slice, _) = self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?;
-                pat = PatKind::Slice(slice);
+                PatKind::Slice(self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?.0)
             }
             token::DotDot => {
                 self.bump();
-                pat = if self.is_pat_range_end_start() {
+                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();
-                pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?;
+                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?
             }
             token::DotDotDot => {
                 // Parse `...42` for recovery.
                 self.bump();
-                pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?;
+                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?
             }
             // At this point, token != &, &&, (, [
             _ => if self.eat_keyword(kw::Underscore) {
                 // Parse _
-                pat = PatKind::Wild;
+                PatKind::Wild
             } else if self.eat_keyword(kw::Mut) {
-                // Parse mut ident @ pat / mut ref ident @ pat
-                let mutref_span = self.prev_span.to(self.token.span);
-                let binding_mode = if self.eat_keyword(kw::Ref) {
-                    self.diagnostic()
-                        .struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
-                        .span_suggestion(
-                            mutref_span,
-                            "try switching the order",
-                            "ref mut".into(),
-                            Applicability::MachineApplicable
-                        ).emit();
-                    BindingMode::ByRef(Mutability::Mutable)
-                } else {
-                    BindingMode::ByValue(Mutability::Mutable)
-                };
-                pat = self.parse_pat_ident(binding_mode)?;
+                self.recover_pat_ident_mut_first()?
             } else if self.eat_keyword(kw::Ref) {
                 // Parse ref ident @ pat / ref mut ident @ pat
                 let mutbl = self.parse_mutability();
-                pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?;
+                self.parse_pat_ident(BindingMode::ByRef(mutbl))?
             } else if self.eat_keyword(kw::Box) {
-                // Parse box pat
-                let subpat = self.parse_pat_with_range_pat(false, None)?;
-                pat = PatKind::Box(subpat);
+                // Parse `box pat`
+                PatKind::Box(self.parse_pat_with_range_pat(false, None)?)
             } else if self.token.is_ident() && !self.token.is_reserved_ident() &&
                       self.parse_as_ident() {
-                // Parse ident @ pat
+                // Parse `ident @ pat`
                 // This can give false positives and parse nullary enums,
-                // they are dealt with later in resolve
-                let binding_mode = BindingMode::ByValue(Mutability::Immutable);
-                pat = self.parse_pat_ident(binding_mode)?;
+                // they are dealt with later in resolve.
+                self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))?
             } else if self.token.is_path_start() {
                 // Parse pattern starting with a path
                 let (qself, path) = if self.eat_lt() {
@@ -206,136 +165,187 @@
                     (None, self.parse_path(PathStyle::Expr)?)
                 };
                 match self.token.kind {
-                    token::Not if qself.is_none() => {
-                        // Parse macro invocation
-                        self.bump();
-                        let (delim, tts) = self.expect_delimited_token_tree()?;
-                        let mac = respan(lo.to(self.prev_span), Mac_ {
-                            path,
-                            tts,
-                            delim,
-                            prior_type_ascription: self.last_type_ascription,
-                        });
-                        pat = PatKind::Mac(mac);
-                    }
+                    token::Not if qself.is_none() => self.parse_pat_mac_invoc(lo, path)?,
                     token::DotDotDot | token::DotDotEq | token::DotDot => {
-                        let (end_kind, form) = match self.token.kind {
-                            token::DotDot => (RangeEnd::Excluded, ".."),
-                            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), ThinVec::new());
-                        self.bump();
-                        let end = self.parse_pat_range_end_opt(&begin, form)?;
-                        pat = PatKind::Range(begin, end, respan(op_span, end_kind));
+                        self.parse_pat_range_starting_with_path(lo, qself, path)?
                     }
-                    token::OpenDelim(token::Brace) => {
-                        if qself.is_some() {
-                            let msg = "unexpected `{` after qualified path";
-                            let mut err = self.fatal(msg);
-                            err.span_label(self.token.span, msg);
-                            return Err(err);
-                        }
-                        // Parse struct pattern
-                        self.bump();
-                        let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
-                            e.emit();
-                            self.recover_stmt();
-                            (vec![], true)
-                        });
-                        self.bump();
-                        pat = PatKind::Struct(path, fields, etc);
-                    }
-                    token::OpenDelim(token::Paren) => {
-                        if qself.is_some() {
-                            let msg = "unexpected `(` after qualified path";
-                            let mut err = self.fatal(msg);
-                            err.span_label(self.token.span, msg);
-                            return Err(err);
-                        }
-                        // Parse tuple struct or enum pattern
-                        let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
-                        pat = PatKind::TupleStruct(path, fields)
-                    }
-                    _ => pat = PatKind::Path(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) => {
-                        let op_span = self.token.span;
-                        if self.check(&token::DotDot) || self.check(&token::DotDotEq) ||
-                                self.check(&token::DotDotDot) {
-                            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) {
-                                (RangeEnd::Excluded, "..")
-                            } else {
-                                panic!("impossible case: we already matched \
-                                        on a range-operator token")
-                            };
-                            let end = self.parse_pat_range_end_opt(&begin, form)?;
-                            pat = PatKind::Range(begin, end, respan(op_span, end_kind))
-                        } else {
-                            pat = PatKind::Lit(begin);
-                        }
+                    Ok(begin)
+                        if self.check(&token::DotDot)
+                            || self.check(&token::DotDotEq)
+                            || self.check(&token::DotDotDot) =>
+                    {
+                        self.parse_pat_range_starting_with_lit(begin)?
                     }
-                    Err(mut err) => {
-                        self.cancel(&mut err);
-                        let expected = expected.unwrap_or("pattern");
-                        let msg = format!(
-                            "expected {}, found {}",
-                            expected,
-                            self.this_token_descr(),
-                        );
-                        let mut err = self.fatal(&msg);
-                        err.span_label(self.token.span, format!("expected {}", expected));
-                        let sp = self.sess.source_map().start_point(self.token.span);
-                        if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
-                            self.sess.expr_parentheses_needed(&mut err, *sp, None);
-                        }
-                        return Err(err);
-                    }
+                    Ok(begin) => PatKind::Lit(begin),
+                    Err(err) => return self.fatal_unexpected_non_pat(err, expected),
                 }
             }
-        }
+        };
 
         let pat = self.mk_pat(lo.to(self.prev_span), pat);
         let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
 
         if !allow_range_pat {
-            match pat.node {
-                PatKind::Range(
-                    _, _, Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. }
-                ) => {},
-                PatKind::Range(..) => {
-                    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
-                    );
-                    return Err(err);
-                }
-                _ => {}
-            }
+            self.ban_pat_range_if_ambiguous(&pat)?
         }
 
         Ok(pat)
     }
 
+    /// Ban a range pattern if it has an ambiguous interpretation.
+    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> {
+        match pat.node {
+            PatKind::Range(
+                .., Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. }
+            ) => return Ok(()),
+            PatKind::Range(..) => {}
+            _ => return Ok(()),
+        }
+
+        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)
+    }
+
+    /// Parse `&pat` / `&mut pat`.
+    fn parse_pat_deref(&mut self, expected: Option<&'static str>) -> PResult<'a, PatKind> {
+        self.expect_and()?;
+        let mutbl = self.parse_mutability();
+
+        if let token::Lifetime(name) = self.token.kind {
+            let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name));
+            err.span_label(self.token.span, "unexpected lifetime");
+            return Err(err);
+        }
+
+        let subpat = self.parse_pat_with_range_pat(false, expected)?;
+        Ok(PatKind::Ref(subpat, mutbl))
+    }
+
+    /// Parse a tuple or parenthesis pattern.
+    fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
+        let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
+
+        // Here, `(pat,)` is a tuple pattern.
+        // For backward compatibility, `(..)` is a tuple pattern as well.
+        Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
+            PatKind::Paren(fields.into_iter().nth(0).unwrap())
+        } else {
+            PatKind::Tuple(fields)
+        })
+    }
+
+    /// Recover on `mut ref? ident @ pat` and suggest
+    /// that the order of `mut` and `ref` is incorrect.
+    fn recover_pat_ident_mut_first(&mut self) -> PResult<'a, PatKind> {
+        let mutref_span = self.prev_span.to(self.token.span);
+        let binding_mode = if self.eat_keyword(kw::Ref) {
+            self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
+                .span_suggestion(
+                    mutref_span,
+                    "try switching the order",
+                    "ref mut".into(),
+                    Applicability::MachineApplicable
+                )
+                .emit();
+            BindingMode::ByRef(Mutability::Mutable)
+        } else {
+            BindingMode::ByValue(Mutability::Mutable)
+        };
+        self.parse_pat_ident(binding_mode)
+    }
+
+    /// Parse macro invocation
+    fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> {
+        self.bump();
+        let (delim, tts) = self.expect_delimited_token_tree()?;
+        let mac = Mac {
+            path,
+            tts,
+            delim,
+            span: lo.to(self.prev_span),
+            prior_type_ascription: self.last_type_ascription,
+        };
+        Ok(PatKind::Mac(mac))
+    }
+
+    /// 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 => (RangeEnd::Excluded, ".."),
+            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), ThinVec::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) {
+            (RangeEnd::Excluded, "..")
+        } 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>,
+        expected: Option<&'static str>,
+    ) -> PResult<'a, P<Pat>> {
+        self.cancel(&mut err);
+
+        let expected = expected.unwrap_or("pattern");
+        let msg = format!("expected {}, found {}", expected, self.this_token_descr());
+
+        let mut err = self.fatal(&msg);
+        err.span_label(self.token.span, format!("expected {}", expected));
+
+        let sp = self.sess.source_map().start_point(self.token.span);
+        if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+            self.sess.expr_parentheses_needed(&mut err, *sp, None);
+        }
+
+        Err(err)
+    }
+
     // Helper function to decide whether to parse as ident binding
     // or to try to do something more complex like range patterns.
     fn parse_as_ident(&mut self) -> bool {
@@ -421,11 +431,9 @@
     }
 
     /// Parses `ident` or `ident @ pat`.
-    /// used by the copy foo and ref foo patterns to give a good
+    /// Used by the copy foo and ref foo patterns to give a good
     /// error message when parsing mistakes like `ref foo(a, b)`.
-    fn parse_pat_ident(&mut self,
-                       binding_mode: ast::BindingMode)
-                       -> PResult<'a, PatKind> {
+    fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> {
         let ident = self.parse_ident()?;
         let sub = if self.eat(&token::At) {
             Some(self.parse_pat(Some("binding pattern"))?)
@@ -433,23 +441,54 @@
             None
         };
 
-        // just to be friendly, if they write something like
-        //   ref Some(i)
-        // we end up here with ( as the current token.  This shortly
-        // leads to a parse error.  Note that if there is no explicit
+        // Just to be friendly, if they write something like `ref Some(i)`,
+        // we end up here with `(` as the current token.
+        // This shortly leads to a parse error. Note that if there is no explicit
         // binding mode then we do not end up here, because the lookahead
-        // will direct us over to parse_enum_variant()
+        // will direct us over to `parse_enum_variant()`.
         if self.token == token::OpenDelim(token::Paren) {
             return Err(self.span_fatal(
                 self.prev_span,
-                "expected identifier, found enum pattern"))
+                "expected identifier, found enum pattern",
+            ))
         }
 
         Ok(PatKind::Ident(binding_mode, ident, sub))
     }
 
+    /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
+    fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
+        if qself.is_some() {
+            let msg = "unexpected `{` after qualified path";
+            let mut err = self.fatal(msg);
+            err.span_label(self.token.span, msg);
+            return Err(err);
+        }
+
+        self.bump();
+        let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
+            e.emit();
+            self.recover_stmt();
+            (vec![], true)
+        });
+        self.bump();
+        Ok(PatKind::Struct(path, fields, etc))
+    }
+
+    /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
+    fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
+        if qself.is_some() {
+            let msg = "unexpected `(` after qualified path";
+            let mut err = self.fatal(msg);
+            err.span_label(self.token.span, msg);
+            return Err(err);
+        }
+        let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
+        Ok(PatKind::TupleStruct(path, fields))
+    }
+
     /// Parses the fields of a struct-like pattern.
-    fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<Spanned<FieldPat>>, bool)> {
+    fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<FieldPat>, bool)> {
         let mut fields = Vec::new();
         let mut etc = false;
         let mut ate_comma = true;
@@ -482,17 +521,7 @@
                 etc = true;
                 let mut etc_sp = self.token.span;
 
-                if self.token == token::DotDotDot { // Issue #46718
-                    // Accept `...` as if it were `..` to avoid further errors
-                    self.struct_span_err(self.token.span, "expected field pattern, found `...`")
-                        .span_suggestion(
-                            self.token.span,
-                            "to omit remaining fields, use one fewer `.`",
-                            "..".to_owned(),
-                            Applicability::MachineApplicable
-                        )
-                        .emit();
-                }
+                self.recover_one_fewer_dotdot();
                 self.bump();  // `..` || `...`
 
                 if self.token == token::CloseDelim(token::Brace) {
@@ -574,11 +603,24 @@
         return Ok((fields, etc));
     }
 
-    fn parse_pat_field(
-        &mut self,
-        lo: Span,
-        attrs: Vec<Attribute>
-    ) -> PResult<'a, Spanned<FieldPat>> {
+    /// Recover on `...` as if it were `..` to avoid further errors.
+    /// See issue #46718.
+    fn recover_one_fewer_dotdot(&self) {
+        if self.token != token::DotDotDot {
+            return;
+        }
+
+        self.struct_span_err(self.token.span, "expected field pattern, found `...`")
+            .span_suggestion(
+                self.token.span,
+                "to omit remaining fields, use one fewer `.`",
+                "..".to_owned(),
+                Applicability::MachineApplicable
+            )
+            .emit();
+    }
+
+    fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, FieldPat> {
         // Check if a colon exists one ahead. This means we're parsing a fieldname.
         let hi;
         let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
@@ -613,14 +655,13 @@
             (subpat, fieldname, true)
         };
 
-        Ok(Spanned {
+        Ok(FieldPat {
+            ident: fieldname,
+            pat: subpat,
+            is_shorthand,
+            attrs: attrs.into(),
+            id: ast::DUMMY_NODE_ID,
             span: lo.to(hi),
-            node: FieldPat {
-                ident: fieldname,
-                pat: subpat,
-                is_shorthand,
-                attrs: attrs.into(),
-           }
         })
     }
 
diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs
index f182edc..c911cab 100644
--- a/src/libsyntax/parse/parser/stmt.rs
+++ b/src/libsyntax/parse/parser/stmt.rs
@@ -5,7 +5,7 @@
 use crate::ptr::P;
 use crate::{maybe_whole, ThinVec};
 use crate::ast::{self, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
-use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac_, MacDelimiter};
+use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter};
 use crate::ext::base::DummyResult;
 use crate::parse::{classify, DirectoryOwnership};
 use crate::parse::diagnostics::Error;
@@ -99,12 +99,13 @@
                 MacStmtStyle::NoBraces
             };
 
-            let mac = respan(lo.to(hi), Mac_ {
+            let mac = Mac {
                 path,
                 tts,
                 delim,
+                span: lo.to(hi),
                 prior_type_ascription: self.last_type_ascription,
-            });
+            };
             let node = if delim == MacDelimiter::Brace ||
                           self.token == token::Semi || self.token == token::Eof {
                 StmtKind::Mac(P((mac, style, attrs.into())))
@@ -167,7 +168,22 @@
                     if self.token == token::Semi {
                         unused_attrs(&attrs, self);
                         self.bump();
-                        return Ok(None);
+                        let mut last_semi = lo;
+                        while self.token == token::Semi {
+                            last_semi = self.token.span;
+                            self.bump();
+                        }
+                        // We are encoding a string of semicolons as an
+                        // an empty tuple that spans the excess semicolons
+                        // to preserve this info until the lint stage
+                        return Ok(Some(Stmt {
+                            id: ast::DUMMY_NODE_ID,
+                            span: lo.to(last_semi),
+                            node: StmtKind::Semi(self.mk_expr(lo.to(last_semi),
+                                ExprKind::Tup(Vec::new()),
+                                ThinVec::new()
+                            )),
+                        }));
                     }
 
                     if self.token == token::CloseDelim(token::Brace) {
diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs
index 1eb3d44..337702b 100644
--- a/src/libsyntax/parse/parser/ty.rs
+++ b/src/libsyntax/parse/parser/ty.rs
@@ -4,9 +4,9 @@
 use crate::ptr::P;
 use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
 use crate::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
-use crate::ast::{Mutability, AnonConst, FnDecl, Mac_};
+use crate::ast::{Mutability, AnonConst, FnDecl, Mac};
 use crate::parse::token::{self, Token};
-use crate::source_map::{respan, Span};
+use crate::source_map::Span;
 use crate::symbol::{kw};
 
 use rustc_target::spec::abi::Abi;
@@ -175,13 +175,14 @@
             if self.eat(&token::Not) {
                 // Macro invocation in type position
                 let (delim, tts) = self.expect_delimited_token_tree()?;
-                let node = Mac_ {
+                let mac = Mac {
                     path,
                     tts,
                     delim,
+                    span: lo.to(self.prev_span),
                     prior_type_ascription: self.last_type_ascription,
                 };
-                TyKind::Mac(respan(lo.to(self.prev_span), node))
+                TyKind::Mac(mac)
             } else {
                 // Just a type path or bound list (trait object type) starting with a trait.
                 //   `Type`
diff --git a/src/libsyntax/parse/tests.rs b/src/libsyntax/parse/tests.rs
index e619fd1..6a789ef 100644
--- a/src/libsyntax/parse/tests.rs
+++ b/src/libsyntax/parse/tests.rs
@@ -12,7 +12,7 @@
 use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse};
 use crate::tokenstream::{DelimSpan, TokenTree, TokenStream};
 use crate::with_default_globals;
-use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION};
+use syntax_pos::{Span, BytePos, Pos};
 
 use std::path::PathBuf;
 
@@ -27,7 +27,7 @@
 
 // produce a syntax_pos::span
 fn sp(a: u32, b: u32) -> Span {
-    Span::new(BytePos(a), BytePos(b), NO_EXPANSION)
+    Span::with_root_ctxt(BytePos(a), BytePos(b))
 }
 
 /// Parse a string, return an expr
@@ -172,8 +172,8 @@
     impl<'a> crate::visit::Visitor<'a> for PatIdentVisitor {
         fn visit_pat(&mut self, p: &'a ast::Pat) {
             match p.node {
-                PatKind::Ident(_ , ref spannedident, _) => {
-                    self.spans.push(spannedident.span.clone());
+                PatKind::Ident(_ , ref ident, _) => {
+                    self.spans.push(ident.span.clone());
                 }
                 _ => {
                     crate::visit::walk_pat(self, p);
@@ -273,7 +273,7 @@
             "foo!( fn main() { body } )".to_string(), &sess).unwrap();
 
         let tts: Vec<_> = match expr.node {
-            ast::ExprKind::Mac(ref mac) => mac.node.stream().trees().collect(),
+            ast::ExprKind::Mac(ref mac) => mac.stream().trees().collect(),
             _ => panic!("not a macro"),
         };
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index bda7612..8a70098 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -123,13 +123,13 @@
         // of the feature gate, so we fake them up here.
 
         // #![feature(prelude_import)]
-        let pi_nested = attr::mk_nested_word_item(ast::Ident::with_empty_ctxt(sym::prelude_import));
-        let list = attr::mk_list_item(ast::Ident::with_empty_ctxt(sym::feature), vec![pi_nested]);
+        let pi_nested = attr::mk_nested_word_item(ast::Ident::with_dummy_span(sym::prelude_import));
+        let list = attr::mk_list_item(ast::Ident::with_dummy_span(sym::feature), vec![pi_nested]);
         let fake_attr = attr::mk_attr_inner(list);
         s.print_attribute(&fake_attr);
 
         // #![no_std]
-        let no_std_meta = attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::no_std));
+        let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std));
         let fake_attr = attr::mk_attr_inner(no_std_meta);
         s.print_attribute(&fake_attr);
     }
@@ -1067,7 +1067,7 @@
             }
             ast::ForeignItemKind::Macro(ref m) => {
                 self.print_mac(m);
-                match m.node.delim {
+                match m.delim {
                     MacDelimiter::Brace => {},
                     _ => self.s.word(";")
                 }
@@ -1341,7 +1341,7 @@
             }
             ast::ItemKind::Mac(ref mac) => {
                 self.print_mac(mac);
-                match mac.node.delim {
+                match mac.delim {
                     MacDelimiter::Brace => {}
                     _ => self.s.word(";"),
                 }
@@ -1402,7 +1402,7 @@
         for v in variants {
             self.space_if_not_bol();
             self.maybe_print_comment(v.span.lo());
-            self.print_outer_attributes(&v.node.attrs);
+            self.print_outer_attributes(&v.attrs);
             self.ibox(INDENT_UNIT);
             self.print_variant(v);
             self.s.word(",");
@@ -1492,8 +1492,8 @@
     crate fn print_variant(&mut self, v: &ast::Variant) {
         self.head("");
         let generics = ast::Generics::default();
-        self.print_struct(&v.node.data, &generics, v.node.ident, v.span, false);
-        match v.node.disr_expr {
+        self.print_struct(&v.data, &generics, v.ident, v.span, false);
+        match v.disr_expr {
             Some(ref d) => {
                 self.s.space();
                 self.word_space("=");
@@ -1554,7 +1554,7 @@
             }
             ast::TraitItemKind::Macro(ref mac) => {
                 self.print_mac(mac);
-                match mac.node.delim {
+                match mac.delim {
                     MacDelimiter::Brace => {}
                     _ => self.s.word(";"),
                 }
@@ -1591,7 +1591,7 @@
             }
             ast::ImplItemKind::Macro(ref mac) => {
                 self.print_mac(mac);
-                match mac.node.delim {
+                match mac.delim {
                     MacDelimiter::Brace => {}
                     _ => self.s.word(";"),
                 }
@@ -1749,11 +1749,11 @@
 
     crate fn print_mac(&mut self, m: &ast::Mac) {
         self.print_mac_common(
-            Some(MacHeader::Path(&m.node.path)),
+            Some(MacHeader::Path(&m.path)),
             true,
             None,
-            m.node.delim.to_token(),
-            m.node.stream(),
+            m.delim.to_token(),
+            m.stream(),
             true,
             m.span,
         );
@@ -2367,14 +2367,14 @@
                     Consistent, &fields[..],
                     |s, f| {
                         s.cbox(INDENT_UNIT);
-                        if !f.node.is_shorthand {
-                            s.print_ident(f.node.ident);
+                        if !f.is_shorthand {
+                            s.print_ident(f.ident);
                             s.word_nbsp(":");
                         }
-                        s.print_pat(&f.node.pat);
+                        s.print_pat(&f.pat);
                         s.end();
                     },
-                    |f| f.node.pat.span);
+                    |f| f.pat.span);
                 if etc {
                     if !fields.is_empty() { self.word_space(","); }
                     self.s.word("..");
diff --git a/src/libsyntax/print/pprust/tests.rs b/src/libsyntax/print/pprust/tests.rs
index 082a430..2521467 100644
--- a/src/libsyntax/print/pprust/tests.rs
+++ b/src/libsyntax/print/pprust/tests.rs
@@ -54,14 +54,15 @@
     with_default_globals(|| {
         let ident = ast::Ident::from_str("principal_skinner");
 
-        let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
+        let var = ast::Variant {
             ident,
             attrs: Vec::new(),
             id: ast::DUMMY_NODE_ID,
             // making this up as I go.... ?
             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
             disr_expr: None,
-        });
+            span: syntax_pos::DUMMY_SP,
+        };
 
         let varstr = variant_to_string(&var);
         assert_eq!(varstr, "principal_skinner");
diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs
index 4e29c77..7190cfd 100644
--- a/src/libsyntax/source_map.rs
+++ b/src/libsyntax/source_map.rs
@@ -8,7 +8,7 @@
 //! information, source code snippets, etc.
 
 pub use syntax_pos::*;
-pub use syntax_pos::hygiene::{ExpnKind, ExpnInfo};
+pub use syntax_pos::hygiene::{ExpnKind, ExpnData};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
@@ -29,14 +29,15 @@
 
 /// Returns the span itself if it doesn't come from a macro expansion,
 /// otherwise return the call site span up to the `enclosing_sp` by
-/// following the `expn_info` chain.
+/// following the `expn_data` chain.
 pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
-    let call_site1 = sp.ctxt().outer_expn_info().map(|ei| ei.call_site);
-    let call_site2 = enclosing_sp.ctxt().outer_expn_info().map(|ei| ei.call_site);
-    match (call_site1, call_site2) {
-        (None, _) => sp,
-        (Some(call_site1), Some(call_site2)) if call_site1 == call_site2 => sp,
-        (Some(call_site1), _) => original_sp(call_site1, enclosing_sp),
+    let expn_data1 = sp.ctxt().outer_expn_data();
+    let expn_data2 = enclosing_sp.ctxt().outer_expn_data();
+    if expn_data1.is_root() ||
+       !expn_data2.is_root() && expn_data1.call_site == expn_data2.call_site {
+        sp
+    } else {
+        original_sp(expn_data1.call_site, enclosing_sp)
     }
 }
 
@@ -170,6 +171,26 @@
         Ok(self.new_source_file(filename, src))
     }
 
+    /// Loads source file as a binary blob.
+    ///
+    /// Unlike `load_file`, guarantees that no normalization like BOM-removal
+    /// takes place.
+    pub fn load_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> {
+        // Ideally, this should use `self.file_loader`, but it can't
+        // deal with binary files yet.
+        let bytes = fs::read(path)?;
+
+        // We need to add file to the `SourceMap`, so that it is present
+        // in dep-info. There's also an edge case that file might be both
+        // loaded as a binary via `include_bytes!` and as proper `SourceFile`
+        // via `mod`, so we try to use real file contents and not just an
+        // empty string.
+        let text = std::str::from_utf8(&bytes).unwrap_or("")
+            .to_string();
+        self.new_source_file(path.to_owned().into(), text);
+        Ok(bytes)
+    }
+
     pub fn files(&self) -> MappedLockGuard<'_, Vec<Lrc<SourceFile>>> {
         LockGuard::map(self.files.borrow(), |files| &mut files.source_files)
     }
@@ -519,7 +540,7 @@
     /// extract function takes three arguments: a string slice containing the source, an index in
     /// the slice for the beginning of the span and an index in the slice for the end of the span.
     fn span_to_source<F>(&self, sp: Span, extract_source: F) -> Result<String, SpanSnippetError>
-        where F: Fn(&str, usize, usize) -> String
+        where F: Fn(&str, usize, usize) -> Result<String, SpanSnippetError>
     {
         if sp.lo() > sp.hi() {
             return Err(SpanSnippetError::IllFormedSpan(sp));
@@ -554,9 +575,9 @@
             }
 
             if let Some(ref src) = local_begin.sf.src {
-                return Ok(extract_source(src, start_index, end_index));
+                return extract_source(src, start_index, end_index);
             } else if let Some(src) = local_begin.sf.external_src.borrow().get_source() {
-                return Ok(extract_source(src, start_index, end_index));
+                return extract_source(src, start_index, end_index);
             } else {
                 return Err(SpanSnippetError::SourceNotAvailable {
                     filename: local_begin.sf.name.clone()
@@ -567,8 +588,9 @@
 
     /// Returns the source snippet as `String` corresponding to the given `Span`
     pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
-        self.span_to_source(sp, |src, start_index, end_index| src[start_index..end_index]
-                                                                .to_string())
+        self.span_to_source(sp, |src, start_index, end_index| src.get(start_index..end_index)
+            .map(|s| s.to_string())
+            .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp)))
     }
 
     pub fn span_to_margin(&self, sp: Span) -> Option<usize> {
@@ -582,7 +604,9 @@
 
     /// Returns the source snippet as `String` before the given `Span`
     pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
-        self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string())
+        self.span_to_source(sp, |src, start_index, _| src.get(..start_index)
+            .map(|s| s.to_string())
+            .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp)))
     }
 
     /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span
diff --git a/src/libsyntax/source_map/tests.rs b/src/libsyntax/source_map/tests.rs
index 427e86b..c7b8332 100644
--- a/src/libsyntax/source_map/tests.rs
+++ b/src/libsyntax/source_map/tests.rs
@@ -91,7 +91,7 @@
 fn t7() {
     // Test span_to_lines for a span ending at the end of source_file
     let sm = init_source_map();
-    let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION);
+    let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
     let file_lines = sm.span_to_lines(span).unwrap();
 
     assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into());
@@ -107,7 +107,7 @@
     assert_eq!(input.len(), selection.len());
     let left_index = selection.find('~').unwrap() as u32;
     let right_index = selection.rfind('~').map(|x|x as u32).unwrap_or(left_index);
-    Span::new(BytePos(left_index), BytePos(right_index + 1), NO_EXPANSION)
+    Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1))
 }
 
 /// Tests span_to_snippet and span_to_lines for a span converting 3
@@ -137,7 +137,7 @@
 fn t8() {
     // Test span_to_snippet for a span ending at the end of source_file
     let sm = init_source_map();
-    let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION);
+    let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
     let snippet = sm.span_to_snippet(span);
 
     assert_eq!(snippet, Ok("second line".to_string()));
@@ -147,7 +147,7 @@
 fn t9() {
     // Test span_to_str for a span ending at the end of source_file
     let sm = init_source_map();
-    let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION);
+    let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
     let sstr =  sm.span_to_string(span);
 
     assert_eq!(sstr, "blork.rs:2:1: 2:12");
@@ -198,10 +198,9 @@
             let lo = hi + offset;
             hi = lo + substring.len();
             if i == n {
-                let span = Span::new(
+                let span = Span::with_root_ctxt(
                     BytePos(lo as u32 + file.start_pos.0),
                     BytePos(hi as u32 + file.start_pos.0),
-                    NO_EXPANSION,
                 );
                 assert_eq!(&self.span_to_snippet(span).unwrap()[..],
                         substring);
diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs
index cff034f..4c0e1e3 100644
--- a/src/libsyntax/tests.rs
+++ b/src/libsyntax/tests.rs
@@ -9,7 +9,7 @@
 use errors::emitter::EmitterWriter;
 use errors::Handler;
 use rustc_data_structures::sync::Lrc;
-use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan};
+use syntax_pos::{BytePos, Span, MultiSpan};
 
 use std::io;
 use std::io::prelude::*;
@@ -169,7 +169,7 @@
     let start = make_pos(file_text, start);
     let end = make_pos(file_text, end) + end.string.len(); // just after matching thing ends
     assert!(start <= end);
-    Span::new(BytePos(start as u32), BytePos(end as u32), NO_EXPANSION)
+    Span::with_root_ctxt(BytePos(start as u32), BytePos(end as u32))
 }
 
 fn make_pos(file_text: &str, pos: &Position) -> usize {
diff --git a/src/libsyntax/tokenstream/tests.rs b/src/libsyntax/tokenstream/tests.rs
index 72e22a4..5017e5f 100644
--- a/src/libsyntax/tokenstream/tests.rs
+++ b/src/libsyntax/tokenstream/tests.rs
@@ -3,14 +3,14 @@
 use crate::ast::Name;
 use crate::with_default_globals;
 use crate::tests::string_to_stream;
-use syntax_pos::{Span, BytePos, NO_EXPANSION};
+use syntax_pos::{Span, BytePos};
 
 fn string_to_ts(string: &str) -> TokenStream {
     string_to_stream(string.to_owned())
 }
 
 fn sp(a: u32, b: u32) -> Span {
-    Span::new(BytePos(a), BytePos(b), NO_EXPANSION)
+    Span::with_root_ctxt(BytePos(a), BytePos(b))
 }
 
 #[test]
diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs
index d71358f..a501541 100644
--- a/src/libsyntax/util/parser.rs
+++ b/src/libsyntax/util/parser.rs
@@ -97,6 +97,8 @@
             // DotDotDot is no longer supported, but we need some way to display the error
             token::DotDotDot => Some(DotDotEq),
             token::Colon => Some(Colon),
+            // `<-` should probably be `< -`
+            token::LArrow => Some(Less),
             _ if t.is_keyword(kw::As) => Some(As),
             _ => None
         }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 596c5b4..6648347 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -311,11 +311,11 @@
                            item_id: NodeId)
     where V: Visitor<'a>,
 {
-    visitor.visit_ident(variant.node.ident);
-    visitor.visit_variant_data(&variant.node.data, variant.node.ident,
+    visitor.visit_ident(variant.ident);
+    visitor.visit_variant_data(&variant.data, variant.ident,
                              generics, item_id, variant.span);
-    walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
-    walk_list!(visitor, visit_attribute, &variant.node.attrs);
+    walk_list!(visitor, visit_anon_const, &variant.disr_expr);
+    walk_list!(visitor, visit_attribute, &variant.attrs);
 }
 
 pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
@@ -442,9 +442,9 @@
         PatKind::Struct(ref path, ref fields, _) => {
             visitor.visit_path(path, pattern.id);
             for field in fields {
-                walk_list!(visitor, visit_attribute, field.node.attrs.iter());
-                visitor.visit_ident(field.node.ident);
-                visitor.visit_pat(&field.node.pat)
+                walk_list!(visitor, visit_attribute, field.attrs.iter());
+                visitor.visit_ident(field.ident);
+                visitor.visit_pat(&field.pat)
             }
         }
         PatKind::Tuple(ref elems) => {
@@ -663,7 +663,7 @@
 }
 
 pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) {
-    visitor.visit_path(&mac.node.path, DUMMY_NODE_ID);
+    visitor.visit_path(&mac.path, DUMMY_NODE_ID);
 }
 
 pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) {
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index c1c2732..950166f 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -47,10 +47,10 @@
                        -> Box<dyn base::MacResult + 'cx> {
     let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
         Ok(Some(inline_asm)) => inline_asm,
-        Ok(None) => return DummyResult::expr(sp),
+        Ok(None) => return DummyResult::any(sp),
         Err(mut err) => {
             err.emit();
-            return DummyResult::expr(sp);
+            return DummyResult::any(sp);
         }
     };
 
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index d7571f4..6301283 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -1,7 +1,6 @@
 use errors::{Applicability, DiagnosticBuilder};
 
 use syntax::ast::{self, *};
-use syntax::source_map::Spanned;
 use syntax::ext::base::*;
 use syntax::parse::token::{self, TokenKind};
 use syntax::parse::parser::Parser;
@@ -20,12 +19,12 @@
         Ok(assert) => assert,
         Err(mut err) => {
             err.emit();
-            return DummyResult::expr(sp);
+            return DummyResult::any(sp);
         }
     };
 
     let sp = sp.apply_mark(cx.current_expansion.id);
-    let panic_call = Mac_ {
+    let panic_call = Mac {
         path: Path::from_ident(Ident::new(sym::panic, sp)),
         tts: custom_message.unwrap_or_else(|| {
             TokenStream::from(TokenTree::token(
@@ -37,6 +36,7 @@
             ))
         }).into(),
         delim: MacDelimiter::Parenthesis,
+        span: sp,
         prior_type_ascription: None,
     };
     let if_expr = cx.expr_if(
@@ -44,10 +44,7 @@
         cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
         cx.expr(
             sp,
-            ExprKind::Mac(Spanned {
-                span: sp,
-                node: panic_call,
-            }),
+            ExprKind::Mac(panic_call),
         ),
         None,
     );
diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs
index 84830e6..0e52c1a 100644
--- a/src/libsyntax_ext/cfg.rs
+++ b/src/libsyntax_ext/cfg.rs
@@ -25,7 +25,7 @@
         }
         Err(mut err) => {
             err.emit();
-            DummyResult::expr(sp)
+            DummyResult::any(sp)
         }
     }
 }
diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs
index f1d079e..4cd1753 100644
--- a/src/libsyntax_ext/concat.rs
+++ b/src/libsyntax_ext/concat.rs
@@ -1,5 +1,5 @@
 use syntax::ast;
-use syntax::ext::base;
+use syntax::ext::base::{self, DummyResult};
 use syntax::symbol::Symbol;
 use syntax::tokenstream;
 
@@ -12,7 +12,7 @@
 ) -> Box<dyn base::MacResult + 'static> {
     let es = match base::get_exprs_from_tts(cx, sp, tts) {
         Some(e) => e,
-        None => return base::DummyResult::expr(sp),
+        None => return DummyResult::any(sp),
     };
     let mut accumulator = String::new();
     let mut missing_literal = vec![];
@@ -55,9 +55,9 @@
         let mut err = cx.struct_span_err(missing_literal, "expected a literal");
         err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`");
         err.emit();
-        return base::DummyResult::expr(sp);
+        return DummyResult::any(sp);
     } else if has_errors {
-        return base::DummyResult::expr(sp);
+        return DummyResult::any(sp);
     }
     let sp = sp.apply_mark(cx.current_expansion.id);
     base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs
index 3b1edf9..d030ea4 100644
--- a/src/libsyntax_ext/deriving/clone.rs
+++ b/src/libsyntax_ext/deriving/clone.rs
@@ -35,7 +35,7 @@
             match annitem.node {
                 ItemKind::Struct(_, Generics { ref params, .. }) |
                 ItemKind::Enum(_, Generics { ref params, .. }) => {
-                    let container_id = cx.current_expansion.id.parent();
+                    let container_id = cx.current_expansion.id.expn_data().parent;
                     if cx.resolver.has_derives(container_id, SpecialDerives::COPY) &&
                         !params.iter().any(|param| match param.kind {
                             ast::GenericParamKind::Type { .. } => true,
@@ -129,7 +129,7 @@
     if is_union {
         // let _: AssertParamIsCopy<Self>;
         let self_ty =
-            cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_empty_ctxt(kw::SelfUpper)));
+            cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_dummy_span(kw::SelfUpper)));
         assert_ty_bounds(cx, &mut stmts, self_ty, trait_span, "AssertParamIsCopy");
     } else {
         match *substr.fields {
@@ -138,7 +138,7 @@
             }
             StaticEnum(enum_def, ..) => {
                 for variant in &enum_def.variants {
-                    process_variant(cx, &mut stmts, &variant.node.data);
+                    process_variant(cx, &mut stmts, &variant.data);
                 }
             }
             _ => cx.span_bug(trait_span, &format!("unexpected substructure in \
@@ -170,9 +170,9 @@
             vdata = vdata_;
         }
         EnumMatching(.., variant, ref af) => {
-            ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.ident]);
+            ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]);
             all_fields = af;
-            vdata = &variant.node.data;
+            vdata = &variant.data;
         }
         EnumNonMatchingCollapsed(..) => {
             cx.span_bug(trait_span,
diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs
index 1909729..54027c6 100644
--- a/src/libsyntax_ext/deriving/cmp/eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/eq.rs
@@ -13,7 +13,7 @@
                           mitem: &MetaItem,
                           item: &Annotatable,
                           push: &mut dyn FnMut(Annotatable)) {
-    cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::EQ);
+    cx.resolver.add_derives(cx.current_expansion.id.expn_data().parent, SpecialDerives::EQ);
 
     let inline = cx.meta_word(span, sym::inline);
     let hidden = cx.meta_list_item_word(span, sym::hidden);
@@ -75,7 +75,7 @@
         }
         StaticEnum(enum_def, ..) => {
             for variant in &enum_def.variants {
-                process_variant(cx, &mut stmts, &variant.node.data);
+                process_variant(cx, &mut stmts, &variant.data);
             }
         }
         _ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`")
diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
index 7d7c4ae..91e1e80 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
@@ -13,7 +13,7 @@
                                   mitem: &MetaItem,
                                   item: &Annotatable,
                                   push: &mut dyn FnMut(Annotatable)) {
-    cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::PARTIAL_EQ);
+    cx.resolver.add_derives(cx.current_expansion.id.expn_data().parent, SpecialDerives::PARTIAL_EQ);
 
     // structures are equal if all fields are equal, and non equal, if
     // any fields are not equal or if the enum variants are different
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 0f70963..1d5234a 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -53,7 +53,7 @@
     // based on the "shape".
     let (ident, vdata, fields) = match substr.fields {
         Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
-        EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields),
+        EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
         EnumNonMatchingCollapsed(..) |
         StaticStruct(..) |
         StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
@@ -82,7 +82,7 @@
 
                 let expr = cx.expr_method_call(span,
                                                 builder_expr.clone(),
-                                                Ident::with_empty_ctxt(sym::field),
+                                                Ident::with_dummy_span(sym::field),
                                                 vec![field]);
 
                 // Use `let _ = expr;` to avoid triggering the
@@ -106,7 +106,7 @@
                 let field = cx.expr_addr_of(field.span, field);
                 let expr = cx.expr_method_call(span,
                                                 builder_expr.clone(),
-                                                Ident::with_empty_ctxt(sym::field),
+                                                Ident::with_dummy_span(sym::field),
                                                 vec![name, field]);
                 stmts.push(stmt_let_undescore(cx, span, expr));
             }
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 6d0d3b9..52e74a7 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -238,7 +238,7 @@
             }
 
             let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
-            let name = cx.expr_str(trait_span, variant.node.ident.name);
+            let name = cx.expr_str(trait_span, variant.ident.name);
             let call = cx.expr_method_call(trait_span,
                                            blkencoder,
                                            cx.ident_of("emit_enum_variant"),
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 7e6d912..55fb767 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -187,7 +187,7 @@
 use syntax::ast::{VariantData, GenericParamKind, GenericArg};
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives};
-use syntax::source_map::{self, respan};
+use syntax::source_map::respan;
 use syntax::util::map_in_place::MapInPlace;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, kw, sym};
@@ -425,7 +425,7 @@
                         return;
                     }
                 };
-                let container_id = cx.current_expansion.id.parent();
+                let container_id = cx.current_expansion.id.expn_data().parent;
                 let is_always_copy =
                     cx.resolver.has_derives(container_id, SpecialDerives::COPY) &&
                     has_no_type_params;
@@ -758,7 +758,7 @@
         let mut field_tys = Vec::new();
 
         for variant in &enum_def.variants {
-            field_tys.extend(variant.node
+            field_tys.extend(variant
                 .data
                 .fields()
                 .iter()
@@ -928,7 +928,7 @@
 
         let args = {
             let self_args = explicit_self.map(|explicit_self| {
-                let ident = Ident::with_empty_ctxt(kw::SelfLower).with_span_pos(trait_.span);
+                let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span);
                 ast::Arg::from_self(ThinVec::default(), explicit_self, ident)
             });
             let nonself_args = arg_types.into_iter()
@@ -1220,7 +1220,7 @@
         let catch_all_substructure =
             EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]);
 
-        let first_fieldless = variants.iter().find(|v| v.node.data.fields().is_empty());
+        let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty());
 
         // These arms are of the form:
         // (Variant1, Variant1, ...) => Body1
@@ -1229,7 +1229,7 @@
         // where each tuple has length = self_args.len()
         let mut match_arms: Vec<ast::Arm> = variants.iter()
             .enumerate()
-            .filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty()))
+            .filter(|&(_, v)| !(self.unify_fieldless_variants && v.data.fields().is_empty()))
             .map(|(index, variant)| {
                 let mk_self_pat = |cx: &mut ExtCtxt<'_>, self_arg_name: &str| {
                     let (p, idents) = trait_.create_enum_variant_pattern(cx,
@@ -1513,8 +1513,8 @@
             .iter()
             .map(|v| {
                 let sp = v.span.with_ctxt(trait_.span.ctxt());
-                let summary = trait_.summarise_struct(cx, &v.node.data);
-                (v.node.ident, sp, summary)
+                let summary = trait_.summarise_struct(cx, &v.data);
+                (v.ident, sp, summary)
             })
             .collect();
         self.call_substructure_method(cx,
@@ -1610,14 +1610,13 @@
                         if ident.is_none() {
                             cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
                         }
-                        source_map::Spanned {
+                        ast::FieldPat {
+                            ident: ident.unwrap(),
+                            is_shorthand: false,
+                            attrs: ThinVec::new(),
+                            id: ast::DUMMY_NODE_ID,
                             span: pat.span.with_ctxt(self.span.ctxt()),
-                            node: ast::FieldPat {
-                                ident: ident.unwrap(),
-                                pat,
-                                is_shorthand: false,
-                                attrs: ThinVec::new(),
-                            },
+                            pat,
                         }
                     })
                     .collect();
@@ -1643,9 +1642,9 @@
          mutbl: ast::Mutability)
          -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
         let sp = variant.span.with_ctxt(self.span.ctxt());
-        let variant_path = cx.path(sp, vec![enum_ident, variant.node.ident]);
+        let variant_path = cx.path(sp, vec![enum_ident, variant.ident]);
         let use_temporaries = false; // enums can't be repr(packed)
-        self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl,
+        self.create_struct_pattern(cx, variant_path, &variant.data, prefix, mutbl,
                                    use_temporaries)
     }
 }
@@ -1776,7 +1775,7 @@
     if let Annotatable::Item(ref item) = *item {
         match item.node {
             ast::ItemKind::Enum(ref enum_def, _) => {
-                enum_def.variants.iter().all(|v| v.node.data.fields().is_empty())
+                enum_def.variants.iter().all(|v| v.data.fields().is_empty())
             }
             ast::ItemKind::Struct(ref variant_data, _) => variant_data.fields().is_empty(),
             _ => false,
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 39fc90d..9834130 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -16,20 +16,20 @@
                               tts: &[tokenstream::TokenTree])
                               -> Box<dyn base::MacResult + 'cx> {
     let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
-        None => return DummyResult::expr(sp),
+        None => return DummyResult::any(sp),
         Some(v) => v,
     };
 
     let sp = sp.apply_mark(cx.current_expansion.id);
     let e = match env::var(&*var.as_str()) {
         Err(..) => {
-            let lt = cx.lifetime(sp, Ident::with_empty_ctxt(kw::StaticLifetime));
+            let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime));
             cx.expr_path(cx.path_all(sp,
                                      true,
                                      cx.std_path(&[sym::option, sym::Option, sym::None]),
                                      vec![GenericArg::Type(cx.ty_rptr(sp,
                                                      cx.ty_ident(sp,
-                                                                 Ident::with_empty_ctxt(sym::str)),
+                                                                 Ident::with_dummy_span(sym::str)),
                                                      Some(lt),
                                                      ast::Mutability::Immutable))],
                                      vec![]))
@@ -50,21 +50,21 @@
     let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
         Some(ref exprs) if exprs.is_empty() => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
-            return DummyResult::expr(sp);
+            return DummyResult::any(sp);
         }
-        None => return DummyResult::expr(sp),
+        None => return DummyResult::any(sp),
         Some(exprs) => exprs.into_iter(),
     };
 
     let var = match expr_to_string(cx, exprs.next().unwrap(), "expected string literal") {
-        None => return DummyResult::expr(sp),
+        None => return DummyResult::any(sp),
         Some((v, _style)) => v,
     };
     let msg = match exprs.next() {
         None => Symbol::intern(&format!("environment variable `{}` not defined", var)),
         Some(second) => {
             match expr_to_string(cx, second, "expected string literal") {
-                None => return DummyResult::expr(sp),
+                None => return DummyResult::any(sp),
                 Some((s, _style)) => s,
             }
         }
@@ -72,13 +72,13 @@
 
     if exprs.next().is_some() {
         cx.span_err(sp, "env! takes 1 or 2 arguments");
-        return DummyResult::expr(sp);
+        return DummyResult::any(sp);
     }
 
     let e = match env::var(&*var.as_str()) {
         Err(_) => {
             cx.span_err(sp, &msg.as_str());
-            return DummyResult::expr(sp);
+            return DummyResult::any(sp);
         }
         Ok(s) => cx.expr_str(sp, Symbol::intern(&s)),
     };
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 2ae13b6..8376420 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -805,7 +805,7 @@
         }
         Err(mut err) => {
             err.emit();
-            DummyResult::expr(sp)
+            DummyResult::any(sp)
         }
     }
 }
@@ -846,9 +846,9 @@
 
     let msg = "format argument must be a string literal";
     let fmt_sp = efmt.span;
-    let fmt = match expr_to_spanned_string(ecx, efmt, msg) {
+    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
         Ok(mut fmt) if append_newline => {
-            fmt.node.0 = Symbol::intern(&format!("{}\n", fmt.node.0));
+            fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
             fmt
         }
         Ok(fmt) => fmt,
@@ -875,7 +875,7 @@
         _ => (false, None),
     };
 
-    let str_style = match fmt.node.1 {
+    let str_style = match fmt_style {
         ast::StrStyle::Cooked => None,
         ast::StrStyle::Raw(raw) => {
             Some(raw as usize)
@@ -981,7 +981,7 @@
         vec![]
     };
 
-    let fmt_str = &*fmt.node.0.as_str();  // for the suggestions below
+    let fmt_str = &*fmt_str.as_str();  // for the suggestions below
     let mut parser = parse::Parser::new(fmt_str, str_style, skips, append_newline);
 
     let mut unverified_pieces = Vec::new();
@@ -995,7 +995,7 @@
 
     if !parser.errors.is_empty() {
         let err = parser.errors.remove(0);
-        let sp = fmt.span.from_inner(err.span);
+        let sp = fmt_span.from_inner(err.span);
         let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}",
                                                      err.description));
         e.span_label(sp, err.label + " in format string");
@@ -1003,7 +1003,7 @@
             e.note(&note);
         }
         if let Some((label, span)) = err.secondary_label {
-            let sp = fmt.span.from_inner(span);
+            let sp = fmt_span.from_inner(span);
             e.span_label(sp, label);
         }
         e.emit();
@@ -1011,7 +1011,7 @@
     }
 
     let arg_spans = parser.arg_places.iter()
-        .map(|span| fmt.span.from_inner(*span))
+        .map(|span| fmt_span.from_inner(*span))
         .collect();
 
     let named_pos: FxHashSet<usize> = names.values().cloned().collect();
@@ -1034,7 +1034,7 @@
         str_pieces: Vec::with_capacity(unverified_pieces.len()),
         all_pieces_simple: true,
         macsp,
-        fmtsp: fmt.span,
+        fmtsp: fmt_span,
         invalid_refs: Vec::new(),
         arg_spans,
         arg_with_formatting: Vec::new(),
diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs
index f788b51..d2121ab 100644
--- a/src/libsyntax_ext/global_allocator.rs
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -29,7 +29,7 @@
     };
 
     // Generate a bunch of new items using the AllocFnFactory
-    let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
+    let span = item.span.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id));
     let f = AllocFnFactory {
         span,
         kind: AllocatorKind::Global,
@@ -44,7 +44,7 @@
     let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item =
-        ecx.item_const(span, Ident::with_empty_ctxt(kw::Underscore), const_ty, const_body);
+        ecx.item_const(span, Ident::with_dummy_span(kw::Underscore), const_ty, const_body);
 
     // Return the original item and the new methods.
     vec![Annotatable::Item(item), Annotatable::Item(const_item)]
@@ -120,7 +120,7 @@
     ) -> P<Expr> {
         match *ty {
             AllocatorTy::Layout => {
-                let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize));
+                let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
                 let ty_usize = self.cx.ty_path(usize);
                 let size = ident();
                 let align = ident();
@@ -178,12 +178,12 @@
     }
 
     fn usize(&self) -> P<Ty> {
-        let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize));
+        let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
         self.cx.ty_path(usize)
     }
 
     fn ptr_u8(&self) -> P<Ty> {
-        let u8 = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::u8));
+        let u8 = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::u8));
         let ty_u8 = self.cx.ty_path(u8);
         self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
     }
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 0f3f5c0..4add226 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -42,7 +42,7 @@
 
 pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) {
     let mut register = |name, kind| resolver.register_builtin_macro(
-        Ident::with_empty_ctxt(name), SyntaxExtension {
+        Ident::with_dummy_span(name), SyntaxExtension {
             is_builtin: true, ..SyntaxExtension::default(kind, edition)
         },
     );
@@ -57,7 +57,6 @@
     }
 
     register_bang! {
-        __rust_unstable_column: source_util::expand_column,
         asm: asm::expand_asm,
         assert: assert::expand_assert,
         cfg: cfg::expand_cfg,
diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs
index a725f5e..dbfd8fe 100644
--- a/src/libsyntax_ext/plugin_macro_defs.rs
+++ b/src/libsyntax_ext/plugin_macro_defs.rs
@@ -11,7 +11,7 @@
 use syntax::symbol::sym;
 use syntax::tokenstream::*;
 use syntax_pos::{Span, DUMMY_SP};
-use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind};
+use syntax_pos::hygiene::{ExpnData, ExpnKind, MacroKind};
 
 use std::mem;
 
@@ -43,12 +43,12 @@
 ) {
     if !named_exts.is_empty() {
         let mut extra_items = Vec::new();
-        let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+        let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
             ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition,
             [sym::rustc_attrs][..].into(),
         ));
         for (name, ext) in named_exts {
-            resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext);
+            resolver.register_builtin_macro(Ident::with_dummy_span(name), ext);
             extra_items.push(plugin_macro_def(name, span));
         }
         // The `macro_rules` items must be inserted before any other items.
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index 7913a74..e772eaf 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -1,18 +1,16 @@
 use std::mem;
 
+use smallvec::smallvec;
 use syntax::ast::{self, Ident};
 use syntax::attr;
-use syntax::source_map::{ExpnInfo, ExpnKind, respan};
+use syntax::source_map::{ExpnData, ExpnKind, respan};
 use syntax::ext::base::{ExtCtxt, MacroKind};
-use syntax::ext::expand::ExpansionConfig;
-use syntax::ext::hygiene::ExpnId;
+use syntax::ext::expand::{AstFragment, ExpansionConfig};
 use syntax::ext::proc_macro::is_proc_macro_attr;
-use syntax::mut_visit::MutVisitor;
 use syntax::parse::ParseSess;
 use syntax::ptr::P;
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
-
 use syntax_pos::{Span, DUMMY_SP};
 
 struct ProcMacroDerive {
@@ -329,7 +327,7 @@
     custom_attrs: &[ProcMacroDef],
     custom_macros: &[ProcMacroDef],
 ) -> P<ast::Item> {
-    let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+    let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
         ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
         [sym::rustc_attrs, sym::proc_macro_internals][..].into(),
     ));
@@ -338,7 +336,7 @@
     let doc = cx.meta_list(span, sym::doc, vec![hidden]);
     let doc_hidden = cx.attribute(doc);
 
-    let proc_macro = Ident::with_empty_ctxt(sym::proc_macro);
+    let proc_macro = Ident::with_dummy_span(sym::proc_macro);
     let krate = cx.item(span,
                         proc_macro,
                         Vec::new(),
@@ -350,7 +348,7 @@
     let custom_derive = Ident::from_str("custom_derive");
     let attr = Ident::from_str("attr");
     let bang = Ident::from_str("bang");
-    let crate_kw = Ident::with_empty_ctxt(kw::Crate);
+    let crate_kw = Ident::with_dummy_span(kw::Crate);
 
     let decls = {
         let local_path = |sp: Span, name| {
@@ -409,5 +407,7 @@
         i
     });
 
-    cx.monotonic_expander().flat_map_item(module).pop().unwrap()
+    // Integrate the new module into existing module structures.
+    let module = AstFragment::Items(smallvec![module]);
+    cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap()
 }
diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs
index 2c8d53a..e008ed7 100644
--- a/src/libsyntax_ext/source_util.rs
+++ b/src/libsyntax_ext/source_util.rs
@@ -9,8 +9,6 @@
 use smallvec::SmallVec;
 use syntax_pos::{self, Pos, Span};
 
-use std::fs;
-use std::io::ErrorKind;
 use rustc_data_structures::sync::Lrc;
 
 // These macros all relate to the file system; they either return
@@ -111,26 +109,23 @@
                           -> Box<dyn base::MacResult+'static> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
         Some(f) => f,
-        None => return DummyResult::expr(sp)
+        None => return DummyResult::any(sp)
     };
     let file = cx.resolve_path(file, sp);
-    match fs::read_to_string(&file) {
-        Ok(src) => {
-            let interned_src = Symbol::intern(&src);
-
-            // Add this input file to the code map to make it available as
-            // dependency information
-            cx.source_map().new_source_file(file.into(), src);
-
-            base::MacEager::expr(cx.expr_str(sp, interned_src))
+    match cx.source_map().load_binary_file(&file) {
+        Ok(bytes) => match std::str::from_utf8(&bytes) {
+            Ok(src) => {
+                let interned_src = Symbol::intern(&src);
+                base::MacEager::expr(cx.expr_str(sp, interned_src))
+            }
+            Err(_) => {
+                cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
+                DummyResult::any(sp)
+            }
         },
-        Err(ref e) if e.kind() == ErrorKind::InvalidData => {
-            cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
-            DummyResult::expr(sp)
-        }
         Err(e) => {
             cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
-            DummyResult::expr(sp)
+            DummyResult::any(sp)
         }
     }
 }
@@ -139,26 +134,16 @@
                             -> Box<dyn base::MacResult+'static> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
         Some(f) => f,
-        None => return DummyResult::expr(sp)
+        None => return DummyResult::any(sp)
     };
     let file = cx.resolve_path(file, sp);
-    match fs::read(&file) {
+    match cx.source_map().load_binary_file(&file) {
         Ok(bytes) => {
-            // Add the contents to the source map if it contains UTF-8.
-            let (contents, bytes) = match String::from_utf8(bytes) {
-                Ok(s) => {
-                    let bytes = s.as_bytes().to_owned();
-                    (s, bytes)
-                },
-                Err(e) => (String::new(), e.into_bytes()),
-            };
-            cx.source_map().new_source_file(file.into(), contents);
-
             base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes))))
         },
         Err(e) => {
             cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
-            DummyResult::expr(sp)
+            DummyResult::any(sp)
         }
     }
 }
diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs
index 68b13bd..8ca3763 100644
--- a/src/libsyntax_ext/standard_library_imports.rs
+++ b/src/libsyntax_ext/standard_library_imports.rs
@@ -1,8 +1,8 @@
 use syntax::{ast, attr};
 use syntax::edition::Edition;
-use syntax::ext::hygiene::{ExpnId, MacroKind};
+use syntax::ext::hygiene::MacroKind;
 use syntax::ptr::P;
-use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
+use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned, respan};
 use syntax::symbol::{Ident, Symbol, kw, sym};
 use syntax_pos::DUMMY_SP;
 
@@ -32,7 +32,7 @@
         // HACK(eddyb) gensym the injected crates on the Rust 2018 edition,
         // so they don't accidentally interfere with the new import paths.
         let orig_name_sym = Symbol::intern(orig_name_str);
-        let orig_name_ident = Ident::with_empty_ctxt(orig_name_sym);
+        let orig_name_ident = Ident::with_dummy_span(orig_name_sym);
         let (rename, orig_name) = if rust_2018 {
             (orig_name_ident.gensym(), Some(orig_name_sym))
         } else {
@@ -40,7 +40,7 @@
         };
         krate.module.items.insert(0, P(ast::Item {
             attrs: vec![attr::mk_attr_outer(
-                attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::macro_use))
+                attr::mk_word_item(ast::Ident::with_dummy_span(sym::macro_use))
             )],
             vis: dummy_spanned(ast::VisibilityKind::Inherited),
             node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)),
@@ -55,7 +55,7 @@
     // the prelude.
     let name = names[0];
 
-    let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+    let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
         ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
         [sym::prelude_import][..].into(),
     ));
@@ -66,7 +66,7 @@
         vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
         node: ast::ItemKind::Use(P(ast::UseTree {
             prefix: ast::Path {
-                segments: iter::once(ast::Ident::with_empty_ctxt(kw::PathRoot))
+                segments: iter::once(ast::Ident::with_dummy_span(kw::PathRoot))
                     .chain(
                         [name, "prelude", "v1"].iter().cloned()
                             .map(ast::Ident::from_str)
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index 993ef25..08582e7 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -29,7 +29,7 @@
 
     if !ecx.ecfg.should_test { return vec![]; }
 
-    let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
+    let sp = attr_sp.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id));
     let mut item = anno_item.expect_item();
     item = item.map(|mut item| {
         item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
@@ -93,7 +93,7 @@
         return vec![Annotatable::Item(item)];
     }
 
-    let ctxt = SyntaxContext::empty().apply_mark(cx.current_expansion.id);
+    let ctxt = SyntaxContext::root().apply_mark(cx.current_expansion.id);
     let (sp, attr_sp) = (item.span.with_ctxt(ctxt), attr_sp.with_ctxt(ctxt));
 
     // Gensym "test" so we can extern crate without conflicting with any local names
diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs
index eec8a3f..4a6ea0e 100644
--- a/src/libsyntax_ext/test_harness.rs
+++ b/src/libsyntax_ext/test_harness.rs
@@ -5,14 +5,13 @@
 use syntax::ast::{self, Ident};
 use syntax::attr;
 use syntax::entry::{self, EntryPointType};
-use syntax::ext::base::{ExtCtxt, Resolver};
-use syntax::ext::expand::ExpansionConfig;
-use syntax::ext::hygiene::{ExpnId, MacroKind};
+use syntax::ext::base::{ExtCtxt, MacroKind, Resolver};
+use syntax::ext::expand::{AstFragment, ExpansionConfig};
 use syntax::feature_gate::Features;
 use syntax::mut_visit::{*, ExpectOne};
 use syntax::parse::ParseSess;
 use syntax::ptr::P;
-use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned};
+use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned};
 use syntax::symbol::{kw, sym, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -74,12 +73,7 @@
         noop_visit_crate(c, self);
 
         // Create a main function to run our tests
-        let test_main = {
-            let unresolved = mk_main(&mut self.cx);
-            self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap()
-        };
-
-        c.module.items.push(test_main);
+        c.module.items.push(mk_main(&mut self.cx));
     }
 
     fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
@@ -155,7 +149,7 @@
             EntryPointType::MainAttr |
             EntryPointType::Start =>
                 item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| {
-                    let allow_ident = Ident::with_empty_ctxt(sym::allow);
+                    let allow_ident = Ident::with_dummy_span(sym::allow);
                     let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code"));
                     let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
                     let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item);
@@ -196,7 +190,7 @@
                    tests: Vec<Ident>,
                    tested_submods: Vec<(Ident, Ident)>)
                    -> (P<ast::Item>, Ident) {
-    let super_ = Ident::with_empty_ctxt(kw::Super);
+    let super_ = Ident::with_dummy_span(kw::Super);
 
     let items = tests.into_iter().map(|r| {
         cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
@@ -216,7 +210,7 @@
     let name = Ident::from_str("__test_reexports").gensym();
     let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent };
     cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent);
-    let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item {
+    let module = P(ast::Item {
         ident: name,
         attrs: Vec::new(),
         id: ast::DUMMY_NODE_ID,
@@ -224,9 +218,14 @@
         vis: dummy_spanned(ast::VisibilityKind::Public),
         span: DUMMY_SP,
         tokens: None,
-    })).pop().unwrap();
+    });
 
-    (it, name)
+    // Integrate the new module into existing module structures.
+    let module = AstFragment::Items(smallvec![module]);
+    let module =
+        cx.ext_cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap();
+
+    (module, name)
 }
 
 /// Crawl over the crate, inserting test reexports and the test main function
@@ -269,12 +268,12 @@
     //            #![main]
     //            test::test_main_static(&[..tests]);
     //        }
-    let sp = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+    let sp = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
         ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition,
         [sym::main, sym::test, sym::rustc_attrs][..].into(),
     ));
     let ecx = &cx.ext_cx;
-    let test_id = Ident::with_empty_ctxt(sym::test);
+    let test_id = Ident::with_dummy_span(sym::test);
 
     // test::test_main_static(...)
     let mut test_runner = cx.test_runner.clone().unwrap_or(
@@ -321,7 +320,7 @@
         None => Ident::from_str_and_span("main", sp).gensym(),
     };
 
-    P(ast::Item {
+    let main = P(ast::Item {
         ident: main_id,
         attrs: vec![main_attr],
         id: ast::DUMMY_NODE_ID,
@@ -329,8 +328,11 @@
         vis: dummy_spanned(ast::VisibilityKind::Public),
         span: sp,
         tokens: None,
-    })
+    });
 
+    // Integrate the new item into existing module structures.
+    let main = AstFragment::Items(smallvec![main]);
+    cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap()
 }
 
 fn path_name_i(idents: &[Ident]) -> String {
diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs
index 2021656..00cd00f 100644
--- a/src/libsyntax_pos/edition.rs
+++ b/src/libsyntax_pos/edition.rs
@@ -1,7 +1,6 @@
 use crate::symbol::{Symbol, sym};
 use std::fmt;
 use std::str::FromStr;
-use crate::GLOBALS;
 
 /// The edition of the compiler (RFC 2052)
 #[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)]
@@ -39,10 +38,6 @@
 }
 
 impl Edition {
-    pub fn from_session() -> Edition {
-        GLOBALS.with(|globals| globals.edition)
-    }
-
     pub fn lint_name(&self) -> &'static str {
         match *self {
             Edition::Edition2015 => "rust_2015_compatibility",
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index f91a229..87d930f 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -13,8 +13,8 @@
 //
 // This explains why `HygieneData`, `SyntaxContext` and `ExpnId` have interfaces
 // with a certain amount of redundancy in them. For example,
-// `SyntaxContext::outer_expn_info` combines `SyntaxContext::outer` and
-// `ExpnId::expn_info` so that two `HygieneData` accesses can be performed within
+// `SyntaxContext::outer_expn_data` combines `SyntaxContext::outer` and
+// `ExpnId::expn_data` so that two `HygieneData` accesses can be performed within
 // a single `HygieneData::with` call.
 //
 // It also explains why many functions appear in `HygieneData` and again in
@@ -56,16 +56,6 @@
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub struct ExpnId(u32);
 
-// FIXME: Find a way to merge this with `ExpnInfo`.
-#[derive(Debug)]
-struct InternalExpnData {
-    parent: ExpnId,
-    /// Each expansion should have an associated expansion info, but sometimes there's a delay
-    /// between creation of an expansion ID and obtaining its info (e.g. macros are collected
-    /// first and then resolved later), so we use an `Option` here.
-    expn_info: Option<ExpnInfo>,
-}
-
 /// A property of a macro expansion that determines how identifiers
 /// produced by that expansion are resolved.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)]
@@ -86,8 +76,8 @@
 }
 
 impl ExpnId {
-    pub fn fresh(parent: ExpnId, expn_info: Option<ExpnInfo>) -> Self {
-        HygieneData::with(|data| data.fresh_expn(parent, expn_info))
+    pub fn fresh(expn_data: Option<ExpnData>) -> Self {
+        HygieneData::with(|data| data.fresh_expn(expn_data))
     }
 
     /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
@@ -107,21 +97,16 @@
     }
 
     #[inline]
-    pub fn parent(self) -> ExpnId {
-        HygieneData::with(|data| data.parent_expn(self))
+    pub fn expn_data(self) -> ExpnData {
+        HygieneData::with(|data| data.expn_data(self).clone())
     }
 
     #[inline]
-    pub fn expn_info(self) -> Option<ExpnInfo> {
-        HygieneData::with(|data| data.expn_info(self).cloned())
-    }
-
-    #[inline]
-    pub fn set_expn_info(self, info: ExpnInfo) {
+    pub fn set_expn_data(self, expn_data: ExpnData) {
         HygieneData::with(|data| {
-            let old_info = &mut data.expn_data[self.0 as usize].expn_info;
-            assert!(old_info.is_none(), "expansion info is reset for an expansion ID");
-            *old_info = Some(info);
+            let old_expn_data = &mut data.expn_data[self.0 as usize];
+            assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
+            *old_expn_data = Some(expn_data);
         })
     }
 
@@ -139,12 +124,9 @@
     #[inline]
     pub fn looks_like_proc_macro_derive(self) -> bool {
         HygieneData::with(|data| {
-            if data.default_transparency(self) == Transparency::Opaque {
-                if let Some(expn_info) = data.expn_info(self) {
-                    if let ExpnKind::Macro(MacroKind::Derive, _) = expn_info.kind {
-                        return true;
-                    }
-                }
+            let expn_data = data.expn_data(self);
+            if let ExpnKind::Macro(MacroKind::Derive, _) = expn_data.kind {
+                return expn_data.default_transparency == Transparency::Opaque;
             }
             false
         })
@@ -153,7 +135,10 @@
 
 #[derive(Debug)]
 crate struct HygieneData {
-    expn_data: Vec<InternalExpnData>,
+    /// Each expansion should have an associated expansion data, but sometimes there's a delay
+    /// between creation of an expansion ID and obtaining its data (e.g. macros are collected
+    /// first and then resolved later), so we use an `Option` here.
+    expn_data: Vec<Option<ExpnData>>,
     syntax_context_data: Vec<SyntaxContextData>,
     syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>,
 }
@@ -161,10 +146,7 @@
 impl HygieneData {
     crate fn new(edition: Edition) -> Self {
         HygieneData {
-            expn_data: vec![InternalExpnData {
-                parent: ExpnId::root(),
-                expn_info: Some(ExpnInfo::default(ExpnKind::Root, DUMMY_SP, edition)),
-            }],
+            expn_data: vec![Some(ExpnData::default(ExpnKind::Root, DUMMY_SP, edition))],
             syntax_context_data: vec![SyntaxContextData {
                 outer_expn: ExpnId::root(),
                 outer_transparency: Transparency::Opaque,
@@ -181,25 +163,14 @@
         GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut()))
     }
 
-    fn fresh_expn(&mut self, parent: ExpnId, expn_info: Option<ExpnInfo>) -> ExpnId {
-        self.expn_data.push(InternalExpnData { parent, expn_info });
+    fn fresh_expn(&mut self, expn_data: Option<ExpnData>) -> ExpnId {
+        self.expn_data.push(expn_data);
         ExpnId(self.expn_data.len() as u32 - 1)
     }
 
-    fn parent_expn(&self, expn_id: ExpnId) -> ExpnId {
-        self.expn_data[expn_id.0 as usize].parent
-    }
-
-    fn expn_info(&self, expn_id: ExpnId) -> Option<&ExpnInfo> {
-        if expn_id != ExpnId::root() {
-            Some(self.expn_data[expn_id.0 as usize].expn_info.as_ref()
-                     .expect("no expansion info for an expansion ID"))
-        } else {
-            // FIXME: Some code relies on `expn_info().is_none()` meaning "no expansion".
-            // Introduce a method for checking for "no expansion" instead and always return
-            // `ExpnInfo` from this function instead of the `Option`.
-            None
-        }
+    fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
+        self.expn_data[expn_id.0 as usize].as_ref()
+            .expect("no expansion data for an expansion ID")
     }
 
     fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
@@ -207,17 +178,11 @@
             if expn_id == ExpnId::root() {
                 return false;
             }
-            expn_id = self.parent_expn(expn_id);
+            expn_id = self.expn_data(expn_id).parent;
         }
         true
     }
 
-    fn default_transparency(&self, expn_id: ExpnId) -> Transparency {
-        self.expn_info(expn_id).map_or(
-            Transparency::SemiTransparent, |einfo| einfo.default_transparency
-        )
-    }
-
     fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].opaque
     }
@@ -246,7 +211,7 @@
 
     fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> {
         let mut marks = Vec::new();
-        while ctxt != SyntaxContext::empty() {
+        while ctxt != SyntaxContext::root() {
             marks.push((self.outer_expn(ctxt), self.outer_transparency(ctxt)));
             ctxt = self.parent_ctxt(ctxt);
         }
@@ -255,12 +220,8 @@
     }
 
     fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
-        while span.ctxt() != crate::NO_EXPANSION && span.ctxt() != to {
-            if let Some(info) = self.expn_info(self.outer_expn(span.ctxt())) {
-                span = info.call_site;
-            } else {
-                break;
-            }
+        while span.from_expansion() && span.ctxt() != to {
+            span = self.expn_data(self.outer_expn(span.ctxt())).call_site;
         }
         span
     }
@@ -275,7 +236,9 @@
 
     fn apply_mark(&mut self, ctxt: SyntaxContext, expn_id: ExpnId) -> SyntaxContext {
         assert_ne!(expn_id, ExpnId::root());
-        self.apply_mark_with_transparency(ctxt, expn_id, self.default_transparency(expn_id))
+        self.apply_mark_with_transparency(
+            ctxt, expn_id, self.expn_data(expn_id).default_transparency
+        )
     }
 
     fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, expn_id: ExpnId,
@@ -285,15 +248,14 @@
             return self.apply_mark_internal(ctxt, expn_id, transparency);
         }
 
-        let call_site_ctxt =
-            self.expn_info(expn_id).map_or(SyntaxContext::empty(), |info| info.call_site.ctxt());
+        let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
         let mut call_site_ctxt = if transparency == Transparency::SemiTransparent {
             self.modern(call_site_ctxt)
         } else {
             self.modern_and_legacy(call_site_ctxt)
         };
 
-        if call_site_ctxt == SyntaxContext::empty() {
+        if call_site_ctxt == SyntaxContext::root() {
             return self.apply_mark_internal(ctxt, expn_id, transparency);
         }
 
@@ -400,7 +362,7 @@
 
 impl SyntaxContext {
     #[inline]
-    pub const fn empty() -> Self {
+    pub const fn root() -> Self {
         SyntaxContext(0)
     }
 
@@ -578,20 +540,20 @@
         HygieneData::with(|data| data.outer_expn(self))
     }
 
-    /// `ctxt.outer_expn_info()` is equivalent to but faster than
-    /// `ctxt.outer_expn().expn_info()`.
+    /// `ctxt.outer_expn_data()` is equivalent to but faster than
+    /// `ctxt.outer_expn().expn_data()`.
     #[inline]
-    pub fn outer_expn_info(self) -> Option<ExpnInfo> {
-        HygieneData::with(|data| data.expn_info(data.outer_expn(self)).cloned())
+    pub fn outer_expn_data(self) -> ExpnData {
+        HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone())
     }
 
-    /// `ctxt.outer_expn_with_info()` is equivalent to but faster than
-    /// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_info()) }`.
+    /// `ctxt.outer_expn_with_data()` is equivalent to but faster than
+    /// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_data()) }`.
     #[inline]
-    pub fn outer_expn_with_info(self) -> (ExpnId, Option<ExpnInfo>) {
+    pub fn outer_expn_with_data(self) -> (ExpnId, ExpnData) {
         HygieneData::with(|data| {
             let outer = data.outer_expn(self);
-            (outer, data.expn_info(outer).cloned())
+            (outer, data.expn_data(outer).clone())
         })
     }
 
@@ -612,10 +574,10 @@
     /// other compiler-generated code to set per-span properties like allowed unstable features.
     /// The returned span belongs to the created expansion and has the new properties,
     /// but its location is inherited from the current span.
-    pub fn fresh_expansion(self, parent: ExpnId, expn_info: ExpnInfo) -> Span {
+    pub fn fresh_expansion(self, expn_data: ExpnData) -> Span {
         HygieneData::with(|data| {
-            let expn_id = data.fresh_expn(parent, Some(expn_info));
-            self.with_ctxt(data.apply_mark(SyntaxContext::empty(), expn_id))
+            let expn_id = data.fresh_expn(Some(expn_data));
+            self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id))
         })
     }
 }
@@ -623,8 +585,12 @@
 /// A subset of properties from both macro definition and macro call available through global data.
 /// Avoid using this if you have access to the original definition or call structures.
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct ExpnInfo {
+pub struct ExpnData {
     // --- The part unique to each expansion.
+    /// The kind of this expansion - macro or compiler desugaring.
+    pub kind: ExpnKind,
+    /// The expansion that produced this expansion.
+    pub parent: ExpnId,
     /// The location of the actual macro invocation or syntax sugar , e.g.
     /// `let x = foo!();` or `if let Some(y) = x {}`
     ///
@@ -632,18 +598,18 @@
     /// `foo!()` invoked `bar!()` internally, and there was an
     /// expression inside `bar!`; the call_site of the expression in
     /// the expansion would point to the `bar!` invocation; that
-    /// call_site span would have its own ExpnInfo, with the call_site
+    /// call_site span would have its own ExpnData, with the call_site
     /// pointing to the `foo!` invocation.
     pub call_site: Span,
-    /// The kind of this expansion - macro or compiler desugaring.
-    pub kind: ExpnKind,
 
     // --- The part specific to the macro/desugaring definition.
-    // --- FIXME: Share it between expansions with the same definition.
+    // --- It may be reasonable to share this part between expansions with the same definition,
+    // --- but such sharing is known to bring some minor inconveniences without also bringing
+    // --- noticeable perf improvements (PR #62898).
     /// The span of the macro definition (possibly dummy).
     /// This span serves only informational purpose and is not used for resolution.
     pub def_site: Span,
-    /// Transparency used by `apply_mark` for the expansion with this expansion info by default.
+    /// Transparency used by `apply_mark` for the expansion with this expansion data by default.
     pub default_transparency: Transparency,
     /// List of #[unstable]/feature-gated features that the macro is allowed to use
     /// internally without forcing the whole crate to opt-in
@@ -659,12 +625,13 @@
     pub edition: Edition,
 }
 
-impl ExpnInfo {
-    /// Constructs an expansion info with default properties.
-    pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnInfo {
-        ExpnInfo {
-            call_site,
+impl ExpnData {
+    /// Constructs expansion data with default properties.
+    pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnData {
+        ExpnData {
             kind,
+            parent: ExpnId::root(),
+            call_site,
             def_site: DUMMY_SP,
             default_transparency: Transparency::SemiTransparent,
             allow_internal_unstable: None,
@@ -675,12 +642,17 @@
     }
 
     pub fn allow_unstable(kind: ExpnKind, call_site: Span, edition: Edition,
-                          allow_internal_unstable: Lrc<[Symbol]>) -> ExpnInfo {
-        ExpnInfo {
+                          allow_internal_unstable: Lrc<[Symbol]>) -> ExpnData {
+        ExpnData {
             allow_internal_unstable: Some(allow_internal_unstable),
-            ..ExpnInfo::default(kind, call_site, edition)
+            ..ExpnData::default(kind, call_site, edition)
         }
     }
+
+    #[inline]
+    pub fn is_root(&self) -> bool {
+        if let ExpnKind::Root = self.kind { true } else { false }
+    }
 }
 
 /// Expansion kind.
@@ -767,6 +739,18 @@
     }
 }
 
+impl Encodable for ExpnId {
+    fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
+        Ok(()) // FIXME(jseyfried) intercrate hygiene
+    }
+}
+
+impl Decodable for ExpnId {
+    fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
+        Ok(ExpnId::root()) // FIXME(jseyfried) intercrate hygiene
+    }
+}
+
 impl Encodable for SyntaxContext {
     fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
         Ok(()) // FIXME(jseyfried) intercrate hygiene
@@ -774,7 +758,7 @@
 }
 
 impl Decodable for SyntaxContext {
-    fn decode<D: Decoder>(_: &mut D) -> Result<SyntaxContext, D::Error> {
-        Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene
+    fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
+        Ok(SyntaxContext::root()) // FIXME(jseyfried) intercrate hygiene
     }
 }
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 02a7433..aa36fe2 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -21,7 +21,7 @@
 pub mod edition;
 use edition::Edition;
 pub mod hygiene;
-pub use hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind, MacroKind, DesugaringKind};
+pub use hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind, MacroKind, DesugaringKind};
 
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
@@ -49,7 +49,6 @@
     symbol_interner: Lock<symbol::Interner>,
     span_interner: Lock<span_encoding::SpanInterner>,
     hygiene_data: Lock<hygiene::HygieneData>,
-    edition: Edition,
 }
 
 impl Globals {
@@ -58,7 +57,6 @@
             symbol_interner: Lock::new(symbol::Interner::fresh()),
             span_interner: Lock::new(span_encoding::SpanInterner::default()),
             hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
-            edition,
         }
     }
 }
@@ -288,6 +286,17 @@
         span.lo.0 == 0 && span.hi.0 == 0
     }
 
+    /// Returns `true` if this span comes from a macro or desugaring.
+    #[inline]
+    pub fn from_expansion(self) -> bool {
+        self.ctxt() != SyntaxContext::root()
+    }
+
+    #[inline]
+    pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
+        Span::new(lo, hi, SyntaxContext::root())
+    }
+
     /// Returns a new span representing an empty span at the beginning of this span
     #[inline]
     pub fn shrink_to_lo(self) -> Span {
@@ -344,20 +353,20 @@
     /// Returns the source span -- this is either the supplied span, or the span for
     /// the macro callsite that expanded to it.
     pub fn source_callsite(self) -> Span {
-        self.ctxt().outer_expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self)
+        let expn_data = self.ctxt().outer_expn_data();
+        if !expn_data.is_root() { expn_data.call_site.source_callsite() } else { self }
     }
 
     /// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
     /// if any.
     pub fn parent(self) -> Option<Span> {
-        self.ctxt().outer_expn_info().map(|i| i.call_site)
+        let expn_data = self.ctxt().outer_expn_data();
+        if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
     }
 
     /// Edition of the crate from which this span came.
     pub fn edition(self) -> edition::Edition {
-        self.ctxt().outer_expn_info().map_or_else(|| {
-            Edition::from_session()
-        }, |einfo| einfo.edition)
+        self.ctxt().outer_expn_data().edition
     }
 
     #[inline]
@@ -373,52 +382,42 @@
     /// Returns the source callee.
     ///
     /// Returns `None` if the supplied span has no expansion trace,
-    /// else returns the `ExpnInfo` for the macro definition
+    /// else returns the `ExpnData` for the macro definition
     /// corresponding to the source callsite.
-    pub fn source_callee(self) -> Option<ExpnInfo> {
-        fn source_callee(info: ExpnInfo) -> ExpnInfo {
-            match info.call_site.ctxt().outer_expn_info() {
-                Some(info) => source_callee(info),
-                None => info,
-            }
+    pub fn source_callee(self) -> Option<ExpnData> {
+        fn source_callee(expn_data: ExpnData) -> ExpnData {
+            let next_expn_data = expn_data.call_site.ctxt().outer_expn_data();
+            if !next_expn_data.is_root() { source_callee(next_expn_data) } else { expn_data }
         }
-        self.ctxt().outer_expn_info().map(source_callee)
+        let expn_data = self.ctxt().outer_expn_data();
+        if !expn_data.is_root() { Some(source_callee(expn_data)) } else { None }
     }
 
     /// Checks if a span is "internal" to a macro in which `#[unstable]`
     /// items can be used (that is, a macro marked with
     /// `#[allow_internal_unstable]`).
     pub fn allows_unstable(&self, feature: Symbol) -> bool {
-        match self.ctxt().outer_expn_info() {
-            Some(info) => info
-                .allow_internal_unstable
-                .map_or(false, |features| features.iter().any(|&f|
-                    f == feature || f == sym::allow_internal_unstable_backcompat_hack
-                )),
-            None => false,
-        }
+        self.ctxt().outer_expn_data().allow_internal_unstable.map_or(false, |features| {
+            features.iter().any(|&f| {
+                f == feature || f == sym::allow_internal_unstable_backcompat_hack
+            })
+        })
     }
 
     /// Checks if this span arises from a compiler desugaring of kind `kind`.
     pub fn is_desugaring(&self, kind: DesugaringKind) -> bool {
-        match self.ctxt().outer_expn_info() {
-            Some(info) => match info.kind {
-                ExpnKind::Desugaring(k) => k == kind,
-                _ => false,
-            },
-            None => false,
+        match self.ctxt().outer_expn_data().kind {
+            ExpnKind::Desugaring(k) => k == kind,
+            _ => false,
         }
     }
 
     /// Returns the compiler desugaring that created this span, or `None`
     /// if this span is not from a desugaring.
     pub fn desugaring_kind(&self) -> Option<DesugaringKind> {
-        match self.ctxt().outer_expn_info() {
-            Some(info) => match info.kind {
-                ExpnKind::Desugaring(k) => Some(k),
-                _ => None
-            },
-            None => None
+        match self.ctxt().outer_expn_data().kind {
+            ExpnKind::Desugaring(k) => Some(k),
+            _ => None
         }
     }
 
@@ -426,19 +425,20 @@
     /// can be used without triggering the `unsafe_code` lint
     //  (that is, a macro marked with `#[allow_internal_unsafe]`).
     pub fn allows_unsafe(&self) -> bool {
-        match self.ctxt().outer_expn_info() {
-            Some(info) => info.allow_internal_unsafe,
-            None => false,
-        }
+        self.ctxt().outer_expn_data().allow_internal_unsafe
     }
 
     pub fn macro_backtrace(mut self) -> Vec<MacroBacktrace> {
         let mut prev_span = DUMMY_SP;
         let mut result = vec![];
-        while let Some(info) = self.ctxt().outer_expn_info() {
+        loop {
+            let expn_data = self.ctxt().outer_expn_data();
+            if expn_data.is_root() {
+                break;
+            }
             // Don't print recursive invocations.
-            if !info.call_site.source_equal(&prev_span) {
-                let (pre, post) = match info.kind {
+            if !expn_data.call_site.source_equal(&prev_span) {
+                let (pre, post) = match expn_data.kind {
                     ExpnKind::Root => break,
                     ExpnKind::Desugaring(..) => ("desugaring of ", ""),
                     ExpnKind::Macro(macro_kind, _) => match macro_kind {
@@ -448,14 +448,14 @@
                     }
                 };
                 result.push(MacroBacktrace {
-                    call_site: info.call_site,
-                    macro_decl_name: format!("{}{}{}", pre, info.kind.descr(), post),
-                    def_site_span: info.def_site,
+                    call_site: expn_data.call_site,
+                    macro_decl_name: format!("{}{}{}", pre, expn_data.kind.descr(), post),
+                    def_site_span: expn_data.def_site,
                 });
             }
 
             prev_span = self;
-            self = info.call_site;
+            self = expn_data.call_site;
         }
         result
     }
@@ -468,9 +468,9 @@
         // Return the macro span on its own to avoid weird diagnostic output. It is preferable to
         // have an incomplete span than a completely nonsensical one.
         if span_data.ctxt != end_data.ctxt {
-            if span_data.ctxt == SyntaxContext::empty() {
+            if span_data.ctxt == SyntaxContext::root() {
                 return end;
-            } else if end_data.ctxt == SyntaxContext::empty() {
+            } else if end_data.ctxt == SyntaxContext::root() {
                 return self;
             }
             // Both spans fall within a macro.
@@ -479,7 +479,7 @@
         Span::new(
             cmp::min(span_data.lo, end_data.lo),
             cmp::max(span_data.hi, end_data.hi),
-            if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt },
+            if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt },
         )
     }
 
@@ -490,7 +490,7 @@
         Span::new(
             span.hi,
             end.lo,
-            if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
+            if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
         )
     }
 
@@ -501,7 +501,7 @@
         Span::new(
             span.lo,
             end.lo,
-            if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
+            if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
         )
     }
 
@@ -611,7 +611,7 @@
         d.read_struct("Span", 2, |d| {
             let lo = d.read_struct_field("lo", 0, Decodable::decode)?;
             let hi = d.read_struct_field("hi", 1, Decodable::decode)?;
-            Ok(Span::new(lo, hi, NO_EXPANSION))
+            Ok(Span::with_root_ctxt(lo, hi))
         })
     }
 }
@@ -755,8 +755,6 @@
     }
 }
 
-pub const NO_EXPANSION: SyntaxContext = SyntaxContext::empty();
-
 /// Identifies an offset of a multi-byte character in a `SourceFile`.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)]
 pub struct MultiByteChar {
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 2d95562..27fc66d 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -14,7 +14,6 @@
 use std::hash::{Hash, Hasher};
 use std::str;
 
-use crate::hygiene::SyntaxContext;
 use crate::{Span, DUMMY_SP, GLOBALS};
 
 #[cfg(test)]
@@ -610,7 +609,6 @@
         rust_eh_personality,
         rust_eh_unwind_resume,
         rust_oom,
-        __rust_unstable_column,
         rvalue_static_promotion,
         sanitizer_runtime,
         _Self,
@@ -745,25 +743,25 @@
         Ident { name, span }
     }
 
-    /// Constructs a new identifier with an empty syntax context.
+    /// Constructs a new identifier with a dummy span.
     #[inline]
-    pub const fn with_empty_ctxt(name: Symbol) -> Ident {
+    pub const fn with_dummy_span(name: Symbol) -> Ident {
         Ident::new(name, DUMMY_SP)
     }
 
     #[inline]
     pub fn invalid() -> Ident {
-        Ident::with_empty_ctxt(kw::Invalid)
+        Ident::with_dummy_span(kw::Invalid)
     }
 
     /// Maps an interned string to an identifier with an empty syntax context.
     pub fn from_interned_str(string: InternedString) -> Ident {
-        Ident::with_empty_ctxt(string.as_symbol())
+        Ident::with_dummy_span(string.as_symbol())
     }
 
     /// Maps a string to an identifier with an empty span.
     pub fn from_str(string: &str) -> Ident {
-        Ident::with_empty_ctxt(Symbol::intern(string))
+        Ident::with_dummy_span(Symbol::intern(string))
     }
 
     /// Maps a string and a span to an identifier.
@@ -851,7 +849,7 @@
 
 impl Encodable for Ident {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        if self.span.ctxt().modern() == SyntaxContext::empty() {
+        if !self.span.modern().from_expansion() {
             s.emit_str(&self.as_str())
         } else { // FIXME(jseyfried): intercrate hygiene
             let mut string = "#".to_owned();
diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml
index f0f1bab..f10df8c 100644
--- a/src/libunwind/Cargo.toml
+++ b/src/libunwind/Cargo.toml
@@ -22,7 +22,7 @@
 cfg-if = "0.1.8"
 
 [build-dependencies]
-cc = { optional = true, version = "1.0.1" }
+cc = { version = "1.0.1" }
 
 [features]
-llvm-libunwind = ["cc"]
+llvm-libunwind = []
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index da31a49..f24d957 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -4,17 +4,15 @@
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
 
-    // FIXME: the not(bootstrap) part is needed because of the issue addressed by #62286,
-    // and could be removed once that change is in beta.
-    if cfg!(all(not(bootstrap), feature = "llvm-libunwind")) &&
-        (target.contains("linux") ||
+    if cfg!(feature = "llvm-libunwind") &&
+        ((target.contains("linux") && !target.contains("musl")) ||
          target.contains("fuchsia")) {
         // Build the unwinding from libunwind C/C++ source code.
-        #[cfg(all(not(bootstrap), feature = "llvm-libunwind"))]
         llvm_libunwind::compile();
     } else if target.contains("linux") {
         if target.contains("musl") {
-            // musl is handled in lib.rs
+            // linking for musl is handled in lib.rs
+            llvm_libunwind::compile();
         } else if !target.contains("android") {
             println!("cargo:rustc-link-lib=gcc_s");
         }
@@ -25,7 +23,11 @@
     } else if target.contains("netbsd") {
         println!("cargo:rustc-link-lib=gcc_s");
     } else if target.contains("openbsd") {
-        println!("cargo:rustc-link-lib=c++abi");
+        if target.contains("sparc64") {
+            println!("cargo:rustc-link-lib=gcc");
+        } else {
+            println!("cargo:rustc-link-lib=c++abi");
+        }
     } else if target.contains("solaris") {
         println!("cargo:rustc-link-lib=gcc_s");
     } else if target.contains("dragonfly") {
@@ -46,7 +48,6 @@
     }
 }
 
-#[cfg(all(not(bootstrap), feature = "llvm-libunwind"))]
 mod llvm_libunwind {
     use std::env;
     use std::path::Path;
@@ -98,6 +99,15 @@
             cfg.file(root.join("src").join(src));
         }
 
+        if target_env == "musl" {
+            // use the same C compiler command to compile C++ code so we do not need to setup the
+            // C++ compiler env variables on the builders
+            cfg.cpp(false);
+            // linking for musl is handled in lib.rs
+            cfg.cargo_metadata(false);
+            println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
+        }
+
         cfg.compile("unwind");
     }
 }
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index aacbfc5..7c9eaa5 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -70,7 +70,7 @@
 
 pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
                                                       exception: *mut _Unwind_Exception);
-#[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind",
+#[cfg_attr(all(feature = "llvm-libunwind",
                any(target_os = "fuchsia", target_os = "linux")),
            link(name = "unwind", kind = "static"))]
 extern "C" {
@@ -97,7 +97,7 @@
     }
     pub use _Unwind_Action::*;
 
-    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind",
+    #[cfg_attr(all(feature = "llvm-libunwind",
                    any(target_os = "fuchsia", target_os = "linux")),
                link(name = "unwind", kind = "static"))]
     extern "C" {
@@ -153,7 +153,7 @@
     pub const UNWIND_POINTER_REG: c_int = 12;
     pub const UNWIND_IP_REG: c_int = 15;
 
-    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind",
+    #[cfg_attr(all(feature = "llvm-libunwind",
                    any(target_os = "fuchsia", target_os = "linux")),
                link(name = "unwind", kind = "static"))]
     extern "C" {
@@ -218,7 +218,7 @@
 cfg_if::cfg_if! {
 if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
     // Not 32-bit iOS
-    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind",
+    #[cfg_attr(all(feature = "llvm-libunwind",
                    any(target_os = "fuchsia", target_os = "linux")),
                link(name = "unwind", kind = "static"))]
     extern "C" {
@@ -230,7 +230,7 @@
     }
 } else {
     // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
-    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind",
+    #[cfg_attr(all(feature = "llvm-libunwind",
                    any(target_os = "fuchsia", target_os = "linux")),
                link(name = "unwind", kind = "static"))]
     extern "C" {
diff --git a/src/stage0.txt b/src/stage0.txt
index 14d65be..1a9e64a 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2019-07-04
+date: 2019-08-13
 rustc: beta
 cargo: beta
 
@@ -25,7 +25,7 @@
 #
 # This means that there's a small window of time (a few days) where artifacts
 # are downloaded from dev-static.rust-lang.org instead of static.rust-lang.org.
-# In order to ease this transition we have an extra key which is in the 
+# In order to ease this transition we have an extra key which is in the
 # configuration file below. When uncommented this will instruct the bootstrap.py
 # script to download from dev-static.rust-lang.org.
 #
diff --git a/src/test/codegen/iter-fold-closure-no-dupes.rs b/src/test/codegen/iter-fold-closure-no-dupes.rs
new file mode 100644
index 0000000..ec58f70
--- /dev/null
+++ b/src/test/codegen/iter-fold-closure-no-dupes.rs
@@ -0,0 +1,14 @@
+//! Check that fold closures aren't duplicated for each iterator type.
+// compile-flags: -C opt-level=0
+
+fn main() {
+    (0i32..10).by_ref().count();
+    (0i32..=10).by_ref().count();
+}
+
+// `count` calls `fold`, which calls `try_fold` -- find the `fold` closure:
+// CHECK: {{^define.*Iterator::fold::.*closure}}
+//
+// Only one closure is needed for both `count` calls, even from different
+// monomorphized iterator types, as it's only generic over the item type.
+// CHECK-NOT: {{^define.*Iterator::fold::.*closure}}
diff --git a/src/test/codegen/iter-fold-closure-no-iterator.rs b/src/test/codegen/iter-fold-closure-no-iterator.rs
new file mode 100644
index 0000000..fbeafd5
--- /dev/null
+++ b/src/test/codegen/iter-fold-closure-no-iterator.rs
@@ -0,0 +1,10 @@
+//! Check that fold closures aren't generic in the iterator type.
+// compile-flags: -C opt-level=0
+
+fn main() {
+    (0i32..10).by_ref().count();
+}
+
+// `count` calls `fold`, which calls `try_fold` -- that `fold` closure should
+// not be generic in the iterator type, only in the item type.
+// CHECK-NOT: {{^define.*Iterator::fold::.*closure.*Range}}
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index 33ee0fe..db36a1f 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32-bare compiled with panic=abort by default
 // ignore-tidy-linelength
 // compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats
 
@@ -11,6 +12,10 @@
     fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { x }
 }
 
+impl Drop for Test {
+    fn drop(&mut self) {}
+}
+
 fn main() {
     let mut x = 0;
     {
@@ -60,10 +65,12 @@
 //     ...
 //     bb0: {
 //         ...
-//         _3 = const Test::foo(move _4, move _6) -> bb1;
+//         _3 = const Test::foo(move _4, move _6) -> [return: bb2, unwind: bb3];
 //     }
 //
-//     bb1: {
+//     ...
+//
+//     bb2: {
 //         Retag(_3);
 //         ...
 //         _9 = move _3;
@@ -80,25 +87,20 @@
 //         _12 = move _13 as *mut i32 (Misc);
 //         Retag([raw] _12);
 //         ...
-//         _16 = move _17(move _18) -> bb2;
+//         _16 = move _17(move _18) -> bb5;
 //     }
 //
-//     bb2: {
+//     bb5: {
 //         Retag(_16);
 //         ...
-//         _20 = const Test::foo_shr(move _21, move _23) -> bb3;
-//     }
-//
-//     bb3: {
-//         ...
-//         return;
+//         _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7];
 //     }
 //
 //     ...
 // }
 // END rustc.main.EraseRegions.after.mir
 // START rustc.main-{{closure}}.EraseRegions.after.mir
-// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(20), local_id: 72 }], _2: &i32) -> &i32 {
+// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(22), local_id: 72 }], _2: &i32) -> &i32 {
 //     ...
 //     bb0: {
 //         Retag([fn entry] _1);
@@ -113,3 +115,17 @@
 //     }
 // }
 // END rustc.main-{{closure}}.EraseRegions.after.mir
+// START rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+// fn  std::ptr::real_drop_in_place(_1: &mut Test) -> () {
+//     ...
+//     bb0: {
+//         Retag([raw] _1);
+//         _2 = &mut (*_1);
+//         _3 = const <Test as std::ops::Drop>::drop(move _2) -> bb1;
+//     }
+//
+//     bb1: {
+//         return;
+//     }
+// }
+// END rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
diff --git a/src/test/run-make-fulldeps/reproducible-build-2/Makefile b/src/test/run-make-fulldeps/reproducible-build-2/Makefile
index b96954f..45c9a74 100644
--- a/src/test/run-make-fulldeps/reproducible-build-2/Makefile
+++ b/src/test/run-make-fulldeps/reproducible-build-2/Makefile
@@ -5,7 +5,8 @@
 # Objects are reproducible but their path is not.
 
 all:  \
-	fat_lto
+	fat_lto \
+	sysroot
 
 fat_lto:
 	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
@@ -14,3 +15,12 @@
 	cp $(TMPDIR)/reproducible-build $(TMPDIR)/reproducible-build-a
 	$(RUSTC) reproducible-build.rs -C lto=fat
 	cmp "$(TMPDIR)/reproducible-build-a" "$(TMPDIR)/reproducible-build" || exit 1
+
+sysroot:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	$(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(shell $(RUSTC) --print sysroot) --remap-path-prefix=$(shell $(RUSTC) --print sysroot)=/sysroot
+	cp -r $(shell $(RUSTC) --print sysroot) $(TMPDIR)/sysroot
+	cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib
+	$(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(TMPDIR)/sysroot --remap-path-prefix=$(TMPDIR)/sysroot=/sysroot
+	cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
diff --git a/src/test/ui/.gitattributes b/src/test/ui/.gitattributes
index b62ade7..489dc8a 100644
--- a/src/test/ui/.gitattributes
+++ b/src/test/ui/.gitattributes
@@ -1,2 +1,3 @@
 lexer-crlf-line-endings-string-literal-doc-comment.rs -text
 trailing-carriage-return-in-string.rs -text
+*.bin -text
diff --git a/src/test/ui/abi-sysv64-arg-passing.rs b/src/test/ui/abi/abi-sysv64-arg-passing.rs
similarity index 100%
rename from src/test/ui/abi-sysv64-arg-passing.rs
rename to src/test/ui/abi/abi-sysv64-arg-passing.rs
diff --git a/src/test/ui/abi-sysv64-register-usage.rs b/src/test/ui/abi/abi-sysv64-register-usage.rs
similarity index 100%
rename from src/test/ui/abi-sysv64-register-usage.rs
rename to src/test/ui/abi/abi-sysv64-register-usage.rs
diff --git a/src/test/ui/abort-on-c-abi.rs b/src/test/ui/abi/abort-on-c-abi.rs
similarity index 100%
rename from src/test/ui/abort-on-c-abi.rs
rename to src/test/ui/abi/abort-on-c-abi.rs
diff --git a/src/test/ui/anon-extern-mod.rs b/src/test/ui/abi/anon-extern-mod.rs
similarity index 100%
rename from src/test/ui/anon-extern-mod.rs
rename to src/test/ui/abi/anon-extern-mod.rs
diff --git a/src/test/ui/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
similarity index 100%
rename from src/test/ui/auxiliary/anon-extern-mod-cross-crate-1.rs
rename to src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
diff --git a/src/test/ui/auxiliary/foreign_lib.rs b/src/test/ui/abi/auxiliary/foreign_lib.rs
similarity index 100%
rename from src/test/ui/auxiliary/foreign_lib.rs
rename to src/test/ui/abi/auxiliary/foreign_lib.rs
diff --git a/src/test/ui/c-stack-as-value.rs b/src/test/ui/abi/c-stack-as-value.rs
similarity index 100%
rename from src/test/ui/c-stack-as-value.rs
rename to src/test/ui/abi/c-stack-as-value.rs
diff --git a/src/test/ui/cabi-int-widening.rs b/src/test/ui/abi/cabi-int-widening.rs
similarity index 100%
rename from src/test/ui/cabi-int-widening.rs
rename to src/test/ui/abi/cabi-int-widening.rs
diff --git a/src/test/ui/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
similarity index 100%
rename from src/test/ui/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
rename to src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
diff --git a/src/test/ui/cross-crate/anon-extern-mod-cross-crate-2.rs b/src/test/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs
similarity index 100%
rename from src/test/ui/cross-crate/anon-extern-mod-cross-crate-2.rs
rename to src/test/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs
diff --git a/src/test/ui/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs
similarity index 100%
rename from src/test/ui/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs
rename to src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs
diff --git a/src/test/ui/duplicated-external-mods.rs b/src/test/ui/abi/duplicated-external-mods.rs
similarity index 100%
rename from src/test/ui/duplicated-external-mods.rs
rename to src/test/ui/abi/duplicated-external-mods.rs
diff --git a/src/test/ui/extern/auxiliary/extern-crosscrate-source.rs b/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
similarity index 100%
rename from src/test/ui/extern/auxiliary/extern-crosscrate-source.rs
rename to src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
diff --git a/src/test/ui/extern/extern-call-deep.rs b/src/test/ui/abi/extern/extern-call-deep.rs
similarity index 100%
rename from src/test/ui/extern/extern-call-deep.rs
rename to src/test/ui/abi/extern/extern-call-deep.rs
diff --git a/src/test/ui/extern/extern-call-deep2.rs b/src/test/ui/abi/extern/extern-call-deep2.rs
similarity index 100%
rename from src/test/ui/extern/extern-call-deep2.rs
rename to src/test/ui/abi/extern/extern-call-deep2.rs
diff --git a/src/test/ui/extern/extern-call-direct.rs b/src/test/ui/abi/extern/extern-call-direct.rs
similarity index 100%
rename from src/test/ui/extern/extern-call-direct.rs
rename to src/test/ui/abi/extern/extern-call-direct.rs
diff --git a/src/test/ui/extern/extern-call-indirect.rs b/src/test/ui/abi/extern/extern-call-indirect.rs
similarity index 100%
rename from src/test/ui/extern/extern-call-indirect.rs
rename to src/test/ui/abi/extern/extern-call-indirect.rs
diff --git a/src/test/ui/extern/extern-call-scrub.rs b/src/test/ui/abi/extern/extern-call-scrub.rs
similarity index 100%
rename from src/test/ui/extern/extern-call-scrub.rs
rename to src/test/ui/abi/extern/extern-call-scrub.rs
diff --git a/src/test/ui/extern/extern-crosscrate.rs b/src/test/ui/abi/extern/extern-crosscrate.rs
similarity index 100%
rename from src/test/ui/extern/extern-crosscrate.rs
rename to src/test/ui/abi/extern/extern-crosscrate.rs
diff --git a/src/test/ui/extern/extern-pass-TwoU16s.rs b/src/test/ui/abi/extern/extern-pass-TwoU16s.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-TwoU16s.rs
rename to src/test/ui/abi/extern/extern-pass-TwoU16s.rs
diff --git a/src/test/ui/extern/extern-pass-TwoU32s.rs b/src/test/ui/abi/extern/extern-pass-TwoU32s.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-TwoU32s.rs
rename to src/test/ui/abi/extern/extern-pass-TwoU32s.rs
diff --git a/src/test/ui/extern/extern-pass-TwoU64s.rs b/src/test/ui/abi/extern/extern-pass-TwoU64s.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-TwoU64s.rs
rename to src/test/ui/abi/extern/extern-pass-TwoU64s.rs
diff --git a/src/test/ui/extern/extern-pass-TwoU8s.rs b/src/test/ui/abi/extern/extern-pass-TwoU8s.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-TwoU8s.rs
rename to src/test/ui/abi/extern/extern-pass-TwoU8s.rs
diff --git a/src/test/ui/extern/extern-pass-char.rs b/src/test/ui/abi/extern/extern-pass-char.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-char.rs
rename to src/test/ui/abi/extern/extern-pass-char.rs
diff --git a/src/test/ui/extern/extern-pass-double.rs b/src/test/ui/abi/extern/extern-pass-double.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-double.rs
rename to src/test/ui/abi/extern/extern-pass-double.rs
diff --git a/src/test/ui/extern/extern-pass-empty.rs b/src/test/ui/abi/extern/extern-pass-empty.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-empty.rs
rename to src/test/ui/abi/extern/extern-pass-empty.rs
diff --git a/src/test/ui/extern/extern-pass-u32.rs b/src/test/ui/abi/extern/extern-pass-u32.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-u32.rs
rename to src/test/ui/abi/extern/extern-pass-u32.rs
diff --git a/src/test/ui/extern/extern-pass-u64.rs b/src/test/ui/abi/extern/extern-pass-u64.rs
similarity index 100%
rename from src/test/ui/extern/extern-pass-u64.rs
rename to src/test/ui/abi/extern/extern-pass-u64.rs
diff --git a/src/test/ui/extern/extern-return-TwoU16s.rs b/src/test/ui/abi/extern/extern-return-TwoU16s.rs
similarity index 100%
rename from src/test/ui/extern/extern-return-TwoU16s.rs
rename to src/test/ui/abi/extern/extern-return-TwoU16s.rs
diff --git a/src/test/ui/extern/extern-return-TwoU32s.rs b/src/test/ui/abi/extern/extern-return-TwoU32s.rs
similarity index 100%
rename from src/test/ui/extern/extern-return-TwoU32s.rs
rename to src/test/ui/abi/extern/extern-return-TwoU32s.rs
diff --git a/src/test/ui/extern/extern-return-TwoU64s.rs b/src/test/ui/abi/extern/extern-return-TwoU64s.rs
similarity index 100%
rename from src/test/ui/extern/extern-return-TwoU64s.rs
rename to src/test/ui/abi/extern/extern-return-TwoU64s.rs
diff --git a/src/test/ui/extern/extern-return-TwoU8s.rs b/src/test/ui/abi/extern/extern-return-TwoU8s.rs
similarity index 100%
rename from src/test/ui/extern/extern-return-TwoU8s.rs
rename to src/test/ui/abi/extern/extern-return-TwoU8s.rs
diff --git a/src/test/ui/foreign/auxiliary/foreign_lib.rs b/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs
similarity index 100%
rename from src/test/ui/foreign/auxiliary/foreign_lib.rs
rename to src/test/ui/abi/foreign/auxiliary/foreign_lib.rs
diff --git a/src/test/ui/foreign/foreign-call-no-runtime.rs b/src/test/ui/abi/foreign/foreign-call-no-runtime.rs
similarity index 100%
rename from src/test/ui/foreign/foreign-call-no-runtime.rs
rename to src/test/ui/abi/foreign/foreign-call-no-runtime.rs
diff --git a/src/test/ui/foreign/foreign-dupe.rs b/src/test/ui/abi/foreign/foreign-dupe.rs
similarity index 100%
rename from src/test/ui/foreign/foreign-dupe.rs
rename to src/test/ui/abi/foreign/foreign-dupe.rs
diff --git a/src/test/ui/foreign/foreign-fn-with-byval.rs b/src/test/ui/abi/foreign/foreign-fn-with-byval.rs
similarity index 100%
rename from src/test/ui/foreign/foreign-fn-with-byval.rs
rename to src/test/ui/abi/foreign/foreign-fn-with-byval.rs
diff --git a/src/test/ui/foreign/foreign-no-abi.rs b/src/test/ui/abi/foreign/foreign-no-abi.rs
similarity index 100%
rename from src/test/ui/foreign/foreign-no-abi.rs
rename to src/test/ui/abi/foreign/foreign-no-abi.rs
diff --git a/src/test/ui/invoke-external-foreign.rs b/src/test/ui/abi/invoke-external-foreign.rs
similarity index 100%
rename from src/test/ui/invoke-external-foreign.rs
rename to src/test/ui/abi/invoke-external-foreign.rs
diff --git a/src/test/ui/lib-defaults.rs b/src/test/ui/abi/lib-defaults.rs
similarity index 100%
rename from src/test/ui/lib-defaults.rs
rename to src/test/ui/abi/lib-defaults.rs
diff --git a/src/test/ui/macros/macros-in-extern.rs b/src/test/ui/abi/macros/macros-in-extern.rs
similarity index 100%
rename from src/test/ui/macros/macros-in-extern.rs
rename to src/test/ui/abi/macros/macros-in-extern.rs
diff --git a/src/test/ui/macros/macros-in-extern.stderr b/src/test/ui/abi/macros/macros-in-extern.stderr
similarity index 100%
rename from src/test/ui/macros/macros-in-extern.stderr
rename to src/test/ui/abi/macros/macros-in-extern.stderr
diff --git a/src/test/ui/mir/mir_codegen_calls_variadic.rs b/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs
similarity index 100%
rename from src/test/ui/mir/mir_codegen_calls_variadic.rs
rename to src/test/ui/abi/mir/mir_codegen_calls_variadic.rs
diff --git a/src/test/ui/numbers-arithmetic/i128-ffi.rs b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs
similarity index 100%
rename from src/test/ui/numbers-arithmetic/i128-ffi.rs
rename to src/test/ui/abi/numbers-arithmetic/i128-ffi.rs
diff --git a/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs b/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs
new file mode 100644
index 0000000..27efa44
--- /dev/null
+++ b/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs
@@ -0,0 +1,112 @@
+// force-host
+// no-prefer-dynamic
+
+// Proc macros commonly used by tests.
+// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros.
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+// Macro that return empty token stream.
+
+#[proc_macro]
+pub fn empty(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+#[proc_macro_attribute]
+pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+#[proc_macro_derive(Empty, attributes(empty_helper))]
+pub fn empty_derive(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+// Macro that panics.
+
+#[proc_macro]
+pub fn panic_bang(_: TokenStream) -> TokenStream {
+    panic!("panic-bang");
+}
+
+#[proc_macro_attribute]
+pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+    panic!("panic-attr");
+}
+
+#[proc_macro_derive(Panic, attributes(panic_helper))]
+pub fn panic_derive(_: TokenStream) -> TokenStream {
+    panic!("panic-derive");
+}
+
+// Macros that return the input stream.
+
+#[proc_macro]
+pub fn identity(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(Identity, attributes(identity_helper))]
+pub fn identity_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+// Macros that iterate and re-collect the input stream.
+
+#[proc_macro]
+pub fn recollect(input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
+
+#[proc_macro_attribute]
+pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
+
+#[proc_macro_derive(Recollect, attributes(recollect_helper))]
+pub fn recollect_derive(input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
+
+// Macros that print their input in the original and re-collected forms (if they differ).
+
+fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
+    let input_display = format!("{}", input);
+    let input_debug = format!("{:#?}", input);
+    let recollected = input.into_iter().collect();
+    let recollected_display = format!("{}", recollected);
+    let recollected_debug = format!("{:#?}", recollected);
+    println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display);
+    if recollected_display != input_display {
+        println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display);
+    }
+    println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
+    if recollected_debug != input_debug {
+        println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
+    }
+    recollected
+}
+
+#[proc_macro]
+pub fn print_bang(input: TokenStream) -> TokenStream {
+    print_helper(input, "BANG")
+}
+
+#[proc_macro_attribute]
+pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    print_helper(input, "ATTR")
+}
+
+#[proc_macro_derive(Print, attributes(print_helper))]
+pub fn print_derive(input: TokenStream) -> TokenStream {
+    print_helper(input, "DERIVE")
+}
diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/abi/proc-macro/macros-in-extern.rs
similarity index 100%
rename from src/test/ui/proc-macro/macros-in-extern.rs
rename to src/test/ui/abi/proc-macro/macros-in-extern.rs
diff --git a/src/test/ui/proc-macro/macros-in-extern.stderr b/src/test/ui/abi/proc-macro/macros-in-extern.stderr
similarity index 100%
rename from src/test/ui/proc-macro/macros-in-extern.stderr
rename to src/test/ui/abi/proc-macro/macros-in-extern.stderr
diff --git a/src/test/ui/segfault-no-out-of-stack.rs b/src/test/ui/abi/segfault-no-out-of-stack.rs
similarity index 100%
rename from src/test/ui/segfault-no-out-of-stack.rs
rename to src/test/ui/abi/segfault-no-out-of-stack.rs
diff --git a/src/test/ui/stack-probes-lto.rs b/src/test/ui/abi/stack-probes-lto.rs
similarity index 100%
rename from src/test/ui/stack-probes-lto.rs
rename to src/test/ui/abi/stack-probes-lto.rs
diff --git a/src/test/ui/stack-probes.rs b/src/test/ui/abi/stack-probes.rs
similarity index 100%
rename from src/test/ui/stack-probes.rs
rename to src/test/ui/abi/stack-probes.rs
diff --git a/src/test/ui/statics/static-mut-foreign.rs b/src/test/ui/abi/statics/static-mut-foreign.rs
similarity index 100%
rename from src/test/ui/statics/static-mut-foreign.rs
rename to src/test/ui/abi/statics/static-mut-foreign.rs
diff --git a/src/test/ui/structs-enums/struct-return.rs b/src/test/ui/abi/struct-enums/struct-return.rs
similarity index 100%
rename from src/test/ui/structs-enums/struct-return.rs
rename to src/test/ui/abi/struct-enums/struct-return.rs
diff --git a/src/test/ui/union/union-c-interop.rs b/src/test/ui/abi/union/union-c-interop.rs
similarity index 100%
rename from src/test/ui/union/union-c-interop.rs
rename to src/test/ui/abi/union/union-c-interop.rs
diff --git a/src/test/ui/variadic-ffi.rs b/src/test/ui/abi/variadic-ffi.rs
similarity index 100%
rename from src/test/ui/variadic-ffi.rs
rename to src/test/ui/abi/variadic-ffi.rs
diff --git a/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs b/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs
new file mode 100644
index 0000000..1cbc513
--- /dev/null
+++ b/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs
@@ -0,0 +1,17 @@
+// Check that `async fn` inside of an impl with `'_`
+// in the header compiles correctly.
+//
+// Regression test for #63500.
+//
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+struct Foo<'a>(&'a u8);
+
+impl Foo<'_> {
+    async fn bar() {}
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issue-61949-self-return-type.rs b/src/test/ui/async-await/issue-61949-self-return-type.rs
new file mode 100644
index 0000000..c5a66d5
--- /dev/null
+++ b/src/test/ui/async-await/issue-61949-self-return-type.rs
@@ -0,0 +1,28 @@
+// ignore-tidy-linelength
+// edition:2018
+#![feature(async_await)]
+
+// This test checks that `Self` is prohibited as a return type. See #61949 for context.
+
+pub struct Foo<'a> {
+    pub bar: &'a i32,
+}
+
+impl<'a> Foo<'a> {
+    pub async fn new(_bar: &'a i32) -> Self {
+    //~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+        Foo {
+            bar: &22
+        }
+    }
+}
+
+async fn foo() {
+    let x = {
+        let bar = 22;
+        Foo::new(&bar).await
+    };
+    drop(x);
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issue-61949-self-return-type.stderr b/src/test/ui/async-await/issue-61949-self-return-type.stderr
new file mode 100644
index 0000000..a9ae544
--- /dev/null
+++ b/src/test/ui/async-await/issue-61949-self-return-type.stderr
@@ -0,0 +1,8 @@
+error: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+  --> $DIR/issue-61949-self-return-type.rs:12:40
+   |
+LL |     pub async fn new(_bar: &'a i32) -> Self {
+   |                                        ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
new file mode 100644
index 0000000..64fd1a4
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
@@ -0,0 +1,24 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/issue-63388-1.rs:14:10
+   |
+LL |     ) -> &dyn Foo
+   |          ^^^^^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#22r
+
+error: lifetime may not live long enough
+  --> $DIR/issue-63388-1.rs:15:5
+   |
+LL |       async fn do_sth<'a>(
+   |                       -- lifetime `'a` defined here
+LL |           &'a self, foo: &dyn Foo
+   |                          - lifetime `'_` defined here
+LL |       ) -> &dyn Foo
+LL | /     {
+LL | |         foo
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'_`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/async-await/issues/issue-63388-1.rs b/src/test/ui/async-await/issues/issue-63388-1.rs
new file mode 100644
index 0000000..80003b0
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-1.rs
@@ -0,0 +1,20 @@
+// edition:2018
+
+#![feature(async_await)]
+
+struct Xyz {
+    a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+    async fn do_sth<'a>(
+        &'a self, foo: &dyn Foo
+    ) -> &dyn Foo //~ ERROR lifetime mismatch
+    {
+        foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-63388-1.stderr b/src/test/ui/async-await/issues/issue-63388-1.stderr
new file mode 100644
index 0000000..5302adc
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-1.stderr
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-63388-1.rs:14:10
+   |
+LL |         &'a self, foo: &dyn Foo
+   |         -------- this parameter and the return type are declared with different lifetimes...
+LL |     ) -> &dyn Foo
+   |          ^^^^^^^^
+   |          |
+   |          ...but data from `foo` is returned here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr
new file mode 100644
index 0000000..b91cdc1
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-63388-2.rs:14:10
+   |
+LL |     ) -> &dyn Foo
+   |          ^ help: consider using the named lifetime: `&'a`
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/async-await/issues/issue-63388-2.rs b/src/test/ui/async-await/issues/issue-63388-2.rs
new file mode 100644
index 0000000..ca9bbef
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-2.rs
@@ -0,0 +1,20 @@
+// edition:2018
+
+#![feature(async_await)]
+
+struct Xyz {
+    a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+    async fn do_sth<'a>(
+        foo: &dyn Foo, bar: &'a dyn Foo //~ ERROR cannot infer
+    ) -> &dyn Foo //~ ERROR missing lifetime specifier
+    {
+        foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr
new file mode 100644
index 0000000..1810138
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-2.stderr
@@ -0,0 +1,29 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-63388-2.rs:14:10
+   |
+LL |     ) -> &dyn Foo
+   |          ^ help: consider using the named lifetime: `&'a`
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar`
+
+error: cannot infer an appropriate lifetime
+  --> $DIR/issue-63388-2.rs:13:9
+   |
+LL |         foo: &dyn Foo, bar: &'a dyn Foo
+   |         ^^^ ...but this borrow...
+LL |     ) -> &dyn Foo
+   |          -------- this return type evaluates to the `'static` lifetime...
+   |
+note: ...can't outlive the lifetime '_ as defined on the method body at 13:14
+  --> $DIR/issue-63388-2.rs:13:14
+   |
+LL |         foo: &dyn Foo, bar: &'a dyn Foo
+   |              ^
+help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 13:14
+   |
+LL |     ) -> &dyn Foo + '_
+   |          ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/async-await/issues/issue-63388-3.rs b/src/test/ui/async-await/issues/issue-63388-3.rs
new file mode 100644
index 0000000..05f23f9
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-3.rs
@@ -0,0 +1,19 @@
+// edition:2018
+// check-pass
+
+#![feature(async_await)]
+
+struct Xyz {
+    a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+    async fn do_sth(
+        &self, foo: &dyn Foo
+    ) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-63388-4.rs b/src/test/ui/async-await/issues/issue-63388-4.rs
new file mode 100644
index 0000000..0939242
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-63388-4.rs
@@ -0,0 +1,12 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+struct A;
+
+impl A {
+    async fn foo(&self, f: &u32) -> &A { self }
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.rs b/src/test/ui/async-await/issues/non-async-enclosing-span.rs
new file mode 100644
index 0000000..838911d
--- /dev/null
+++ b/src/test/ui/async-await/issues/non-async-enclosing-span.rs
@@ -0,0 +1,12 @@
+// edition:2018
+#![feature(async_await)]
+
+async fn do_the_thing() -> u8 {
+    8
+}
+// #63398: point at the enclosing scope and not the previously seen closure
+fn main() {  //~ NOTE this is not `async`
+    let x = move || {};
+    let y = do_the_thing().await; //~ ERROR `await` is only allowed inside `async` functions
+    //~^ NOTE only allowed inside `async` functions and blocks
+}
diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr
new file mode 100644
index 0000000..f492c1a
--- /dev/null
+++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr
@@ -0,0 +1,11 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+  --> $DIR/non-async-enclosing-span.rs:10:13
+   |
+LL | fn main() {
+   |    ---- this is not `async`
+LL |     let x = move || {};
+LL |     let y = do_the_thing().await;
+   |             ^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/nested-in-impl.rs b/src/test/ui/async-await/nested-in-impl.rs
new file mode 100644
index 0000000..3c82160
--- /dev/null
+++ b/src/test/ui/async-await/nested-in-impl.rs
@@ -0,0 +1,17 @@
+// Test that async fn works when nested inside of
+// impls with lifetime parameters.
+//
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+struct Foo<'a>(&'a ());
+
+impl<'a> Foo<'a> {
+    fn test() {
+        async fn test() {}
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.rs b/src/test/ui/async-await/suggest-switching-edition-on-await.rs
new file mode 100644
index 0000000..1402f1c
--- /dev/null
+++ b/src/test/ui/async-await/suggest-switching-edition-on-await.rs
@@ -0,0 +1,45 @@
+use std::pin::Pin;
+use std::future::Future;
+
+fn main() {}
+
+fn await_on_struct_missing() {
+    struct S;
+    let x = S;
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE unknown field
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_struct_similar() {
+    struct S {
+        awai: u8,
+    }
+    let x = S { awai: 42 };
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| HELP a field with a similar name exists
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE unknown field
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_apit(x: impl Future<Output = ()>) {
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.stderr b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr
new file mode 100644
index 0000000..f623511
--- /dev/null
+++ b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr
@@ -0,0 +1,43 @@
+error[E0609]: no field `await` on type `await_on_struct_missing::S`
+  --> $DIR/suggest-switching-edition-on-await.rs:9:7
+   |
+LL |     x.await;
+   |       ^^^^^ unknown field
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `await_on_struct_similar::S`
+  --> $DIR/suggest-switching-edition-on-await.rs:22:7
+   |
+LL |     x.await;
+   |       ^^^^^ help: a field with a similar name exists: `awai`
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `std::pin::Pin<&mut dyn std::future::Future<Output = ()>>`
+  --> $DIR/suggest-switching-edition-on-await.rs:31:7
+   |
+LL |     x.await;
+   |       ^^^^^ unknown field
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `impl Future<Output = ()>`
+  --> $DIR/suggest-switching-edition-on-await.rs:40:7
+   |
+LL |     x.await;
+   |       ^^^^^
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/block-expr-precedence.stderr b/src/test/ui/block-expr-precedence.stderr
new file mode 100644
index 0000000..1307b5d
--- /dev/null
+++ b/src/test/ui/block-expr-precedence.stderr
@@ -0,0 +1,8 @@
+warning: unnecessary trailing semicolons
+  --> $DIR/block-expr-precedence.rs:60:21
+   |
+LL |   if (true) { 12; };;; -num;
+   |                     ^^ help: remove these semicolons
+   |
+   = note: `#[warn(redundant_semicolon)]` on by default
+
diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs
new file mode 100644
index 0000000..e3b642a
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs
@@ -0,0 +1,6 @@
+extern {
+    fn foo(...);
+    //~^ ERROR C-variadic function must be declared with at least one named argument
+}
+
+fn main() {}
diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
new file mode 100644
index 0000000..cb60605
--- /dev/null
+++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
@@ -0,0 +1,8 @@
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-no-fixed-args.rs:2:11
+   |
+LL |     fn foo(...);
+   |           ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/auxiliary/issue-63226.rs b/src/test/ui/consts/auxiliary/issue-63226.rs
new file mode 100644
index 0000000..39cc01a
--- /dev/null
+++ b/src/test/ui/consts/auxiliary/issue-63226.rs
@@ -0,0 +1,14 @@
+pub struct VTable{
+    state:extern fn(),
+}
+
+impl VTable{
+    pub const fn vtable()->&'static VTable{
+        Self::VTABLE
+    }
+
+    const VTABLE: &'static VTable =
+        &VTable{state};
+}
+
+extern fn state() {}
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
index bcbb435..431ff35 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.rs
+++ b/src/test/ui/consts/const-eval/ub-nonnull.rs
@@ -11,10 +11,11 @@
 const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
 //~^ ERROR it is undefined behavior to use this value
 
+#[deny(const_err)] // this triggers a `const_err` so validation does not even happen
 const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-//~^ ERROR it is undefined behavior to use this value
-    let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-    let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic
+    let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
+    // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
+    let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error
     mem::transmute(out_of_bounds_ptr)
 } };
 
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
index 2f9423f..7b3c97e 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -6,21 +6,26 @@
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:14:1
+error: any use of this value will cause an error
+  --> $DIR/ub-nonnull.rs:18:29
    |
 LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-LL | |
-LL | |     let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-LL | |     let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic
+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
 LL | |     mem::transmute(out_of_bounds_ptr)
 LL | | } };
-   | |____^ type validation failed: encountered a potentially NULL pointer, but expected something that cannot possibly fail to be greater or equal to 1
+   | |____-
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+note: lint level defined here
+  --> $DIR/ub-nonnull.rs:14:8
+   |
+LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
+   |        ^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:21:1
+  --> $DIR/ub-nonnull.rs:22:1
    |
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -28,7 +33,7 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:23:1
+  --> $DIR/ub-nonnull.rs:24:1
    |
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -36,7 +41,7 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:30:1
+  --> $DIR/ub-nonnull.rs:31:1
    |
 LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1
@@ -44,7 +49,7 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:38:1
+  --> $DIR/ub-nonnull.rs:39:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
@@ -52,7 +57,7 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:44:1
+  --> $DIR/ub-nonnull.rs:45:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
diff --git a/src/test/ui/consts/issue-63226.rs b/src/test/ui/consts/issue-63226.rs
new file mode 100644
index 0000000..deec449
--- /dev/null
+++ b/src/test/ui/consts/issue-63226.rs
@@ -0,0 +1,12 @@
+// aux-build:issue-63226.rs
+// compile-flags:--extern issue_63226
+// edition:2018
+// build-pass
+// A regression test for issue #63226.
+// Checks if `const fn` is marked as reachable.
+
+use issue_63226::VTable;
+
+static ICE_ICE:&'static VTable=VTable::vtable();
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
index f1c93d5..f5edbe2 100644
--- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
@@ -28,7 +28,10 @@
 LL |     if not  // lack of braces is [sic]
    |     -- this `if` statement has a condition, but no block
 LL |         println!("Then when?");
-   |                               ^ expected `{`
+   |                               ^
+   |                               |
+   |                               expected `{`
+   |                               help: try placing this code inside a block: `{ ; }`
 
 error: unexpected `2` after identifier
   --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr
index 1e77920..dc3fbed 100644
--- a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr
+++ b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr
@@ -2,7 +2,7 @@
   --> $DIR/dropck_trait_cycle_checked.rs:111:13
    |
 LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                               -------- cast requires that `o2` is borrowed for `'static`
+   |                                                                     -------- cast requires that `o2` is borrowed for `'static`
 LL |     o1.set0(&o2);
    |             ^^^ borrowed value does not live long enough
 ...
@@ -13,7 +13,7 @@
   --> $DIR/dropck_trait_cycle_checked.rs:112:13
    |
 LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                                         -------- cast requires that `o3` is borrowed for `'static`
+   |                                                                     -------- cast requires that `o3` is borrowed for `'static`
 LL |     o1.set0(&o2);
 LL |     o1.set1(&o3);
    |             ^^^ borrowed value does not live long enough
@@ -37,7 +37,7 @@
   --> $DIR/dropck_trait_cycle_checked.rs:114:13
    |
 LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                                         -------- cast requires that `o3` is borrowed for `'static`
+   |                                                                               -------- cast requires that `o3` is borrowed for `'static`
 ...
 LL |     o2.set1(&o3);
    |             ^^^ borrowed value does not live long enough
@@ -49,7 +49,7 @@
   --> $DIR/dropck_trait_cycle_checked.rs:115:13
    |
 LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                     -------- cast requires that `o1` is borrowed for `'static`
+   |                                                                                         -------- cast requires that `o1` is borrowed for `'static`
 ...
 LL |     o3.set0(&o1);
    |             ^^^ borrowed value does not live long enough
@@ -61,7 +61,7 @@
   --> $DIR/dropck_trait_cycle_checked.rs:116:13
    |
 LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                               -------- cast requires that `o2` is borrowed for `'static`
+   |                                                                                         -------- cast requires that `o2` is borrowed for `'static`
 ...
 LL |     o3.set1(&o2);
    |             ^^^ borrowed value does not live long enough
diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr
index 3a5040e..0f610a5 100644
--- a/src/test/ui/error-codes/E0282.stderr
+++ b/src/test/ui/error-codes/E0282.stderr
@@ -2,10 +2,7 @@
   --> $DIR/E0282.rs:2:9
    |
 LL |     let x = "hello".chars().rev().collect();
-   |         ^
-   |         |
-   |         cannot infer type
-   |         consider giving `x` a type
+   |         ^ consider giving `x` a type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs
index cee930f..382d891 100644
--- a/src/test/ui/feature-gates/feature-gate-generators.rs
+++ b/src/test/ui/feature-gates/feature-gate-generators.rs
@@ -2,3 +2,9 @@
     yield true; //~ ERROR yield syntax is experimental
                 //~^ ERROR yield statement outside of generator literal
 }
+
+#[cfg(FALSE)]
+fn foo() {
+    yield; //~ ERROR yield syntax is experimental
+    yield 0; //~ ERROR yield syntax is experimental
+}
diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr
index cdb0560..24b814b 100644
--- a/src/test/ui/feature-gates/feature-gate-generators.stderr
+++ b/src/test/ui/feature-gates/feature-gate-generators.stderr
@@ -7,12 +7,30 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/43122
    = help: add `#![feature(generators)]` to the crate attributes to enable
 
+error[E0658]: yield syntax is experimental
+  --> $DIR/feature-gate-generators.rs:8:5
+   |
+LL |     yield;
+   |     ^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43122
+   = help: add `#![feature(generators)]` to the crate attributes to enable
+
+error[E0658]: yield syntax is experimental
+  --> $DIR/feature-gate-generators.rs:9:5
+   |
+LL |     yield 0;
+   |     ^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43122
+   = help: add `#![feature(generators)]` to the crate attributes to enable
+
 error[E0627]: yield statement outside of generator literal
   --> $DIR/feature-gate-generators.rs:2:5
    |
 LL |     yield true;
    |     ^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr
index 478bc09..676b8b9 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr
@@ -4,17 +4,17 @@
 LL | __build_diagnostic_array!(DIAGNOSTICS);
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: cannot find macro `__register_diagnostic!` in this scope
-  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1
-   |
-LL | __register_diagnostic!(E0001);
-   | ^^^^^^^^^^^^^^^^^^^^^
-
 error: cannot find macro `__diagnostic_used!` in this scope
   --> $DIR/feature-gate-rustc-diagnostic-macros.rs:8:5
    |
 LL |     __diagnostic_used!(E0001);
    |     ^^^^^^^^^^^^^^^^^
 
+error: cannot find macro `__register_diagnostic!` in this scope
+  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1
+   |
+LL | __register_diagnostic!(E0001);
+   | ^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.stderr b/src/test/ui/for/for-loop-unconstrained-element-type.stderr
index 02fdb80..0672014 100644
--- a/src/test/ui/for/for-loop-unconstrained-element-type.stderr
+++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr
@@ -2,10 +2,7 @@
   --> $DIR/for-loop-unconstrained-element-type.rs:8:14
    |
 LL |     for i in Vec::new() { }
-   |              ^^^^^^^^^^
-   |              |
-   |              cannot infer type
-   |              the element type for this iterator is not specified
+   |              ^^^^^^^^^^ the element type for this iterator is not specified
 
 error: aborting due to previous error
 
diff --git a/src/test/run-pass/generator/niche-in-generator.rs b/src/test/ui/generator/niche-in-generator.rs
similarity index 95%
rename from src/test/run-pass/generator/niche-in-generator.rs
rename to src/test/ui/generator/niche-in-generator.rs
index 9a644ed..42bee81 100644
--- a/src/test/run-pass/generator/niche-in-generator.rs
+++ b/src/test/ui/generator/niche-in-generator.rs
@@ -1,5 +1,7 @@
 // Test that niche finding works with captured generator upvars.
 
+// run-pass
+
 #![feature(generators)]
 
 use std::mem::size_of_val;
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index a89176f..643f803 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -1,3 +1,11 @@
+error: cannot find macro `panic!` in this scope
+  --> $DIR/no_implicit_prelude.rs:16:9
+   |
+LL |         assert_eq!(0, 0);
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = 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[E0433]: failed to resolve: use of undeclared type or module `Vec`
   --> $DIR/no_implicit_prelude.rs:11:9
    |
@@ -7,14 +15,6 @@
 LL |         Vec::new();
    |         ^^^ use of undeclared type or module `Vec`
 
-error: cannot find macro `panic!` in this scope
-  --> $DIR/no_implicit_prelude.rs:16:9
-   |
-LL |         assert_eq!(0, 0);
-   |         ^^^^^^^^^^^^^^^^^
-   |
-   = 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[E0599]: no method named `clone` found for type `()` in the current scope
   --> $DIR/no_implicit_prelude.rs:12:12
    |
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs
index c33261b..9ba7c91 100644
--- a/src/test/ui/impl-trait/bound-normalization-fail.rs
+++ b/src/test/ui/impl-trait/bound-normalization-fail.rs
@@ -1,4 +1,5 @@
 // compile-fail
+// ignore-tidy-linelength
 // edition:2018
 
 #![feature(async_await)]
@@ -44,7 +45,8 @@
 
     /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
-        //~^ ERROR: type mismatch
+    //~^ ERROR: type mismatch
+    //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
         Foo(())
     }
 }
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr
index aa306a7..b5c8e07 100644
--- a/src/test/ui/impl-trait/bound-normalization-fail.stderr
+++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr
@@ -1,5 +1,5 @@
 warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
-  --> $DIR/bound-normalization-fail.rs:5:12
+  --> $DIR/bound-normalization-fail.rs:6:12
    |
 LL | #![feature(impl_trait_in_bindings)]
    |            ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:29:32
+  --> $DIR/bound-normalization-fail.rs:30:32
    |
 LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type
@@ -16,8 +16,14 @@
               found type `<T as impl_trait::Trait>::Assoc`
    = note: the return type of a function must have a statically known size
 
+error: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+  --> $DIR/bound-normalization-fail.rs:47:41
+   |
+LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:46:41
+  --> $DIR/bound-normalization-fail.rs:47:41
    |
 LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type
@@ -26,6 +32,6 @@
               found type `<T as lifetimes::Trait<'static>>::Assoc`
    = note: the return type of a function must have a statically known size
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
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 5afdd88..7d01382 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -21,25 +21,6 @@
    |     ^^^^^^^^^
    = help: consider adding an explicit import of `exported` to disambiguate
 
-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
-   |
-LL | include!();
-   | ^^^^^^^ ambiguous name
-   |
-   = note: `include` could refer to a macro from prelude
-note: `include` could also refer to the macro defined here
-  --> $DIR/local-modularized-tricky-fail-1.rs:17:5
-   |
-LL | /     macro_rules! include {
-LL | |         () => ()
-LL | |     }
-   | |_____^
-...
-LL |       define_include!();
-   |       ------------------ in this macro invocation
-   = help: use `crate::include` to refer to this macro unambiguously
-
 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
    |
@@ -59,6 +40,25 @@
    |       ---------------- in this macro invocation
    = 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
+   |
+LL | include!();
+   | ^^^^^^^ ambiguous name
+   |
+   = note: `include` could refer to a macro from prelude
+note: `include` could also refer to the macro defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:17:5
+   |
+LL | /     macro_rules! include {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_include!();
+   |       ------------------ in this macro invocation
+   = help: use `crate::include` to refer to this macro unambiguously
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr
index c84226e..2f2ab20 100644
--- a/src/test/ui/imports/shadow_builtin_macros.stderr
+++ b/src/test/ui/imports/shadow_builtin_macros.stderr
@@ -14,20 +14,6 @@
    = help: or use `self::panic` to refer to this macro unambiguously
 
 error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/shadow_builtin_macros.rs:20:14
-   |
-LL |     fn f() { panic!(); }
-   |              ^^^^^ ambiguous name
-   |
-   = note: `panic` could refer to a macro from prelude
-note: `panic` could also refer to the macro imported here
-  --> $DIR/shadow_builtin_macros.rs:19:26
-   |
-LL |     ::two_macros::m!(use foo::panic;);
-   |                          ^^^^^^^^^^
-   = help: use `self::panic` to refer to this macro unambiguously
-
-error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
   --> $DIR/shadow_builtin_macros.rs:33:5
    |
 LL |     panic!();
@@ -62,6 +48,20 @@
 LL | #[macro_use(n)]
    |             ^
 
+error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/shadow_builtin_macros.rs:20:14
+   |
+LL |     fn f() { panic!(); }
+   |              ^^^^^ ambiguous name
+   |
+   = note: `panic` could refer to a macro from prelude
+note: `panic` could also refer to the macro imported here
+  --> $DIR/shadow_builtin_macros.rs:19:26
+   |
+LL |     ::two_macros::m!(use foo::panic;);
+   |                          ^^^^^^^^^^
+   = help: use `self::panic` to refer to this macro unambiguously
+
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/in-band-lifetimes/nested-items.rs b/src/test/ui/in-band-lifetimes/nested-items.rs
new file mode 100644
index 0000000..7de2071
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/nested-items.rs
@@ -0,0 +1,20 @@
+// Test that the `'a` from the impl doesn't
+// prevent us from creating a `'a` parameter
+// on the `blah` function.
+//
+// check-pass
+
+#![feature(in_band_lifetimes)]
+
+struct Foo<'a> {
+    x: &'a u32
+
+}
+
+impl Foo<'a> {
+    fn method(&self) {
+        fn blah(f: Foo<'a>) { }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/include-macros/data.bin b/src/test/ui/include-macros/data.bin
new file mode 100644
index 0000000..ce4e0b8
--- /dev/null
+++ b/src/test/ui/include-macros/data.bin
@@ -0,0 +1,2 @@
+This file starts with BOM.

+Lines are separated by \r\n.

diff --git a/src/test/ui/include-macros/normalization.rs b/src/test/ui/include-macros/normalization.rs
new file mode 100644
index 0000000..889f08e
--- /dev/null
+++ b/src/test/ui/include-macros/normalization.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+fn main() {
+    assert_eq!(
+        &include_bytes!("data.bin")[..],
+        &b"\xEF\xBB\xBFThis file starts with BOM.\r\nLines are separated by \\r\\n.\r\n"[..],
+    );
+    assert_eq!(
+        include_str!("data.bin"),
+        "\u{FEFF}This file starts with BOM.\r\nLines are separated by \\r\\n.\r\n",
+    );
+}
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
new file mode 100644
index 0000000..30ed505
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
@@ -0,0 +1,18 @@
+// edition:2018
+#![feature(async_await)]
+#![feature(impl_trait_in_bindings)]
+//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
+
+use std::io::Error;
+
+fn make_unit() -> Result<(), Error> {
+    Ok(())
+}
+
+fn main() {
+    let fut = async {
+        make_unit()?; //~ ERROR type annotations needed
+
+        Ok(())
+    };
+}
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
new file mode 100644
index 0000000..67a834a
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
@@ -0,0 +1,19 @@
+warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
+  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:3:12
+   |
+LL | #![feature(impl_trait_in_bindings)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0282]: type annotations needed for `impl std::future::Future`
+  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:14:9
+   |
+LL |     let fut = async {
+   |         --- consider giving `fut` the explicit type `impl std::future::Future`, with the type parameters specified
+LL |         make_unit()?;
+   |         ^^^^^^^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs
new file mode 100644
index 0000000..edc6427
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async.rs
@@ -0,0 +1,16 @@
+// edition:2018
+#![feature(async_await)]
+
+use std::io::Error;
+
+fn make_unit() -> Result<(), Error> {
+    Ok(())
+}
+
+fn main() {
+    let fut = async {
+        make_unit()?; //~ ERROR type annotations needed
+
+        Ok(())
+    };
+}
diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr
new file mode 100644
index 0000000..36608a1
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-async.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-async.rs:12:9
+   |
+LL |     let fut = async {
+   |         --- consider giving `fut` a type
+LL |         make_unit()?;
+   |         ^^^^^^^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs
new file mode 100644
index 0000000..8f48483
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-closure.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let x = |a: (), b: ()| {
+        Err(a)?; //~ ERROR type annotations needed for the closure
+        Ok(b)
+    };
+}
diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr
new file mode 100644
index 0000000..5f30b5d
--- /dev/null
+++ b/src/test/ui/inference/cannot-infer-closure.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>`
+  --> $DIR/cannot-infer-closure.rs:3:9
+   |
+LL |         Err(a)?;
+   |         ^^^^^^^ cannot infer type
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |     let x = |a: (), b: ()| -> std::result::Result<(), _> {
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr
index 739f061..df9f1dd 100644
--- a/src/test/ui/issues/issue-13483.stderr
+++ b/src/test/ui/issues/issue-13483.stderr
@@ -1,10 +1,10 @@
-error: missing condition for `if` statemement
+error: missing condition for `if` expression
   --> $DIR/issue-13483.rs:3:14
    |
 LL |     } else if {
    |              ^ expected if condition here
 
-error: missing condition for `if` statemement
+error: missing condition for `if` expression
   --> $DIR/issue-13483.rs:10:14
    |
 LL |     } else if {
diff --git a/src/test/ui/issues/issue-18159.stderr b/src/test/ui/issues/issue-18159.stderr
index 6048344..9b890be 100644
--- a/src/test/ui/issues/issue-18159.stderr
+++ b/src/test/ui/issues/issue-18159.stderr
@@ -2,10 +2,7 @@
   --> $DIR/issue-18159.rs:2:9
    |
 LL |     let x;
-   |         ^
-   |         |
-   |         cannot infer type
-   |         consider giving `x` a type
+   |         ^ consider giving `x` a type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr
index c557255..e0d3bb3 100644
--- a/src/test/ui/issues/issue-49074.stderr
+++ b/src/test/ui/issues/issue-49074.stderr
@@ -1,9 +1,3 @@
-error: cannot find attribute macro `marco_use` in this scope
-  --> $DIR/issue-49074.rs:3:3
-   |
-LL | #[marco_use] // typo
-   |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
-
 error: cannot find macro `bar!` in this scope
   --> $DIR/issue-49074.rs:12:4
    |
@@ -12,5 +6,11 @@
    |
    = help: have you added the `#[macro_use]` on the module/import?
 
+error: cannot find attribute macro `marco_use` in this scope
+  --> $DIR/issue-49074.rs:3:3
+   |
+LL | #[marco_use] // typo
+   |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
+
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-50301.rs b/src/test/ui/issues/issue-50301.rs
new file mode 100644
index 0000000..47ee3e7
--- /dev/null
+++ b/src/test/ui/issues/issue-50301.rs
@@ -0,0 +1,31 @@
+// Tests that HRTBs are correctly accepted -- https://github.com/rust-lang/rust/issues/50301
+// check-pass
+trait Trait
+where
+    for<'a> &'a Self::IntoIter: IntoIterator<Item = u32>,
+{
+    type IntoIter;
+    fn get(&self) -> Self::IntoIter;
+}
+
+struct Impl(Vec<u32>);
+
+impl Trait for Impl {
+    type IntoIter = ImplIntoIter;
+    fn get(&self) -> Self::IntoIter {
+        ImplIntoIter(self.0.clone())
+    }
+}
+
+struct ImplIntoIter(Vec<u32>);
+
+impl<'a> IntoIterator for &'a ImplIntoIter {
+    type Item = <Self::IntoIter as Iterator>::Item;
+    type IntoIter = std::iter::Cloned<std::slice::Iter<'a, u32>>;
+    fn into_iter(self) -> Self::IntoIter {
+        (&self.0).into_iter().cloned()
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs
new file mode 100644
index 0000000..d661203
--- /dev/null
+++ b/src/test/ui/iterators/iter-count-overflow-debug.rs
@@ -0,0 +1,16 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// ignore-wasm32-bare compiled with panic=abort by default
+// compile-flags: -C debug_assertions=yes -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    assert_eq!((0..MAX).by_ref().count(), MAX);
+
+    let r = panic::catch_unwind(|| {
+        (0..=MAX).by_ref().count()
+    });
+    assert!(r.is_err());
+}
diff --git a/src/test/ui/iterators/iter-count-overflow-ndebug.rs b/src/test/ui/iterators/iter-count-overflow-ndebug.rs
new file mode 100644
index 0000000..b755bb5
--- /dev/null
+++ b/src/test/ui/iterators/iter-count-overflow-ndebug.rs
@@ -0,0 +1,11 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// compile-flags: -C debug_assertions=no -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    assert_eq!((0..MAX).by_ref().count(), MAX);
+    assert_eq!((0..=MAX).by_ref().count(), 0);
+}
diff --git a/src/test/ui/iterators/iter-map-fold-type-length.rs b/src/test/ui/iterators/iter-map-fold-type-length.rs
new file mode 100644
index 0000000..8ce4fcd
--- /dev/null
+++ b/src/test/ui/iterators/iter-map-fold-type-length.rs
@@ -0,0 +1,38 @@
+// run-pass
+//! Check that type lengths don't explode with `Map` folds.
+//!
+//! The normal limit is a million, and this test used to exceed 1.5 million, but
+//! now we can survive an even tighter limit. Still seems excessive though...
+#![type_length_limit = "256000"]
+
+// Custom wrapper so Iterator methods aren't specialized.
+struct Iter<I>(I);
+
+impl<I> Iterator for Iter<I>
+where
+    I: Iterator
+{
+    type Item = I::Item;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    let c = Iter(0i32..10)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .count();
+    assert_eq!(c, 10);
+}
diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs
new file mode 100644
index 0000000..f1eded3
--- /dev/null
+++ b/src/test/ui/iterators/iter-position-overflow-debug.rs
@@ -0,0 +1,22 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// ignore-wasm32-bare compiled with panic=abort by default
+// compile-flags: -C debug_assertions=yes -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    let n = MAX as u64;
+    assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX));
+
+    let r = panic::catch_unwind(|| {
+        (0..).by_ref().position(|i| i > n)
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        (0..=n + 1).by_ref().position(|_| false)
+    });
+    assert!(r.is_err());
+}
diff --git a/src/test/ui/iterators/iter-position-overflow-ndebug.rs b/src/test/ui/iterators/iter-position-overflow-ndebug.rs
new file mode 100644
index 0000000..368f9c0
--- /dev/null
+++ b/src/test/ui/iterators/iter-position-overflow-ndebug.rs
@@ -0,0 +1,13 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// compile-flags: -C debug_assertions=no -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    let n = MAX as u64;
+    assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX));
+    assert_eq!((0..).by_ref().position(|i| i > n), Some(0));
+    assert_eq!((0..=n + 1).by_ref().position(|_| false), None);
+}
diff --git a/src/test/ui/lint/lint-qualification.rs b/src/test/ui/lint/lint-qualification.rs
index 1b24191..0cace0c 100644
--- a/src/test/ui/lint/lint-qualification.rs
+++ b/src/test/ui/lint/lint-qualification.rs
@@ -1,5 +1,5 @@
 #![deny(unused_qualifications)]
-#[allow(deprecated)]
+#![allow(deprecated)]
 
 mod foo {
     pub fn bar() {}
diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs
index 8f9ca87..d816479 100644
--- a/src/test/ui/lint/uninitialized-zeroed.rs
+++ b/src/test/ui/lint/uninitialized-zeroed.rs
@@ -11,8 +11,10 @@
 enum Void {}
 
 struct Ref(&'static i32);
+struct RefPair((&'static i32, i32));
 
 struct Wrap<T> { wrapped: T }
+enum WrapEnum<T> { Wrapped(T) }
 
 #[allow(unused)]
 fn generic<T: 'static>() {
@@ -48,6 +50,12 @@
         let _val: Wrap<fn()> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
         let _val: Wrap<fn()> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
 
+        let _val: WrapEnum<fn()> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
+        let _val: WrapEnum<fn()> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
+        let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
+        let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
         // Some types that should work just fine.
         let _val: Option<&'static i32> = mem::zeroed();
         let _val: Option<fn()> = mem::zeroed();
diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr
index af54b16..1b15fc2 100644
--- a/src/test/ui/lint/uninitialized-zeroed.stderr
+++ b/src/test/ui/lint/uninitialized-zeroed.stderr
@@ -1,169 +1,289 @@
 error: the type `&'static T` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:20:32
+  --> $DIR/uninitialized-zeroed.rs:22:32
    |
 LL |         let _val: &'static T = mem::zeroed();
    |                                ^^^^^^^^^^^^^
+   |                                |
+   |                                this code causes undefined behavior when executed
+   |                                help: use `MaybeUninit<T>` instead
    |
 note: lint level defined here
   --> $DIR/uninitialized-zeroed.rs:7:9
    |
 LL | #![deny(invalid_value)]
    |         ^^^^^^^^^^^^^
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: References must be non-null
 
 error: the type `&'static T` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:21:32
+  --> $DIR/uninitialized-zeroed.rs:23:32
    |
 LL |         let _val: &'static T = mem::uninitialized();
    |                                ^^^^^^^^^^^^^^^^^^^^
+   |                                |
+   |                                this code causes undefined behavior when executed
+   |                                help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: References must be non-null
 
 error: the type `Wrap<&'static T>` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:23:38
+  --> $DIR/uninitialized-zeroed.rs:25:38
    |
 LL |         let _val: Wrap<&'static T> = mem::zeroed();
    |                                      ^^^^^^^^^^^^^
+   |                                      |
+   |                                      this code causes undefined behavior when executed
+   |                                      help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+note: References must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:16:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
 
 error: the type `Wrap<&'static T>` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:24:38
+  --> $DIR/uninitialized-zeroed.rs:26:38
    |
 LL |         let _val: Wrap<&'static T> = mem::uninitialized();
    |                                      ^^^^^^^^^^^^^^^^^^^^
+   |                                      |
+   |                                      this code causes undefined behavior when executed
+   |                                      help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+note: References must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:16:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
 
 error: the type `!` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:30:23
+  --> $DIR/uninitialized-zeroed.rs:32:23
    |
 LL |         let _val: ! = mem::zeroed();
    |                       ^^^^^^^^^^^^^
+   |                       |
+   |                       this code causes undefined behavior when executed
+   |                       help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: The never type (`!`) has no valid value
 
 error: the type `!` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:31:23
+  --> $DIR/uninitialized-zeroed.rs:33:23
    |
 LL |         let _val: ! = mem::uninitialized();
    |                       ^^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       this code causes undefined behavior when executed
+   |                       help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: The never type (`!`) has no valid value
 
 error: the type `(i32, !)` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:33:30
+  --> $DIR/uninitialized-zeroed.rs:35:30
    |
 LL |         let _val: (i32, !) = mem::zeroed();
    |                              ^^^^^^^^^^^^^
+   |                              |
+   |                              this code causes undefined behavior when executed
+   |                              help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: The never type (`!`) has no valid value
 
 error: the type `(i32, !)` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:34:30
+  --> $DIR/uninitialized-zeroed.rs:36:30
    |
 LL |         let _val: (i32, !) = mem::uninitialized();
    |                              ^^^^^^^^^^^^^^^^^^^^
+   |                              |
+   |                              this code causes undefined behavior when executed
+   |                              help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: The never type (`!`) has no valid value
 
 error: the type `Void` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:36:26
+  --> $DIR/uninitialized-zeroed.rs:38:26
    |
 LL |         let _val: Void = mem::zeroed();
    |                          ^^^^^^^^^^^^^
+   |                          |
+   |                          this code causes undefined behavior when executed
+   |                          help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: 0-variant enums have no valid value
 
 error: the type `Void` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:37:26
+  --> $DIR/uninitialized-zeroed.rs:39:26
    |
 LL |         let _val: Void = mem::uninitialized();
    |                          ^^^^^^^^^^^^^^^^^^^^
+   |                          |
+   |                          this code causes undefined behavior when executed
+   |                          help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: 0-variant enums have no valid value
 
 error: the type `&'static i32` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:39:34
+  --> $DIR/uninitialized-zeroed.rs:41:34
    |
 LL |         let _val: &'static i32 = mem::zeroed();
    |                                  ^^^^^^^^^^^^^
+   |                                  |
+   |                                  this code causes undefined behavior when executed
+   |                                  help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: References must be non-null
 
 error: the type `&'static i32` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:40:34
+  --> $DIR/uninitialized-zeroed.rs:42:34
    |
 LL |         let _val: &'static i32 = mem::uninitialized();
    |                                  ^^^^^^^^^^^^^^^^^^^^
+   |                                  |
+   |                                  this code causes undefined behavior when executed
+   |                                  help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: References must be non-null
 
 error: the type `Ref` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:42:25
+  --> $DIR/uninitialized-zeroed.rs:44:25
    |
 LL |         let _val: Ref = mem::zeroed();
    |                         ^^^^^^^^^^^^^
+   |                         |
+   |                         this code causes undefined behavior when executed
+   |                         help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+note: References must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:13:12
+   |
+LL | struct Ref(&'static i32);
+   |            ^^^^^^^^^^^^
 
 error: the type `Ref` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:43:25
+  --> $DIR/uninitialized-zeroed.rs:45:25
    |
 LL |         let _val: Ref = mem::uninitialized();
    |                         ^^^^^^^^^^^^^^^^^^^^
+   |                         |
+   |                         this code causes undefined behavior when executed
+   |                         help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+note: References must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:13:12
+   |
+LL | struct Ref(&'static i32);
+   |            ^^^^^^^^^^^^
 
 error: the type `fn()` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:45:26
+  --> $DIR/uninitialized-zeroed.rs:47:26
    |
 LL |         let _val: fn() = mem::zeroed();
    |                          ^^^^^^^^^^^^^
+   |                          |
+   |                          this code causes undefined behavior when executed
+   |                          help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: Function pointers must be non-null
 
 error: the type `fn()` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:46:26
+  --> $DIR/uninitialized-zeroed.rs:48:26
    |
 LL |         let _val: fn() = mem::uninitialized();
    |                          ^^^^^^^^^^^^^^^^^^^^
+   |                          |
+   |                          this code causes undefined behavior when executed
+   |                          help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+   = note: Function pointers must be non-null
 
 error: the type `Wrap<fn()>` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:48:32
+  --> $DIR/uninitialized-zeroed.rs:50:32
    |
 LL |         let _val: Wrap<fn()> = mem::zeroed();
    |                                ^^^^^^^^^^^^^
+   |                                |
+   |                                this code causes undefined behavior when executed
+   |                                help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+note: Function pointers must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:16:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
 
 error: the type `Wrap<fn()>` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:49:32
+  --> $DIR/uninitialized-zeroed.rs:51:32
    |
 LL |         let _val: Wrap<fn()> = mem::uninitialized();
    |                                ^^^^^^^^^^^^^^^^^^^^
+   |                                |
+   |                                this code causes undefined behavior when executed
+   |                                help: use `MaybeUninit<T>` instead
    |
-   = note: this means that this code causes undefined behavior when executed
-   = help: use `MaybeUninit` instead
+note: Function pointers must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:16:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
 
-error: aborting due to 18 previous errors
+error: the type `WrapEnum<fn()>` does not permit zero-initialization
+  --> $DIR/uninitialized-zeroed.rs:53:36
+   |
+LL |         let _val: WrapEnum<fn()> = mem::zeroed();
+   |                                    ^^^^^^^^^^^^^
+   |                                    |
+   |                                    this code causes undefined behavior when executed
+   |                                    help: use `MaybeUninit<T>` instead
+   |
+note: Function pointers must be non-null (in this enum field)
+  --> $DIR/uninitialized-zeroed.rs:17:28
+   |
+LL | enum WrapEnum<T> { Wrapped(T) }
+   |                            ^
+
+error: the type `WrapEnum<fn()>` does not permit being left uninitialized
+  --> $DIR/uninitialized-zeroed.rs:54:36
+   |
+LL |         let _val: WrapEnum<fn()> = mem::uninitialized();
+   |                                    ^^^^^^^^^^^^^^^^^^^^
+   |                                    |
+   |                                    this code causes undefined behavior when executed
+   |                                    help: use `MaybeUninit<T>` instead
+   |
+note: Function pointers must be non-null (in this enum field)
+  --> $DIR/uninitialized-zeroed.rs:17:28
+   |
+LL | enum WrapEnum<T> { Wrapped(T) }
+   |                            ^
+
+error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization
+  --> $DIR/uninitialized-zeroed.rs:56:42
+   |
+LL |         let _val: Wrap<(RefPair, i32)> = mem::zeroed();
+   |                                          ^^^^^^^^^^^^^
+   |                                          |
+   |                                          this code causes undefined behavior when executed
+   |                                          help: use `MaybeUninit<T>` instead
+   |
+note: References must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:14:16
+   |
+LL | struct RefPair((&'static i32, i32));
+   |                ^^^^^^^^^^^^^^^^^^^
+
+error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized
+  --> $DIR/uninitialized-zeroed.rs:57:42
+   |
+LL |         let _val: Wrap<(RefPair, i32)> = mem::uninitialized();
+   |                                          ^^^^^^^^^^^^^^^^^^^^
+   |                                          |
+   |                                          this code causes undefined behavior when executed
+   |                                          help: use `MaybeUninit<T>` instead
+   |
+note: References must be non-null (in this struct field)
+  --> $DIR/uninitialized-zeroed.rs:14:16
+   |
+LL | struct RefPair((&'static i32, i32));
+   |                ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr
index 287f7b2..202a923 100644
--- a/src/test/ui/macros/trace-macro.stderr
+++ b/src/test/ui/macros/trace-macro.stderr
@@ -5,5 +5,5 @@
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `println! { "Hello, World!" }`
-   = note: to `{ $crate :: io :: _print (format_args_nl ! ("Hello, World!")) ; }`
+   = note: to `{ $crate :: io :: _print ($crate :: format_args_nl ! ("Hello, World!")) ; }`
 
diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr
index ad8569b..77df992 100644
--- a/src/test/ui/match/match-unresolved-one-arm.stderr
+++ b/src/test/ui/match/match-unresolved-one-arm.stderr
@@ -2,10 +2,7 @@
   --> $DIR/match-unresolved-one-arm.rs:4:9
    |
 LL |     let x = match () {
-   |         ^
-   |         |
-   |         cannot infer type
-   |         consider giving `x` a type
+   |         ^ consider giving `x` a type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/obsolete-in-place/bad.rs b/src/test/ui/obsolete-in-place/bad.rs
index 3530862..a491bb2 100644
--- a/src/test/ui/obsolete-in-place/bad.rs
+++ b/src/test/ui/obsolete-in-place/bad.rs
@@ -2,7 +2,7 @@
 
 fn foo() {
     let (x, y) = (0, 0);
-    x <- y; //~ ERROR expected one of
+    x <- y; //~ ERROR unexpected token: `<-`
 }
 
 fn main() {
diff --git a/src/test/ui/obsolete-in-place/bad.stderr b/src/test/ui/obsolete-in-place/bad.stderr
index 373b7ea..8a731b6 100644
--- a/src/test/ui/obsolete-in-place/bad.stderr
+++ b/src/test/ui/obsolete-in-place/bad.stderr
@@ -1,8 +1,12 @@
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `<-`
+error: unexpected token: `<-`
   --> $DIR/bad.rs:5:7
    |
 LL |     x <- y;
-   |       ^^ expected one of 8 possible tokens here
+   |       ^^
+help: if you meant to write a comparison against a negative value, add a space in between `<` and `-`
+   |
+LL |     x < - y;
+   |       ^^^
 
 error: expected expression, found keyword `in`
   --> $DIR/bad.rs:10:5
diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs
index 405a7e1..c3f478f 100644
--- a/src/test/ui/parser/doc-before-semi.rs
+++ b/src/test/ui/parser/doc-before-semi.rs
@@ -3,4 +3,6 @@
     //~^ ERROR found a documentation comment that doesn't document anything
     //~| HELP maybe a comment was intended
     ;
+    //~^ WARNING unnecessary trailing semicolon
+    //~| HELP remove this semicolon
 }
diff --git a/src/test/ui/parser/doc-before-semi.stderr b/src/test/ui/parser/doc-before-semi.stderr
index e6bade1..b9ac30b 100644
--- a/src/test/ui/parser/doc-before-semi.stderr
+++ b/src/test/ui/parser/doc-before-semi.stderr
@@ -6,6 +6,14 @@
    |
    = help: doc comments must come before what they document, maybe a comment was intended with `//`?
 
+warning: unnecessary trailing semicolon
+  --> $DIR/doc-before-semi.rs:5:5
+   |
+LL |     ;
+   |     ^ help: remove this semicolon
+   |
+   = note: `#[warn(redundant_semicolon)]` on by default
+
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0585`.
diff --git a/src/test/ui/placement-syntax.rs b/src/test/ui/placement-syntax.rs
index 2edd78e..4df96de 100644
--- a/src/test/ui/placement-syntax.rs
+++ b/src/test/ui/placement-syntax.rs
@@ -1,6 +1,6 @@
 fn main() {
     let x = -5;
-    if x<-1 { //~ ERROR expected `{`, found `<-`
+    if x<-1 { //~ ERROR unexpected token: `<-`
         println!("ok");
     }
 }
diff --git a/src/test/ui/placement-syntax.stderr b/src/test/ui/placement-syntax.stderr
index e90acce..e26931e 100644
--- a/src/test/ui/placement-syntax.stderr
+++ b/src/test/ui/placement-syntax.stderr
@@ -1,10 +1,12 @@
-error: expected `{`, found `<-`
+error: unexpected token: `<-`
   --> $DIR/placement-syntax.rs:3:9
    |
 LL |     if x<-1 {
-   |     --  ^^ expected `{`
-   |     |
-   |     this `if` statement has a condition, but no block
+   |         ^^
+help: if you meant to write a comparison against a negative value, add a space in between `<` and `-`
+   |
+LL |     if x< -1 {
+   |         ^^^
 
 error: aborting due to previous error
 
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 b2f1247..0c863e9 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -88,18 +88,6 @@
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^ not a derive macro
 
-error: cannot find attribute macro `my_macro` in this scope
-  --> $DIR/macro-namespace-reserved-2.rs:38:3
-   |
-LL | #[my_macro]
-   |   ^^^^^^^^
-
-error: cannot find derive macro `my_macro` in this scope
-  --> $DIR/macro-namespace-reserved-2.rs:48:10
-   |
-LL | #[derive(my_macro)]
-   |          ^^^^^^^^
-
 error: cannot find macro `my_macro_attr!` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:28:5
    |
@@ -112,5 +100,17 @@
 LL |     MyTrait!();
    |     ^^^^^^^
 
+error: cannot find attribute macro `my_macro` in this scope
+  --> $DIR/macro-namespace-reserved-2.rs:38:3
+   |
+LL | #[my_macro]
+   |   ^^^^^^^^
+
+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 19 previous errors
 
diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs
index 0a82d28..55835cb 100644
--- a/src/test/ui/proc-macro/span-preservation.rs
+++ b/src/test/ui/proc-macro/span-preservation.rs
@@ -9,7 +9,7 @@
 
 #[recollect_attr]
 fn a() {
-    let x: usize = "hello";;;;; //~ ERROR mismatched types
+    let x: usize = "hello"; //~ ERROR mismatched types
 }
 
 #[recollect_attr]
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index cf03dee..0290f4b 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -6,7 +6,7 @@
 error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:12:20
    |
-LL |     let x: usize = "hello";;;;;
+LL |     let x: usize = "hello";
    |                    ^^^^^^^ expected usize, found reference
    |
    = note: expected type `usize`
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr
index d4b97d2..856162b 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.stderr
+++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr
@@ -7,12 +7,6 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
-  --> $DIR/reserved-attr-on-macro.rs:1:3
-   |
-LL | #[rustc_attribute_should_be_reserved]
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: cannot determine resolution for the macro `foo`
   --> $DIR/reserved-attr-on-macro.rs:10:5
    |
@@ -21,6 +15,12 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
+error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
+  --> $DIR/reserved-attr-on-macro.rs:1:3
+   |
+LL | #[rustc_attribute_should_be_reserved]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rust-unstable-column-gated.rs b/src/test/ui/rust-unstable-column-gated.rs
deleted file mode 100644
index 053806e..0000000
--- a/src/test/ui/rust-unstable-column-gated.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    println!("{}", __rust_unstable_column!());
-    //~^ ERROR use of unstable library feature '__rust_unstable_column'
-}
diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr
deleted file mode 100644
index 7db1b01..0000000
--- a/src/test/ui/rust-unstable-column-gated.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `panic` macro
-  --> $DIR/rust-unstable-column-gated.rs:2:20
-   |
-LL |     println!("{}", __rust_unstable_column!());
-   |                    ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(__rust_unstable_column)]` 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/self/arbitrary_self_types_pin_lifetime-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs
new file mode 100644
index 0000000..b853f88
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs
@@ -0,0 +1,37 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+struct Foo;
+
+impl Foo {
+    async fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self }
+
+    async fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self }
+
+    async fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self }
+
+    async fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self }
+
+    fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self }
+}
+
+type Alias<T> = Pin<T>;
+impl Foo {
+    async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self }
+}
+
+// FIXME(Centril): extend with the rest of the non-`async fn` test
+// when we allow `async fn`s inside traits and trait implementations.
+
+fn main() {
+    let mut foo = Foo;
+    { Pin::new(&foo).pin_ref() };
+    { Pin::new(&mut foo).pin_mut() };
+    { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() };
+    { Pin::new(&foo).pin_ref_impl_trait() };
+}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
new file mode 100644
index 0000000..2421632
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:10:48
+   |
+LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                          -                     ^^^^^^^^ returning this value requires that `'_` must outlive `'static`
+   |                          |
+   |                          lifetime `'_` defined here
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'_`, add `'_` as a constraint
+   |
+LL |     async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
+   |                                     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs
new file mode 100644
index 0000000..aecb823
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs
@@ -0,0 +1,16 @@
+// edition:2018
+
+#![feature(async_await)]
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    async fn f(self: Pin<&Self>) -> impl Clone { self }
+    //~^ ERROR cannot infer an appropriate lifetime
+}
+
+fn main() {
+    { Pin::new(&Foo).f() };
+}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
new file mode 100644
index 0000000..f003244
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -0,0 +1,20 @@
+error: cannot infer an appropriate lifetime
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:10:16
+   |
+LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                ^^^^                 ---------- this return type evaluates to the `'static` lifetime...
+   |                |
+   |                ...but this borrow...
+   |
+note: ...can't outlive the lifetime '_ as defined on the method body at 10:26
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:10:26
+   |
+LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                          ^
+help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 10:26
+   |
+LL |     async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
+   |                                     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
new file mode 100644
index 0000000..e33001b9
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
@@ -0,0 +1,46 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:10:45
+   |
+LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                                             ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:10:50
+   |
+LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                          -                       ^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+   |                          |
+   |                          lifetime `'_` defined here
+   |                          lifetime `'_` defined here
+
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:13:73
+   |
+LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                          -                                              ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+   |                          |
+   |                          lifetime `'_` defined here
+   |                          lifetime `'_` defined here
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:19:58
+   |
+LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |                                                          ^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:19:62
+   |
+LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |                  --              -                           ^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'a`
+   |                  |               |
+   |                  |               lifetime `'_` defined here
+   |                  lifetime `'a` defined here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs
new file mode 100644
index 0000000..53ab75e
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs
@@ -0,0 +1,22 @@
+// edition:2018
+
+#![feature(async_await)]
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+    //~^ ERROR lifetime mismatch
+
+    async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+    //~^ ERROR lifetime mismatch
+}
+
+type Alias<T> = Pin<T>;
+impl Foo {
+    async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
new file mode 100644
index 0000000..74fc474
--- /dev/null
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
@@ -0,0 +1,29 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:10:45
+   |
+LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                          ----               ^^^^
+   |                          |                  |
+   |                          |                  ...but data from `f` is returned here
+   |                          this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:13:55
+   |
+LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                          -----                        ^^^^^^^^^^^^^^^^^
+   |                          |                            |
+   |                          |                            ...but data from `f` is returned here
+   |                          this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:19:58
+   |
+LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |                                  -----                   ^^^
+   |                                  |                       |
+   |                                  |                       ...but data from `arg` is returned here
+   |                                  this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/self/elision/README.md b/src/test/ui/self/elision/README.md
index 7ace2e0..3bd7a6c 100644
--- a/src/test/ui/self/elision/README.md
+++ b/src/test/ui/self/elision/README.md
@@ -42,3 +42,34 @@
 - `self: Box<Pin<XXX>>`
 
 In the non-reference cases, `Pin` causes errors so we substitute `Rc`.
+
+### `async fn`
+
+For each of the tests above we also check that `async fn` behaves as an `fn` would.
+These tests are in files named `*-async.rs`.
+
+Legends:
+- ✓ ⟹ Yes / Pass
+- X ⟹ No
+- α ⟹ lifetime mismatch
+- β ⟹ cannot infer an appropriate lifetime
+- γ ⟹ missing lifetime specifier
+
+| `async` file | Pass? | Conforms to `fn`? | How does it diverge? <br/> `fn` ⟶ `async fn` |
+| --- | --- | --- | --- |
+| `self-async.rs` | ✓ | ✓ | N/A |
+| `struct-async.rs`| ✓ | ✓ | N/A |
+| `alias-async.rs`| ✓ | ✓ | N/A |
+| `assoc-async.rs`| ✓ | ✓ | N/A |
+| `ref-self-async.rs` | X | ✓ | N/A |
+| `ref-mut-self-async.rs` | X | ✓ | N/A |
+| `ref-struct-async.rs` | X | ✓ | N/A |
+| `ref-mut-struct-async.rs` | X | ✓ | N/A |
+| `ref-alias-async.rs` | ✓ | ✓ | N/A |
+| `ref-assoc-async.rs` | ✓ | ✓ | N/A |
+| `ref-mut-alias-async.rs` | ✓ | ✓ | N/A |
+| `lt-self-async.rs` | ✓ | ✓ | N/A
+| `lt-struct-async.rs` | ✓ | ✓ | N/A
+| `lt-alias-async.rs` | ✓ | ✓ | N/A
+| `lt-assoc-async.rs` | ✓ | ✓ | N/A
+| `lt-ref-self-async.rs` | X | ✓ | N/A |
diff --git a/src/test/ui/self/elision/alias-async.rs b/src/test/ui/self/elision/alias-async.rs
new file mode 100644
index 0000000..3d5b24a
--- /dev/null
+++ b/src/test/ui/self/elision/alias-async.rs
@@ -0,0 +1,39 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct { }
+
+type Alias = Struct;
+
+impl Struct {
+    // Test using an alias for `Struct`:
+
+    async fn alias(self: Alias, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_Alias(self: Box<Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn rc_Alias(self: Rc<Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_box_Alias(self: Box<Box<Alias>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_rc_Alias(self: Box<Rc<Alias>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/assoc-async.rs b/src/test/ui/self/elision/assoc-async.rs
new file mode 100644
index 0000000..0f33f28
--- /dev/null
+++ b/src/test/ui/self/elision/assoc-async.rs
@@ -0,0 +1,43 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+trait Trait {
+    type AssocType;
+}
+
+struct Struct { }
+
+impl Trait for Struct {
+    type AssocType = Self;
+}
+
+impl Struct {
+    async fn assoc(self: <Struct as Trait>::AssocType, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_AssocType(self: Box<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn rc_AssocType(self: Rc<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_box_AssocType(self: Box<Box<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_rc_AssocType(self: Box<Rc<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-alias-async.rs b/src/test/ui/self/elision/lt-alias-async.rs
new file mode 100644
index 0000000..5a8989f
--- /dev/null
+++ b/src/test/ui/self/elision/lt-alias-async.rs
@@ -0,0 +1,41 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct<'a> { x: &'a u32 }
+
+type Alias<'a> = Struct<'a>;
+
+impl<'a> Alias<'a> {
+    async fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Alias(self: Box<Alias<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Box_Alias(self: Box<Box<Alias<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Rc_Alias(self: Rc<Alias<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Rc_Alias(self: Box<Rc<Alias<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-assoc-async.rs b/src/test/ui/self/elision/lt-assoc-async.rs
new file mode 100644
index 0000000..98c9aa3
--- /dev/null
+++ b/src/test/ui/self/elision/lt-assoc-async.rs
@@ -0,0 +1,53 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+trait Trait {
+    type AssocType;
+}
+
+struct Struct<'a> { x: &'a u32 }
+
+impl<'a> Trait for Struct<'a> {
+    type AssocType = Self;
+}
+
+impl<'a> Struct<'a> {
+    async fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_AssocType(self: <Struct<'a> as Trait>::AssocType, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_AssocType(self: Box<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Box_AssocType(
+        self: Box<Box<<Struct<'a> as Trait>::AssocType>>,
+        f: &u32
+    ) -> &u32 {
+        f
+    }
+
+    async fn take_Rc_AssocType(self: Rc<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Rc_AssocType(
+        self: Box<Rc<<Struct<'a> as Trait>::AssocType>>,
+        f: &u32
+    ) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
new file mode 100644
index 0000000..3e58c97
--- /dev/null
+++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
@@ -0,0 +1,123 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/lt-ref-self-async.rs:15:42
+   |
+LL |     async fn ref_self(&self, f: &u32) -> &u32 {
+   |                                          ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#23r
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self-async.rs:15:47
+   |
+LL |       async fn ref_self(&self, f: &u32) -> &u32 {
+   |  _______________________-_______________________^
+   | |                       |
+   | |                       lifetime `'_` defined here
+   | |                       lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/lt-ref-self-async.rs:21:48
+   |
+LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                                ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#23r
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self-async.rs:21:53
+   |
+LL |       async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |  _____________________________-_______________________^
+   | |                             |
+   | |                             lifetime `'_` defined here
+   | |                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/lt-ref-self-async.rs:25:57
+   |
+LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                                         ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#23r
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self-async.rs:25:62
+   |
+LL |       async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |  _____________________________________-________________________^
+   | |                                     |
+   | |                                     lifetime `'_` defined here
+   | |                                     lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/lt-ref-self-async.rs:29:57
+   |
+LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                                         ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#23r
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self-async.rs:29:62
+   |
+LL |       async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |  _____________________________________-________________________^
+   | |                                     |
+   | |                                     lifetime `'_` defined here
+   | |                                     lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/lt-ref-self-async.rs:33:66
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                                  ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#23r
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self-async.rs:33:71
+   |
+LL |       async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |  _____________________________________________-_________________________^
+   | |                                             |
+   | |                                             lifetime `'_` defined here
+   | |                                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/lt-ref-self-async.rs:37:62
+   |
+LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                                              ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#23r
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self-async.rs:37:67
+   |
+LL |       async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |  _________________________________________-_________________________^
+   | |                                         |
+   | |                                         lifetime `'_` defined here
+   | |                                         lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/self/elision/lt-ref-self-async.rs b/src/test/ui/self/elision/lt-ref-self-async.rs
new file mode 100644
index 0000000..79a4771
--- /dev/null
+++ b/src/test/ui/self/elision/lt-ref-self-async.rs
@@ -0,0 +1,42 @@
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct<'a> { data: &'a u32 }
+
+impl<'a> Struct<'a> {
+    // Test using `&self` sugar:
+
+    async fn ref_self(&self, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    // Test using `&Self` explicitly:
+
+    async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr
new file mode 100644
index 0000000..0a45925
--- /dev/null
+++ b/src/test/ui/self/elision/lt-ref-self-async.stderr
@@ -0,0 +1,56 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:15:42
+   |
+LL |     async fn ref_self(&self, f: &u32) -> &u32 {
+   |                       -----              ^^^^
+   |                       |                  |
+   |                       |                  ...but data from `f` is returned here
+   |                       this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:21:48
+   |
+LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                             -----              ^^^^
+   |                             |                  |
+   |                             |                  ...but data from `f` is returned here
+   |                             this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:25:57
+   |
+LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                     -----               ^^^^
+   |                                     |                   |
+   |                                     |                   ...but data from `f` is returned here
+   |                                     this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:29:57
+   |
+LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                     -----               ^^^^
+   |                                     |                   |
+   |                                     |                   ...but data from `f` is returned here
+   |                                     this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:33:66
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                             -----                ^^^^
+   |                                             |                    |
+   |                                             |                    ...but data from `f` is returned here
+   |                                             this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self-async.rs:37:62
+   |
+LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                         -----                ^^^^
+   |                                         |                    |
+   |                                         |                    ...but data from `f` is returned here
+   |                                         this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/self/elision/lt-self-async.rs b/src/test/ui/self/elision/lt-self-async.rs
new file mode 100644
index 0000000..0202db8
--- /dev/null
+++ b/src/test/ui/self/elision/lt-self-async.rs
@@ -0,0 +1,52 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+use std::rc::Rc;
+
+struct Struct<'a> {
+    x: &'a u32
+}
+
+impl<'a> Struct<'a> {
+    async fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Self(self: Self, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    // N/A
+    //fn take_Pin_Self(self: Pin<Self>, f: &u32) -> &u32 {
+    //    f
+    //}
+
+    // N/A
+    //fn take_Box_Pin_Self(self: Box<Pin<Self>>, f: &u32) -> &u32 {
+    //    f
+    //}
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-struct-async.rs b/src/test/ui/self/elision/lt-struct-async.rs
new file mode 100644
index 0000000..c0fc63d
--- /dev/null
+++ b/src/test/ui/self/elision/lt-struct-async.rs
@@ -0,0 +1,39 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct<'a> { x: &'a u32 }
+
+impl<'a> Struct<'a> {
+    async fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Struct(self: Box<Struct<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Box_Struct(self: Box<Box<Struct<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Rc_Struct(self: Rc<Struct<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Rc_Struct(self: Box<Rc<Struct<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/multiple-ref-self-async.rs b/src/test/ui/self/elision/multiple-ref-self-async.rs
new file mode 100644
index 0000000..eb8c252
--- /dev/null
+++ b/src/test/ui/self/elision/multiple-ref-self-async.rs
@@ -0,0 +1,46 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::pin::Pin;
+
+struct Struct { }
+
+struct Wrap<T, P>(T, PhantomData<P>);
+
+impl<T, P> Deref for Wrap<T, P> {
+    type Target = T;
+    fn deref(&self) -> &T { &self.0 }
+}
+
+impl Struct {
+    // Test using multiple `&Self`:
+
+    async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
+        f
+    }
+
+    async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-alias-async.rs b/src/test/ui/self/elision/ref-alias-async.rs
new file mode 100644
index 0000000..acc4b21
--- /dev/null
+++ b/src/test/ui/self/elision/ref-alias-async.rs
@@ -0,0 +1,42 @@
+// edition:2018
+// check-pass
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+type Alias = Struct;
+
+impl Struct {
+    // Test using an alias for `Struct`:
+    //
+    // FIXME. We currently fail to recognize this as the self type, which
+    // feels like a bug.
+
+    async fn ref_Alias(self: &Alias, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_box_ref_Alias(self: Box<Box<&Alias>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_pin_ref_Alias(self: Box<Pin<&Alias>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-assoc-async.rs b/src/test/ui/self/elision/ref-assoc-async.rs
new file mode 100644
index 0000000..a6b6cbd
--- /dev/null
+++ b/src/test/ui/self/elision/ref-assoc-async.rs
@@ -0,0 +1,43 @@
+// edition:2018
+// check-pass
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+trait Trait {
+    type AssocType;
+}
+
+struct Struct { }
+
+impl Trait for Struct {
+    type AssocType = Self;
+}
+
+impl Struct {
+    async fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-alias-async.rs b/src/test/ui/self/elision/ref-mut-alias-async.rs
new file mode 100644
index 0000000..873e92b
--- /dev/null
+++ b/src/test/ui/self/elision/ref-mut-alias-async.rs
@@ -0,0 +1,38 @@
+// edition:2018
+// check-pass
+
+#![feature(async_await)]
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+type Alias = Struct;
+
+impl Struct {
+    // Test using an alias for `Struct`:
+
+    async fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_box_ref_Alias(self: Box<Box<&mut Alias>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_pin_ref_Alias(self: Box<Pin<&mut Alias>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
new file mode 100644
index 0000000..b8a5380
--- /dev/null
+++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
@@ -0,0 +1,123 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-self-async.rs:15:46
+   |
+LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
+   |                                              ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self-async.rs:15:51
+   |
+LL |       async fn ref_self(&mut self, f: &u32) -> &u32 {
+   |  _______________________-___________________________^
+   | |                       |
+   | |                       lifetime `'_` defined here
+   | |                       lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-self-async.rs:21:52
+   |
+LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+   |                                                    ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self-async.rs:21:57
+   |
+LL |       async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+   |  _____________________________-___________________________^
+   | |                             |
+   | |                             lifetime `'_` defined here
+   | |                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-self-async.rs:25:61
+   |
+LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+   |                                                             ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self-async.rs:25:66
+   |
+LL |       async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+   |  _____________________________________-____________________________^
+   | |                                     |
+   | |                                     lifetime `'_` defined here
+   | |                                     lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-self-async.rs:29:61
+   |
+LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+   |                                                             ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self-async.rs:29:66
+   |
+LL |       async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+   |  _____________________________________-____________________________^
+   | |                                     |
+   | |                                     lifetime `'_` defined here
+   | |                                     lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-self-async.rs:33:70
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+   |                                                                      ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self-async.rs:33:75
+   |
+LL |       async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+   |  _____________________________________________-_____________________________^
+   | |                                             |
+   | |                                             lifetime `'_` defined here
+   | |                                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-self-async.rs:37:70
+   |
+LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+   |                                                                      ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self-async.rs:37:75
+   |
+LL |       async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+   |  _____________________________________________-_____________________________^
+   | |                                             |
+   | |                                             lifetime `'_` defined here
+   | |                                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/self/elision/ref-mut-self-async.rs b/src/test/ui/self/elision/ref-mut-self-async.rs
new file mode 100644
index 0000000..a6bd9d6
--- /dev/null
+++ b/src/test/ui/self/elision/ref-mut-self-async.rs
@@ -0,0 +1,42 @@
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&mut self` sugar:
+
+    async fn ref_self(&mut self, f: &u32) -> &u32 { //~ ERROR lifetime mismatch
+        f
+    }
+
+    // Test using `&mut Self` explicitly:
+
+    async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr
new file mode 100644
index 0000000..805833f
--- /dev/null
+++ b/src/test/ui/self/elision/ref-mut-self-async.stderr
@@ -0,0 +1,56 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:15:46
+   |
+LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
+   |                       ---------              ^^^^
+   |                       |                      |
+   |                       |                      ...but data from `f` is returned here
+   |                       this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:21:52
+   |
+LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+   |                             ---------              ^^^^
+   |                             |                      |
+   |                             |                      ...but data from `f` is returned here
+   |                             this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:25:61
+   |
+LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+   |                                     ---------               ^^^^
+   |                                     |                       |
+   |                                     |                       ...but data from `f` is returned here
+   |                                     this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:29:61
+   |
+LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+   |                                     ---------               ^^^^
+   |                                     |                       |
+   |                                     |                       ...but data from `f` is returned here
+   |                                     this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:33:70
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+   |                                             ---------                ^^^^
+   |                                             |                        |
+   |                                             |                        ...but data from `f` is returned here
+   |                                             this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self-async.rs:37:70
+   |
+LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+   |                                             ---------                ^^^^
+   |                                             |                        |
+   |                                             |                        ...but data from `f` is returned here
+   |                                             this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
new file mode 100644
index 0000000..cee008d
--- /dev/null
+++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
@@ -0,0 +1,103 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-struct-async.rs:15:56
+   |
+LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+   |                                                        ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct-async.rs:15:61
+   |
+LL |       async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+   |  _______________________________-_____________________________^
+   | |                               |
+   | |                               lifetime `'_` defined here
+   | |                               lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-struct-async.rs:19:65
+   |
+LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+   |                                                                 ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct-async.rs:19:70
+   |
+LL |       async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+   |  _______________________________________-______________________________^
+   | |                                       |
+   | |                                       lifetime `'_` defined here
+   | |                                       lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-struct-async.rs:23:65
+   |
+LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+   |                                                                 ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct-async.rs:23:70
+   |
+LL |       async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+   |  _______________________________________-______________________________^
+   | |                                       |
+   | |                                       lifetime `'_` defined here
+   | |                                       lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-struct-async.rs:27:74
+   |
+LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                                          ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct-async.rs:27:79
+   |
+LL |       async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+   |  _______________________________________________-_______________________________^
+   | |                                               |
+   | |                                               lifetime `'_` defined here
+   | |                                               lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-mut-struct-async.rs:31:74
+   |
+LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                                          ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct-async.rs:31:79
+   |
+LL |       async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+   |  _______________________________________________-_______________________________^
+   | |                                               |
+   | |                                               lifetime `'_` defined here
+   | |                                               lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.rs b/src/test/ui/self/elision/ref-mut-struct-async.rs
new file mode 100644
index 0000000..7a89ef9
--- /dev/null
+++ b/src/test/ui/self/elision/ref-mut-struct-async.rs
@@ -0,0 +1,36 @@
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&mut Struct` explicitly:
+
+    async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr
new file mode 100644
index 0000000..4c98387
--- /dev/null
+++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr
@@ -0,0 +1,47 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:15:56
+   |
+LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+   |                               -----------              ^^^^
+   |                               |                        |
+   |                               |                        ...but data from `f` is returned here
+   |                               this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:19:65
+   |
+LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+   |                                       -----------               ^^^^
+   |                                       |                         |
+   |                                       |                         ...but data from `f` is returned here
+   |                                       this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:23:65
+   |
+LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+   |                                       -----------               ^^^^
+   |                                       |                         |
+   |                                       |                         ...but data from `f` is returned here
+   |                                       this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:27:74
+   |
+LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+   |                                               -----------                ^^^^
+   |                                               |                          |
+   |                                               |                          ...but data from `f` is returned here
+   |                                               this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct-async.rs:31:74
+   |
+LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+   |                                               -----------                ^^^^
+   |                                               |                          |
+   |                                               |                          ...but data from `f` is returned here
+   |                                               this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/self/elision/ref-self-async.nll.stderr b/src/test/ui/self/elision/ref-self-async.nll.stderr
new file mode 100644
index 0000000..c3c1548
--- /dev/null
+++ b/src/test/ui/self/elision/ref-self-async.nll.stderr
@@ -0,0 +1,143 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-self-async.rs:24:42
+   |
+LL |     async fn ref_self(&self, f: &u32) -> &u32 {
+   |                                          ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self-async.rs:24:47
+   |
+LL |       async fn ref_self(&self, f: &u32) -> &u32 {
+   |  _______________________-_______________________^
+   | |                       |
+   | |                       lifetime `'_` defined here
+   | |                       lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-self-async.rs:30:48
+   |
+LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                                ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self-async.rs:30:53
+   |
+LL |       async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |  _____________________________-_______________________^
+   | |                             |
+   | |                             lifetime `'_` defined here
+   | |                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-self-async.rs:34:57
+   |
+LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                                         ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self-async.rs:34:62
+   |
+LL |       async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |  _____________________________________-________________________^
+   | |                                     |
+   | |                                     lifetime `'_` defined here
+   | |                                     lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-self-async.rs:38:57
+   |
+LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                                         ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self-async.rs:38:62
+   |
+LL |       async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |  _____________________________________-________________________^
+   | |                                     |
+   | |                                     lifetime `'_` defined here
+   | |                                     lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-self-async.rs:42:66
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                                  ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self-async.rs:42:71
+   |
+LL |       async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |  _____________________________________________-_________________________^
+   | |                                             |
+   | |                                             lifetime `'_` defined here
+   | |                                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-self-async.rs:46:66
+   |
+LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                                                  ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self-async.rs:46:71
+   |
+LL |       async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |  _____________________________________________-_________________________^
+   | |                                             |
+   | |                                             lifetime `'_` defined here
+   | |                                             lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-self-async.rs:50:69
+   |
+LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+   |                                                                     ^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self-async.rs:50:73
+   |
+LL |       async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+   |  ____________________________________________-____________________________^
+   | |                                            |
+   | |                                            lifetime `'_` defined here
+   | |                                            lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/self/elision/ref-self-async.rs b/src/test/ui/self/elision/ref-self-async.rs
new file mode 100644
index 0000000..5a5705d
--- /dev/null
+++ b/src/test/ui/self/elision/ref-self-async.rs
@@ -0,0 +1,55 @@
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::pin::Pin;
+
+struct Struct { }
+
+struct Wrap<T, P>(T, PhantomData<P>);
+
+impl<T, P> Deref for Wrap<T, P> {
+    type Target = T;
+    fn deref(&self) -> &T { &self.0 }
+}
+
+impl Struct {
+    // Test using `&self` sugar:
+
+    async fn ref_self(&self, f: &u32) -> &u32 { //~ ERROR lifetime mismatch
+        f
+    }
+
+    // Test using `&Self` explicitly:
+
+    async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+        f //~^ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr
new file mode 100644
index 0000000..eb796a0
--- /dev/null
+++ b/src/test/ui/self/elision/ref-self-async.stderr
@@ -0,0 +1,65 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:24:42
+   |
+LL |     async fn ref_self(&self, f: &u32) -> &u32 {
+   |                       -----              ^^^^
+   |                       |                  |
+   |                       |                  ...but data from `f` is returned here
+   |                       this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:30:48
+   |
+LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                             -----              ^^^^
+   |                             |                  |
+   |                             |                  ...but data from `f` is returned here
+   |                             this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:34:57
+   |
+LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                     -----               ^^^^
+   |                                     |                   |
+   |                                     |                   ...but data from `f` is returned here
+   |                                     this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:38:57
+   |
+LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                     -----               ^^^^
+   |                                     |                   |
+   |                                     |                   ...but data from `f` is returned here
+   |                                     this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:42:66
+   |
+LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                             -----                ^^^^
+   |                                             |                    |
+   |                                             |                    ...but data from `f` is returned here
+   |                                             this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:46:66
+   |
+LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                             -----                ^^^^
+   |                                             |                    |
+   |                                             |                    ...but data from `f` is returned here
+   |                                             this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self-async.rs:50:69
+   |
+LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+   |                                            -----                    ^^^
+   |                                            |                        |
+   |                                            |                        ...but data from `f` is returned here
+   |                                            this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/self/elision/ref-struct-async.nll.stderr b/src/test/ui/self/elision/ref-struct-async.nll.stderr
new file mode 100644
index 0000000..ff50f68
--- /dev/null
+++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr
@@ -0,0 +1,103 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-struct-async.rs:15:52
+   |
+LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                                                    ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct-async.rs:15:57
+   |
+LL |       async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |  _______________________________-_________________________^
+   | |                               |
+   | |                               lifetime `'_` defined here
+   | |                               lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-struct-async.rs:19:61
+   |
+LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+   |                                                             ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct-async.rs:19:66
+   |
+LL |       async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+   |  _______________________________________-__________________________^
+   | |                                       |
+   | |                                       lifetime `'_` defined here
+   | |                                       lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-struct-async.rs:23:61
+   |
+LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+   |                                                             ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct-async.rs:23:66
+   |
+LL |       async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+   |  _______________________________________-__________________________^
+   | |                                       |
+   | |                                       lifetime `'_` defined here
+   | |                                       lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-struct-async.rs:27:70
+   |
+LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+   |                                                                      ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct-async.rs:27:75
+   |
+LL |       async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+   |  _______________________________________________-___________________________^
+   | |                                               |
+   | |                                               lifetime `'_` defined here
+   | |                                               lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ref-struct-async.rs:31:66
+   |
+LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+   |                                                                  ^^^^
+   |
+   = note: hidden type `impl std::future::Future` captures lifetime '_#15r
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct-async.rs:31:71
+   |
+LL |       async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+   |  ___________________________________________-___________________________^
+   | |                                           |
+   | |                                           lifetime `'_` defined here
+   | |                                           lifetime `'_` defined here
+LL | |         f
+LL | |     }
+   | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/self/elision/ref-struct-async.rs b/src/test/ui/self/elision/ref-struct-async.rs
new file mode 100644
index 0000000..f0410bb
--- /dev/null
+++ b/src/test/ui/self/elision/ref-struct-async.rs
@@ -0,0 +1,36 @@
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&Struct` explicitly:
+
+    async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+
+    async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+        f //~^ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr
new file mode 100644
index 0000000..574b0fd
--- /dev/null
+++ b/src/test/ui/self/elision/ref-struct-async.stderr
@@ -0,0 +1,47 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:15:52
+   |
+LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                               -------              ^^^^
+   |                               |                    |
+   |                               |                    ...but data from `f` is returned here
+   |                               this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:19:61
+   |
+LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+   |                                       -------               ^^^^
+   |                                       |                     |
+   |                                       |                     ...but data from `f` is returned here
+   |                                       this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:23:61
+   |
+LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+   |                                       -------               ^^^^
+   |                                       |                     |
+   |                                       |                     ...but data from `f` is returned here
+   |                                       this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:27:70
+   |
+LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+   |                                               -------                ^^^^
+   |                                               |                      |
+   |                                               |                      ...but data from `f` is returned here
+   |                                               this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct-async.rs:31:66
+   |
+LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+   |                                           -------                ^^^^
+   |                                           |                      |
+   |                                           |                      ...but data from `f` is returned here
+   |                                           this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/self/elision/self-async.rs b/src/test/ui/self/elision/self-async.rs
new file mode 100644
index 0000000..d1dc050
--- /dev/null
+++ b/src/test/ui/self/elision/self-async.rs
@@ -0,0 +1,39 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct { }
+
+impl Struct {
+    async fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Self(self: Self, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/struct-async.rs b/src/test/ui/self/elision/struct-async.rs
new file mode 100644
index 0000000..f7c8591
--- /dev/null
+++ b/src/test/ui/self/elision/struct-async.rs
@@ -0,0 +1,35 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct { }
+
+impl Struct {
+    async fn ref_Struct(self: Struct, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_Struct(self: Box<Struct>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn rc_Struct(self: Rc<Struct>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_box_Struct(self: Box<Box<Struct>>, f: &u32) -> &u32 {
+        f
+    }
+
+    async fn box_rc_Struct(self: Box<Rc<Struct>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/self_lifetime-async.rs b/src/test/ui/self/self_lifetime-async.rs
new file mode 100644
index 0000000..ec4c3d1
--- /dev/null
+++ b/src/test/ui/self/self_lifetime-async.rs
@@ -0,0 +1,16 @@
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+struct Foo<'a>(&'a ());
+impl<'a> Foo<'a> {
+    async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
+}
+
+type Alias = Foo<'static>;
+impl Alias {
+    async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs
new file mode 100644
index 0000000..d625199
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs
@@ -0,0 +1,3 @@
+fn main() {
+    assert_eq!(10u64, 10usize); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr
new file mode 100644
index 0000000..f043069
--- /dev/null
+++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/dont-suggest-try_into-in-macros.rs:2:5
+   |
+LL |     assert_eq!(10u64, 10usize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-61226.rs b/src/test/ui/suggestions/issue-61226.rs
new file mode 100644
index 0000000..e83b0b4
--- /dev/null
+++ b/src/test/ui/suggestions/issue-61226.rs
@@ -0,0 +1,5 @@
+struct X {}
+fn main() {
+    vec![X]; //…
+    //~^ ERROR expected value, found struct `X`
+}
diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr
new file mode 100644
index 0000000..6d7d98a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-61226.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected value, found struct `X`
+  --> $DIR/issue-61226.rs:3:10
+   |
+LL |     vec![X]; //…
+   |          ^ did you mean `X { /* fields */ }`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/suggestions/suggest-box.fixed b/src/test/ui/suggestions/suggest-box.fixed
new file mode 100644
index 0000000..3de02cd
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-box.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+    let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types
+        Err(())?;
+        Ok(())
+    });
+}
diff --git a/src/test/ui/suggestions/suggest-box.rs b/src/test/ui/suggestions/suggest-box.rs
new file mode 100644
index 0000000..e680a61
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-box.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+    let _x: Box<dyn Fn() -> Result<(), ()>> = || { //~ ERROR mismatched types
+        Err(())?;
+        Ok(())
+    };
+}
diff --git a/src/test/ui/suggestions/suggest-box.stderr b/src/test/ui/suggestions/suggest-box.stderr
new file mode 100644
index 0000000..50c106d
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-box.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-box.rs:4:47
+   |
+LL |       let _x: Box<dyn Fn() -> Result<(), ()>> = || {
+   |  _______________________________________________^
+LL | |         Err(())?;
+LL | |         Ok(())
+LL | |     };
+   | |_____^ expected struct `std::boxed::Box`, found closure
+   |
+   = note: expected type `std::boxed::Box<dyn std::ops::Fn() -> std::result::Result<(), ()>>`
+              found type `[closure@$DIR/suggest-box.rs:4:47: 7:6]`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |     let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| {
+LL |         Err(())?;
+LL |         Ok(())
+LL |     });
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.rs b/src/test/ui/suggestions/suggest-closure-return-type-1.rs
new file mode 100644
index 0000000..910f273
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-closure-return-type-1.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _v = || -> _ { [] }; //~ ERROR type annotations needed for the closure
+}
diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr
new file mode 100644
index 0000000..de2d29f
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed for the closure `fn() -> [_; 0]`
+  --> $DIR/suggest-closure-return-type-1.rs:2:24
+   |
+LL |     let _v = || -> _ { [] };
+   |                        ^^ cannot infer type
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |     let _v = || -> [_; 0] { [] };
+   |                    ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.rs b/src/test/ui/suggestions/suggest-closure-return-type-2.rs
new file mode 100644
index 0000000..6955b37
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-closure-return-type-2.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _v = || { [] }; //~ ERROR type annotations needed for the closure
+}
diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr
new file mode 100644
index 0000000..9dbd822
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed for the closure `fn() -> [_; 0]`
+  --> $DIR/suggest-closure-return-type-2.rs:2:19
+   |
+LL |     let _v = || { [] };
+   |                   ^^ cannot infer type
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |     let _v = || -> [_; 0] { [] };
+   |                 ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.rs b/src/test/ui/suggestions/suggest-closure-return-type-3.rs
new file mode 100644
index 0000000..ec6c094
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-closure-return-type-3.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _v = || []; //~ ERROR type annotations needed for the closure
+}
diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr
new file mode 100644
index 0000000..ad0d4e4
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed for the closure `fn() -> [_; 0]`
+  --> $DIR/suggest-closure-return-type-3.rs:2:17
+   |
+LL |     let _v = || [];
+   |                 ^^ cannot infer type
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |     let _v = || -> [_; 0] { [] };
+   |                 ^^^^^^^^^^^    ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index 52bb118..137b72d 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -64,9 +64,9 @@
             //[legacy]~^ ERROR symbol-name(_ZN198_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method
             //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method
             //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method)
-             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG0_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-                //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method)
-                //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
+             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+                //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method)
+                //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
             #[rustc_def_path]
             //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
                //[v0]~^^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr
index 1c4b256..e024799 100644
--- a/src/test/ui/symbol-names/impl1.v0.stderr
+++ b/src/test/ui/symbol-names/impl1.v0.stderr
@@ -46,19 +46,19 @@
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG0_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
   --> $DIR/impl1.rs:63:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method)
+error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method)
   --> $DIR/impl1.rs:63:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
+error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
   --> $DIR/impl1.rs:63:13
    |
 LL |             #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr
index 7fcd2ed..de8efdd 100644
--- a/src/test/ui/symbol-names/issue-60925.legacy.stderr
+++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr
@@ -4,13 +4,13 @@
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo::h059a991a004536ad)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h059a991a004536ad)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo)
+error: demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs
index 89de15c..0243835 100644
--- a/src/test/ui/symbol-names/issue-60925.rs
+++ b/src/test/ui/symbol-names/issue-60925.rs
@@ -20,8 +20,8 @@
     impl Foo<::llvm::Foo> {
         #[rustc_symbol_name]
         //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo
-        //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo
-        //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo)
+        //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo
+        //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo)
          //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs4fqI2P2rA04_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
             //[v0]~| ERROR demangling(<issue_60925[317d481089b8c8fe]::foo::Foo<issue_60925[317d481089b8c8fe]::llvm::Foo>>::foo)
             //[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 05cfdf1..3da6be7 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1659,10 +1659,10 @@
             _ if self.config.target.contains("vxworks") => {
                 let aux_dir = self.aux_output_dir_name();
                 let ProcArgs { prog, args } = self.make_run_args();
-                let mut vx_run = Command::new("vx-run");
-                vx_run.args(&[&prog]).args(args).envs(env.clone());
+                let mut wr_run = Command::new("wr-run");
+                wr_run.args(&[&prog]).args(args).envs(env.clone());
                 self.compose_and_run(
-                    vx_run,
+                    wr_run,
                     self.config.run_lib_path.to_str().unwrap(),
                     Some(aux_dir.to_str().unwrap()),
                     None,
diff --git a/src/tools/miri b/src/tools/miri
index c1cb249..4f6f264 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit c1cb24969e84dfaded2769ab5575effc8d4f5c30
+Subproject commit 4f6f264c305ea30f1de90ad0c2f341e84d972b2e
diff --git a/src/tools/rls b/src/tools/rls
index 7b0a20b..496c892 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 7b0a20bf13b7061b1eb31a058117ac5517ff8cc9
+Subproject commit 496c89275221303a4b0c2779cb8203fb3ce2a136