diff --git a/Cargo.lock b/Cargo.lock
index bdc746c0bb0e0..f02a7574e63bb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2751,20 +2751,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 +2808,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 +2862,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 +2920,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 +3007,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 +3051,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",
 ]
 
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index bc4ae16798478..881d499c0745b 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -494,10 +494,10 @@ impl<T> [T] {
     /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn concat<Separator: ?Sized>(&self) -> T::Output
-        where T: SliceConcat<Separator>
+    pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
+        where Self: Concat<Item>
     {
-        SliceConcat::concat(self)
+        Concat::concat(self)
     }
 
     /// Flattens a slice of `T` into a single value `Self::Output`, placing a
@@ -508,12 +508,13 @@ impl<T> [T] {
     /// ```
     /// assert_eq!(["hello", "world"].join(" "), "hello world");
     /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
+    /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);
     /// ```
     #[stable(feature = "rename_connect_to_join", since = "1.3.0")]
-    pub fn join<Separator: ?Sized>(&self, sep: &Separator) -> T::Output
-        where T: SliceConcat<Separator>
+    pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
+        where Self: Join<Separator>
     {
-        SliceConcat::join(self, sep)
+        Join::join(self, sep)
     }
 
     /// Flattens a slice of `T` into a single value `Self::Output`, placing a
@@ -528,10 +529,10 @@ impl<T> [T] {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
-    pub fn connect<Separator: ?Sized>(&self, sep: &Separator) -> T::Output
-        where T: SliceConcat<Separator>
+    pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
+        where Self: Join<Separator>
     {
-        SliceConcat::join(self, sep)
+        Join::join(self, sep)
     }
 
 }
@@ -578,30 +579,63 @@ impl [u8] {
 // Extension traits for slices over specific kinds of data
 ////////////////////////////////////////////////////////////////////////////////
 
-/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat)
-/// and [`[T]::join`](../../std/primitive.slice.html#method.join)
+/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat).
+///
+/// Note: the `Item` type parameter is not used in this trait,
+/// but it allows impls to be more generic.
+/// Without it, we get this error:
+///
+/// ```error
+/// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica
+///    --> src/liballoc/slice.rs:608:6
+///     |
+/// 608 | impl<T: Clone, V: Borrow<[T]>> Concat for [V] {
+///     |      ^ unconstrained type parameter
+/// ```
+///
+/// This is because there could exist `V` types with multiple `Borrow<[_]>` impls,
+/// such that multiple `T` types would apply:
+///
+/// ```
+/// # #[allow(dead_code)]
+/// pub struct Foo(Vec<u32>, Vec<String>);
+///
+/// impl std::borrow::Borrow<[u32]> for Foo {
+///     fn borrow(&self) -> &[u32] { &self.0 }
+/// }
+///
+/// impl std::borrow::Borrow<[String]> for Foo {
+///     fn borrow(&self) -> &[String] { &self.1 }
+/// }
+/// ```
 #[unstable(feature = "slice_concat_trait", issue = "27747")]
-pub trait SliceConcat<Separator: ?Sized>: Sized {
+pub trait Concat<Item: ?Sized> {
     #[unstable(feature = "slice_concat_trait", issue = "27747")]
     /// The resulting type after concatenation
     type Output;
 
     /// Implementation of [`[T]::concat`](../../std/primitive.slice.html#method.concat)
     #[unstable(feature = "slice_concat_trait", issue = "27747")]
-    fn concat(slice: &[Self]) -> Self::Output;
+    fn concat(slice: &Self) -> Self::Output;
+}
+
+/// Helper trait for [`[T]::join`](../../std/primitive.slice.html#method.join)
+#[unstable(feature = "slice_concat_trait", issue = "27747")]
+pub trait Join<Separator> {
+    #[unstable(feature = "slice_concat_trait", issue = "27747")]
+    /// The resulting type after concatenation
+    type Output;
 
     /// Implementation of [`[T]::join`](../../std/primitive.slice.html#method.join)
     #[unstable(feature = "slice_concat_trait", issue = "27747")]
-    fn join(slice: &[Self], sep: &Separator) -> Self::Output;
+    fn join(slice: &Self, sep: Separator) -> Self::Output;
 }
 
-#[unstable(feature = "slice_concat_ext",
-           reason = "trait should not have to exist",
-           issue = "27747")]
-impl<T: Clone, V: Borrow<[T]>> SliceConcat<T> for V {
+#[unstable(feature = "slice_concat_ext", issue = "27747")]
+impl<T: Clone, V: Borrow<[T]>> Concat<T> for [V] {
     type Output = Vec<T>;
 
-    fn concat(slice: &[Self]) -> Vec<T> {
+    fn concat(slice: &Self) -> Vec<T> {
         let size = slice.iter().map(|slice| slice.borrow().len()).sum();
         let mut result = Vec::with_capacity(size);
         for v in slice {
@@ -609,14 +643,19 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcat<T> for V {
         }
         result
     }
+}
+
+#[unstable(feature = "slice_concat_ext", issue = "27747")]
+impl<T: Clone, V: Borrow<[T]>> Join<&T> for [V] {
+    type Output = Vec<T>;
 
-    fn join(slice: &[Self], sep: &T) -> Vec<T> {
+    fn join(slice: &Self, sep: &T) -> Vec<T> {
         let mut iter = slice.iter();
         let first = match iter.next() {
             Some(first) => first,
             None => return vec![],
         };
-        let size = slice.iter().map(|slice| slice.borrow().len()).sum::<usize>() + slice.len() - 1;
+        let size = slice.iter().map(|v| v.borrow().len()).sum::<usize>() + slice.len() - 1;
         let mut result = Vec::with_capacity(size);
         result.extend_from_slice(first.borrow());
 
@@ -628,6 +667,29 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcat<T> for V {
     }
 }
 
+#[unstable(feature = "slice_concat_ext", issue = "27747")]
+impl<T: Clone, V: Borrow<[T]>> Join<&[T]> for [V] {
+    type Output = Vec<T>;
+
+    fn join(slice: &Self, sep: &[T]) -> Vec<T> {
+        let mut iter = slice.iter();
+        let first = match iter.next() {
+            Some(first) => first,
+            None => return vec![],
+        };
+        let size = slice.iter().map(|v| v.borrow().len()).sum::<usize>() +
+            sep.len() * (slice.len() - 1);
+        let mut result = Vec::with_capacity(size);
+        result.extend_from_slice(first.borrow());
+
+        for v in iter {
+            result.extend_from_slice(sep);
+            result.extend_from_slice(v.borrow())
+        }
+        result
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Standard trait implementations for slices
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 37a1046d0942d..9a1342c30d502 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -37,7 +37,7 @@ use core::unicode::conversions;
 
 use crate::borrow::ToOwned;
 use crate::boxed::Box;
-use crate::slice::{SliceConcat, SliceIndex};
+use crate::slice::{Concat, Join, SliceIndex};
 use crate::string::String;
 use crate::vec::Vec;
 
@@ -71,17 +71,22 @@ pub use core::str::SplitAsciiWhitespace;
 #[stable(feature = "str_escape", since = "1.34.0")]
 pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode};
 
-#[unstable(feature = "slice_concat_ext",
-           reason = "trait should not have to exist",
-           issue = "27747")]
-impl<S: Borrow<str>> SliceConcat<str> for S {
+/// Note: `str` in `Concat<str>` is not meaningful here.
+/// This type parameter of the trait only exists to enable another impl.
+#[unstable(feature = "slice_concat_ext", issue = "27747")]
+impl<S: Borrow<str>> Concat<str> for [S] {
     type Output = String;
 
-    fn concat(slice: &[Self]) -> String {
-        Self::join(slice, "")
+    fn concat(slice: &Self) -> String {
+        Join::join(slice, "")
     }
+}
+
+#[unstable(feature = "slice_concat_ext", issue = "27747")]
+impl<S: Borrow<str>> Join<&str> for [S] {
+    type Output = String;
 
-    fn join(slice: &[Self], sep: &str) -> String {
+    fn join(slice: &Self, sep: &str) -> String {
         unsafe {
             String::from_utf8_unchecked( join_generic_copy(slice, sep.as_bytes()) )
         }
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 8c7b9cf1c5db7..e7b820e79e5cf 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1263,6 +1263,15 @@ impl<T> [T] {
     /// assert!(v.contains(&30));
     /// assert!(!v.contains(&50));
     /// ```
+    ///
+    /// If you do not have an `&T`, but just an `&U` such that `T: Borrow<U>`
+    /// (e.g. `String: Borrow<str>`), you can use `iter().any`:
+    ///
+    /// ```
+    /// let v = [String::from("hello"), String::from("world")]; // slice of `String`
+    /// assert!(v.iter().any(|e| e == "hello")); // search with `&str`
+    /// assert!(!v.iter().any(|e| e == "hi"));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains(&self, x: &T) -> bool
         where T: PartialEq
diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml
index a95193b85952f..82a9e34c065b1 100644
--- a/src/libfmt_macros/Cargo.toml
+++ b/src/libfmt_macros/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2018"
 [lib]
 name = "fmt_macros"
 path = "lib.rs"
-crate-type = ["dylib"]
 
 [dependencies]
 syntax_pos = { path = "../libsyntax_pos" }
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/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index d06c4434b3aaf..4bfe953e45c0b 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -764,16 +764,17 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             }
         }
 
-        span_bug!(
+        // Errors in earlier passes can yield error variables without
+        // resolution errors here; delay ICE in favor of those errors.
+        self.tcx().sess.delay_span_bug(
             self.var_infos[node_idx].origin.span(),
-            "collect_error_for_expanding_node() could not find \
-             error for var {:?} in universe {:?}, lower_bounds={:#?}, \
-             upper_bounds={:#?}",
-            node_idx,
-            node_universe,
-            lower_bounds,
-            upper_bounds
-        );
+            &format!("collect_error_for_expanding_node() could not find \
+                      error for var {:?} in universe {:?}, lower_bounds={:#?}, \
+                      upper_bounds={:#?}",
+                     node_idx,
+                     node_universe,
+                     lower_bounds,
+                     upper_bounds));
     }
 
     fn collect_concrete_regions(
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/mir/mod.rs b/src/librustc/mir/mod.rs
index d8b641fbe31f4..75f03949d995b 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1931,7 +1931,7 @@ impl<'tcx> Place<'tcx> {
         iterate_over2(place_base, place_projection, &Projections::Empty, op)
     }
 
-    pub fn as_place_ref(&self) -> PlaceRef<'_, 'tcx> {
+    pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
         PlaceRef {
             base: &self.base,
             projection: &self.projection,
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/context.rs b/src/librustc/ty/context.rs
index 16fc46b66d9f4..f1550b9d756a5 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -46,7 +46,6 @@ use crate::util::common::ErrorReported;
 use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet};
 use crate::util::nodemap::{FxHashMap, FxHashSet};
 use errors::DiagnosticBuilder;
-use rustc_data_structures::interner::HashInterner;
 use smallvec::SmallVec;
 use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
                                            StableHasher, StableHasherResult,
@@ -54,6 +53,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
 use arena::SyncDroplessArena;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
+use rustc_data_structures::sharded::ShardedHashMap;
 use std::any::Any;
 use std::borrow::Borrow;
 use std::cmp::Ordering;
@@ -88,7 +88,7 @@ impl AllArenas {
     }
 }
 
-type InternedSet<'tcx, T> = Lock<FxHashMap<Interned<'tcx, T>, ()>>;
+type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;
 
 pub struct CtxtInterners<'tcx> {
     /// The arena that types, regions, etc are allocated from
@@ -135,7 +135,7 @@ impl<'tcx> CtxtInterners<'tcx> {
     fn intern_ty(&self,
         st: TyKind<'tcx>
     ) -> Ty<'tcx> {
-        self.type_.borrow_mut().intern(st, |st| {
+        self.type_.intern(st, |st| {
             let flags = super::flags::FlagComputation::for_sty(&st);
 
             let ty_struct = TyS {
@@ -924,7 +924,7 @@ impl<'tcx> CommonTypes<'tcx> {
 impl<'tcx> CommonLifetimes<'tcx> {
     fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> {
         let mk = |r| {
-            interners.region.borrow_mut().intern(r, |r| {
+            interners.region.intern(r, |r| {
                 Interned(interners.arena.alloc(r))
             }).0
         };
@@ -940,7 +940,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
 impl<'tcx> CommonConsts<'tcx> {
     fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
         let mk_const = |c| {
-            interners.const_.borrow_mut().intern(c, |c| {
+            interners.const_.intern(c, |c| {
                 Interned(interners.arena.alloc(c))
             }).0
         };
@@ -1053,14 +1053,14 @@ pub struct GlobalCtxt<'tcx> {
     /// Data layout specification for the current target.
     pub data_layout: TargetDataLayout,
 
-    stability_interner: Lock<FxHashMap<&'tcx attr::Stability, ()>>,
+    stability_interner: ShardedHashMap<&'tcx attr::Stability, ()>,
 
     /// Stores the value of constants (and deduplicates the actual memory)
-    allocation_interner: Lock<FxHashMap<&'tcx Allocation, ()>>,
+    allocation_interner: ShardedHashMap<&'tcx Allocation, ()>,
 
     pub alloc_map: Lock<interpret::AllocMap<'tcx>>,
 
-    layout_interner: Lock<FxHashMap<&'tcx LayoutDetails, ()>>,
+    layout_interner: ShardedHashMap<&'tcx LayoutDetails, ()>,
 
     /// A general purpose channel to throw data out the back towards LLVM worker
     /// threads.
@@ -1103,7 +1103,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn intern_const_alloc(self, alloc: Allocation) -> &'tcx Allocation {
-        self.allocation_interner.borrow_mut().intern(alloc, |alloc| {
+        self.allocation_interner.intern(alloc, |alloc| {
             self.arena.alloc(alloc)
         })
     }
@@ -1117,13 +1117,13 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability {
-        self.stability_interner.borrow_mut().intern(stab, |stab| {
+        self.stability_interner.intern(stab, |stab| {
             self.arena.alloc(stab)
         })
     }
 
     pub fn intern_layout(self, layout: LayoutDetails) -> &'tcx LayoutDetails {
-        self.layout_interner.borrow_mut().intern(layout, |layout| {
+        self.layout_interner.intern(layout, |layout| {
             self.arena.alloc(layout)
         })
     }
@@ -2023,7 +2023,9 @@ macro_rules! sty_debug_print {
                 };
                 $(let mut $variant = total;)*
 
-                for &Interned(t) in tcx.interners.type_.borrow().keys() {
+                let shards = tcx.interners.type_.lock_shards();
+                let types = shards.iter().flat_map(|shard| shard.keys());
+                for &Interned(t) in types {
                     let variant = match t.sty {
                         ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
                             ty::Float(..) | ty::Str | ty::Never => continue,
@@ -2074,11 +2076,11 @@ impl<'tcx> TyCtxt<'tcx> {
             Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound,
             Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
 
-        println!("InternalSubsts interner: #{}", self.interners.substs.borrow().len());
-        println!("Region interner: #{}", self.interners.region.borrow().len());
-        println!("Stability interner: #{}", self.stability_interner.borrow().len());
-        println!("Allocation interner: #{}", self.allocation_interner.borrow().len());
-        println!("Layout interner: #{}", self.layout_interner.borrow().len());
+        println!("InternalSubsts interner: #{}", self.interners.substs.len());
+        println!("Region interner: #{}", self.interners.region.len());
+        println!("Stability interner: #{}", self.stability_interner.len());
+        println!("Allocation interner: #{}", self.allocation_interner.len());
+        println!("Layout interner: #{}", self.layout_interner.len());
     }
 }
 
@@ -2207,7 +2209,7 @@ macro_rules! intern_method {
             pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
                 let key = ($alloc_to_key)(&v);
 
-                self.interners.$name.borrow_mut().intern_ref(key, || {
+                self.interners.$name.intern_ref(key, || {
                     Interned($alloc_method(&self.interners.arena, v))
 
                 }).0
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_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/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 09c346117f9d9..907689541f978 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -238,7 +238,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                    context: PlaceContext,
                    location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
-        self.process_place(&place.as_place_ref(), context, location);
+        self.process_place(&place.as_ref(), context, location);
     }
 
     fn visit_local(&mut self,
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index d4b434ffe809c..54afefd1a64e2 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -253,7 +253,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             PassMode::Direct(_) | PassMode::Pair(..) => {
                 let op =
-                    self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE.as_place_ref());
+                    self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE.as_ref());
                 if let Ref(llval, _, align) = op.val {
                     bx.load(llval, align)
                 } else {
@@ -314,7 +314,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             return
         }
 
-        let place = self.codegen_place(&mut bx, &location.as_place_ref());
+        let place = self.codegen_place(&mut bx, &location.as_ref());
         let (args1, args2);
         let mut args = if let Some(llextra) = place.llextra {
             args2 = [place.llval, llextra];
@@ -1171,7 +1171,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
                 LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
                 LocalRef::Operand(None) => {
-                    let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_place_ref()));
+                    let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref()));
                     assert!(!dst_layout.ty.has_erasable_regions());
                     let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
                     place.storage_live(bx);
@@ -1186,7 +1186,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
         } else {
-            let dst = self.codegen_place(bx, &dst.as_place_ref());
+            let dst = self.codegen_place(bx, &dst.as_ref());
             self.codegen_transmute_into(bx, src, dst);
         }
     }
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 0f6a95c1968b8..302dcfcc682a3 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -462,7 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         match *operand {
             mir::Operand::Copy(ref place) |
             mir::Operand::Move(ref place) => {
-                self.codegen_consume(bx, &place.as_place_ref())
+                self.codegen_consume(bx, &place.as_ref())
             }
 
             mir::Operand::Constant(ref constant) => {
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index cfb7db7365802..202cf147f1fcb 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -355,7 +355,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             mir::Rvalue::Ref(_, bk, ref place) => {
-                let cg_place = self.codegen_place(&mut bx, &place.as_place_ref());
+                let cg_place = self.codegen_place(&mut bx, &place.as_ref());
 
                 let ty = cg_place.layout.ty;
 
@@ -446,7 +446,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             mir::Rvalue::Discriminant(ref place) => {
                 let discr_ty = rvalue.ty(&*self.mir, bx.tcx());
-                let discr =  self.codegen_place(&mut bx, &place.as_place_ref())
+                let discr =  self.codegen_place(&mut bx, &place.as_ref())
                     .codegen_get_discr(&mut bx, discr_ty);
                 (bx, OperandRef {
                     val: OperandValue::Immediate(discr),
@@ -527,7 +527,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
         }
         // use common size calculation for non zero-sized types
-        let cg_value = self.codegen_place(bx, &place.as_place_ref());
+        let cg_value = self.codegen_place(bx, &place.as_ref());
         cg_value.len(bx.cx())
     }
 
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index 499cda1cf8449..3717be4b41753 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -46,12 +46,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         }
                     }
                 } else {
-                    let cg_dest = self.codegen_place(&mut bx, &place.as_place_ref());
+                    let cg_dest = self.codegen_place(&mut bx, &place.as_ref());
                     self.codegen_rvalue(bx, cg_dest, rvalue)
                 }
             }
             mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
-                self.codegen_place(&mut bx, &place.as_place_ref())
+                self.codegen_place(&mut bx, &place.as_ref())
                     .codegen_set_discr(&mut bx, variant_index);
                 bx
             }
@@ -73,7 +73,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
             mir::StatementKind::InlineAsm(ref asm) => {
                 let outputs = asm.outputs.iter().map(|output| {
-                    self.codegen_place(&mut bx, &output.as_place_ref())
+                    self.codegen_place(&mut bx, &output.as_ref())
                 }).collect();
 
                 let input_vals = asm.inputs.iter()
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_data_structures/interner.rs b/src/librustc_data_structures/interner.rs
deleted file mode 100644
index 36ccbb704a733..0000000000000
--- a/src/librustc_data_structures/interner.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use std::hash::Hash;
-use std::hash::BuildHasher;
-use std::hash::Hasher;
-use std::collections::HashMap;
-use std::collections::hash_map::RawEntryMut;
-use std::borrow::Borrow;
-
-pub trait HashInterner<K: Eq + Hash> {
-    fn intern_ref<Q: ?Sized, F: FnOnce() -> K>(&mut self, value: &Q, make: F) -> K
-        where K: Borrow<Q>,
-              Q: Hash + Eq;
-
-    fn intern<Q, F: FnOnce(Q) -> K>(&mut self, value: Q, make: F) -> K
-        where K: Borrow<Q>,
-              Q: Hash + Eq;
-}
-
-impl<K: Eq + Hash + Copy, S: BuildHasher> HashInterner<K> for HashMap<K, (), S> {
-    #[inline]
-    fn intern_ref<Q: ?Sized, F: FnOnce() -> K>(&mut self, value: &Q, make: F) -> K
-        where K: Borrow<Q>,
-              Q: Hash + Eq
-    {
-        let mut hasher = self.hasher().build_hasher();
-        value.hash(&mut hasher);
-        let hash = hasher.finish();
-        let entry = self.raw_entry_mut().from_key_hashed_nocheck(hash, value);
-
-        match entry {
-            RawEntryMut::Occupied(e) => *e.key(),
-            RawEntryMut::Vacant(e) => {
-                let v = make();
-                e.insert_hashed_nocheck(hash, v, ());
-                v
-            }
-        }
-    }
-
-    #[inline]
-    fn intern<Q, F: FnOnce(Q) -> K>(&mut self, value: Q, make: F) -> K
-        where K: Borrow<Q>,
-              Q: Hash + Eq
-    {
-        let mut hasher = self.hasher().build_hasher();
-        value.hash(&mut hasher);
-        let hash = hasher.finish();
-        let entry = self.raw_entry_mut().from_key_hashed_nocheck(hash, &value);
-
-        match entry {
-            RawEntryMut::Occupied(e) => *e.key(),
-            RawEntryMut::Vacant(e) => {
-                let v = make(value);
-                e.insert_hashed_nocheck(hash, v, ());
-                v
-            }
-        }
-    }
-}
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index b479643a5e8cd..a2407681e6d3f 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -77,7 +77,6 @@ pub mod flock;
 pub mod fx;
 pub mod graph;
 pub mod indexed_vec;
-pub mod interner;
 pub mod jobserver;
 pub mod obligation_forest;
 pub mod owning_ref;
@@ -89,6 +88,7 @@ pub use ena::snapshot_vec;
 pub mod sorted_map;
 #[macro_use] pub mod stable_hasher;
 pub mod sync;
+pub mod sharded;
 pub mod tiny_list;
 pub mod thin_vec;
 pub mod transitive_relation;
diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs
new file mode 100644
index 0000000000000..31cb22098b8e9
--- /dev/null
+++ b/src/librustc_data_structures/sharded.rs
@@ -0,0 +1,128 @@
+use std::hash::{Hasher, Hash};
+use std::mem;
+use std::borrow::Borrow;
+use std::collections::hash_map::RawEntryMut;
+use crate::fx::{FxHasher, FxHashMap};
+use crate::sync::{Lock, LockGuard};
+
+#[derive(Clone, Default)]
+#[cfg_attr(parallel_compiler, repr(align(64)))]
+struct CacheAligned<T>(T);
+
+#[cfg(parallel_compiler)]
+// 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700,
+// but this should be tested on higher core count CPUs. How the `Sharded` type gets used
+// may also affect the ideal nunber of shards.
+const SHARD_BITS: usize = 5;
+
+#[cfg(not(parallel_compiler))]
+const SHARD_BITS: usize = 0;
+
+const SHARDS: usize = 1 << SHARD_BITS;
+
+/// An array of cache-line aligned inner locked structures with convenience methods.
+#[derive(Clone)]
+pub struct Sharded<T> {
+    shards: [CacheAligned<Lock<T>>; SHARDS],
+}
+
+impl<T: Default> Default for Sharded<T> {
+    #[inline]
+    fn default() -> Self {
+        let mut shards: mem::MaybeUninit<[CacheAligned<Lock<T>>; SHARDS]> =
+            mem::MaybeUninit::uninit();
+        let first = shards.as_mut_ptr() as *mut CacheAligned<Lock<T>>;
+        unsafe {
+            for i in 0..SHARDS {
+                first.add(i).write(CacheAligned(Lock::new(T::default())));
+            }
+            Sharded {
+                shards: shards.assume_init(),
+            }
+        }
+    }
+}
+
+impl<T> Sharded<T> {
+    #[inline]
+    pub fn get_shard_by_value<K: Hash + ?Sized>(&self, val: &K) -> &Lock<T> {
+        if SHARDS == 1 {
+            &self.shards[0].0
+        } else {
+            self.get_shard_by_hash(make_hash(val))
+        }
+    }
+
+    #[inline]
+    pub fn get_shard_by_hash(&self, hash: u64) -> &Lock<T> {
+        let hash_len = mem::size_of::<usize>();
+        // Ignore the top 7 bits as hashbrown uses these and get the next SHARD_BITS highest bits.
+        // hashbrown also uses the lowest bits, so we can't use those
+        let bits = (hash >> (hash_len * 8 - 7 - SHARD_BITS)) as usize;
+        let i = bits % SHARDS;
+        &self.shards[i].0
+    }
+
+    pub fn lock_shards(&self) -> Vec<LockGuard<'_, T>> {
+        (0..SHARDS).map(|i| self.shards[i].0.lock()).collect()
+    }
+
+    pub fn try_lock_shards(&self) -> Option<Vec<LockGuard<'_, T>>> {
+        (0..SHARDS).map(|i| self.shards[i].0.try_lock()).collect()
+    }
+}
+
+pub type ShardedHashMap<K, V> = Sharded<FxHashMap<K, V>>;
+
+impl<K: Eq + Hash, V> ShardedHashMap<K, V> {
+    pub fn len(&self) -> usize {
+        self.lock_shards().iter().map(|shard| shard.len()).sum()
+    }
+}
+
+impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
+    #[inline]
+    pub fn intern_ref<Q: ?Sized>(&self, value: &Q, make: impl FnOnce() -> K) -> K
+        where K: Borrow<Q>,
+              Q: Hash + Eq
+    {
+        let hash = make_hash(value);
+        let mut shard = self.get_shard_by_hash(hash).lock();
+        let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, value);
+
+        match entry {
+            RawEntryMut::Occupied(e) => *e.key(),
+            RawEntryMut::Vacant(e) => {
+                let v = make();
+                e.insert_hashed_nocheck(hash, v, ());
+                v
+            }
+        }
+    }
+
+    #[inline]
+    pub fn intern<Q>(&self, value: Q, make: impl FnOnce(Q) -> K) -> K
+        where K: Borrow<Q>,
+              Q: Hash + Eq
+    {
+        let hash = make_hash(&value);
+        let mut shard = self.get_shard_by_hash(hash).lock();
+        let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, &value);
+
+        match entry {
+            RawEntryMut::Occupied(e) => *e.key(),
+            RawEntryMut::Vacant(e) => {
+                let v = make(value);
+                e.insert_hashed_nocheck(hash, v, ());
+                v
+            }
+        }
+    }
+}
+
+#[inline]
+fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
+    let mut state = FxHasher::default();
+    val.hash(&mut state);
+    state.finish()
+}
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_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/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 95fc22dc5eb76..5d0e490ebea5a 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -139,14 +139,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let is_partial_move = move_site_vec.iter().any(|move_site| {
                 let move_out = self.move_data.moves[(*move_site).moi];
                 let moved_place = &self.move_data.move_paths[move_out.path].place;
-                used_place != moved_place.as_place_ref()
-                    && used_place.is_prefix_of(moved_place.as_place_ref())
+                used_place != moved_place.as_ref()
+                    && used_place.is_prefix_of(moved_place.as_ref())
             });
             for move_site in &move_site_vec {
                 let move_out = self.move_data.moves[(*move_site).moi];
                 let moved_place = &self.move_data.move_paths[move_out.path].place;
 
-                let move_spans = self.move_spans(moved_place.as_place_ref(), move_out.source);
+                let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
                 let move_span = move_spans.args_or_use();
 
                 let move_msg = if move_spans.for_closure() {
@@ -223,7 +223,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
                 let ty = place.ty(self.body, self.infcx.tcx).ty;
                 let opt_name =
-                    self.describe_place_with_options(place.as_place_ref(), IncludingDowncast(true));
+                    self.describe_place_with_options(place.as_ref(), IncludingDowncast(true));
                 let note_msg = match opt_name {
                     Some(ref name) => format!("`{}`", name),
                     None => "value".to_owned(),
@@ -275,11 +275,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}",
             location, place, span, borrow
         );
-        let value_msg = match self.describe_place(place.as_place_ref()) {
+        let value_msg = match self.describe_place(place.as_ref()) {
             Some(name) => format!("`{}`", name),
             None => "value".to_owned(),
         };
-        let borrow_msg = match self.describe_place(borrow.borrowed_place.as_place_ref()) {
+        let borrow_msg = match self.describe_place(borrow.borrowed_place.as_ref()) {
             Some(name) => format!("`{}`", name),
             None => "value".to_owned(),
         };
@@ -287,12 +287,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let borrow_spans = self.retrieve_borrow_spans(borrow);
         let borrow_span = borrow_spans.args_or_use();
 
-        let move_spans = self.move_spans(place.as_place_ref(), location);
+        let move_spans = self.move_spans(place.as_ref(), location);
         let span = move_spans.args_or_use();
 
         let mut err = self.cannot_move_when_borrowed(
             span,
-            &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+            &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
         );
         err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg));
         err.span_label(span, format!("move out of {} occurs here", value_msg));
@@ -326,21 +326,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         // Conflicting borrows are reported separately, so only check for move
         // captures.
-        let use_spans = self.move_spans(place.as_place_ref(), location);
+        let use_spans = self.move_spans(place.as_ref(), location);
         let span = use_spans.var_or_use();
 
         let mut err = self.cannot_use_when_mutably_borrowed(
             span,
-            &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+            &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
             borrow_span,
-            &self.describe_place(borrow.borrowed_place.as_place_ref())
+            &self.describe_place(borrow.borrowed_place.as_ref())
                 .unwrap_or_else(|| "_".to_owned()),
         );
 
         borrow_spans.var_span_label(&mut err, {
             let place = &borrow.borrowed_place;
             let desc_place =
-                self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned());
+                self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned());
 
             format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe())
         });
@@ -517,7 +517,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             );
         } else {
             let borrow_place = &issued_borrow.borrowed_place;
-            let borrow_place_desc = self.describe_place(borrow_place.as_place_ref())
+            let borrow_place_desc = self.describe_place(borrow_place.as_ref())
                                         .unwrap_or_else(|| "_".to_owned());
             issued_spans.var_span_label(
                 &mut err,
@@ -650,8 +650,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
                                 return Some((
                                     describe_base_place,
-                                    describe_place(first_borrowed_place.as_place_ref()),
-                                    describe_place(second_borrowed_place.as_place_ref()),
+                                    describe_place(first_borrowed_place.as_ref()),
+                                    describe_place(second_borrowed_place.as_ref()),
                                     union_ty.to_string(),
                                 ));
                             }
@@ -666,7 +666,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // If we didn't find a field access into a union, or both places match, then
                 // only return the description of the first place.
                 (
-                    describe_place(first_borrowed_place.as_place_ref()),
+                    describe_place(first_borrowed_place.as_ref()),
                     "".to_string(),
                     "".to_string(),
                     "".to_string(),
@@ -697,7 +697,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         );
 
         let drop_span = place_span.1;
-        let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(), PrefixSet::All)
+        let root_place = self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All)
             .last()
             .unwrap();
 
@@ -730,13 +730,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }, borrow_span));
 
         if let StorageDeadOrDrop::Destructor(dropped_ty) =
-            self.classify_drop_access_kind(borrow.borrowed_place.as_place_ref())
+            self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
         {
             // If a borrow of path `B` conflicts with drop of `D` (and
             // we're not in the uninteresting case where `B` is a
             // prefix of `D`), then report this as a more interesting
             // destructor conflict.
-            if !borrow.borrowed_place.as_place_ref().is_prefix_of(place_span.0.as_place_ref()) {
+            if !borrow.borrowed_place.as_ref().is_prefix_of(place_span.0.as_ref()) {
                 self.report_borrow_conflicts_with_destructor(
                     location, borrow, place_span, kind, dropped_ty,
                 );
@@ -744,7 +744,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
-        let place_desc = self.describe_place(borrow.borrowed_place.as_place_ref());
+        let place_desc = self.describe_place(borrow.borrowed_place.as_ref());
 
         let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0));
         let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place);
@@ -951,12 +951,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         let mut err = self.cannot_borrow_across_destructor(borrow_span);
 
-        let what_was_dropped = match self.describe_place(place.as_place_ref()) {
+        let what_was_dropped = match self.describe_place(place.as_ref()) {
             Some(name) => format!("`{}`", name.as_str()),
             None => String::from("temporary value"),
         };
 
-        let label = match self.describe_place(borrow.borrowed_place.as_place_ref()) {
+        let label = match self.describe_place(borrow.borrowed_place.as_ref()) {
             Some(borrowed) => format!(
                 "here, drop of {D} needs exclusive access to `{B}`, \
                  because the type `{T}` implements the `Drop` trait",
@@ -1127,7 +1127,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 format!("`{}` is borrowed here", place_desc),
             )
         } else {
-            let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(),
+            let root_place = self.prefixes(borrow.borrowed_place.as_ref(),
                                            PrefixSet::All)
                 .last()
                 .unwrap();
@@ -1390,7 +1390,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let mut err = self.cannot_mutate_in_match_guard(
                 span,
                 loan_span,
-                &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+                &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
                 "assign",
             );
             loan_spans.var_span_label(
@@ -1406,7 +1406,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let mut err = self.cannot_assign_to_borrowed(
             span,
             loan_span,
-            &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+            &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
         );
 
         loan_spans.var_span_label(
@@ -1466,8 +1466,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 is_user_variable: None,
                 ..
             })
-            | None => (self.describe_place(place.as_place_ref()), assigned_span),
-            Some(decl) => (self.describe_place(err_place.as_place_ref()), decl.source_info.span),
+            | None => (self.describe_place(place.as_ref()), assigned_span),
+            Some(decl) => (self.describe_place(err_place.as_ref()), decl.source_info.span),
         };
 
         let mut err = self.cannot_reassign_immutable(
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 156897aedb70a..a05c77aad6700 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -855,7 +855,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     def_id, is_generator, places
                 );
                 if let Some((args_span, var_span)) = self.closure_span(
-                    *def_id, Place::from(target).as_place_ref(), places
+                    *def_id, Place::from(target).as_ref(), places
                 ) {
                     return ClosureUse {
                         is_generator,
@@ -895,7 +895,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
                 match place {
                     Operand::Copy(place) |
-                    Operand::Move(place) if target_place == place.as_place_ref() => {
+                    Operand::Move(place) if target_place == place.as_ref() => {
                         debug!("closure_span: found captured local {:?}", place);
                         return Some((*args_span, upvar.span));
                     },
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index cfc7e77f4e5a8..5ec1e514100de 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -560,7 +560,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -591,7 +591,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
                         self.check_if_path_or_subpath_is_moved(
                             location,
                             InitializationRequiringAction::Use,
-                            (output.as_place_ref(), o.span),
+                            (output.as_ref(), o.span),
                             flow_state,
                         );
                     } else {
@@ -1154,7 +1154,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Update,
-                    (place_span.0.as_place_ref(), place_span.1),
+                    (place_span.0.as_ref(), place_span.1),
                     flow_state,
                 );
             }
@@ -1232,7 +1232,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     action,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1260,7 +1260,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1309,7 +1309,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
         let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
             if place.projection.is_some() {
-                if let Some(field) = this.is_upvar_field_projection(place.as_place_ref()) {
+                if let Some(field) = this.is_upvar_field_projection(place.as_ref()) {
                     this.used_mut_upvars.push(field);
                 }
             } else if let PlaceBase::Local(local) = place.base {
@@ -1401,7 +1401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1419,7 +1419,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1437,7 +1437,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) {
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
-        let root_place = self.prefixes(place.as_place_ref(), PrefixSet::All).last().unwrap();
+        let root_place = self.prefixes(place.as_ref(), PrefixSet::All).last().unwrap();
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
         // we just know that all locals are dropped at function exit (otherwise
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 38653dc0e5e9b..738a091b0dd76 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -131,7 +131,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     }
                 }
 
-                let move_spans = self.move_spans(original_path.as_place_ref(), location);
+                let move_spans = self.move_spans(original_path.as_ref(), location);
                 grouped_errors.push(GroupedMoveError::OtherIllegalMove {
                     use_spans: move_spans,
                     original_path,
@@ -160,7 +160,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let from_simple_let = match_place.is_none();
         let match_place = match_place.as_ref().unwrap_or(move_from);
 
-        match self.move_data.rev_lookup.find(match_place.as_place_ref()) {
+        match self.move_data.rev_lookup.find(match_place.as_ref()) {
             // Error with the match place
             LookupResult::Parent(_) => {
                 for ge in &mut *grouped_errors {
@@ -192,7 +192,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
             // Error with the pattern
             LookupResult::Exact(_) => {
-                let mpi = match self.move_data.rev_lookup.find(move_from.as_place_ref()) {
+                let mpi = match self.move_data.rev_lookup.find(move_from.as_ref()) {
                     LookupResult::Parent(Some(mpi)) => mpi,
                     // move_from should be a projection from match_place.
                     _ => unreachable!("Probably not unreachable..."),
@@ -242,7 +242,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 };
             debug!("report: original_path={:?} span={:?}, kind={:?} \
                    original_path.is_upvar_field_projection={:?}", original_path, span, kind,
-                   self.is_upvar_field_projection(original_path.as_place_ref()));
+                   self.is_upvar_field_projection(original_path.as_ref()));
             (
                 match kind {
                     IllegalMoveOriginKind::Static => {
@@ -277,7 +277,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         span: Span
     ) -> DiagnosticBuilder<'a> {
         let description = if place.projection.is_none() {
-            format!("static item `{}`", self.describe_place(place.as_place_ref()).unwrap())
+            format!("static item `{}`", self.describe_place(place.as_ref()).unwrap())
         } else {
             let mut base_static = &place.projection;
             while let Some(box Projection { base: Some(ref proj), .. }) = base_static {
@@ -290,7 +290,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
             format!(
                 "`{:?}` as `{:?}` is a static item",
-                self.describe_place(place.as_place_ref()).unwrap(),
+                self.describe_place(place.as_ref()).unwrap(),
                 self.describe_place(base_static).unwrap(),
             )
         };
@@ -308,7 +308,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         // borrow to provide feedback about why this
         // was a move rather than a copy.
         let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty;
-        let upvar_field = self.prefixes(move_place.as_place_ref(), PrefixSet::All)
+        let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All)
             .find_map(|p| self.is_upvar_field_projection(p));
 
         let deref_base = match deref_target_place.projection {
@@ -363,10 +363,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 let upvar_name = upvar.name;
                 let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id);
 
-                let place_name = self.describe_place(move_place.as_place_ref()).unwrap();
+                let place_name = self.describe_place(move_place.as_ref()).unwrap();
 
                 let place_description = if self
-                    .is_upvar_field_projection(move_place.as_place_ref())
+                    .is_upvar_field_projection(move_place.as_ref())
                     .is_some()
                 {
                     format!("`{}`, a {}", place_name, capture_description)
@@ -393,7 +393,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             _ => {
                 let source = self.borrowed_content_source(deref_base);
                 match (
-                    self.describe_place(move_place.as_place_ref()),
+                    self.describe_place(move_place.as_ref()),
                     source.describe_for_named_place(),
                 ) {
                     (Some(place_desc), Some(source_desc)) => {
@@ -455,7 +455,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
                 if binds_to.is_empty() {
                     let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
-                    let place_desc = match self.describe_place(move_from.as_place_ref()) {
+                    let place_desc = match self.describe_place(move_from.as_ref()) {
                         Some(desc) => format!("`{}`", desc),
                         None => format!("value"),
                     };
@@ -483,7 +483,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => {
                 let span = use_spans.var_or_use();
                 let place_ty = original_path.ty(self.body, self.infcx.tcx).ty;
-                let place_desc = match self.describe_place(original_path.as_place_ref()) {
+                let place_desc = match self.describe_place(original_path.as_ref()) {
                     Some(desc) => format!("`{}`", desc),
                     None => format!("value"),
                 };
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index c424c06c41add..937c6383be341 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let item_msg;
         let reason;
         let mut opt_source = None;
-        let access_place_desc = self.describe_place(access_place.as_place_ref());
+        let access_place_desc = self.describe_place(access_place.as_ref());
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
@@ -77,7 +77,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if self.is_upvar_field_projection(access_place.as_place_ref()).is_some() {
+                if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
                     let name = self.upvars[upvar_index.index()].name;
@@ -109,7 +109,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     ));
 
                     reason =
-                        if self.is_upvar_field_projection(access_place.as_place_ref()).is_some() {
+                        if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
                             ", as it is a captured variable in a `Fn` closure".to_string()
                         } else {
                             ", as `Fn` closures cannot mutate their captured variables".to_string()
@@ -244,7 +244,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     format!(
                         "mutable borrow occurs due to use of `{}` in closure",
                         // always Some() if the message is printed.
-                        self.describe_place(access_place.as_place_ref()).unwrap_or_default(),
+                        self.describe_place(access_place.as_ref()).unwrap_or_default(),
                     )
                 );
                 borrow_span
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index abb84c59d9b9e..aba3ef1cbbfc9 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -252,7 +252,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             Some(Cause::LiveVar(local, location)) => {
                 let span = body.source_info(location).span;
                 let spans = self
-                    .move_spans(Place::from(local).as_place_ref(), location)
+                    .move_spans(Place::from(local).as_ref(), location)
                     .or_else(|| self.borrow_spans(span, location));
 
                 let borrow_location = location;
@@ -305,7 +305,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
                     if let Some(region_name) = region_name {
                         let opt_place_desc =
-                            self.describe_place(borrow.borrowed_place.as_place_ref());
+                            self.describe_place(borrow.borrowed_place.as_ref());
                         BorrowExplanation::MustBeValidFor {
                             category,
                             from_closure,
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index 75065816df050..da3f165482655 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -50,7 +50,7 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>(
             body,
             &borrowed.borrowed_place,
             borrowed.kind,
-            place.as_place_ref(),
+            place.as_ref(),
             access,
             places_conflict::PlaceConflictBias::Overlap,
         ) {
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 348214f97f256..b2a03147ecf80 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -36,7 +36,7 @@ crate fn places_conflict<'tcx>(
         body,
         borrow_place,
         BorrowKind::Mut { allow_two_phase_borrow: true },
-        access_place.as_place_ref(),
+        access_place.as_ref(),
         AccessDepth::Deep,
         bias,
     )
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index b58cef9cce1e7..d72b0addae915 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -1304,7 +1304,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 prefix_cursor = base;
             }
 
-            all_fake_borrows.push(place.as_place_ref());
+            all_fake_borrows.push(place.as_ref());
         }
 
         // Deduplicate and ensure a deterministic order.
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index b6dd544d39561..c071b3101fce3 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -171,7 +171,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'tcx, F>(
     let move_data = &ctxt.move_data;
     for arg in body.args_iter() {
         let place = mir::Place::from(arg);
-        let lookup_result = move_data.rev_lookup.find(place.as_place_ref());
+        let lookup_result = move_data.rev_lookup.find(place.as_ref());
         on_lookup_result_bits(tcx, body, move_data,
                               lookup_result,
                               |mpi| callback(mpi, DropFlagState::Present));
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index ade732bbb7597..69bbe08792140 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -309,7 +309,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_place to 1 (initialized).
         on_lookup_result_bits(self.tcx, self.body, self.move_data(),
-                              self.move_data().rev_lookup.find(dest_place.as_place_ref()),
+                              self.move_data().rev_lookup.find(dest_place.as_ref()),
                               |mpi| { in_out.insert(mpi); });
     }
 }
@@ -367,7 +367,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_place to 0 (initialized).
         on_lookup_result_bits(self.tcx, self.body, self.move_data(),
-                              self.move_data().rev_lookup.find(dest_place.as_place_ref()),
+                              self.move_data().rev_lookup.find(dest_place.as_ref()),
                               |mpi| { in_out.remove(mpi); });
     }
 }
@@ -423,7 +423,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_place to 1 (initialized).
         on_lookup_result_bits(self.tcx, self.body, self.move_data(),
-                              self.move_data().rev_lookup.find(dest_place.as_place_ref()),
+                              self.move_data().rev_lookup.find(dest_place.as_ref()),
                               |mpi| { in_out.insert(mpi); });
     }
 }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 436ac30ffb42e..366b96b53b423 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -274,9 +274,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                     // move-path for the interior so it will be separate from
                     // the exterior.
                     self.create_move_path(&place.clone().deref());
-                    self.gather_init(place.as_place_ref(), InitKind::Shallow);
+                    self.gather_init(place.as_ref(), InitKind::Shallow);
                 } else {
-                    self.gather_init(place.as_place_ref(), InitKind::Deep);
+                    self.gather_init(place.as_ref(), InitKind::Deep);
                 }
                 self.gather_rvalue(rval);
             }
@@ -286,7 +286,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             StatementKind::InlineAsm(ref asm) => {
                 for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
                     if !kind.is_indirect {
-                        self.gather_init(output.as_place_ref(), InitKind::Deep);
+                        self.gather_init(output.as_ref(), InitKind::Deep);
                     }
                 }
                 for (_, input) in asm.inputs.iter() {
@@ -376,7 +376,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             TerminatorKind::DropAndReplace { ref location, ref value, .. } => {
                 self.create_move_path(location);
                 self.gather_operand(value);
-                self.gather_init(location.as_place_ref(), InitKind::Deep);
+                self.gather_init(location.as_ref(), InitKind::Deep);
             }
             TerminatorKind::Call {
                 ref func,
@@ -391,7 +391,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 }
                 if let Some((ref destination, _bb)) = *destination {
                     self.create_move_path(destination);
-                    self.gather_init(destination.as_place_ref(), InitKind::NonPanicPathOnly);
+                    self.gather_init(destination.as_ref(), InitKind::NonPanicPathOnly);
                 }
             }
         }
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index 887f93c647878..d573423906c2a 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -79,7 +79,7 @@ impl MirPass for AddRetag {
         let needs_retag = |place: &Place<'tcx>| {
             // FIXME: Instead of giving up for unstable places, we should introduce
             // a temporary and retag on that.
-            is_stable(place.as_place_ref())
+            is_stable(place.as_ref())
                 && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx)
         };
 
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 0748321f60593..0a021d9b8fa06 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -105,7 +105,7 @@ fn find_dead_unwinds<'tcx>(
             init_data.apply_location(tcx, body, env, loc);
         }
 
-        let path = match env.move_data.rev_lookup.find(location.as_place_ref()) {
+        let path = match env.move_data.rev_lookup.find(location.as_ref()) {
             LookupResult::Exact(e) => e,
             LookupResult::Parent(..) => {
                 debug!("find_dead_unwinds: has parent; skipping");
@@ -360,7 +360,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 statement_index: data.statements.len()
             });
 
-            let path = self.move_data().rev_lookup.find(location.as_place_ref());
+            let path = self.move_data().rev_lookup.find(location.as_ref());
             debug!("collect_drop_flags: {:?}, place {:?} ({:?})",
                    bb, location, path);
 
@@ -399,7 +399,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             match terminator.kind {
                 TerminatorKind::Drop { ref location, target, unwind } => {
                     let init_data = self.initialization_data_at(loc);
-                    match self.move_data().rev_lookup.find(location.as_place_ref()) {
+                    match self.move_data().rev_lookup.find(location.as_ref()) {
                         LookupResult::Exact(path) => {
                             elaborate_drop(
                                 &mut Elaborator {
@@ -488,7 +488,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             is_cleanup: false,
         });
 
-        match self.move_data().rev_lookup.find(location.as_place_ref()) {
+        match self.move_data().rev_lookup.find(location.as_ref()) {
             LookupResult::Exact(path) => {
                 debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path);
                 let init_data = self.initialization_data_at(loc);
@@ -558,7 +558,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: tgt, statement_index: 0 };
-                let path = self.move_data().rev_lookup.find(place.as_place_ref());
+                let path = self.move_data().rev_lookup.find(place.as_ref());
                 on_lookup_result_bits(
                     self.tcx, self.body, self.move_data(), path,
                     |child| self.set_drop_flag(loc, child, DropFlagState::Present)
@@ -632,7 +632,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: bb, statement_index: data.statements.len() };
-                let path = self.move_data().rev_lookup.find(place.as_place_ref());
+                let path = self.move_data().rev_lookup.find(place.as_ref());
                 on_lookup_result_bits(
                     self.tcx, self.body, self.move_data(), path,
                     |child| self.set_drop_flag(loc, child, DropFlagState::Present)
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 739e2172b03bc..ffeaf4e19c22a 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -243,7 +243,7 @@ trait Qualif {
     fn in_operand(cx: &ConstCx<'_, 'tcx>, operand: &Operand<'tcx>) -> bool {
         match *operand {
             Operand::Copy(ref place) |
-            Operand::Move(ref place) => Self::in_place(cx, place.as_place_ref()),
+            Operand::Move(ref place) => Self::in_place(cx, place.as_ref()),
 
             Operand::Constant(ref constant) => {
                 if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
@@ -272,7 +272,7 @@ trait Qualif {
             Rvalue::NullaryOp(..) => false,
 
             Rvalue::Discriminant(ref place) |
-            Rvalue::Len(ref place) => Self::in_place(cx, place.as_place_ref()),
+            Rvalue::Len(ref place) => Self::in_place(cx, place.as_ref()),
 
             Rvalue::Use(ref operand) |
             Rvalue::Repeat(ref operand, _) |
@@ -298,7 +298,7 @@ trait Qualif {
                     }
                 }
 
-                Self::in_place(cx, place.as_place_ref())
+                Self::in_place(cx, place.as_ref())
             }
 
             Rvalue::Aggregate(_, ref operands) => {
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 1fd865c42fcdb..7fe8480c819e6 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -168,7 +168,7 @@ fn each_block<'tcx, O>(
         if place == peek_arg_place {
             if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = **rvalue {
                 // Okay, our search is over.
-                match move_data.rev_lookup.find(peeking_at_place.as_place_ref()) {
+                match move_data.rev_lookup.find(peeking_at_place.as_ref()) {
                     LookupResult::Exact(peek_mpi) => {
                         let bit_state = on_entry.contains(peek_mpi);
                         debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
@@ -192,7 +192,7 @@ fn each_block<'tcx, O>(
             }
         }
 
-        let lhs_mpi = move_data.rev_lookup.find(place.as_place_ref());
+        let lhs_mpi = move_data.rev_lookup.find(place.as_ref());
 
         debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}",
                place, lhs_mpi, stmt);
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 ee11228654b6f..d4135778a57d0 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/spec/x86_64_unknown_linux_gnux32.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
index 73151b194de42..0b2d7aacc4ddf 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
@@ -5,8 +5,7 @@ pub fn target() -> TargetResult {
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
-    // BUG: temporarily workaround #59674
-    base.stack_probes = false;
+    base.stack_probes = true;
     base.has_elf_tls = false;
     // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
     // breaks code gen. See LLVM bug 36743
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index d314228a232c9..5799e58a727a8 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1650,7 +1650,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             Applicability::MaybeIncorrect,
                         );
                     } else {
-                        err.span_label(span, format!("variant not found in `{}`", qself_ty));
+                        err.span_label(
+                            assoc_ident.span,
+                            format!("variant not found in `{}`", qself_ty),
+                        );
                     }
 
                     if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index bde6db78aef32..21cd4b694ae4c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -759,40 +759,40 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
 fn primary_body_of(
     tcx: TyCtxt<'_>,
     id: hir::HirId,
-) -> Option<(hir::BodyId, Option<&hir::FnHeader>, Option<&hir::FnDecl>)> {
+) -> Option<(hir::BodyId, Option<&hir::Ty>, Option<&hir::FnHeader>, Option<&hir::FnDecl>)> {
     match tcx.hir().get(id) {
         Node::Item(item) => {
             match item.node {
-                hir::ItemKind::Const(_, body) |
-                hir::ItemKind::Static(_, _, body) =>
-                    Some((body, None, None)),
+                hir::ItemKind::Const(ref ty, body) |
+                hir::ItemKind::Static(ref ty, _, body) =>
+                    Some((body, Some(ty), None, None)),
                 hir::ItemKind::Fn(ref decl, ref header, .., body) =>
-                    Some((body, Some(header), Some(decl))),
+                    Some((body, None, Some(header), Some(decl))),
                 _ =>
                     None,
             }
         }
         Node::TraitItem(item) => {
             match item.node {
-                hir::TraitItemKind::Const(_, Some(body)) =>
-                    Some((body, None, None)),
+                hir::TraitItemKind::Const(ref ty, Some(body)) =>
+                    Some((body, Some(ty), None, None)),
                 hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) =>
-                    Some((body, Some(&sig.header), Some(&sig.decl))),
+                    Some((body, None, Some(&sig.header), Some(&sig.decl))),
                 _ =>
                     None,
             }
         }
         Node::ImplItem(item) => {
             match item.node {
-                hir::ImplItemKind::Const(_, body) =>
-                    Some((body, None, None)),
+                hir::ImplItemKind::Const(ref ty, body) =>
+                    Some((body, Some(ty), None, None)),
                 hir::ImplItemKind::Method(ref sig, body) =>
-                    Some((body, Some(&sig.header), Some(&sig.decl))),
+                    Some((body, None, Some(&sig.header), Some(&sig.decl))),
                 _ =>
                     None,
             }
         }
-        Node::AnonConst(constant) => Some((constant.body, None, None)),
+        Node::AnonConst(constant) => Some((constant.body, None, None, None)),
         _ => None,
     }
 }
@@ -825,7 +825,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
     let span = tcx.hir().span(id);
 
     // Figure out what primary body this item has.
-    let (body_id, fn_header, fn_decl) = primary_body_of(tcx, id)
+    let (body_id, body_ty, fn_header, fn_decl) = primary_body_of(tcx, id)
         .unwrap_or_else(|| {
             span_bug!(span, "can't type-check body of {:?}", def_id);
         });
@@ -856,7 +856,10 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
             fcx
         } else {
             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
-            let expected_type = tcx.type_of(def_id);
+            let expected_type = body_ty.and_then(|ty| match ty.node {
+                hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)),
+                _ => None
+            }).unwrap_or_else(|| tcx.type_of(def_id));
             let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index a5457c45d378c..053ef1f8f8297 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1135,6 +1135,26 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     checked_type_of(tcx, def_id, true).unwrap()
 }
 
+fn infer_placeholder_type(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    body_id: hir::BodyId,
+    span: Span,
+) -> Ty<'_> {
+    let ty = tcx.typeck_tables_of(def_id).node_type(body_id.hir_id);
+    let mut diag = bad_placeholder_type(tcx, span);
+    if ty != tcx.types.err {
+        diag.span_suggestion(
+            span,
+            "replace `_` with the correct type",
+            ty.to_string(),
+            Applicability::MaybeIncorrect,
+        );
+    }
+    diag.emit();
+    ty
+}
+
 /// Same as [`type_of`] but returns [`Option`] instead of failing.
 ///
 /// If you want to fail anyway, you can set the `fail` parameter to true, but in this case,
@@ -1160,7 +1180,16 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
-            TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
+            TraitItemKind::Const(ref ty, body_id)  => {
+                body_id.and_then(|body_id| {
+                    if let hir::TyKind::Infer = ty.node {
+                        Some(infer_placeholder_type(tcx, def_id, body_id, ty.span))
+                    } else {
+                        None
+                    }
+                }).unwrap_or_else(|| icx.to_ty(ty))
+            },
+            TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
             TraitItemKind::Type(_, None) => {
                 if !fail {
                     return None;
@@ -1174,7 +1203,13 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
-            ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
+            ImplItemKind::Const(ref ty, body_id) => {
+                if let hir::TyKind::Infer = ty.node {
+                    infer_placeholder_type(tcx, def_id, body_id, ty.span)
+                } else {
+                    icx.to_ty(ty)
+                }
+            },
             ImplItemKind::Existential(_) => {
                 if tcx
                     .impl_trait_ref(tcx.hir().get_parent_did(hir_id))
@@ -1199,10 +1234,16 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
 
         Node::Item(item) => {
             match item.node {
-                ItemKind::Static(ref t, ..)
-                | ItemKind::Const(ref t, _)
-                | ItemKind::Ty(ref t, _)
-                | ItemKind::Impl(.., ref t, _) => icx.to_ty(t),
+                ItemKind::Static(ref ty, .., body_id)
+                | ItemKind::Const(ref ty, body_id) => {
+                    if let hir::TyKind::Infer = ty.node {
+                        infer_placeholder_type(tcx, def_id, body_id, ty.span)
+                    } else {
+                        icx.to_ty(ty)
+                    }
+                },
+                ItemKind::Ty(ref ty, _)
+                | ItemKind::Impl(.., ref ty, _) => icx.to_ty(ty),
                 ItemKind::Fn(..) => {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_fn_def(def_id, substs)
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 65fd8c83e1ce5..ead1987d04b56 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -362,8 +362,13 @@ mod prim_unit { }
 ///
 /// *[See also the `std::ptr` module](ptr/index.html).*
 ///
-/// Working with raw pointers in Rust is uncommon,
-/// typically limited to a few patterns.
+/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns.
+/// Raw pointers can be unaligned or [`null`] when unused. However, when a raw pointer is
+/// dereferenced (using the `*` operator), it must be non-null and aligned.
+///
+/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so
+/// [`write`] must be used if the type has drop glue and memory is not already
+/// initialized---otherwise `drop` would be called on the uninitialized memory.
 ///
 /// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
 /// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
@@ -442,6 +447,7 @@ mod prim_unit { }
 /// [`offset`]: ../std/primitive.pointer.html#method.offset
 /// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
 /// [`drop`]: ../std/mem/fn.drop.html
+/// [`write`]: ../std/ptr/fn.write.html
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer { }
 
@@ -891,9 +897,10 @@ mod prim_usize { }
 /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
 /// operators on a value, or by using a `ref` or `ref mut` pattern.
 ///
-/// For those familiar with pointers, a reference is just a pointer that is assumed to not be null.
-/// In fact, `Option<&T>` has the same memory representation as a nullable pointer, and can be
-/// passed across FFI boundaries as such.
+/// For those familiar with pointers, a reference is just a pointer that is assumed to be
+/// aligned, not null, and pointing to valid (initialized) memory.
+/// In fact, `Option<&T>` has the same memory representation as a
+/// nullable but aligned pointer, and can be passed across FFI boundaries as such.
 ///
 /// In most cases, references can be used much like the original value. Field access, method
 /// calling, and indexing work the same (save for mutability rules, of course). In addition, the
@@ -1036,6 +1043,11 @@ mod prim_ref { }
 /// [`FnMut`]: ops/trait.FnMut.html
 /// [`FnOnce`]: ops/trait.FnOnce.html
 ///
+/// Function pointers are pointers that point to *code*, not data. They can be called
+/// just like functions. Like references, function pointers are, among other things, assumed to
+/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
+/// pointers, make your type `Option<fn()>` with your required signature.
+///
 /// Plain function pointers are obtained by casting either plain functions, or closures that don't
 /// capture an environment:
 ///
@@ -1091,10 +1103,6 @@ mod prim_ref { }
 ///
 /// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
 ///
-/// Like references in rust, function pointers are assumed to not be null, so if you want to pass a
-/// function pointer over FFI and be able to accommodate null pointers, make your type
-/// `Option<fn()>` with your required signature.
-///
 /// Function pointers implement the following traits:
 ///
 /// * [`Clone`]
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 bfefd9adbfe8f..fa8a81fb3d3ac 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 4c4551b1757ac..4794b5a4831c8 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;
 
@@ -59,6 +60,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 {
@@ -87,6 +89,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 87373364c4d9e..690315326f39e 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 da0f8ca6da090..46742a91e353e 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -1,22 +1,18 @@
-//! 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)]
 
 #![recursion_limit="256"]
 
-extern crate proc_macro;
-
 mod error_codes;
 
 mod asm;
@@ -25,19 +21,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;
@@ -93,7 +90,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,
@@ -135,7 +132,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/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr
index 1a16aab6a41d1..beb8941320bc2 100644
--- a/src/test/ui/error-codes/E0121.stderr
+++ b/src/test/ui/error-codes/E0121.stderr
@@ -11,7 +11,10 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/E0121.rs:3:13
    |
 LL | static BAR: _ = "test";
-   |             ^ not allowed in type signatures
+   |             ^
+   |             |
+   |             not allowed in type signatures
+   |             help: replace `_` with the correct type: `&'static str`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/existential-type/issue-58887.rs b/src/test/ui/existential-type/issue-58887.rs
new file mode 100644
index 0000000000000..f038648ec2149
--- /dev/null
+++ b/src/test/ui/existential-type/issue-58887.rs
@@ -0,0 +1,23 @@
+#![feature(existential_type)]
+
+trait UnwrapItemsExt {
+    type Iter;
+    fn unwrap_items(self) -> Self::Iter;
+}
+
+impl<I, T, E> UnwrapItemsExt for I
+where
+    I: Iterator<Item = Result<T, E>>,
+    E: std::fmt::Debug,
+{
+    existential type Iter: Iterator<Item = T>;
+    //~^ ERROR: could not find defining uses
+
+    fn unwrap_items(self) -> Self::Iter {
+    //~^ ERROR: type parameter `T` is part of concrete type
+    //~| ERROR: type parameter `E` is part of concrete type
+        self.map(|x| x.unwrap())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/existential-type/issue-58887.stderr b/src/test/ui/existential-type/issue-58887.stderr
new file mode 100644
index 0000000000000..800f4b7e059fb
--- /dev/null
+++ b/src/test/ui/existential-type/issue-58887.stderr
@@ -0,0 +1,30 @@
+error: type parameter `T` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/issue-58887.rs:16:41
+   |
+LL |       fn unwrap_items(self) -> Self::Iter {
+   |  _________________________________________^
+LL | |
+LL | |
+LL | |         self.map(|x| x.unwrap())
+LL | |     }
+   | |_____^
+
+error: type parameter `E` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/issue-58887.rs:16:41
+   |
+LL |       fn unwrap_items(self) -> Self::Iter {
+   |  _________________________________________^
+LL | |
+LL | |
+LL | |         self.map(|x| x.unwrap())
+LL | |     }
+   | |_____^
+
+error: could not find defining uses
+  --> $DIR/issue-58887.rs:13:5
+   |
+LL |     existential type Iter: Iterator<Item = T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.rs b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs
new file mode 100644
index 0000000000000..454d7e5e9cdea
--- /dev/null
+++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs
@@ -0,0 +1,50 @@
+trait T0<'a, A> {
+    type O;
+}
+
+struct L<T> {
+    f: T,
+}
+
+// explicitly named variants of what one would normally denote by the
+// unit type `()`. Why do this? So that we can differentiate them in
+// the diagnostic output.
+struct Unit1;
+struct Unit2;
+struct Unit3;
+struct Unit4;
+
+impl<'a, A, T> T0<'a, A> for L<T>
+where
+    T: FnMut(A) -> Unit3,
+{
+    type O = T::Output;
+}
+
+trait T1: for<'r> Ty<'r> {
+    fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1
+    where
+        F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
+    {
+        unimplemented!();
+    }
+}
+
+trait Ty<'a> {
+    type V;
+}
+
+fn main() {
+    let v = Unit2.m(
+        //~^ ERROR type mismatch
+        //~| ERROR type mismatch
+        L {
+            f : |x| { drop(x); Unit4 }
+        });
+}
+
+impl<'a> Ty<'a> for Unit2 {
+    type V = &'a u8;
+}
+
+impl T1 for Unit2 {}
diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr
new file mode 100644
index 0000000000000..c2d0e0c2a26bc
--- /dev/null
+++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr
@@ -0,0 +1,22 @@
+error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]> as T0<'r, (<Unit2 as Ty<'r>>::V,)>>::O == <_ as Ty<'r>>::V`
+  --> $DIR/issue-62203-hrtb-ice.rs:38:19
+   |
+LL |     let v = Unit2.m(
+   |                   ^ expected struct `Unit4`, found associated type
+   |
+   = note: expected type `Unit4`
+              found type `<_ as Ty<'_>>::V`
+
+error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as std::ops::FnOnce<((&u8,),)>>::Output == Unit3`
+  --> $DIR/issue-62203-hrtb-ice.rs:38:19
+   |
+LL |     let v = Unit2.m(
+   |                   ^ expected struct `Unit4`, found struct `Unit3`
+   |
+   = note: expected type `Unit4`
+              found type `Unit3`
+   = note: required because of the requirements on the impl of `for<'r> T0<'r, (<Unit2 as Ty<'r>>::V,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr
index ef0ba70c34066..b4338e2055431 100644
--- a/src/test/ui/suggestions/suggest-variants.stderr
+++ b/src/test/ui/suggestions/suggest-variants.stderr
@@ -23,9 +23,7 @@ LL | enum Shape {
    | ---------- variant `Rombus` not found here
 ...
 LL |     println!("My shape is {:?}", Shape::Rombus{ size: 5});
-   |                                  -------^^^^^^
-   |                                  |
-   |                                  variant not found in `Shape`
+   |                                         ^^^^^^ variant not found in `Shape`
 
 error[E0599]: no variant or associated item named `Squareee` found for type `Shape` in the current scope
   --> $DIR/suggest-variants.rs:15:12
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
index ddaa5de4d3e27..2b4d9966c3d0b 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -23,13 +23,19 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/typeck_type_placeholder_item.rs:11:15
    |
 LL | static TEST3: _ = "test";
-   |               ^ not allowed in type signatures
+   |               ^
+   |               |
+   |               not allowed in type signatures
+   |               help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:14:15
    |
 LL | static TEST4: _ = 145;
-   |               ^ not allowed in type signatures
+   |               ^
+   |               |
+   |               not allowed in type signatures
+   |               help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:17:16
@@ -122,13 +128,19 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/typeck_type_placeholder_item.rs:64:22
    |
 LL |     static FN_TEST3: _ = "test";
-   |                      ^ not allowed in type signatures
+   |                      ^
+   |                      |
+   |                      not allowed in type signatures
+   |                      help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:67:22
    |
 LL |     static FN_TEST4: _ = 145;
-   |                      ^ not allowed in type signatures
+   |                      ^
+   |                      |
+   |                      not allowed in type signatures
+   |                      help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:70:23
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs
index 5f4cb4c1316d5..905fc35350ed0 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs
@@ -4,6 +4,24 @@
 fn test1() -> _ { Some(42) }
 //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 
+const TEST2: _ = 42u32;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+const TEST3: _ = Some(42);
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+trait Test4 {
+    const TEST4: _ = 42;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+}
+
+struct Test5;
+
+impl Test5 {
+    const TEST5: _ = 13;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+}
+
 pub fn main() {
     let _: Option<usize> = test1();
     let _: f64 = test1();
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
index 7fb5549825cc5..c5b9566290c11 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
@@ -7,6 +7,42 @@ LL | fn test1() -> _ { Some(42) }
    |               not allowed in type signatures
    |               help: replace `_` with the correct return type: `std::option::Option<i32>`
 
-error: aborting due to previous error
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:7:14
+   |
+LL | const TEST2: _ = 42u32;
+   |              ^
+   |              |
+   |              not allowed in type signatures
+   |              help: replace `_` with the correct type: `u32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:10:14
+   |
+LL | const TEST3: _ = Some(42);
+   |              ^
+   |              |
+   |              not allowed in type signatures
+   |              help: replace `_` with the correct type: `std::option::Option<i32>`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:14:18
+   |
+LL |     const TEST4: _ = 42;
+   |                  ^
+   |                  |
+   |                  not allowed in type signatures
+   |                  help: replace `_` with the correct type: `i32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:21:18
+   |
+LL |     const TEST5: _ = 13;
+   |                  ^
+   |                  |
+   |                  not allowed in type signatures
+   |                  help: replace `_` with the correct type: `i32`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0121`.