diff --git a/Cargo.lock b/Cargo.lock
index bdc746c0bb0e0..fe4682581d600 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -97,18 +97,12 @@ dependencies = [
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "autocfg"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "backtrace"
-version = "0.3.29"
+version = "0.3.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -118,7 +112,7 @@ dependencies = [
 
 [[package]]
 name = "backtrace-sys"
-version = "0.1.27"
+version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -868,7 +862,7 @@ name = "error-chain"
 version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -883,7 +877,7 @@ name = "failure"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2513,7 +2507,7 @@ name = "rustc"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2751,20 +2745,6 @@ dependencies = [
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "rustc_allocator"
-version = "0.0.0"
-dependencies = [
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc 0.0.0",
- "rustc_data_structures 0.0.0",
- "rustc_errors 0.0.0",
- "rustc_target 0.0.0",
- "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "syntax 0.0.0",
- "syntax_pos 0.0.0",
-]
-
 [[package]]
 name = "rustc_apfloat"
 version = "0.0.0"
@@ -2822,7 +2802,6 @@ dependencies = [
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc_allocator 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_codegen_utils 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -2877,34 +2856,21 @@ dependencies = [
 name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
- "arena 0.0.0",
  "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_allocator 0.0.0",
  "rustc_ast_borrowck 0.0.0",
  "rustc_codegen_utils 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_incremental 0.0.0",
  "rustc_interface 0.0.0",
- "rustc_lint 0.0.0",
  "rustc_metadata 0.0.0",
  "rustc_mir 0.0.0",
- "rustc_passes 0.0.0",
- "rustc_plugin 0.0.0",
- "rustc_privacy 0.0.0",
- "rustc_resolve 0.0.0",
  "rustc_save_analysis 0.0.0",
  "rustc_target 0.0.0",
- "rustc_traits 0.0.0",
- "rustc_typeck 0.0.0",
  "serialize 0.0.0",
- "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
- "syntax_ext 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
@@ -2948,7 +2914,6 @@ dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_allocator 0.0.0",
  "rustc_ast_borrowck 0.0.0",
  "rustc_codegen_ssa 0.0.0",
  "rustc_codegen_utils 0.0.0",
@@ -3036,7 +3001,6 @@ dependencies = [
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
- "syntax_ext 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
@@ -3081,9 +3045,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_mir 0.0.0",
  "syntax 0.0.0",
- "syntax_ext 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
@@ -3491,7 +3453,7 @@ name = "std"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4308,9 +4270,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
-"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
-"checksum backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)" = "2d631cd7af21b7ff796293f1990104e3cdb606852863bac32f000c193aa35dfb"
-"checksum backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "6ea90dd7b012b3d1a2cb6bec16670a0db2c95d4e931e84f4047e0460c1b34c8d"
+"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6"
+"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61"
 "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
 "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
 "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 53d3dbf60d1d7..907983d43ade7 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -76,11 +76,11 @@ def v(*args):
 o("llvm-assertions", "llvm.assertions", "build LLVM with assertions")
 o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
 o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata")
-o("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code")
-o("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler")
-o("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library")
-o("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools")
-o("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest")
+v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code")
+v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler")
+v("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library")
+v("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools")
+v("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest")
 v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file")
 
 v("prefix", "install.prefix", "set installation prefix")
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index 5ab4be328a9f7..2a81de75a69b9 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -112,6 +112,7 @@ ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
 ENV TARGETS=$TARGETS,thumbv8m.base-none-eabi
 ENV TARGETS=$TARGETS,thumbv8m.main-none-eabi
 ENV TARGETS=$TARGETS,thumbv8m.main-none-eabihf
+ENV TARGETS=$TARGETS,riscv32i-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 1039343827d87..f1eb417cdf982 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -50,7 +50,7 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo"
-  RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.debuginfo-level-std=1"
+  RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level-std=1"
 
   if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index fe149d634e223..2b3bad8894e60 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -120,6 +120,7 @@
 #![feature(cmpxchg16b_target_feature)]
 #![feature(rtm_target_feature)]
 #![feature(f16c_target_feature)]
+#![feature(hexagon_target_feature)]
 #![feature(const_slice_len)]
 #![feature(const_str_as_bytes)]
 #![feature(const_str_len)]
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index e2b743b379704..236ed15050571 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -126,6 +126,9 @@ const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7
 #[cfg(target_arch = "sparc64")]
 const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1
 
+#[cfg(target_arch = "hexagon")]
+const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
+
 // The following code is based on GCC's C and C++ personality routines.  For reference, see:
 // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 288fd2714e251..0ec9b43cf3bce 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -63,7 +63,6 @@ use syntax::errors;
 use syntax::ext::hygiene::ExpnId;
 use syntax::print::pprust;
 use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
-use syntax::std_inject;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::parse::token::{self, Token};
@@ -241,7 +240,7 @@ pub fn lower_crate(
     dep_graph.assert_ignored();
 
     LoweringContext {
-        crate_root: std_inject::injected_crate_name().map(Symbol::intern),
+        crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
         sess,
         cstore,
         resolver,
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 63e0107a4d882..45c6aa63c5581 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -112,7 +112,6 @@ pub mod infer;
 pub mod lint;
 
 pub mod middle {
-    pub mod allocator;
     pub mod borrowck;
     pub mod expr_use_visitor;
     pub mod cstore;
diff --git a/src/librustc/middle/allocator.rs b/src/librustc/middle/allocator.rs
deleted file mode 100644
index bb2e3b4ec1971..0000000000000
--- a/src/librustc/middle/allocator.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-#[derive(Clone, Copy)]
-pub enum AllocatorKind {
-    Global,
-    DefaultLib,
-    DefaultExe,
-}
-
-impl AllocatorKind {
-    pub fn fn_name(&self, base: &str) -> String {
-        match *self {
-            AllocatorKind::Global => format!("__rg_{}", base),
-            AllocatorKind::DefaultLib => format!("__rdl_{}", base),
-            AllocatorKind::DefaultExe => format!("__rde_{}", base),
-        }
-    }
-}
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 664926a152f14..d7620817f0448 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -7,7 +7,6 @@ use rustc_data_structures::fingerprint::Fingerprint;
 
 use crate::lint;
 use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::middle::allocator::AllocatorKind;
 use crate::middle::dependency_format;
 use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath};
 use crate::session::search_paths::{PathKind, SearchPath};
@@ -27,6 +26,7 @@ use errors::emitter::HumanReadableErrorType;
 use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter};
 use syntax::ast::{self, NodeId};
 use syntax::edition::Edition;
+use syntax::ext::allocator::AllocatorKind;
 use syntax::feature_gate::{self, AttributeType};
 use syntax::json::JsonEmitter;
 use syntax::source_map;
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 4ed52a1e96638..3b4b814c92a90 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -246,6 +246,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         let align = a.value.align(dl).max(b_align).max(dl.aggregate_align);
         let b_offset = a.value.size(dl).align_to(b_align.abi);
         let size = (b_offset + b.value.size(dl)).align_to(align.abi);
+
+        // HACK(nox): We iter on `b` and then `a` because `max_by_key`
+        // returns the last maximum.
+        let largest_niche = Niche::from_scalar(dl, b_offset, b.clone())
+            .into_iter()
+            .chain(Niche::from_scalar(dl, Size::ZERO, a.clone()))
+            .max_by_key(|niche| niche.available(dl));
+
         LayoutDetails {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldPlacement::Arbitrary {
@@ -253,6 +261,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                 memory_index: vec![0, 1]
             },
             abi: Abi::ScalarPair(a, b),
+            largest_niche,
             align,
             size
         }
@@ -321,6 +330,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
 
         let mut offset = Size::ZERO;
+        let mut largest_niche = None;
+        let mut largest_niche_available = 0;
 
         if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
             let prefix_align = if packed {
@@ -355,6 +366,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             debug!("univariant offset: {:?} field: {:#?}", offset, field);
             offsets[i as usize] = offset;
 
+            if let Some(mut niche) = field.largest_niche.clone() {
+                let available = niche.available(dl);
+                if available > largest_niche_available {
+                    largest_niche_available = available;
+                    niche.offset += offset;
+                    largest_niche = Some(niche);
+                }
+            }
+
             offset = offset.checked_add(field.size, dl)
                 .ok_or(LayoutError::SizeOverflow(ty))?;
         }
@@ -466,6 +486,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                 memory_index
             },
             abi,
+            largest_niche,
             align,
             size
         })
@@ -525,6 +546,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Union(0),
                     abi: Abi::Uninhabited,
+                    largest_niche: None,
                     align: dl.i8_align,
                     size: Size::ZERO
                 })
@@ -583,6 +605,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     Abi::Aggregate { sized: true }
                 };
 
+                let largest_niche = if count != 0 {
+                    element.largest_niche.clone()
+                } else {
+                    None
+                };
+
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
@@ -590,6 +618,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         count
                     },
                     abi,
+                    largest_niche,
                     align: element.align,
                     size
                 })
@@ -603,6 +632,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         count: 0
                     },
                     abi: Abi::Aggregate { sized: false },
+                    largest_niche: None,
                     align: element.align,
                     size: Size::ZERO
                 })
@@ -615,6 +645,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         count: 0
                     },
                     abi: Abi::Aggregate { sized: false },
+                    largest_niche: None,
                     align: dl.i8_align,
                     size: Size::ZERO
                 })
@@ -683,6 +714,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         element: scalar,
                         count
                     },
+                    largest_niche: element.largest_niche.clone(),
                     size,
                     align,
                 })
@@ -768,6 +800,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         variants: Variants::Single { index },
                         fields: FieldPlacement::Union(variants[index].len()),
                         abi,
+                        largest_niche: None,
                         align,
                         size: size.align_to(align.abi)
                     }));
@@ -829,14 +862,38 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                             // `#[rustc_layout_scalar_valid_range(n)]`
                             // attribute to widen the range of anything as that would probably
                             // result in UB somewhere
+                            // FIXME(eddyb) the asserts are probably not needed,
+                            // as larger validity ranges would result in missed
+                            // optimizations, *not* wrongly assuming the inner
+                            // value is valid. e.g. unions enlarge validity ranges,
+                            // because the values may be uninitialized.
                             if let Bound::Included(start) = start {
+                                // FIXME(eddyb) this might be incorrect - it doesn't
+                                // account for wrap-around (end < start) ranges.
                                 assert!(*scalar.valid_range.start() <= start);
                                 scalar.valid_range = start..=*scalar.valid_range.end();
                             }
                             if let Bound::Included(end) = end {
+                                // FIXME(eddyb) this might be incorrect - it doesn't
+                                // account for wrap-around (end < start) ranges.
                                 assert!(*scalar.valid_range.end() >= end);
                                 scalar.valid_range = *scalar.valid_range.start()..=end;
                             }
+
+                            // Update `largest_niche` if we have introduced a larger niche.
+                            let niche = Niche::from_scalar(dl, Size::ZERO, scalar.clone());
+                            if let Some(niche) = niche {
+                                match &st.largest_niche {
+                                    Some(largest_niche) => {
+                                        // Replace the existing niche even if they're equal,
+                                        // because this one is at a lower offset.
+                                        if largest_niche.available(dl) <= niche.available(dl) {
+                                            st.largest_niche = Some(niche);
+                                        }
+                                    }
+                                    None => st.largest_niche = Some(niche),
+                                }
+                            }
                         }
                         _ => assert!(
                             start == Bound::Unbounded && end == Bound::Unbounded,
@@ -845,6 +902,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                             st,
                         ),
                     }
+
                     return Ok(tcx.intern_layout(st));
                 }
 
@@ -886,8 +944,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         let count = (
                             niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1
                         ) as u128;
+                        // FIXME(#62691) use the largest niche across all fields,
+                        // not just the first one.
                         for (field_index, &field) in variants[i].iter().enumerate() {
-                            let niche = match self.find_niche(field)? {
+                            let niche = match &field.largest_niche {
                                 Some(niche) => niche,
                                 _ => continue,
                             };
@@ -937,6 +997,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                                 abi = Abi::Uninhabited;
                             }
 
+
+                            let largest_niche =
+                                Niche::from_scalar(dl, offset, niche_scalar.clone());
+
                             return Ok(tcx.intern_layout(LayoutDetails {
                                 variants: Variants::Multiple {
                                     discr: niche_scalar,
@@ -953,6 +1017,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                                     memory_index: vec![0]
                                 },
                                 abi,
+                                largest_niche,
                                 size,
                                 align,
                             }));
@@ -1164,6 +1229,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     abi = Abi::Uninhabited;
                 }
 
+                let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone());
+
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Multiple {
                         discr: tag,
@@ -1175,6 +1242,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         offsets: vec![Size::ZERO],
                         memory_index: vec![0]
                     },
+                    largest_niche,
                     abi,
                     align,
                     size
@@ -1332,16 +1400,31 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         // locals as part of the prefix. We compute the layout of all of
         // these fields at once to get optimal packing.
         let discr_index = substs.prefix_tys(def_id, tcx).count();
-        let promoted_tys =
-            ineligible_locals.iter().map(|local| subst_field(info.field_tys[local]));
-        let prefix_tys = substs.prefix_tys(def_id, tcx)
-            .chain(iter::once(substs.discr_ty(tcx)))
-            .chain(promoted_tys);
-        let prefix = self.univariant_uninterned(
+        // FIXME(eddyb) set the correct vaidity range for the discriminant.
+        let discr_layout = self.layout_of(substs.discr_ty(tcx))?;
+        let discr = match &discr_layout.abi {
+            Abi::Scalar(s) => s.clone(),
+            _ => bug!(),
+        };
+        // FIXME(eddyb) wrap each promoted type in `MaybeUninit` so that they
+        // don't poison the `largest_niche` or `abi` fields of `prefix`.
+        let promoted_layouts = ineligible_locals.iter()
+            .map(|local| subst_field(info.field_tys[local]))
+            .map(|ty| self.layout_of(ty));
+        let prefix_layouts = substs.prefix_tys(def_id, tcx)
+            .map(|ty| self.layout_of(ty))
+            .chain(iter::once(Ok(discr_layout)))
+            .chain(promoted_layouts)
+            .collect::<Result<Vec<_>, _>>()?;
+        let mut prefix = self.univariant_uninterned(
             ty,
-            &prefix_tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+            &prefix_layouts,
             &ReprOptions::default(),
-            StructKind::AlwaysSized)?;
+            StructKind::AlwaysSized,
+        )?;
+        // FIXME(eddyb) need `MaybeUninit` around promoted types (see above).
+        prefix.largest_niche = None;
+
         let (prefix_size, prefix_align) = (prefix.size, prefix.align);
 
         // Split the prefix layout into the "outer" fields (upvars and
@@ -1463,10 +1546,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         } else {
             Abi::Aggregate { sized: true }
         };
-        let discr = match &self.layout_of(substs.discr_ty(tcx))?.abi {
-            Abi::Scalar(s) => s.clone(),
-            _ => bug!(),
-        };
 
         let layout = tcx.intern_layout(LayoutDetails {
             variants: Variants::Multiple {
@@ -1477,6 +1556,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             },
             fields: outer_fields,
             abi,
+            largest_niche: prefix.largest_niche,
             size,
             align,
         });
@@ -1950,6 +2030,7 @@ where
                     variants: Variants::Single { index: variant_index },
                     fields: FieldPlacement::Union(fields),
                     abi: Abi::Uninhabited,
+                    largest_niche: None,
                     align: tcx.data_layout.i8_align,
                     size: Size::ZERO
                 })
@@ -2222,120 +2303,6 @@ where
     }
 }
 
-struct Niche {
-    offset: Size,
-    scalar: Scalar,
-    available: u128,
-}
-
-impl Niche {
-    fn reserve<'tcx>(
-        &self,
-        cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
-        count: u128,
-    ) -> Option<(u128, Scalar)> {
-        if count > self.available {
-            return None;
-        }
-        let Scalar { value, valid_range: ref v } = self.scalar;
-        let bits = value.size(cx).bits();
-        assert!(bits <= 128);
-        let max_value = !0u128 >> (128 - bits);
-        let start = v.end().wrapping_add(1) & max_value;
-        let end = v.end().wrapping_add(count) & max_value;
-        Some((start, Scalar { value, valid_range: *v.start()..=end }))
-    }
-}
-
-impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
-    /// Find the offset of a niche leaf field, starting from
-    /// the given type and recursing through aggregates.
-    // FIXME(eddyb) traverse already optimized enums.
-    fn find_niche(&self, layout: TyLayout<'tcx>) -> Result<Option<Niche>, LayoutError<'tcx>> {
-        let scalar_niche = |scalar: &Scalar, offset| {
-            let Scalar { value, valid_range: ref v } = *scalar;
-
-            let bits = value.size(self).bits();
-            assert!(bits <= 128);
-            let max_value = !0u128 >> (128 - bits);
-
-            // Find out how many values are outside the valid range.
-            let available = if v.start() <= v.end() {
-                v.start() + (max_value - v.end())
-            } else {
-                v.start() - v.end() - 1
-            };
-
-            // Give up if there is no niche value available.
-            if available == 0 {
-                return None;
-            }
-
-            Some(Niche { offset, scalar: scalar.clone(), available })
-        };
-
-        // Locals variables which live across yields are stored
-        // in the generator type as fields. These may be uninitialized
-        // so we don't look for niches there.
-        if let ty::Generator(..) = layout.ty.sty {
-            return Ok(None);
-        }
-
-        match layout.abi {
-            Abi::Scalar(ref scalar) => {
-                return Ok(scalar_niche(scalar, Size::ZERO));
-            }
-            Abi::ScalarPair(ref a, ref b) => {
-                // HACK(nox): We iter on `b` and then `a` because `max_by_key`
-                // returns the last maximum.
-                let niche = iter::once(
-                    (b, a.value.size(self).align_to(b.value.align(self).abi))
-                )
-                    .chain(iter::once((a, Size::ZERO)))
-                    .filter_map(|(scalar, offset)| scalar_niche(scalar, offset))
-                    .max_by_key(|niche| niche.available);
-                return Ok(niche);
-            }
-            Abi::Vector { ref element, .. } => {
-                return Ok(scalar_niche(element, Size::ZERO));
-            }
-            _ => {}
-        }
-
-        // Perhaps one of the fields is non-zero, let's recurse and find out.
-        if let FieldPlacement::Union(_) = layout.fields {
-            // Only Rust enums have safe-to-inspect fields
-            // (a discriminant), other unions are unsafe.
-            if let Variants::Single { .. } = layout.variants {
-                return Ok(None);
-            }
-        }
-        if let FieldPlacement::Array { count: original_64_bit_count, .. } = layout.fields {
-            // rust-lang/rust#57038: avoid ICE within FieldPlacement::count when count too big
-            if original_64_bit_count > usize::max_value() as u64 {
-                return Err(LayoutError::SizeOverflow(layout.ty));
-            }
-            if layout.fields.count() > 0 {
-                return self.find_niche(layout.field(self, 0)?);
-            } else {
-                return Ok(None);
-            }
-        }
-        let mut niche = None;
-        let mut available = 0;
-        for i in 0..layout.fields.count() {
-            if let Some(mut c) = self.find_niche(layout.field(self, i)?)? {
-                if c.available > available {
-                    available = c.available;
-                    c.offset += layout.fields.offset(i);
-                    niche = Some(c);
-                }
-            }
-        }
-        Ok(niche)
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for Variants {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
@@ -2456,10 +2423,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for Scalar {
     }
 }
 
+impl_stable_hash_for!(struct crate::ty::layout::Niche {
+    offset,
+    scalar
+});
+
 impl_stable_hash_for!(struct crate::ty::layout::LayoutDetails {
     variants,
     fields,
     abi,
+    largest_niche,
     size,
     align
 });
diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml
deleted file mode 100644
index a964f323c9e7d..0000000000000
--- a/src/librustc_allocator/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "rustc_allocator"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-path = "lib.rs"
-test = false
-
-[dependencies]
-rustc = { path = "../librustc" }
-rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_errors = { path = "../librustc_errors" }
-rustc_target = { path = "../librustc_target" }
-syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
-log = "0.4"
-smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs
index 02a05fd110200..5d43bf6ae28bf 100644
--- a/src/librustc_codegen_llvm/allocator.rs
+++ b/src/librustc_codegen_llvm/allocator.rs
@@ -2,9 +2,8 @@ use std::ffi::CString;
 
 use crate::attributes;
 use libc::c_uint;
-use rustc::middle::allocator::AllocatorKind;
 use rustc::ty::TyCtxt;
-use rustc_allocator::{ALLOCATOR_METHODS, AllocatorTy};
+use syntax::ext::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
 
 use crate::ModuleLlvm;
 use crate::llvm::{self, False, True};
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 0f0b9f279175c..8dd241bd81a0a 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -32,7 +32,6 @@ extern crate flate2;
 #[macro_use] extern crate bitflags;
 extern crate libc;
 #[macro_use] extern crate rustc;
-extern crate rustc_allocator;
 extern crate rustc_target;
 #[macro_use] extern crate rustc_data_structures;
 extern crate rustc_incremental;
@@ -52,13 +51,13 @@ use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModul
 use rustc_codegen_ssa::CompiledModule;
 use errors::{FatalError, Handler};
 use rustc::dep_graph::WorkProduct;
+use syntax::ext::allocator::AllocatorKind;
 use syntax_pos::symbol::InternedString;
 pub use llvm_util::target_features;
 use std::any::Any;
 use std::sync::{mpsc, Arc};
 
 use rustc::dep_graph::DepGraph;
-use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
 use rustc::session::Session;
 use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 274c89659628d..541d3d98b79bd 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -174,7 +174,7 @@ const X86_WHITELIST: &[(&str, Option<Symbol>)] = &[
 
 const HEXAGON_WHITELIST: &[(&str, Option<Symbol>)] = &[
     ("hvx", Some(sym::hexagon_target_feature)),
-    ("hvx-double", Some(sym::hexagon_target_feature)),
+    ("hvx-length128b", Some(sym::hexagon_target_feature)),
 ];
 
 const POWERPC_WHITELIST: &[(&str, Option<Symbol>)] = &[
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index e7ee06df7e12d..3c51c777f53e1 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -24,7 +24,6 @@ serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc = { path = "../librustc" }
-rustc_allocator = { path = "../librustc_allocator" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
 rustc_data_structures = { path = "../librustc_data_structures"}
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index c5553fa93cf67..2d9220f897cff 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -1,3 +1,4 @@
+use std::collections::hash_map::Entry::*;
 use std::sync::Arc;
 
 use rustc::ty::Instance;
@@ -12,9 +13,8 @@ use rustc::ty::{TyCtxt, SymbolName};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::util::nodemap::{FxHashMap, DefIdMap};
-use rustc_allocator::ALLOCATOR_METHODS;
 use rustc_data_structures::indexed_vec::IndexVec;
-use std::collections::hash_map::Entry::*;
+use syntax::ext::allocator::ALLOCATOR_METHODS;
 
 pub type ExportedSymbols = FxHashMap<
     CrateNum,
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 9d5aaa7655db8..9fbb44dcc9959 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -3,12 +3,12 @@ use rustc::ty::Ty;
 
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
-use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::{Session, config};
 use rustc::ty::TyCtxt;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use std::sync::Arc;
+use syntax::ext::allocator::AllocatorKind;
 use syntax_pos::symbol::InternedString;
 
 pub trait BackendTypes {
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index d4c30dc6c4507..6a2cfaf60324c 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -10,32 +10,19 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 env_logger = { version = "0.5", default-features = false }
-rayon = { version = "0.2.0", package = "rustc-rayon" }
 rustc = { path = "../librustc" }
-rustc_allocator = { path = "../librustc_allocator" }
 rustc_target = { path = "../librustc_target" }
 rustc_ast_borrowck = { path = "../librustc_ast_borrowck" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
-rustc_incremental = { path = "../librustc_incremental" }
-rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
-rustc_passes = { path = "../librustc_passes" }
-rustc_plugin = { path = "../librustc_plugin" }
-rustc_privacy = { path = "../librustc_privacy" }
-rustc_resolve = { path = "../librustc_resolve" }
 rustc_save_analysis = { path = "../librustc_save_analysis" }
-rustc_traits = { path = "../librustc_traits" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
-rustc_typeck = { path = "../librustc_typeck" }
 rustc_interface = { path = "../librustc_interface" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
-smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
-syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index a0efec5ee7a7f..44fe3ff2c9df8 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -18,7 +18,6 @@ syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
 serialize = { path = "../libserialize" }
 rustc = { path = "../librustc" }
-rustc_allocator = { path = "../librustc_allocator" }
 rustc_ast_borrowck = { path = "../librustc_ast_borrowck" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_traits = { path = "../librustc_traits" }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 6bf56bf851553..010a3c9d657b9 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -277,7 +277,12 @@ pub fn register_plugins<'a>(
 
     krate = time(sess, "crate injection", || {
         let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
-        syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name, sess.edition())
+        let (krate, name) =
+            syntax_ext::standard_library_imports::inject(krate, alt_std_name, sess.edition());
+        if let Some(name) = name {
+            sess.parse_sess.injected_crate_name.set(name);
+        }
+        krate
     });
 
     let registrars = time(sess, "plugin loading", || {
@@ -452,7 +457,7 @@ fn configure_and_expand_inner<'a>(
     sess.profiler(|p| p.end_activity("macro expansion"));
 
     time(sess, "maybe building test harness", || {
-        syntax::test::modify_for_testing(
+        syntax_ext::test_harness::inject(
             &sess.parse_sess,
             &mut resolver,
             sess.opts.test,
@@ -481,7 +486,7 @@ fn configure_and_expand_inner<'a>(
             let num_crate_types = crate_types.len();
             let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro);
             let is_test_crate = sess.opts.test;
-            syntax_ext::proc_macro_decls::modify(
+            syntax_ext::proc_macro_harness::inject(
                 &sess.parse_sess,
                 &mut resolver,
                 krate,
@@ -497,7 +502,7 @@ fn configure_and_expand_inner<'a>(
     if has_global_allocator {
         // Expand global allocators, which are treated as an in-tree proc macro
         time(sess, "creating allocators", || {
-            allocator::expand::modify(
+            syntax_ext::global_allocator::modify(
                 &sess.parse_sess,
                 &mut resolver,
                 &mut krate,
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 21fa872c8dadb..3def2d8232f63 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -71,7 +71,8 @@ fn main() {
 
     let mut optional_components =
         vec!["x86", "arm", "aarch64", "amdgpu", "mips", "powerpc",
-             "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx"];
+             "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx",
+             "hexagon"];
 
     let mut version_cmd = Command::new(&llvm_config);
     version_cmd.arg("--version");
@@ -82,27 +83,19 @@ fn main() {
         if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
             (major, minor)
         } else {
-            (3, 9)
+            (6, 0)
         };
 
-    if major > 3 {
-        optional_components.push("hexagon");
-    }
-
     if major > 6 {
         optional_components.push("riscv");
     }
 
-    // FIXME: surely we don't need all these components, right? Stuff like mcjit
-    //        or interpreter the compiler itself never uses.
     let required_components = &["ipo",
                                 "bitreader",
                                 "bitwriter",
                                 "linker",
                                 "asmparser",
-                                "mcjit",
                                 "lto",
-                                "interpreter",
                                 "instrumentation"];
 
     let components = output(Command::new(&llvm_config).arg("--components"));
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index e5c9f1bf2057b..b21bf89b0de7f 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -21,5 +21,4 @@ rustc_target = { path = "../librustc_target" }
 serialize = { path = "../libserialize" }
 stable_deref_trait = "1.0.0"
 syntax = { path = "../libsyntax" }
-syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 126cfec157ff3..939404b2f45e0 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -8,7 +8,6 @@ use rustc_data_structures::sync::{Lrc, RwLock, Lock};
 
 use rustc::hir::def_id::CrateNum;
 use rustc_data_structures::svh::Svh;
-use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::DepKind;
 use rustc::mir::interpret::AllocDecodingState;
 use rustc::session::{Session, CrateDisambiguator};
@@ -26,6 +25,7 @@ use std::{cmp, fs};
 
 use syntax::ast;
 use syntax::attr;
+use syntax::ext::allocator::AllocatorKind;
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
 use syntax::symbol::{Symbol, sym};
 use syntax::visit;
@@ -587,8 +587,7 @@ impl<'a> CrateLoader<'a> {
         use std::{env, mem};
         use crate::dynamic_lib::DynamicLibrary;
         use proc_macro::bridge::client::ProcMacro;
-        use syntax_ext::deriving::custom::ProcMacroDerive;
-        use syntax_ext::proc_macro_impl::{AttrProcMacro, BangProcMacro};
+        use syntax::ext::proc_macro::{BangProcMacro, AttrProcMacro, ProcMacroDerive};
 
         let path = match dylib {
             Some(dylib) => dylib,
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 914084d7e9ece..ee1175e798d80 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -31,10 +31,10 @@ use syntax::attr;
 use syntax::source_map;
 use syntax::edition::Edition;
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
+use syntax::ext::proc_macro::BangProcMacro;
 use syntax::parse::source_file_to_stream;
 use syntax::parse::parser::emit_unclosed_delims;
 use syntax::symbol::{Symbol, sym};
-use syntax_ext::proc_macro_impl::BangProcMacro;
 use syntax_pos::{Span, NO_EXPANSION, FileName};
 use rustc_data_structures::bit_set::BitSet;
 
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 055568f0a27a2..95c3299693b68 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -3,12 +3,15 @@ use crate::borrow_check::location::LocationTable;
 use crate::borrow_check::nll::ToRegionVid;
 use crate::borrow_check::nll::facts::AllFacts;
 use crate::borrow_check::nll::region_infer::values::LivenessValues;
+use crate::borrow_check::places_conflict;
 use rustc::infer::InferCtxt;
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, BasicBlockData, Location, Body, Place, PlaceBase, Rvalue};
-use rustc::mir::{SourceInfo, Statement, Terminator};
-use rustc::mir::UserTypeProjection;
+use rustc::mir::{
+    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, Projection,
+    ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind,
+    UserTypeProjection,
+};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
 use rustc::ty::subst::SubstsRef;
@@ -27,6 +30,7 @@ pub(super) fn generate_constraints<'cx, 'tcx>(
         liveness_constraints,
         location_table,
         all_facts,
+        body,
     };
 
     for (bb, data) in body.basic_blocks().iter_enumerated() {
@@ -41,6 +45,7 @@ struct ConstraintGeneration<'cg, 'cx, 'tcx> {
     location_table: &'cg LocationTable,
     liveness_constraints: &'cg mut LivenessValues<RegionVid>,
     borrow_set: &'cg BorrowSet<'tcx>,
+    body: &'cg Body<'tcx>,
 }
 
 impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
@@ -114,6 +119,17 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
                 self.location_table
                     .start_index(location.successor_within_block()),
             ));
+
+            // If there are borrows on this now dead local, we need to record them as `killed`.
+            if let StatementKind::StorageDead(ref local) = statement.kind {
+                record_killed_borrows_for_local(
+                    all_facts,
+                    self.borrow_set,
+                    self.location_table,
+                    local,
+                    location,
+                );
+            }
         }
 
         self.super_statement(statement, location);
@@ -127,20 +143,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
     ) {
         // When we see `X = ...`, then kill borrows of
         // `(*X).foo` and so forth.
-        if let Some(all_facts) = self.all_facts {
-            if let Place {
-                base: PlaceBase::Local(temp),
-                projection: None,
-            } = place {
-                if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) {
-                    all_facts.killed.reserve(borrow_indices.len());
-                    for &borrow_index in borrow_indices {
-                        let location_index = self.location_table.mid_index(location);
-                        all_facts.killed.push((borrow_index, location_index));
-                    }
-                }
-            }
-        }
+        self.record_killed_borrows_for_place(place, location);
 
         self.super_assign(place, rvalue, location);
     }
@@ -167,6 +170,14 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
             }
         }
 
+        // A `Call` terminator's return value can be a local which has borrows,
+        // so we need to record those as `killed` as well.
+        if let TerminatorKind::Call { ref destination, .. } = terminator.kind {
+            if let Some((place, _)) = destination {
+                self.record_killed_borrows_for_place(place, location);
+            }
+        }
+
         self.super_terminator(terminator, location);
     }
 
@@ -201,4 +212,96 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
                 self.liveness_constraints.add_element(vid, location);
             });
     }
+
+    /// When recording facts for Polonius, records the borrows on the specified place
+    /// as `killed`. For example, when assigning to a local, or on a call's return destination.
+    fn record_killed_borrows_for_place(&mut self, place: &Place<'tcx>, location: Location) {
+        if let Some(all_facts) = self.all_facts {
+            // Depending on the `Place` we're killing:
+            // - if it's a local, or a single deref of a local,
+            //   we kill all the borrows on the local.
+            // - if it's a deeper projection, we have to filter which
+            //   of the borrows are killed: the ones whose `borrowed_place`
+            //   conflicts with the `place`.
+            match place {
+                Place {
+                    base: PlaceBase::Local(local),
+                    projection: None,
+                } |
+                Place {
+                    base: PlaceBase::Local(local),
+                    projection: Some(box Projection {
+                        base: None,
+                        elem: ProjectionElem::Deref,
+                    }),
+                } => {
+                    debug!(
+                        "Recording `killed` facts for borrows of local={:?} at location={:?}",
+                        local, location
+                    );
+
+                    record_killed_borrows_for_local(
+                        all_facts,
+                        self.borrow_set,
+                        self.location_table,
+                        local,
+                        location,
+                    );
+                }
+
+                Place {
+                    base: PlaceBase::Static(_),
+                    ..
+                } => {
+                    // Ignore kills of static or static mut variables.
+                }
+
+                Place {
+                    base: PlaceBase::Local(local),
+                    projection: Some(_),
+                } => {
+                    // Kill conflicting borrows of the innermost local.
+                    debug!(
+                        "Recording `killed` facts for borrows of \
+                            innermost projected local={:?} at location={:?}",
+                        local, location
+                    );
+
+                    if let Some(borrow_indices) = self.borrow_set.local_map.get(local) {
+                        for &borrow_index in borrow_indices {
+                            let places_conflict = places_conflict::places_conflict(
+                                self.infcx.tcx,
+                                self.body,
+                                &self.borrow_set.borrows[borrow_index].borrowed_place,
+                                place,
+                                places_conflict::PlaceConflictBias::NoOverlap,
+                            );
+
+                            if places_conflict {
+                                let location_index = self.location_table.mid_index(location);
+                                all_facts.killed.push((borrow_index, location_index));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+/// When recording facts for Polonius, records the borrows on the specified local as `killed`.
+fn record_killed_borrows_for_local(
+    all_facts: &mut AllFacts,
+    borrow_set: &BorrowSet<'_>,
+    location_table: &LocationTable,
+    local: &Local,
+    location: Location,
+) {
+    if let Some(borrow_indices) = borrow_set.local_map.get(local) {
+        all_facts.killed.reserve(borrow_indices.len());
+        for &borrow_index in borrow_indices {
+            let location_index = location_table.mid_index(location);
+            all_facts.killed.push((borrow_index, location_index));
+        }
+    }
 }
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index de2476775b07e..596ec6c19bcbf 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -11,9 +11,7 @@ path = "lib.rs"
 [dependencies]
 log = "0.4"
 rustc = { path = "../librustc" }
-rustc_mir = { path = "../librustc_mir"}
 rustc_data_structures = { path = "../librustc_data_structures" }
 syntax = { path = "../libsyntax" }
-syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 560635962995c..32d0564d12410 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -14,12 +14,12 @@ use rustc::session::Session;
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast::*;
 use syntax::attr;
+use syntax::ext::proc_macro::is_proc_macro_attr;
 use syntax::feature_gate::is_builtin_attr;
 use syntax::source_map::Spanned;
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 use syntax::{span_err, struct_span_err, walk_list};
-use syntax_ext::proc_macro_decls::is_proc_macro_attr;
 use syntax_pos::{Span, MultiSpan};
 use errors::{Applicability, FatalError};
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index cfba42580fcef..2f3f2b3842505 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -35,7 +35,6 @@ use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::is_builtin_attr;
 use syntax::parse::token::{self, Token};
 use syntax::span_err;
-use syntax::std_inject::injected_crate_name;
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 
@@ -368,8 +367,10 @@ impl<'a> Resolver<'a> {
                 };
 
                 self.populate_module_if_necessary(module);
-                if injected_crate_name().map_or(false, |name| ident.name.as_str() == name) {
-                    self.injected_crate = Some(module);
+                if let Some(name) = self.session.parse_sess.injected_crate_name.try_get() {
+                    if name.as_str() == ident.name.as_str() {
+                        self.injected_crate = Some(module);
+                    }
                 }
 
                 let used = self.process_legacy_macro_imports(item, module, &parent_scope);
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 01586e92aeb1c..4a4c6799c005e 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -878,23 +878,94 @@ pub enum DiscriminantKind {
     },
 }
 
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct Niche {
+    pub offset: Size,
+    pub scalar: Scalar,
+}
+
+impl Niche {
+    pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
+        let niche = Niche {
+            offset,
+            scalar,
+        };
+        if niche.available(cx) > 0 {
+            Some(niche)
+        } else {
+            None
+        }
+    }
+
+    pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
+        let Scalar { value, valid_range: ref v } = self.scalar;
+        let bits = value.size(cx).bits();
+        assert!(bits <= 128);
+        let max_value = !0u128 >> (128 - bits);
+
+        // Find out how many values are outside the valid range.
+        let niche = v.end().wrapping_add(1)..*v.start();
+        niche.end.wrapping_sub(niche.start) & max_value
+    }
+
+    pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
+        assert!(count > 0);
+
+        let Scalar { value, valid_range: ref v } = self.scalar;
+        let bits = value.size(cx).bits();
+        assert!(bits <= 128);
+        let max_value = !0u128 >> (128 - bits);
+
+        if count > max_value {
+            return None;
+        }
+
+        // Compute the range of invalid values being reserved.
+        let start = v.end().wrapping_add(1) & max_value;
+        let end = v.end().wrapping_add(count) & max_value;
+
+        // If the `end` of our range is inside the valid range,
+        // then we ran out of invalid values.
+        // FIXME(eddyb) abstract this with a wraparound range type.
+        let valid_range_contains = |x| {
+            if v.start() <= v.end() {
+                *v.start() <= x && x <= *v.end()
+            } else {
+                *v.start() <= x || x <= *v.end()
+            }
+        };
+        if valid_range_contains(end) {
+            return None;
+        }
+
+        Some((start, Scalar { value, valid_range: *v.start()..=end }))
+    }
+}
+
 #[derive(PartialEq, Eq, Hash, Debug)]
 pub struct LayoutDetails {
     pub variants: Variants,
     pub fields: FieldPlacement,
     pub abi: Abi,
+
+    /// The leaf scalar with the largest number of invalid values
+    /// (i.e. outside of its `valid_range`), if it exists.
+    pub largest_niche: Option<Niche>,
+
     pub align: AbiAndPrefAlign,
     pub size: Size
 }
 
 impl LayoutDetails {
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
+        let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone());
         let size = scalar.value.size(cx);
         let align = scalar.value.align(cx);
         LayoutDetails {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldPlacement::Union(0),
             abi: Abi::Scalar(scalar),
+            largest_niche,
             size,
             align,
         }
diff --git a/src/librustc_target/spec/hexagon_unknown_linux_musl.rs b/src/librustc_target/spec/hexagon_unknown_linux_musl.rs
new file mode 100644
index 0000000000000..1d3b13d488366
--- /dev/null
+++ b/src/librustc_target/spec/hexagon_unknown_linux_musl.rs
@@ -0,0 +1,36 @@
+use crate::spec::{LinkerFlavor, Target, TargetResult, LinkArgs};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+    base.cpu = "hexagonv60".to_string();
+    base.max_atomic_width = Some(32);
+        // FIXME: HVX length defaults are per-CPU
+    base.features = "-small-data,+hvx-length128b".to_string();
+
+    base.crt_static_default = false;
+    base.atomic_cas = true;
+    base.has_rpath = true;
+    base.linker_is_gnu = false;
+    base.dynamic_linking = true;
+    base.executables = true;
+
+    base.pre_link_args = LinkArgs::new();
+    base.post_link_args = LinkArgs::new();
+
+    Ok(Target {
+        llvm_target: "hexagon-unknown-linux-musl".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: concat!("e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
+                     ":32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32",
+                     ":32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048",
+                     ":2048:2048").to_string(),
+        arch: "hexagon".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 4765d1a045504..ed62eb0dd20fc 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -368,6 +368,7 @@ supported_targets! {
     ("i586-unknown-linux-musl", i586_unknown_linux_musl),
     ("mips-unknown-linux-musl", mips_unknown_linux_musl),
     ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
+    ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
 
     ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
     ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
@@ -464,6 +465,7 @@ supported_targets! {
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
 
+    ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
     ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
diff --git a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
new file mode 100644
index 0000000000000..314778408f7e5
--- /dev/null
+++ b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
@@ -0,0 +1,32 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy,
+           Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        llvm_target: "riscv32".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: "unknown".to_string(),
+        arch: "riscv32".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+
+        options: TargetOptions {
+            linker: Some("rust-lld".to_string()),
+            cpu: "generic-rv32".to_string(),
+            max_atomic_width: None,
+            atomic_cas: false,
+            features: String::new(),
+            executables: true,
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: "static".to_string(),
+            emit_debug_gdb_scripts: false,
+            abi_blacklist: super::riscv_base::abi_blacklist(),
+            eliminate_frame_pointer: false,
+            .. Default::default()
+        },
+    })
+}
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 00e840a53e9c0..1f5de25b65c90 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -975,6 +975,11 @@ mod arch {
     pub const ARCH: &str = "wasm32";
 }
 
+#[cfg(target_arch = "hexagon")]
+mod arch {
+    pub const ARCH: &'static str = "hexagon";
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index 77eeacb4b477c..21e1cf8a22b4b 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -147,6 +147,62 @@ mod arch {
     }
 }
 
+#[cfg(target_arch = "hexagon")]
+mod arch {
+    use crate::os::raw::{c_long, c_int, c_longlong, culonglong};
+
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = c_longlong;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = c_long;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = c_ulonglong;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = c_uint;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = c_longlong;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = c_long;
+
+    #[repr(C)]
+    #[derive(Clone)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: ::dev_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: ::c_ulonglong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: ::c_ulonglong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad1: ::c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: ::c_longlong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: ::blksize_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad2: ::c_int,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: ::blkcnt_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: ::time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: ::c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: ::time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: ::c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: ::time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: ::c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad3: [::c_int;2],
+    }
+}
+
 #[cfg(any(target_arch = "mips64",
           target_arch = "s390x",
           target_arch = "sparc64"))]
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index c0b0b6d40d891..cf8be393a4049 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -11,6 +11,7 @@
 #[doc(include = "os/raw/char.md")]
 #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                        target_arch = "arm",
+                                       target_arch = "hexagon",
                                        target_arch = "powerpc",
                                        target_arch = "powerpc64",
                                        target_arch = "s390x")),
@@ -34,6 +35,7 @@
 #[doc(include = "os/raw/char.md")]
 #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                            target_arch = "arm",
+                                           target_arch = "hexagon",
                                            target_arch = "powerpc",
                                            target_arch = "powerpc64",
                                            target_arch = "s390x")),
diff --git a/src/libstd/sys_common/alloc.rs b/src/libstd/sys_common/alloc.rs
index 978a70bee0983..1cfc7ed17f2e4 100644
--- a/src/libstd/sys_common/alloc.rs
+++ b/src/libstd/sys_common/alloc.rs
@@ -12,7 +12,8 @@ use crate::ptr;
               target_arch = "powerpc",
               target_arch = "powerpc64",
               target_arch = "asmjs",
-              target_arch = "wasm32")))]
+              target_arch = "wasm32",
+              target_arch = "hexagon")))]
 pub const MIN_ALIGN: usize = 8;
 #[cfg(all(any(target_arch = "x86_64",
               target_arch = "aarch64",
diff --git a/src/librustc_allocator/lib.rs b/src/libsyntax/ext/allocator.rs
similarity index 68%
rename from src/librustc_allocator/lib.rs
rename to src/libsyntax/ext/allocator.rs
index 8d380c47bc4a3..f2c6bf27cee0c 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/libsyntax/ext/allocator.rs
@@ -1,10 +1,33 @@
-#![feature(nll)]
-#![feature(rustc_private)]
+#[derive(Clone, Copy)]
+pub enum AllocatorKind {
+    Global,
+    DefaultLib,
+    DefaultExe,
+}
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
+impl AllocatorKind {
+    pub fn fn_name(&self, base: &str) -> String {
+        match *self {
+            AllocatorKind::Global => format!("__rg_{}", base),
+            AllocatorKind::DefaultLib => format!("__rdl_{}", base),
+            AllocatorKind::DefaultExe => format!("__rde_{}", base),
+        }
+    }
+}
 
-pub mod expand;
+pub enum AllocatorTy {
+    Layout,
+    Ptr,
+    ResultPtr,
+    Unit,
+    Usize,
+}
+
+pub struct AllocatorMethod {
+    pub name: &'static str,
+    pub inputs: &'static [AllocatorTy],
+    pub output: AllocatorTy,
+}
 
 pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
     AllocatorMethod {
@@ -28,17 +51,3 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
         output: AllocatorTy::ResultPtr,
     },
 ];
-
-pub struct AllocatorMethod {
-    pub name: &'static str,
-    pub inputs: &'static [AllocatorTy],
-    pub output: AllocatorTy,
-}
-
-pub enum AllocatorTy {
-    Layout,
-    Ptr,
-    ResultPtr,
-    Unit,
-    Usize,
-}
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 926c9e88efe15..c6427d6e72411 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -14,7 +14,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree};
 
 use errors::{DiagnosticBuilder, DiagnosticId};
 use smallvec::{smallvec, SmallVec};
-use syntax_pos::{Span, MultiSpan, DUMMY_SP};
+use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP};
 use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
 
 use rustc_data_structures::fx::FxHashMap;
@@ -889,6 +889,27 @@ impl<'a> ExtCtxt<'a> {
     pub fn check_unused_macros(&self) {
         self.resolver.check_unused_macros();
     }
+
+    // resolve a file-system path to an absolute file-system path (if it
+    // isn't already)
+    pub fn res_rel_file(&self, sp: syntax_pos::Span, arg: String) -> PathBuf {
+        let arg = PathBuf::from(arg);
+        // Relative paths are resolved relative to the file in which they are found
+        // after macro expansion (that is, they are unhygienic).
+        if !arg.is_absolute() {
+            let callsite = sp.source_callsite();
+            let mut path = match self.source_map().span_to_unmapped_path(callsite) {
+                FileName::Real(path) => path,
+                FileName::DocTest(path, _) => path,
+                other => panic!("cannot resolve relative path in non-file source `{}`", other),
+            };
+            path.pop();
+            path.push(arg);
+            path
+        } else {
+            arg
+        }
+    }
 }
 
 /// Extracts a string literal from the macro expanded version of `expr`,
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
deleted file mode 100644
index ff9ad46deecc0..0000000000000
--- a/src/libsyntax/ext/derive.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use crate::attr::HasAttrs;
-use crate::ast;
-use crate::source_map::{ExpnInfo, ExpnKind};
-use crate::ext::base::{ExtCtxt, MacroKind};
-use crate::ext::build::AstBuilder;
-use crate::parse::parser::PathStyle;
-use crate::symbol::{Symbol, sym};
-use crate::errors::Applicability;
-
-use syntax_pos::Span;
-use rustc_data_structures::fx::FxHashSet;
-
-pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
-    let mut result = Vec::new();
-    attrs.retain(|attr| {
-        if attr.path != sym::derive {
-            return true;
-        }
-        if !attr.is_meta_item_list() {
-            cx.struct_span_err(attr.span, "malformed `derive` attribute input")
-                .span_suggestion(
-                    attr.span,
-                    "missing traits to be derived",
-                    "#[derive(Trait1, Trait2, ...)]".to_owned(),
-                    Applicability::HasPlaceholders,
-                ).emit();
-            return false;
-        }
-
-        match attr.parse_list(cx.parse_sess,
-                              |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
-            Ok(traits) => {
-                result.extend(traits);
-                true
-            }
-            Err(mut e) => {
-                e.emit();
-                false
-            }
-        }
-    });
-    result
-}
-
-pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T)
-    where T: HasAttrs,
-{
-    let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
-    for (i, path) in traits.iter().enumerate() {
-        if i > 0 {
-            pretty_name.push_str(", ");
-        }
-        pretty_name.push_str(&path.to_string());
-        names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
-    }
-
-    let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable(
-        ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
-        cx.parse_sess.edition, cx.allow_derive_markers.clone(),
-    ));
-
-    item.visit_attrs(|attrs| {
-        if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
-            let meta = cx.meta_word(span, sym::structural_match);
-            attrs.push(cx.attribute(span, meta));
-        }
-        if names.contains(&sym::Copy) {
-            let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
-            attrs.push(cx.attribute(span, meta));
-        }
-    });
-}
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index ae72f1fd108ed..6553c23e1cf5f 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -4,7 +4,7 @@ use crate::attr::{self, HasAttrs};
 use crate::source_map::{dummy_spanned, respan};
 use crate::config::StripUnconfigured;
 use crate::ext::base::*;
-use crate::ext::derive::{add_derived_markers, collect_derives};
+use crate::ext::proc_macro::{add_derived_markers, collect_derives};
 use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind};
 use crate::ext::placeholders::{placeholder, PlaceholderExpander};
 use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs
new file mode 100644
index 0000000000000..425b9813f5904
--- /dev/null
+++ b/src/libsyntax/ext/proc_macro.rs
@@ -0,0 +1,249 @@
+use crate::ast::{self, ItemKind, Attribute, Mac};
+use crate::attr::{mark_used, mark_known, HasAttrs};
+use crate::errors::{Applicability, FatalError};
+use crate::ext::base::{self, *};
+use crate::ext::build::AstBuilder;
+use crate::ext::proc_macro_server;
+use crate::parse::{self, token};
+use crate::parse::parser::PathStyle;
+use crate::symbol::{sym, Symbol};
+use crate::tokenstream::{self, TokenStream};
+use crate::visit::Visitor;
+
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
+use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
+use syntax_pos::{Span, DUMMY_SP};
+
+const EXEC_STRATEGY: proc_macro::bridge::server::SameThread =
+    proc_macro::bridge::server::SameThread;
+
+pub struct BangProcMacro {
+    pub client: proc_macro::bridge::client::Client<
+        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
+    >,
+}
+
+impl base::ProcMacro for BangProcMacro {
+    fn expand<'cx>(&self,
+                   ecx: &'cx mut ExtCtxt<'_>,
+                   span: Span,
+                   input: TokenStream)
+                   -> TokenStream {
+        let server = proc_macro_server::Rustc::new(ecx);
+        match self.client.run(&EXEC_STRATEGY, server, input) {
+            Ok(stream) => stream,
+            Err(e) => {
+                let msg = "proc macro panicked";
+                let mut err = ecx.struct_span_fatal(span, msg);
+                if let Some(s) = e.as_str() {
+                    err.help(&format!("message: {}", s));
+                }
+
+                err.emit();
+                FatalError.raise();
+            }
+        }
+    }
+}
+
+pub struct AttrProcMacro {
+    pub client: proc_macro::bridge::client::Client<
+        fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream,
+    >,
+}
+
+impl base::AttrProcMacro for AttrProcMacro {
+    fn expand<'cx>(&self,
+                   ecx: &'cx mut ExtCtxt<'_>,
+                   span: Span,
+                   annotation: TokenStream,
+                   annotated: TokenStream)
+                   -> TokenStream {
+        let server = proc_macro_server::Rustc::new(ecx);
+        match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
+            Ok(stream) => stream,
+            Err(e) => {
+                let msg = "custom attribute panicked";
+                let mut err = ecx.struct_span_fatal(span, msg);
+                if let Some(s) = e.as_str() {
+                    err.help(&format!("message: {}", s));
+                }
+
+                err.emit();
+                FatalError.raise();
+            }
+        }
+    }
+}
+
+pub struct ProcMacroDerive {
+    pub client: proc_macro::bridge::client::Client<
+        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
+    >,
+    pub attrs: Vec<ast::Name>,
+}
+
+impl MultiItemModifier for ProcMacroDerive {
+    fn expand(&self,
+              ecx: &mut ExtCtxt<'_>,
+              span: Span,
+              _meta_item: &ast::MetaItem,
+              item: Annotatable)
+              -> Vec<Annotatable> {
+        let item = match item {
+            Annotatable::Item(item) => item,
+            Annotatable::ImplItem(_) |
+            Annotatable::TraitItem(_) |
+            Annotatable::ForeignItem(_) |
+            Annotatable::Stmt(_) |
+            Annotatable::Expr(_) => {
+                ecx.span_err(span, "proc-macro derives may only be \
+                                    applied to a struct, enum, or union");
+                return Vec::new()
+            }
+        };
+        match item.node {
+            ItemKind::Struct(..) |
+            ItemKind::Enum(..) |
+            ItemKind::Union(..) => {},
+            _ => {
+                ecx.span_err(span, "proc-macro derives may only be \
+                                    applied to a struct, enum, or union");
+                return Vec::new()
+            }
+        }
+
+        // Mark attributes as known, and used.
+        MarkAttrs(&self.attrs).visit_item(&item);
+
+        let token = token::Interpolated(Lrc::new(token::NtItem(item)));
+        let input = tokenstream::TokenTree::token(token, DUMMY_SP).into();
+
+        let server = proc_macro_server::Rustc::new(ecx);
+        let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
+            Ok(stream) => stream,
+            Err(e) => {
+                let msg = "proc-macro derive panicked";
+                let mut err = ecx.struct_span_fatal(span, msg);
+                if let Some(s) = e.as_str() {
+                    err.help(&format!("message: {}", s));
+                }
+
+                err.emit();
+                FatalError.raise();
+            }
+        };
+
+        let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
+        let msg = "proc-macro derive produced unparseable tokens";
+
+        let mut parser = parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive"));
+        let mut items = vec![];
+
+        loop {
+            match parser.parse_item() {
+                Ok(None) => break,
+                Ok(Some(item)) => {
+                    items.push(Annotatable::Item(item))
+                }
+                Err(mut err) => {
+                    // FIXME: handle this better
+                    err.cancel();
+                    ecx.struct_span_fatal(span, msg).emit();
+                    FatalError.raise();
+                }
+            }
+        }
+
+
+        // fail if there have been errors emitted
+        if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
+            ecx.struct_span_fatal(span, msg).emit();
+            FatalError.raise();
+        }
+
+        items
+    }
+}
+
+struct MarkAttrs<'a>(&'a [ast::Name]);
+
+impl<'a> Visitor<'a> for MarkAttrs<'a> {
+    fn visit_attribute(&mut self, attr: &Attribute) {
+        if let Some(ident) = attr.ident() {
+            if self.0.contains(&ident.name) {
+                mark_used(attr);
+                mark_known(attr);
+            }
+        }
+    }
+
+    fn visit_mac(&mut self, _mac: &Mac) {}
+}
+
+pub fn is_proc_macro_attr(attr: &Attribute) -> bool {
+    [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
+        .iter().any(|kind| attr.check_name(*kind))
+}
+
+crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
+    let mut result = Vec::new();
+    attrs.retain(|attr| {
+        if attr.path != sym::derive {
+            return true;
+        }
+        if !attr.is_meta_item_list() {
+            cx.struct_span_err(attr.span, "malformed `derive` attribute input")
+                .span_suggestion(
+                    attr.span,
+                    "missing traits to be derived",
+                    "#[derive(Trait1, Trait2, ...)]".to_owned(),
+                    Applicability::HasPlaceholders,
+                ).emit();
+            return false;
+        }
+
+        match attr.parse_list(cx.parse_sess,
+                              |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
+            Ok(traits) => {
+                result.extend(traits);
+                true
+            }
+            Err(mut e) => {
+                e.emit();
+                false
+            }
+        }
+    });
+    result
+}
+
+crate fn add_derived_markers<T: HasAttrs>(
+    cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T
+) {
+    let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
+    for (i, path) in traits.iter().enumerate() {
+        if i > 0 {
+            pretty_name.push_str(", ");
+        }
+        pretty_name.push_str(&path.to_string());
+        names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
+    }
+
+    let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
+        cx.parse_sess.edition, cx.allow_derive_markers.clone(),
+    ));
+
+    item.visit_attrs(|attrs| {
+        if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
+            let meta = cx.meta_word(span, sym::structural_match);
+            attrs.push(cx.attribute(span, meta));
+        }
+        if names.contains(&sym::Copy) {
+            let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
+            attrs.push(cx.attribute(span, meta));
+        }
+    });
+}
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
similarity index 98%
rename from src/libsyntax_ext/proc_macro_server.rs
rename to src/libsyntax/ext/proc_macro_server.rs
index e94d79a140da8..8d0023c9ab1eb 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax/ext/proc_macro_server.rs
@@ -1,21 +1,19 @@
-use errors::{Diagnostic, DiagnosticBuilder};
-
-use std::panic;
-
-use proc_macro::bridge::{server, TokenTree};
-use proc_macro::{Delimiter, Level, LineColumn, Spacing};
+use crate::ast;
+use crate::ext::base::ExtCtxt;
+use crate::parse::{self, token, ParseSess};
+use crate::parse::lexer::comments;
+use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
 
+use errors::{Diagnostic, DiagnosticBuilder};
 use rustc_data_structures::sync::Lrc;
-use std::ascii;
-use std::ops::Bound;
-use syntax::ast;
-use syntax::ext::base::ExtCtxt;
-use syntax::parse::lexer::comments;
-use syntax::parse::{self, token, ParseSess};
-use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
+use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
 use syntax_pos::hygiene::{SyntaxContext, Transparency};
 use syntax_pos::symbol::{kw, sym, Symbol};
-use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
+
+use proc_macro::{Delimiter, Level, LineColumn, Spacing};
+use proc_macro::bridge::{server, TokenTree};
+use std::{ascii, panic};
+use std::ops::Bound;
 
 trait FromInternal<T> {
     fn from_internal(x: T) -> Self;
@@ -52,7 +50,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
 {
     fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>))
                     -> Self {
-        use syntax::parse::token::*;
+        use crate::parse::token::*;
 
         let joint = is_joint == Joint;
         let Token { kind, span } = match tree {
@@ -193,7 +191,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
 
 impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
     fn to_internal(self) -> TokenStream {
-        use syntax::parse::token::*;
+        use crate::parse::token::*;
 
         let (ch, joint, span) = match self {
             TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span),
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 3dea1977c4dac..6bb61e90f500e 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -18,13 +18,16 @@
 #![feature(label_break_value)]
 #![feature(mem_take)]
 #![feature(nll)]
+#![feature(proc_macro_diagnostic)]
+#![feature(proc_macro_internals)]
+#![feature(proc_macro_span)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(try_trait)]
 #![feature(unicode_internals)]
 
 #![recursion_limit="256"]
 
-#[allow(unused_extern_crates)]
+extern crate proc_macro;
 extern crate serialize as rustc_serialize; // used by deriving
 
 pub use errors;
@@ -40,6 +43,7 @@ const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments");
 // way towards a non-panic!-prone parser. It should be used for fatal parsing
 // errors; eventually we plan to convert all code using panictry to just use
 // normal try.
+#[macro_export]
 macro_rules! panictry {
     ($e:expr) => ({
         use std::result::Result::{Ok, Err};
@@ -150,10 +154,8 @@ pub mod mut_visit;
 pub mod parse;
 pub mod ptr;
 pub mod show_span;
-pub mod std_inject;
 pub use syntax_pos::edition;
 pub use syntax_pos::symbol;
-pub mod test;
 pub mod tokenstream;
 pub mod visit;
 
@@ -164,13 +166,15 @@ pub mod print {
 }
 
 pub mod ext {
+    mod placeholders;
+    mod proc_macro_server;
+
     pub use syntax_pos::hygiene;
+    pub mod allocator;
     pub mod base;
     pub mod build;
-    pub mod derive;
     pub mod expand;
-    pub mod placeholders;
-    pub mod source_util;
+    pub mod proc_macro;
 
     pub mod tt {
         pub mod transcribe;
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index b97801a50d472..e6f7889fe01fe 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -784,7 +784,7 @@ mod tests {
     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;
+    use rustc_data_structures::sync::{Lock, Once};
 
     fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
         let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
@@ -807,6 +807,7 @@ mod tests {
             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(),
         }
     }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 225065c1cf11f..1aac8bbb7aa46 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -10,9 +10,10 @@ use crate::parse::token::TokenKind;
 use crate::tokenstream::{TokenStream, TokenTree};
 use crate::diagnostics::plugin::ErrorMap;
 use crate::print::pprust;
+use crate::symbol::Symbol;
 
 use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
-use rustc_data_structures::sync::{Lrc, Lock};
+use rustc_data_structures::sync::{Lrc, Lock, Once};
 use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
 use syntax_pos::edition::Edition;
 
@@ -58,6 +59,7 @@ pub struct ParseSess {
     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>>,
+    pub injected_crate_name: Once<Symbol>,
 }
 
 impl ParseSess {
@@ -86,6 +88,7 @@ impl ParseSess {
             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(),
         }
     }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 16e0bace92584..c462357639506 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -10,7 +10,6 @@ use crate::parse::{self, ParseSess};
 use crate::print::pp::{self, Breaks};
 use crate::print::pp::Breaks::{Consistent, Inconsistent};
 use crate::ptr::P;
-use crate::std_inject;
 use crate::symbol::{kw, sym};
 use crate::tokenstream::{self, TokenStream, TokenTree};
 
@@ -114,7 +113,7 @@ pub fn print_crate<'a>(cm: &'a SourceMap,
         is_expanded,
     };
 
-    if is_expanded && std_inject::injected_crate_name().is_some() {
+    if is_expanded && sess.injected_crate_name.try_get().is_some() {
         // We need to print `#![no_std]` (and its feature gate) so that
         // compiling pretty-printed source won't inject libstd again.
         // However we don't want these attributes in the AST because
diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml
index eafbe6371a3c5..73310df305b32 100644
--- a/src/libsyntax_ext/Cargo.toml
+++ b/src/libsyntax_ext/Cargo.toml
@@ -10,11 +10,11 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-fmt_macros = { path = "../libfmt_macros" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
-syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
+fmt_macros = { path = "../libfmt_macros" }
+log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
-log = "0.4"
+syntax = { path = "../libsyntax" }
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
deleted file mode 100644
index 98465d75e4680..0000000000000
--- a/src/libsyntax_ext/deriving/custom.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-use crate::proc_macro_impl::EXEC_STRATEGY;
-use crate::proc_macro_server;
-
-use errors::FatalError;
-use rustc_data_structures::sync::Lrc;
-use syntax::ast::{self, ItemKind, Attribute, Mac};
-use syntax::attr::{mark_used, mark_known};
-use syntax::source_map::Span;
-use syntax::ext::base::*;
-use syntax::parse;
-use syntax::parse::token;
-use syntax::tokenstream;
-use syntax::visit::Visitor;
-use syntax_pos::DUMMY_SP;
-
-struct MarkAttrs<'a>(&'a [ast::Name]);
-
-impl<'a> Visitor<'a> for MarkAttrs<'a> {
-    fn visit_attribute(&mut self, attr: &Attribute) {
-        if let Some(ident) = attr.ident() {
-            if self.0.contains(&ident.name) {
-                mark_used(attr);
-                mark_known(attr);
-            }
-        }
-    }
-
-    fn visit_mac(&mut self, _mac: &Mac) {}
-}
-
-pub struct ProcMacroDerive {
-    pub client: proc_macro::bridge::client::Client<
-        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
-    >,
-    pub attrs: Vec<ast::Name>,
-}
-
-impl MultiItemModifier for ProcMacroDerive {
-    fn expand(&self,
-              ecx: &mut ExtCtxt<'_>,
-              span: Span,
-              _meta_item: &ast::MetaItem,
-              item: Annotatable)
-              -> Vec<Annotatable> {
-        let item = match item {
-            Annotatable::Item(item) => item,
-            Annotatable::ImplItem(_) |
-            Annotatable::TraitItem(_) |
-            Annotatable::ForeignItem(_) |
-            Annotatable::Stmt(_) |
-            Annotatable::Expr(_) => {
-                ecx.span_err(span, "proc-macro derives may only be \
-                                    applied to a struct, enum, or union");
-                return Vec::new()
-            }
-        };
-        match item.node {
-            ItemKind::Struct(..) |
-            ItemKind::Enum(..) |
-            ItemKind::Union(..) => {},
-            _ => {
-                ecx.span_err(span, "proc-macro derives may only be \
-                                    applied to a struct, enum, or union");
-                return Vec::new()
-            }
-        }
-
-        // Mark attributes as known, and used.
-        MarkAttrs(&self.attrs).visit_item(&item);
-
-        let token = token::Interpolated(Lrc::new(token::NtItem(item)));
-        let input = tokenstream::TokenTree::token(token, DUMMY_SP).into();
-
-        let server = proc_macro_server::Rustc::new(ecx);
-        let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
-            Ok(stream) => stream,
-            Err(e) => {
-                let msg = "proc-macro derive panicked";
-                let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.as_str() {
-                    err.help(&format!("message: {}", s));
-                }
-
-                err.emit();
-                FatalError.raise();
-            }
-        };
-
-        let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
-        let msg = "proc-macro derive produced unparseable tokens";
-
-        let mut parser = parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive"));
-        let mut items = vec![];
-
-        loop {
-            match parser.parse_item() {
-                Ok(None) => break,
-                Ok(Some(item)) => {
-                    items.push(Annotatable::Item(item))
-                }
-                Err(mut err) => {
-                    // FIXME: handle this better
-                    err.cancel();
-                    ecx.struct_span_fatal(span, msg).emit();
-                    FatalError.raise();
-                }
-            }
-        }
-
-
-        // fail if there have been errors emitted
-        if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
-            ecx.struct_span_fatal(span, msg).emit();
-            FatalError.raise();
-        }
-
-        items
-    }
-}
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 12482f7248e90..7f27769f236e2 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -1770,50 +1770,6 @@ pub fn cs_fold1<F, B>(use_foldl: bool,
     }
 }
 
-/// Call the method that is being derived on all the fields, and then
-/// process the collected results. i.e.
-///
-/// ```ignore (only-for-syntax-highlight)
-/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
-///                  self_2.method(__arg_1_2, __arg_2_2)])
-/// ```
-#[inline]
-pub fn cs_same_method<F>(f: F,
-                         mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
-                         cx: &mut ExtCtxt<'_>,
-                         trait_span: Span,
-                         substructure: &Substructure<'_>)
-                         -> P<Expr>
-    where F: FnOnce(&mut ExtCtxt<'_>, Span, Vec<P<Expr>>) -> P<Expr>
-{
-    match *substructure.fields {
-        EnumMatching(.., ref all_fields) |
-        Struct(_, ref all_fields) => {
-            // call self_n.method(other_1_n, other_2_n, ...)
-            let called = all_fields.iter()
-                .map(|field| {
-                    cx.expr_method_call(field.span,
-                                        field.self_.clone(),
-                                        substructure.method_ident,
-                                        field.other
-                                            .iter()
-                                            .map(|e| cx.expr_addr_of(field.span, e.clone()))
-                                            .collect())
-                })
-                .collect();
-
-            f(cx, trait_span, called)
-        }
-        EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => {
-            enum_nonmatch_f(cx,
-                            trait_span,
-                            (&all_self_args[..], tuple),
-                            substructure.nonself_args)
-        }
-        StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
-    }
-}
-
 /// Returns `true` if the type has no value fields
 /// (for an enum, no variant has any fields)
 pub fn is_type_without_fields(item: &Annotatable) -> bool {
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index fef1b4eebcf96..394beb141712d 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -18,6 +18,7 @@ pub enum PtrTy<'a> {
     /// &'lifetime mut
     Borrowed(Option<&'a str>, ast::Mutability),
     /// *mut
+    #[allow(dead_code)]
     Raw(ast::Mutability),
 }
 
@@ -107,13 +108,6 @@ pub enum Ty<'a> {
     Tuple(Vec<Ty<'a>>),
 }
 
-/// A const expression. Supports literals and blocks.
-#[derive(Clone, Eq, PartialEq)]
-pub enum Const {
-    Literal,
-    Block,
-}
-
 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
     Borrowed(None, ast::Mutability::Immutable)
 }
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index e491e93256d1c..405b4ed9924ab 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -30,7 +30,6 @@ pub mod decodable;
 pub mod hash;
 pub mod debug;
 pub mod default;
-pub mod custom;
 
 #[path="cmp/partial_eq.rs"]
 pub mod partial_eq;
diff --git a/src/librustc_allocator/expand.rs b/src/libsyntax_ext/global_allocator.rs
similarity index 98%
rename from src/librustc_allocator/expand.rs
rename to src/libsyntax_ext/global_allocator.rs
index af63fffc0f9b4..e8f94bff14470 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -1,5 +1,4 @@
 use log::debug;
-use rustc::middle::allocator::AllocatorKind;
 use smallvec::{smallvec, SmallVec};
 use syntax::{
     ast::{
@@ -11,6 +10,7 @@ use syntax::{
         respan, ExpnInfo, ExpnKind,
     },
     ext::{
+        allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS},
         base::{ExtCtxt, MacroKind, Resolver},
         build::AstBuilder,
         expand::ExpansionConfig,
@@ -23,14 +23,12 @@ use syntax::{
 };
 use syntax_pos::Span;
 
-use crate::{AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};
-
 pub fn modify(
     sess: &ParseSess,
     resolver: &mut dyn Resolver,
     krate: &mut Crate,
     crate_name: String,
-    handler: &rustc_errors::Handler,
+    handler: &errors::Handler,
 ) {
     ExpandAllocatorDirectives {
         handler,
@@ -44,7 +42,7 @@ pub fn modify(
 
 struct ExpandAllocatorDirectives<'a> {
     found: bool,
-    handler: &'a rustc_errors::Handler,
+    handler: &'a errors::Handler,
     sess: &'a ParseSess,
     resolver: &'a mut dyn Resolver,
     crate_name: Option<String>,
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 7de90278ed732..f54f6e1101364 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -1,23 +1,19 @@
-//! Syntax extensions in the Rust compiler.
+//! This crate contains implementations of built-in macros and other code generating facilities
+//! injecting code into the crate before it is lowered to HIR.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
 #![deny(unused_lifetimes)]
 
-#![feature(in_band_lifetimes)]
-#![feature(proc_macro_diagnostic)]
-#![feature(proc_macro_internals)]
-#![feature(proc_macro_span)]
 #![feature(decl_macro)]
+#![feature(mem_take)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(unicode_internals)]
 
 #![recursion_limit="256"]
 
-extern crate proc_macro;
-
 mod error_codes;
 
 mod asm;
@@ -26,19 +22,20 @@ mod cfg;
 mod compile_error;
 mod concat;
 mod concat_idents;
+mod deriving;
 mod env;
 mod format;
 mod format_foreign;
 mod global_asm;
 mod log_syntax;
-mod proc_macro_server;
+mod source_util;
 mod test;
-mod test_case;
 mod trace_macros;
 
-pub mod deriving;
-pub mod proc_macro_decls;
-pub mod proc_macro_impl;
+pub mod global_allocator;
+pub mod proc_macro_harness;
+pub mod standard_library_imports;
+pub mod test_harness;
 
 use rustc_data_structures::sync::Lrc;
 use syntax::ast;
@@ -94,7 +91,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
         )* }
     }
 
-    use syntax::ext::source_util::*;
+    use source_util::*;
     register! {
         line: expand_line,
         column: expand_column,
@@ -136,7 +133,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
         )),
         allow_internal_unstable: allow_internal_unstable.clone(),
         ..SyntaxExtension::default(
-            SyntaxExtensionKind::LegacyAttr(Box::new(test_case::expand)), edition
+            SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test_case)), edition
         )
     });
     register(sym::test, SyntaxExtension {
diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_harness.rs
similarity index 97%
rename from src/libsyntax_ext/proc_macro_decls.rs
rename to src/libsyntax_ext/proc_macro_harness.rs
index 08c40dde56c85..838e09b106c26 100644
--- a/src/libsyntax_ext/proc_macro_decls.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -9,21 +9,15 @@ use syntax::ext::base::{ExtCtxt, MacroKind};
 use syntax::ext::build::AstBuilder;
 use syntax::ext::expand::ExpansionConfig;
 use syntax::ext::hygiene::ExpnId;
+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::Symbol;
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
 
-const PROC_MACRO_KINDS: [Symbol; 3] = [
-    sym::proc_macro_derive,
-    sym::proc_macro_attribute,
-    sym::proc_macro
-];
-
 struct ProcMacroDerive {
     trait_name: ast::Name,
     function_name: Ident,
@@ -46,7 +40,7 @@ struct CollectProcMacros<'a> {
     is_test_crate: bool,
 }
 
-pub fn modify(sess: &ParseSess,
+pub fn inject(sess: &ParseSess,
               resolver: &mut dyn (::syntax::ext::base::Resolver),
               mut krate: ast::Crate,
               is_proc_macro_crate: bool,
@@ -90,10 +84,6 @@ pub fn modify(sess: &ParseSess,
     krate
 }
 
-pub fn is_proc_macro_attr(attr: &ast::Attribute) -> bool {
-    PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(*kind))
-}
-
 impl<'a> CollectProcMacros<'a> {
     fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
         if self.is_proc_macro_crate && self.in_root && vis.node.is_pub() {
diff --git a/src/libsyntax_ext/proc_macro_impl.rs b/src/libsyntax_ext/proc_macro_impl.rs
deleted file mode 100644
index f0fc6392cd73f..0000000000000
--- a/src/libsyntax_ext/proc_macro_impl.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use crate::proc_macro_server;
-
-use errors::FatalError;
-use syntax::source_map::Span;
-use syntax::ext::base::{self, *};
-use syntax::tokenstream::TokenStream;
-
-pub const EXEC_STRATEGY: proc_macro::bridge::server::SameThread =
-    proc_macro::bridge::server::SameThread;
-
-pub struct AttrProcMacro {
-    pub client: proc_macro::bridge::client::Client<
-        fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream,
-    >,
-}
-
-impl base::AttrProcMacro for AttrProcMacro {
-    fn expand<'cx>(&self,
-                   ecx: &'cx mut ExtCtxt<'_>,
-                   span: Span,
-                   annotation: TokenStream,
-                   annotated: TokenStream)
-                   -> TokenStream {
-        let server = proc_macro_server::Rustc::new(ecx);
-        match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
-            Ok(stream) => stream,
-            Err(e) => {
-                let msg = "custom attribute panicked";
-                let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.as_str() {
-                    err.help(&format!("message: {}", s));
-                }
-
-                err.emit();
-                FatalError.raise();
-            }
-        }
-    }
-}
-
-pub struct BangProcMacro {
-    pub client: proc_macro::bridge::client::Client<
-        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
-    >,
-}
-
-impl base::ProcMacro for BangProcMacro {
-    fn expand<'cx>(&self,
-                   ecx: &'cx mut ExtCtxt<'_>,
-                   span: Span,
-                   input: TokenStream)
-                   -> TokenStream {
-        let server = proc_macro_server::Rustc::new(ecx);
-        match self.client.run(&EXEC_STRATEGY, server, input) {
-            Ok(stream) => stream,
-            Err(e) => {
-                let msg = "proc macro panicked";
-                let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.as_str() {
-                    err.help(&format!("message: {}", s));
-                }
-
-                err.emit();
-                FatalError.raise();
-            }
-        }
-    }
-}
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax_ext/source_util.rs
similarity index 82%
rename from src/libsyntax/ext/source_util.rs
rename to src/libsyntax_ext/source_util.rs
index c2ba8b983f5a8..7233bec6406e6 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax_ext/source_util.rs
@@ -1,18 +1,17 @@
-use crate::ast;
-use crate::ext::base::{self, *};
-use crate::ext::build::AstBuilder;
-use crate::parse::{self, token, DirectoryOwnership};
-use crate::print::pprust;
-use crate::ptr::P;
-use crate::symbol::Symbol;
-use crate::tokenstream;
+use syntax::{ast, panictry};
+use syntax::ext::base::{self, *};
+use syntax::ext::build::AstBuilder;
+use syntax::parse::{self, token, DirectoryOwnership};
+use syntax::print::pprust;
+use syntax::ptr::P;
+use syntax::symbol::Symbol;
+use syntax::tokenstream;
 
 use smallvec::SmallVec;
-use syntax_pos::{self, Pos, Span, FileName};
+use syntax_pos::{self, Pos, Span};
 
 use std::fs;
 use std::io::ErrorKind;
-use std::path::PathBuf;
 use rustc_data_structures::sync::Lrc;
 
 // These macros all relate to the file system; they either return
@@ -78,7 +77,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea
         None => return DummyResult::any(sp),
     };
     // The file will be added to the code map by the parser
-    let path = res_rel_file(cx, sp, file);
+    let path = cx.res_rel_file(sp, file);
     let directory_ownership = DirectoryOwnership::Owned { relative: None };
     let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
 
@@ -95,7 +94,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea
             while self.p.token != token::Eof {
                 match panictry!(self.p.parse_item()) {
                     Some(item) => ret.push(item),
-                    None => self.p.diagnostic().span_fatal(self.p.token.span,
+                    None => self.p.sess.span_diagnostic.span_fatal(self.p.token.span,
                                                            &format!("expected item, found `{}`",
                                                                     self.p.this_token_to_string()))
                                                .raise()
@@ -115,7 +114,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To
         Some(f) => f,
         None => return DummyResult::expr(sp)
     };
-    let file = res_rel_file(cx, sp, file);
+    let file = cx.res_rel_file(sp, file);
     match fs::read_to_string(&file) {
         Ok(src) => {
             let interned_src = Symbol::intern(&src);
@@ -143,7 +142,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
         Some(f) => f,
         None => return DummyResult::expr(sp)
     };
-    let file = res_rel_file(cx, sp, file);
+    let file = cx.res_rel_file(sp, file);
     match fs::read(&file) {
         Ok(bytes) => {
             // Add the contents to the source map if it contains UTF-8.
@@ -164,24 +163,3 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
         }
     }
 }
-
-// resolve a file-system path to an absolute file-system path (if it
-// isn't already)
-fn res_rel_file(cx: &mut ExtCtxt<'_>, sp: syntax_pos::Span, arg: String) -> PathBuf {
-    let arg = PathBuf::from(arg);
-    // Relative paths are resolved relative to the file in which they are found
-    // after macro expansion (that is, they are unhygienic).
-    if !arg.is_absolute() {
-        let callsite = sp.source_callsite();
-        let mut path = match cx.source_map().span_to_unmapped_path(callsite) {
-            FileName::Real(path) => path,
-            FileName::DocTest(path, _) => path,
-            other => panic!("cannot resolve relative path in non-file source `{}`", other),
-        };
-        path.pop();
-        path.push(arg);
-        path
-    } else {
-        arg
-    }
-}
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax_ext/standard_library_imports.rs
similarity index 77%
rename from src/libsyntax/std_inject.rs
rename to src/libsyntax_ext/standard_library_imports.rs
index 3fba81c0b6911..81bb32d79a2aa 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax_ext/standard_library_imports.rs
@@ -1,37 +1,22 @@
-use crate::ast;
-use crate::attr;
-use crate::edition::Edition;
-use crate::ext::hygiene::{ExpnId, MacroKind};
-use crate::symbol::{Ident, Symbol, kw, sym};
-use crate::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
-use crate::ptr::P;
-use crate::tokenstream::TokenStream;
-
-use std::cell::Cell;
-use std::iter;
+use syntax::{ast, attr};
+use syntax::edition::Edition;
+use syntax::ext::hygiene::{ExpnId, MacroKind};
+use syntax::ptr::P;
+use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
+use syntax::symbol::{Ident, Symbol, kw, sym};
+use syntax::tokenstream::TokenStream;
 use syntax_pos::DUMMY_SP;
 
-pub fn injected_crate_name() -> Option<&'static str> {
-    INJECTED_CRATE_NAME.with(|name| name.get())
-}
-
-thread_local! {
-    // A `Symbol` might make more sense here, but it doesn't work, probably for
-    // reasons relating to the use of thread-local storage for the Symbol
-    // interner.
-    static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
-}
+use std::iter;
 
-pub fn maybe_inject_crates_ref(
-    mut krate: ast::Crate,
-    alt_std_name: Option<&str>,
-    edition: Edition,
-) -> ast::Crate {
+pub fn inject(
+    mut krate: ast::Crate, alt_std_name: Option<&str>, edition: Edition
+) -> (ast::Crate, Option<Symbol>) {
     let rust_2018 = edition >= Edition::Edition2018;
 
     // the first name in this list is the crate name of the crate with the prelude
     let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) {
-        return krate;
+        return (krate, None);
     } else if attr::contains_name(&krate.attrs, sym::no_std) {
         if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
             &["core"]
@@ -73,8 +58,6 @@ pub fn maybe_inject_crates_ref(
     // the prelude.
     let name = names[0];
 
-    INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
-
     let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
         ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
         [sym::prelude_import][..].into(),
@@ -108,5 +91,5 @@ pub fn maybe_inject_crates_ref(
         tokens: None,
     }));
 
-    krate
+    (krate, Some(Symbol::intern(name)))
 }
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index f8755a1d1d791..8a1a5379753c1 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -6,11 +6,41 @@ use syntax::ext::build::AstBuilder;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::attr;
 use syntax::ast;
-use syntax::print::pprust;
+use syntax::source_map::respan;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::Span;
 use std::iter;
 
+// #[test_case] is used by custom test authors to mark tests
+// When building for test, it needs to make the item public and gensym the name
+// Otherwise, we'll omit the item. This behavior means that any item annotated
+// with #[test_case] is never addressable.
+//
+// We mark item with an inert attribute "rustc_test_marker" which the test generation
+// logic will pick up on.
+pub fn expand_test_case(
+    ecx: &mut ExtCtxt<'_>,
+    attr_sp: Span,
+    _meta_item: &ast::MetaItem,
+    anno_item: Annotatable
+) -> Vec<Annotatable> {
+    if !ecx.ecfg.should_test { return vec![]; }
+
+    let sp = attr_sp.with_ctxt(SyntaxContext::empty().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);
+        item.ident = item.ident.gensym();
+        item.attrs.push(
+            ecx.attribute(sp,
+                ecx.meta_word(sp, sym::rustc_test_marker))
+        );
+        item
+    });
+
+    return vec![Annotatable::Item(item)]
+}
+
 pub fn expand_test(
     cx: &mut ExtCtxt<'_>,
     attr_sp: Span,
@@ -167,8 +197,6 @@ pub fn expand_test_or_bench(
         ast::ItemKind::ExternCrate(Some(sym::test))
     );
 
-    log::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
-
     vec![
         // Access to libtest under a gensymed name
         Annotatable::Item(test_extern),
diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs
deleted file mode 100644
index 355f2428e0806..0000000000000
--- a/src/libsyntax_ext/test_case.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// http://rust-lang.org/COPYRIGHT.
-//
-
-// #[test_case] is used by custom test authors to mark tests
-// When building for test, it needs to make the item public and gensym the name
-// Otherwise, we'll omit the item. This behavior means that any item annotated
-// with #[test_case] is never addressable.
-//
-// We mark item with an inert attribute "rustc_test_marker" which the test generation
-// logic will pick up on.
-
-use syntax::ext::base::*;
-use syntax::ext::build::AstBuilder;
-use syntax::ext::hygiene::SyntaxContext;
-use syntax::ast;
-use syntax::source_map::respan;
-use syntax::symbol::sym;
-use syntax_pos::Span;
-
-pub fn expand(
-    ecx: &mut ExtCtxt<'_>,
-    attr_sp: Span,
-    _meta_item: &ast::MetaItem,
-    anno_item: Annotatable
-) -> Vec<Annotatable> {
-    if !ecx.ecfg.should_test { return vec![]; }
-
-    let sp = attr_sp.with_ctxt(SyntaxContext::empty().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);
-        item.ident = item.ident.gensym();
-        item.attrs.push(
-            ecx.attribute(sp,
-                ecx.meta_word(sp, sym::rustc_test_marker))
-        );
-        item
-    });
-
-    return vec![Annotatable::Item(item)]
-}
diff --git a/src/libsyntax/test.rs b/src/libsyntax_ext/test_harness.rs
similarity index 89%
rename from src/libsyntax/test.rs
rename to src/libsyntax_ext/test_harness.rs
index d82cdce2ce92b..0ab3ff9ce78fc 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax_ext/test_harness.rs
@@ -1,35 +1,23 @@
 // Code that generates a test runner to run all the tests in a crate
 
-#![allow(dead_code)]
-#![allow(unused_imports)]
-
-use HasTestSignature::*;
-
-use std::iter;
-use std::slice;
-use std::mem;
-use std::vec;
-
 use log::debug;
 use smallvec::{smallvec, SmallVec};
-use syntax_pos::{DUMMY_SP, NO_EXPANSION, Span, SourceFile, BytePos};
-
-use crate::attr::{self, HasAttrs};
-use crate::source_map::{self, SourceMap, ExpnInfo, ExpnKind, dummy_spanned, respan};
-use crate::config;
-use crate::entry::{self, EntryPointType};
-use crate::ext::base::{ExtCtxt, Resolver};
-use crate::ext::build::AstBuilder;
-use crate::ext::expand::ExpansionConfig;
-use crate::ext::hygiene::{self, ExpnId, SyntaxContext, MacroKind};
-use crate::mut_visit::{*, ExpectOne};
-use crate::feature_gate::Features;
-use crate::util::map_in_place::MapInPlace;
-use crate::parse::{token, ParseSess};
-use crate::ast::{self, Ident};
-use crate::ptr::P;
-use crate::symbol::{self, Symbol, kw, sym};
-use crate::ThinVec;
+use syntax::ast::{self, Ident};
+use syntax::attr;
+use syntax::entry::{self, EntryPointType};
+use syntax::ext::base::{ExtCtxt, Resolver};
+use syntax::ext::build::AstBuilder;
+use syntax::ext::expand::ExpansionConfig;
+use syntax::ext::hygiene::{ExpnId, MacroKind};
+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::symbol::{kw, sym, Symbol};
+use syntax_pos::{Span, DUMMY_SP};
+
+use std::{iter, mem};
 
 struct Test {
     span: Span,
@@ -42,22 +30,21 @@ struct TestCtxt<'a> {
     ext_cx: ExtCtxt<'a>,
     test_cases: Vec<Test>,
     reexport_test_harness_main: Option<Symbol>,
-    is_libtest: bool,
-    features: &'a Features,
     test_runner: Option<ast::Path>,
-
     // top-level re-export submodule, filled out after folding is finished
     toplevel_reexport: Option<Ident>,
 }
 
 // Traverse the crate, collecting all the test functions, eliding any
 // existing main functions, and synthesizing a main test harness
-pub fn modify_for_testing(sess: &ParseSess,
-                          resolver: &mut dyn Resolver,
-                          should_test: bool,
-                          krate: &mut ast::Crate,
-                          span_diagnostic: &errors::Handler,
-                          features: &Features) {
+pub fn inject(
+    sess: &ParseSess,
+    resolver: &mut dyn Resolver,
+    should_test: bool,
+    krate: &mut ast::Crate,
+    span_diagnostic: &errors::Handler,
+    features: &Features,
+) {
     // Check for #[reexport_test_harness_main = "some_name"] which
     // creates a `use __test::main as some_name;`. This needs to be
     // unconditional, so that the attribute is still marked as used in
@@ -267,11 +254,7 @@ fn generate_test_harness(sess: &ParseSess,
         path: Vec::new(),
         test_cases: Vec::new(),
         reexport_test_harness_main,
-        // N.B., doesn't consider the value of `--crate-name` passed on the command line.
-        is_libtest: attr::find_crate_name(&krate.attrs)
-            .map(|s| s == sym::test).unwrap_or(false),
         toplevel_reexport: None,
-        features,
         test_runner
     };
 
@@ -282,19 +265,6 @@ fn generate_test_harness(sess: &ParseSess,
     }.visit_crate(krate);
 }
 
-enum HasTestSignature {
-    Yes,
-    No(BadTestSignature),
-}
-
-#[derive(PartialEq)]
-enum BadTestSignature {
-    NotEvenAFunction,
-    WrongTypeSignature,
-    NoArgumentsAllowed,
-    ShouldPanicOnlyWithNoArgs,
-}
-
 /// Creates a function item for use as the main function of a test build.
 /// This function will call the `test_runner` as specified by the crate attribute
 fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index 30897970fa220..aacbfc547d472 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -56,6 +56,9 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(target_os = "emscripten")]
 pub const unwinder_private_data_size: usize = 20;
 
+#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
+pub const unwinder_private_data_size: usize = 35;
+
 #[repr(C)]
 pub struct _Unwind_Exception {
     pub exception_class: _Unwind_Exception_Class,
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 7d20086d9a22e..0cda3465dc093 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -26,8 +26,6 @@
 using namespace llvm;
 using namespace llvm::legacy;
 
-extern cl::opt<bool> EnableARMEHABI;
-
 typedef struct LLVMOpaquePass *LLVMPassRef;
 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
 
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index a9d267cdb3175..c3f0d174d4b41 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -1,15 +1,11 @@
 #include "llvm-c/BitReader.h"
 #include "llvm-c/Core.h"
-#include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/Object.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/Lint.h"
 #include "llvm/Analysis/Passes.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/Interpreter.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs
index a2a934513d2f7..af5ccb45727a1 100644
--- a/src/test/run-pass/backtrace-debuginfo.rs
+++ b/src/test/run-pass/backtrace-debuginfo.rs
@@ -10,7 +10,6 @@
 // ignore-pretty issue #37195
 // ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
-// ignore-msvc issue #62844
 // ignore-sgx no processes
 // normalize-stderr-test ".*\n" -> ""
 
diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs
index 93e8c9f172997..c73ba293ee25b 100644
--- a/src/test/run-pass/backtrace.rs
+++ b/src/test/run-pass/backtrace.rs
@@ -2,7 +2,6 @@
 // ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-openbsd no support for libbacktrace without filename
-// ignore-msvc issue #62844
 // ignore-sgx no processes
 // compile-flags:-g
 
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr
new file mode 100644
index 0000000000000..89af8764557ff
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `books` does not live long enough
+  --> $DIR/borrowck-escaping-closure-error-2.rs:11:17
+   |
+LL |     Box::new(|| books.push(4))
+   |     ------------^^^^^---------
+   |     |        |  |
+   |     |        |  borrowed value does not live long enough
+   |     |        value captured here
+   |     borrow later used here
+LL |
+LL | }
+   | - `books` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
index 663164cfc2c1c..d97883ad47a50 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
@@ -1,5 +1,5 @@
 warning[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/borrowck-migrate-to-nll.rs:25:18
+  --> $DIR/borrowck-migrate-to-nll.rs:26:18
    |
 LL |                 (|| { let bar = foo; bar.take() })();
    |                  ^^             ---
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
index 5b7018df91931..a64df9df25948 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
@@ -10,6 +10,7 @@
 // just ignore it instead:
 
 // ignore-compare-mode-nll
+// ignore-compare-mode-polonius
 
 // revisions: zflag edition
 //[zflag]compile-flags: -Z borrowck=migrate
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
index 663164cfc2c1c..d97883ad47a50 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
@@ -1,5 +1,5 @@
 warning[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/borrowck-migrate-to-nll.rs:25:18
+  --> $DIR/borrowck-migrate-to-nll.rs:26:18
    |
 LL |                 (|| { let bar = foo; bar.take() })();
    |                  ^^             ---
diff --git a/src/test/ui/borrowck/issue-45983.migrate.stderr b/src/test/ui/borrowck/issue-45983.migrate.stderr
index 3a6b2f69a1ffc..c1564cf07e68a 100644
--- a/src/test/ui/borrowck/issue-45983.migrate.stderr
+++ b/src/test/ui/borrowck/issue-45983.migrate.stderr
@@ -1,5 +1,5 @@
 error: borrowed data cannot be stored outside of its closure
-  --> $DIR/issue-45983.rs:19:27
+  --> $DIR/issue-45983.rs:20:27
    |
 LL |     let x = None;
    |         - borrowed data cannot be stored into here...
diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr
index 94360b65ffe36..dff0b4cebace9 100644
--- a/src/test/ui/borrowck/issue-45983.nll.stderr
+++ b/src/test/ui/borrowck/issue-45983.nll.stderr
@@ -1,5 +1,5 @@
 error[E0521]: borrowed data escapes outside of closure
-  --> $DIR/issue-45983.rs:19:18
+  --> $DIR/issue-45983.rs:20:18
    |
 LL |     let x = None;
    |         - `x` is declared here, outside of the closure body
@@ -9,7 +9,7 @@ LL |     give_any(|y| x = Some(y));
    |               `y` is a reference that is only valid in the closure body
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-45983.rs:19:18
+  --> $DIR/issue-45983.rs:20:18
    |
 LL |     let x = None;
    |         - help: consider changing this to be mutable: `mut x`
diff --git a/src/test/ui/borrowck/issue-45983.rs b/src/test/ui/borrowck/issue-45983.rs
index a2656f5939aa1..3cd282077424b 100644
--- a/src/test/ui/borrowck/issue-45983.rs
+++ b/src/test/ui/borrowck/issue-45983.rs
@@ -7,6 +7,7 @@
 // revisions, don't worry about the --compare-mode=nll on this test.
 
 // ignore-compare-mode-nll
+// ignore-compare-mode-polonius
 
 //[nll]compile-flags: -Z borrowck=mir
 
diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr
new file mode 100644
index 0000000000000..a5b2e8762746c
--- /dev/null
+++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr
@@ -0,0 +1,59 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:5:21
+   |
+LL |     let ref mut x = 1234543;
+   |                     ^^^^^^^ creates a temporary which is freed while still in use
+LL |     x
+   |     - borrow later used here
+LL | }
+   | - temporary value is freed at the end of this statement
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:10:25
+   |
+LL |     let (ref mut x, ) = (1234543, );
+   |                         ^^^^^^^^^^^ creates a temporary which is freed while still in use
+LL |     x
+   |     - borrow later used here
+LL | }
+   | - temporary value is freed at the end of this statement
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:5
+   |
+LL |       match 1234543 {
+   |       ^     ------- temporary value created here
+   |  _____|
+   | |
+LL | |         ref mut x => x
+LL | |     }
+   | |_____^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:21:5
+   |
+LL |       match (123443,) {
+   |       ^     --------- temporary value created here
+   |  _____|
+   | |
+LL | |         (ref mut x,) => x,
+LL | |     }
+   | |_____^ returns a value referencing data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:27:5
+   |
+LL |     &mut 1234543
+   |     ^^^^^-------
+   |     |    |
+   |     |    temporary value created here
+   |     returns a reference to data owned by the current function
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0515, E0716.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr
index 565e433f77361..88e9ced03ddde 100644
--- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:18:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
@@ -11,7 +11,7 @@ LL |     v.extend(shared);
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:28:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:29:5
    |
 LL |     v.extend(&v);
    |     ^^------^--^
@@ -21,7 +21,7 @@ LL |     v.extend(&v);
    |     mutable borrow occurs here
 
 warning: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:39:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:40:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr
index 565e433f77361..88e9ced03ddde 100644
--- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:18:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
@@ -11,7 +11,7 @@ LL |     v.extend(shared);
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:28:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:29:5
    |
 LL |     v.extend(&v);
    |     ^^------^--^
@@ -21,7 +21,7 @@ LL |     v.extend(&v);
    |     mutable borrow occurs here
 
 warning: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:39:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:40:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr
index 730741c7a9ae2..52017394e898e 100644
--- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:18:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
@@ -10,7 +10,7 @@ LL |     v.extend(shared);
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:28:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:29:5
    |
 LL |     v.extend(&v);
    |     ^^------^--^
@@ -20,7 +20,7 @@ LL |     v.extend(&v);
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:39:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:40:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr
index 730741c7a9ae2..52017394e898e 100644
--- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:18:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
@@ -10,7 +10,7 @@ LL |     v.extend(shared);
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:28:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:29:5
    |
 LL |     v.extend(&v);
    |     ^^------^--^
@@ -20,7 +20,7 @@ LL |     v.extend(&v);
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:39:5
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:40:5
    |
 LL |     let shared = &v;
    |                  -- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
index de1af3aaa05e4..14f687c23780c 100644
--- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
@@ -3,6 +3,7 @@
 // everyone else.
 
 //ignore-compare-mode-nll
+//ignore-compare-mode-polonius
 
 //revisions: migrate2015 migrate2018 nll2015 nll2018
 
diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr
new file mode 100644
index 0000000000000..7b246426a2333
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr
@@ -0,0 +1,148 @@
+error[E0503]: cannot use `self.cx` because it was mutably borrowed
+  --> $DIR/two-phase-surprise-no-conflict.rs:21:23
+   |
+LL |         let _mut_borrow = &mut *self;
+   |                           ---------- borrow of `*self` occurs here
+LL |         let _access = self.cx;
+   |                       ^^^^^^^ use of borrowed `*self`
+LL |
+LL |         _mut_borrow;
+   |         ----------- borrow later used here
+
+error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:57:17
+   |
+LL |                 self.hash_expr(&self.cx_mut.body(eid).value);
+   |                 ^^^^^---------^^-----------^^^^^^^^^^^^^^^^^
+   |                 |    |          |
+   |                 |    |          immutable borrow occurs here
+   |                 |    immutable borrow later used by call
+   |                 mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:119:51
+   |
+LL |     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
+   |     --- ---------------                           ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:122:54
+   |
+LL |     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:125:53
+   |
+LL |     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:128:44
+   |
+LL |     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:138:5
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
+   |     |   |                                        |
+   |     |   |                                        immutable borrow occurs here
+   |     |   immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:141:5
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
+   |     ^^^^-------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
+   |     |   |                                       |
+   |     |   |                                       immutable borrow occurs here
+   |     |   immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-surprise-no-conflict.rs:144:5
+   |
+LL |     reg.register_ref(&CapturePass::new(&reg.sess_mut));
+   |     ^^^^------------^^^^^^^^^^^^^^^^^^^-------------^^
+   |     |   |                              |
+   |     |   |                              immutable borrow occurs here
+   |     |   immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0499]: cannot borrow `*reg` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:154:5
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
+   |     |   |                                            |
+   |     |   |                                            first mutable borrow occurs here
+   |     |   first borrow later used by call
+   |     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:154:54
+   |
+LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `*reg` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:158:5
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     ^^^^-------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
+   |     |   |                                           |
+   |     |   |                                           first mutable borrow occurs here
+   |     |   first borrow later used by call
+   |     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:158:53
+   |
+LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error[E0499]: cannot borrow `*reg` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:162:5
+   |
+LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
+   |     ^^^^------------^^^^^^^^^^^^^^^^^^^^^^^-----------------^^
+   |     |   |                                  |
+   |     |   |                                  first mutable borrow occurs here
+   |     |   first borrow later used by call
+   |     second mutable borrow occurs here
+
+error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
+  --> $DIR/two-phase-surprise-no-conflict.rs:162:44
+   |
+LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
+   |     first mutable borrow occurs here
+
+error: aborting due to 15 previous errors
+
+Some errors have detailed explanations: E0499, E0502, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/consts/promote_const_let.polonius.stderr b/src/test/ui/consts/promote_const_let.polonius.stderr
new file mode 100644
index 0000000000000..cf41bd7bdb1eb
--- /dev/null
+++ b/src/test/ui/consts/promote_const_let.polonius.stderr
@@ -0,0 +1,29 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/promote_const_let.rs:4:9
+   |
+LL |     let x: &'static u32 = {
+   |         - borrow later stored here
+LL |         let y = 42;
+LL |         &y
+   |         ^^ borrowed value does not live long enough
+LL |     };
+   |     - `y` dropped here while still borrowed
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote_const_let.rs:6:28
+   |
+LL |       let x: &'static u32 = &{
+   |  ____________------------____^
+   | |            |
+   | |            type annotation requires that borrow lasts for `'static`
+LL | |         let y = 42;
+LL | |         y
+LL | |     };
+   | |_____^ creates a temporary which is freed while still in use
+LL |   }
+   |   - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
new file mode 100644
index 0000000000000..dbcb0fcebb73d
--- /dev/null
+++ b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
@@ -0,0 +1,74 @@
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:111:13
+   |
+LL |     o1.set0(&o2);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `o2` dropped here while still borrowed
+   | borrow might be used here, when `o2` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+
+error[E0597]: `o3` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:112:13
+   |
+LL |     o1.set1(&o3);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `o3` dropped here while still borrowed
+   | borrow might be used here, when `o3` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+
+error[E0597]: `o2` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:113: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`
+...
+LL |     o2.set0(&o2);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `o2` dropped here while still borrowed
+
+error[E0597]: `o3` does not live long enough
+  --> $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`
+...
+LL |     o2.set1(&o3);
+   |             ^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `o3` dropped here while still borrowed
+
+error[E0597]: `o1` does not live long enough
+  --> $DIR/dropck_trait_cycle_checked.rs:115:13
+   |
+LL |     o3.set0(&o1);
+   |             ^^^ borrowed value does not live long enough
+LL |     o3.set1(&o2);
+LL | }
+   | -
+   | |
+   | `o1` dropped here while still borrowed
+   | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+
+error[E0597]: `o2` does not live long enough
+  --> $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`
+...
+LL |     o3.set1(&o2);
+   |             ^^^ borrowed value does not live long enough
+LL | }
+   | - `o2` dropped here while still borrowed
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/emit-artifact-notifications.polonius.stderr b/src/test/ui/emit-artifact-notifications.polonius.stderr
new file mode 100644
index 0000000000000..47b48b399c25c
--- /dev/null
+++ b/src/test/ui/emit-artifact-notifications.polonius.stderr
@@ -0,0 +1 @@
+{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.polonius/libemit_artifact_notifications.rmeta","emit":"metadata"}
diff --git a/src/test/ui/feature-gates/feature-gate-nll.rs b/src/test/ui/feature-gates/feature-gate-nll.rs
index ec5eacd162547..8ec752409ab00 100644
--- a/src/test/ui/feature-gates/feature-gate-nll.rs
+++ b/src/test/ui/feature-gates/feature-gate-nll.rs
@@ -3,6 +3,7 @@
 
 // Don't use compare-mode=nll, since that turns on NLL.
 // ignore-compare-mode-nll
+// ignore-compare-mode-polonius
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/feature-gates/feature-gate-nll.stderr b/src/test/ui/feature-gates/feature-gate-nll.stderr
index 37542d52dc2ce..e5b28bbfa2477 100644
--- a/src/test/ui/feature-gates/feature-gate-nll.stderr
+++ b/src/test/ui/feature-gates/feature-gate-nll.stderr
@@ -1,5 +1,5 @@
 warning[E0502]: cannot borrow `*x.1` as immutable because it is also borrowed as mutable
-  --> $DIR/feature-gate-nll.rs:14:13
+  --> $DIR/feature-gate-nll.rs:15:13
    |
 LL |     let m = &mut x;
    |             ------ mutable borrow occurs here
@@ -14,7 +14,7 @@ LL |     m;
    = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
-  --> $DIR/feature-gate-nll.rs:10:1
+  --> $DIR/feature-gate-nll.rs:11:1
    |
 LL | / fn main() {
 LL | |     let mut x = (33, &0);
diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr
new file mode 100644
index 0000000000000..530bf368f676e
--- /dev/null
+++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr
@@ -0,0 +1,20 @@
+error[E0597]: `b` does not live long enough
+  --> $DIR/ref-escapes-but-not-over-yield.rs:11:13
+   |
+LL |       let mut b = move || {
+   |  _________________-
+LL | |         yield();
+LL | |         let b = 5;
+LL | |         a = &b;
+   | |             ^^ borrowed value does not live long enough
+LL | |
+LL | |     };
+   | |     -
+   | |     |
+   | |     `b` dropped here while still borrowed
+   | |_____... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator
+   |       a temporary with access to the borrow is created here ...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr
index 9a4f877282245..e7deca7644b0e 100644
--- a/src/test/ui/hrtb/issue-30786.migrate.stderr
+++ b/src/test/ui/hrtb/issue-30786.migrate.stderr
@@ -1,11 +1,11 @@
 error: implementation of `Stream` is not general enough
-  --> $DIR/issue-30786.rs:107:22
+  --> $DIR/issue-30786.rs:108:22
    |
 LL |     let map = source.map(|x: &_| x);
    |                      ^^^
    |
-   = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:107:26: 107:35]>`, for any lifetime `'0`
-   = note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:107:26: 107:35]>`, for some specific lifetime `'1`
+   = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`
+   = note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
index 5c865d76851d3..8614d86d93ac3 100644
--- a/src/test/ui/hrtb/issue-30786.nll.stderr
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -1,11 +1,11 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:111:18
+  --> $DIR/issue-30786.rs:112:18
    |
 LL |     let filter = map.filter(|x: &_| true);
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:113:17
+  --> $DIR/issue-30786.rs:114:17
    |
 LL |     let count = filter.count(); // Assert that we still have a valid stream.
    |                 ^^^^^^^^^^^^^^
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
index 321b83c3459d0..b9920a1950498 100644
--- a/src/test/ui/hrtb/issue-30786.rs
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -12,6 +12,7 @@
 // revisions, don't worry about the --compare-mode=nll on this test.
 
 // ignore-compare-mode-nll
+// ignore-compare-mode-polonius
 
 //[nll]compile-flags: -Z borrowck=mir
 
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
index 479b724ad18f1..2e99572d01828 100644
--- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
@@ -1,5 +1,5 @@
 warning[E0713]: borrow may still be in use when destructor runs
-  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:51:5
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:52:5
    |
 LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
    |              -- lifetime `'a` defined here
@@ -14,7 +14,7 @@ LL | }
    = note: for more information, try `rustc --explain E0729`
 
 warning[E0713]: borrow may still be in use when destructor runs
-  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:5
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
    |
 LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
    |                    -- lifetime `'a` defined here
@@ -29,7 +29,7 @@ LL | }
    = note: for more information, try `rustc --explain E0729`
 
 warning[E0713]: borrow may still be in use when destructor runs
-  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:74:5
    |
 LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
    |                          -- lifetime `'a` defined here
@@ -44,7 +44,7 @@ LL | }
    = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
-  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:80:1
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:81:1
    |
 LL | / fn main() {
 LL | |     let mut x = 1;
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
index 1b9fb0499260c..45b22511d27d6 100644
--- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
@@ -1,5 +1,5 @@
 error[E0713]: borrow may still be in use when destructor runs
-  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:51:5
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:52:5
    |
 LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
    |              -- lifetime `'a` defined here
@@ -10,7 +10,7 @@ LL | }
    | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
 
 error[E0713]: borrow may still be in use when destructor runs
-  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:5
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
    |
 LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
    |                    -- lifetime `'a` defined here
@@ -21,7 +21,7 @@ LL | }
    | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
 
 error[E0713]: borrow may still be in use when destructor runs
-  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:74:5
    |
 LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
    |                          -- lifetime `'a` defined here
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs
index f568efa487cd7..9f261884f3d2d 100644
--- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs
@@ -7,6 +7,7 @@
 
 // revisions: nll migrate
 // ignore-compare-mode-nll
+// ignore-compare-mode-polonius
 
 // This test is going to pass in the migrate revision, because the AST-borrowck
 // accepted this code in the past (see notes below). So we use `#[rustc_error]`
diff --git a/src/test/ui/nll/get_default.polonius.stderr b/src/test/ui/nll/get_default.polonius.stderr
new file mode 100644
index 0000000000000..2df6d5d61fc46
--- /dev/null
+++ b/src/test/ui/nll/get_default.polonius.stderr
@@ -0,0 +1,15 @@
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable
+  --> $DIR/get_default.rs:32:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+LL |             Some(v) => {
+LL |                 map.set(String::new()); // Both AST and MIR error here
+   |                 ^^^ mutable borrow occurs here
+LL |
+LL |                 return v;
+   |                        - immutable borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/issue-46589.rs b/src/test/ui/nll/issue-46589.rs
index 8c0c356e96721..0a4c20d15159f 100644
--- a/src/test/ui/nll/issue-46589.rs
+++ b/src/test/ui/nll/issue-46589.rs
@@ -1,3 +1,9 @@
+// This tests passes in Polonius mode, so is skipped in the automated compare-mode.
+// We will manually check it passes in Polonius tests, as we can't have a test here
+// which conditionally passes depending on a test revision/compile-flags.
+
+// ignore-compare-mode-polonius
+
 struct Foo;
 
 impl Foo {
diff --git a/src/test/ui/nll/issue-46589.stderr b/src/test/ui/nll/issue-46589.stderr
index 397909a436610..82cd364eeffd0 100644
--- a/src/test/ui/nll/issue-46589.stderr
+++ b/src/test/ui/nll/issue-46589.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `**other` as mutable more than once at a time
-  --> $DIR/issue-46589.rs:17:21
+  --> $DIR/issue-46589.rs:23:21
    |
 LL |         *other = match (*other).get_self() {
    |                        -------- first mutable borrow occurs here
diff --git a/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr b/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr
new file mode 100644
index 0000000000000..eb8442b31d7c7
--- /dev/null
+++ b/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `data.0` because it is borrowed
+  --> $DIR/loan_ends_mid_block_pair.rs:12:5
+   |
+LL |     let c = &mut data.0;
+   |             ----------- borrow of `data.0` occurs here
+LL |     capitalize(c);
+LL |     data.0 = 'e';
+   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+...
+LL |     capitalize(c);
+   |                - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/polonius/assignment-kills-loans.rs b/src/test/ui/nll/polonius/assignment-kills-loans.rs
new file mode 100644
index 0000000000000..a80c62d19d5a6
--- /dev/null
+++ b/src/test/ui/nll/polonius/assignment-kills-loans.rs
@@ -0,0 +1,88 @@
+#![allow(dead_code)]
+
+// This tests the various kinds of assignments there are. Polonius used to generate `killed`
+// facts only on simple assigments, but not projections, incorrectly causing errors to be emitted
+// for code accepted by NLL. They are all variations from example code in the NLL RFC.
+
+// check-pass
+// compile-flags: -Z borrowck=mir -Z polonius
+// ignore-compare-mode-nll
+
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+// Assignment to a local: the `list` assignment should clear the existing
+// borrows of `list.value` and `list.next`
+fn assignment_to_local<T>(mut list: &mut List<T>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            list = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Assignment to a deref projection: the `*list` assignment should clear the existing
+// borrows of `list.value` and `list.next`
+fn assignment_to_deref_projection<T>(mut list: Box<&mut List<T>>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            *list = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Assignment to a field projection: the `list.0` assignment should clear the existing
+// borrows of `list.0.value` and `list.0.next`
+fn assignment_to_field_projection<T>(mut list: (&mut List<T>,)) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.0.value);
+        if let Some(n) = list.0.next.as_mut() {
+            list.0 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Assignment to a deref field projection: the `*list.0` assignment should clear the existing
+// borrows of `list.0.value` and `list.0.next`
+fn assignment_to_deref_field_projection<T>(mut list: (Box<&mut List<T>>,)) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.0.value);
+        if let Some(n) = list.0.next.as_mut() {
+            *list.0 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Similar to `assignment_to_deref_field_projection` but through a longer projection chain
+fn assignment_through_projection_chain<T>(
+    mut list: (((((Box<&mut List<T>>,),),),),),
+) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut ((((list.0).0).0).0).0.value);
+        if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() {
+            *((((list.0).0).0).0).0 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/polonius/assignment-to-differing-field.rs b/src/test/ui/nll/polonius/assignment-to-differing-field.rs
new file mode 100644
index 0000000000000..c0ba1b983fc35
--- /dev/null
+++ b/src/test/ui/nll/polonius/assignment-to-differing-field.rs
@@ -0,0 +1,50 @@
+#![allow(dead_code)]
+
+// Compared to `assignment-kills-loans.rs`, we check here
+// that we do not kill too many borrows. Assignments to the `.1`
+// field projections should leave the borrows on `.0` intact.
+
+// compile-flags: -Z borrowck=mir -Z polonius
+// ignore-compare-mode-nll
+
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+
+fn assignment_to_field_projection<'a, T>(
+    mut list: (&'a mut List<T>, &'a mut List<T>),
+) -> Vec<&'a mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut (list.0).value);
+        //~^ ERROR cannot borrow `list.0.value` as mutable
+
+        if let Some(n) = (list.0).next.as_mut() {
+        //~^ ERROR cannot borrow `list.0.next` as mutable
+            list.1 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+fn assignment_through_projection_chain<'a, T>(
+    mut list: (((((Box<&'a mut List<T>>, Box<&'a mut List<T>>),),),),),
+) -> Vec<&'a mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut ((((list.0).0).0).0).0.value);
+        //~^ ERROR cannot borrow `list.0.0.0.0.0.value` as mutable
+
+        if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() {
+        //~^ ERROR cannot borrow `list.0.0.0.0.0.next` as mutable
+            *((((list.0).0).0).0).1 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/polonius/assignment-to-differing-field.stderr b/src/test/ui/nll/polonius/assignment-to-differing-field.stderr
new file mode 100644
index 0000000000000..07ca021b53bce
--- /dev/null
+++ b/src/test/ui/nll/polonius/assignment-to-differing-field.stderr
@@ -0,0 +1,51 @@
+error[E0499]: cannot borrow `list.0.value` as mutable more than once at a time
+  --> $DIR/assignment-to-differing-field.rs:21:21
+   |
+LL | fn assignment_to_field_projection<'a, T>(
+   |                                   -- lifetime `'a` defined here
+...
+LL |         result.push(&mut (list.0).value);
+   |                     ^^^^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
+...
+LL |             return result;
+   |                    ------ returning this value requires that `list.0.value` is borrowed for `'a`
+
+error[E0499]: cannot borrow `list.0.next` as mutable more than once at a time
+  --> $DIR/assignment-to-differing-field.rs:24:26
+   |
+LL | fn assignment_to_field_projection<'a, T>(
+   |                                   -- lifetime `'a` defined here
+...
+LL |         if let Some(n) = (list.0).next.as_mut() {
+   |                          ^^^^^^^^^^^^^---------
+   |                          |
+   |                          mutable borrow starts here in previous iteration of loop
+   |                          argument requires that `list.0.next` is borrowed for `'a`
+
+error[E0499]: cannot borrow `list.0.0.0.0.0.value` as mutable more than once at a time
+  --> $DIR/assignment-to-differing-field.rs:38:21
+   |
+LL | fn assignment_through_projection_chain<'a, T>(
+   |                                        -- lifetime `'a` defined here
+...
+LL |         result.push(&mut ((((list.0).0).0).0).0.value);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
+...
+LL |             return result;
+   |                    ------ returning this value requires that `list.0.0.0.0.0.value` is borrowed for `'a`
+
+error[E0499]: cannot borrow `list.0.0.0.0.0.next` as mutable more than once at a time
+  --> $DIR/assignment-to-differing-field.rs:41:26
+   |
+LL | fn assignment_through_projection_chain<'a, T>(
+   |                                        -- lifetime `'a` defined here
+...
+LL |         if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() {
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^---------
+   |                          |
+   |                          mutable borrow starts here in previous iteration of loop
+   |                          argument requires that `list.0.0.0.0.0.next` is borrowed for `'a`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/nll/polonius/call-kills-loans.rs b/src/test/ui/nll/polonius/call-kills-loans.rs
new file mode 100644
index 0000000000000..57dc140110246
--- /dev/null
+++ b/src/test/ui/nll/polonius/call-kills-loans.rs
@@ -0,0 +1,24 @@
+// `Call` terminators can write to a local which has existing loans
+// and those need to be killed like a regular assignment to a local.
+// This is a simplified version of issue 47680, is correctly accepted
+// by NLL but was incorrectly rejected by Polonius because of these
+// missing `killed` facts.
+
+// check-pass
+// compile-flags: -Z borrowck=mir -Z polonius
+// ignore-compare-mode-nll
+
+struct Thing;
+
+impl Thing {
+    fn next(&mut self) -> &mut Self { unimplemented!() }
+}
+
+fn main() {
+    let mut temp = &mut Thing;
+
+    loop {
+        let v = temp.next();
+        temp = v; // accepted by NLL, was incorrectly rejected by Polonius
+    }
+}
diff --git a/src/test/ui/nll/polonius/issue-46589.rs b/src/test/ui/nll/polonius/issue-46589.rs
new file mode 100644
index 0000000000000..b5792587ff0ec
--- /dev/null
+++ b/src/test/ui/nll/polonius/issue-46589.rs
@@ -0,0 +1,32 @@
+// This test is a copy of `ui/nll/issue-46589.rs` which fails in NLL but succeeds in Polonius.
+// As we can't have a test here which conditionally passes depending on a test
+// revision/compile-flags. We ensure here that it passes in Polonius mode.
+
+// check-pass
+// compile-flags: -Z borrowck=mir -Z polonius
+// ignore-compare-mode-nll
+
+struct Foo;
+
+impl Foo {
+    fn get_self(&mut self) -> Option<&mut Self> {
+        Some(self)
+    }
+
+    fn new_self(&mut self) -> &mut Self {
+        self
+    }
+
+    fn trigger_bug(&mut self) {
+        let other = &mut (&mut *self);
+
+        *other = match (*other).get_self() {
+            Some(s) => s,
+            None => (*other).new_self()
+        };
+
+        let c = other;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/polonius-smoke-test.rs b/src/test/ui/nll/polonius/polonius-smoke-test.rs
similarity index 100%
rename from src/test/ui/nll/polonius-smoke-test.rs
rename to src/test/ui/nll/polonius/polonius-smoke-test.rs
diff --git a/src/test/ui/nll/polonius-smoke-test.stderr b/src/test/ui/nll/polonius/polonius-smoke-test.stderr
similarity index 100%
rename from src/test/ui/nll/polonius-smoke-test.stderr
rename to src/test/ui/nll/polonius/polonius-smoke-test.stderr
diff --git a/src/test/ui/nll/polonius/storagedead-kills-loans.rs b/src/test/ui/nll/polonius/storagedead-kills-loans.rs
new file mode 100644
index 0000000000000..ff801cbf9f35d
--- /dev/null
+++ b/src/test/ui/nll/polonius/storagedead-kills-loans.rs
@@ -0,0 +1,29 @@
+// Whenever a `StorageDead` MIR statement destroys a value `x`,
+// we should kill all loans of `x`. This is extracted from `rand 0.4.6`,
+// is correctly accepted by NLL but was incorrectly rejected by
+// Polonius because of these missing `killed` facts.
+
+// check-pass
+// compile-flags: -Z borrowck=mir -Z polonius
+// ignore-compare-mode-nll
+
+use std::{io, mem};
+use std::io::Read;
+
+#[allow(dead_code)]
+fn fill(r: &mut dyn Read, mut buf: &mut [u8]) -> io::Result<()> {
+    while buf.len() > 0 {
+        match r.read(buf).unwrap() {
+            0 => return Err(io::Error::new(io::ErrorKind::Other,
+                                           "end of file reached")),
+            n => buf = &mut mem::replace(&mut buf, &mut [])[n..],
+            // ^- Polonius had multiple errors on the previous line (where NLL has none)
+            // as it didn't know `buf` was killed here, and would
+            // incorrectly reject both the borrow expression, and the assignment.
+        }
+    }
+    Ok(())
+}
+
+fn main() {
+}
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr
new file mode 100644
index 0000000000000..8e3cf59cffb44
--- /dev/null
+++ b/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr
@@ -0,0 +1,15 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/return-ref-mut-issue-46557.rs:4:21
+   |
+LL |     let ref mut x = 1234543;
+   |                     ^^^^^^^ creates a temporary which is freed while still in use
+LL |     x
+   |     - borrow later used here
+LL | }
+   | - temporary value is freed at the end of this statement
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/save-analysis/emit-notifications.polonius.stderr b/src/test/ui/save-analysis/emit-notifications.polonius.stderr
new file mode 100644
index 0000000000000..a1a1b8c63dac3
--- /dev/null
+++ b/src/test/ui/save-analysis/emit-notifications.polonius.stderr
@@ -0,0 +1,2 @@
+{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/save-analysis/libemit_notifications.json","emit":"save-analysis"}
+{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/libemit_notifications.rlib","emit":"link"}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr
new file mode 100644
index 0000000000000..4b906f75149af
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr
@@ -0,0 +1,60 @@
+error[E0597]: `factorial` does not live long enough
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- value captured here
+LL |         let g = factorial.as_ref().unwrap();
+   |                 ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `factorial` dropped here while still borrowed
+   | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option<std::boxed::Box<dyn std::ops::Fn(u32) -> u32>>`
+
+error[E0506]: cannot assign to `factorial` because it is borrowed
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:20:5
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- borrow of `factorial` occurs here
+LL |         let g = factorial.as_ref().unwrap();
+   |                 --------- borrow occurs due to use in closure
+...
+LL |     factorial = Some(Box::new(f));
+   |     ^^^^^^^^^
+   |     |
+   |     assignment to borrowed `factorial` occurs here
+   |     borrow later used here
+
+error[E0597]: `factorial` does not live long enough
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- value captured here
+LL |         let g = factorial.as_ref().unwrap();
+   |                 ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | `factorial` dropped here while still borrowed
+   | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option<std::boxed::Box<dyn std::ops::Fn(u32) -> u32>>`
+
+error[E0506]: cannot assign to `factorial` because it is borrowed
+  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:33:5
+   |
+LL |     let f = |x: u32| -> u32 {
+   |             --------------- borrow of `factorial` occurs here
+LL |         let g = factorial.as_ref().unwrap();
+   |                 --------- borrow occurs due to use in closure
+...
+LL |     factorial = Some(Box::new(f));
+   |     ^^^^^^^^^
+   |     |
+   |     assignment to borrowed `factorial` occurs here
+   |     borrow later used here
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0506, E0597.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index b6e087c3844fa..20176557bcbeb 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -92,6 +92,7 @@ static TARGETS: &[&str] = &[
     "powerpc-unknown-linux-gnu",
     "powerpc64-unknown-linux-gnu",
     "powerpc64le-unknown-linux-gnu",
+    "riscv32i-unknown-none-elf",
     "riscv32imc-unknown-none-elf",
     "riscv32imac-unknown-none-elf",
     "riscv64imac-unknown-none-elf",