about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-07-25 22:34:23 +0000
committerbors <bors@rust-lang.org>2019-07-25 22:34:23 +0000
commit18630677cf6c7ac50e6786c504b35bc09501dbe2 (patch)
treeb6f28ed1be746076ce883fa0ccda880019eb91fd
parent890881f8f4c77e8670d4b32104c0325fcfefc90f (diff)
parent1a775b3b55263a82c3e69a942de5d2cdfb374bf1 (diff)
downloadrust-18630677cf6c7ac50e6786c504b35bc09501dbe2.tar.gz
rust-18630677cf6c7ac50e6786c504b35bc09501dbe2.zip
Auto merge of #62990 - Centril:rollup-k9n0hvs, r=Centril
Rollup of 15 pull requests

Successful merges:

 - #60066 (Stabilize the type_name intrinsic in core::any)
 - #60938 (rustdoc: make #[doc(include)] relative to the containing file)
 - #61884 (Stablize Euclidean Modulo (feature euclidean_division))
 - #61890 (Fix some sanity checks)
 - #62528 (Add joining slices of slices with a slice separator, not just a single item)
 - #62707 (Add tests for overlapping explicitly dropped locals in generators)
 - #62735 (Turn `#[global_allocator]` into a regular attribute macro)
 - #62822 (Improve some pointer-related documentation)
 - #62887 (Make the parser TokenStream more resilient after mismatched delimiter recovery)
 - #62921 (Add method disambiguation help for trait implementation)
 - #62930 (Add test for #51559)
 - #62942 (Use match ergonomics in Condvar documentation)
 - #62977 (Fix inconsistent highlight blocks.)
 - #62978 (Remove `cfg(bootstrap)` code for array implementations)
 - #62981 (Add note suggesting to borrow a String argument to find)

Failed merges:

 - #62964 (clarify and unify some type test names)

r? @ghost
-rw-r--r--Cargo.lock18
-rw-r--r--src/bootstrap/sanity.rs15
-rw-r--r--src/doc/rustdoc/src/unstable-features.md5
-rw-r--r--src/liballoc/slice.rs104
-rw-r--r--src/liballoc/str.rs21
-rw-r--r--src/libcore/any.rs26
-rw-r--r--src/libcore/array.rs673
-rw-r--r--src/libcore/char/methods.rs14
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/macros.rs7
-rw-r--r--src/libcore/num/mod.rs48
-rw-r--r--src/libcore/ops/function.rs4
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/middle/allocator.rs16
-rw-r--r--src/librustc/middle/dead.rs5
-rw-r--r--src/librustc/session/mod.rs2
-rw-r--r--src/librustc/traits/query/normalize.rs2
-rw-r--r--src/librustc/traits/query/normalize_erasing_regions.rs2
-rw-r--r--src/librustc/ty/query/config.rs2
-rw-r--r--src/librustc/ty/query/mod.rs2
-rw-r--r--src/librustc/ty/query/on_disk_cache.rs2
-rw-r--r--src/librustc/ty/query/plumbing.rs4
-rw-r--r--src/librustc_allocator/Cargo.toml19
-rw-r--r--src/librustc_allocator/expand.rs298
-rw-r--r--src/librustc_allocator/lib.rs44
-rw-r--r--src/librustc_codegen_llvm/allocator.rs3
-rw-r--r--src/librustc_codegen_llvm/lib.rs3
-rw-r--r--src/librustc_codegen_ssa/Cargo.toml1
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs4
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs2
-rw-r--r--src/librustc_driver/Cargo.toml2
-rw-r--r--src/librustc_interface/Cargo.toml1
-rw-r--r--src/librustc_interface/passes.rs15
-rw-r--r--src/librustc_lint/builtin.rs4
-rw-r--r--src/librustc_metadata/creader.rs29
-rw-r--r--src/librustc_metadata/lib.rs5
-rw-r--r--src/librustc_mir/transform/mod.rs2
-rw-r--r--src/librustc_passes/ast_validation.rs10
-rw-r--r--src/librustc_typeck/check/intrinsic.rs2
-rw-r--r--src/librustc_typeck/check/method/suggest.rs50
-rw-r--r--src/libserialize/serialize.rs6
-rw-r--r--src/libstd/f32.rs6
-rw-r--r--src/libstd/f64.rs6
-rw-r--r--src/libstd/os/raw/mod.rs48
-rw-r--r--src/libstd/primitive_docs.rs29
-rw-r--r--src/libstd/sync/condvar.rs36
-rw-r--r--src/libsyntax/attr/builtin.rs97
-rw-r--r--src/libsyntax/ext/allocator.rs75
-rw-r--r--src/libsyntax/ext/base.rs27
-rw-r--r--src/libsyntax/ext/expand.rs6
-rw-r--r--src/libsyntax/ext/source_util.rs32
-rw-r--r--src/libsyntax/feature_gate.rs91
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/parse/parser.rs15
-rw-r--r--src/libsyntax_ext/global_allocator.rs191
-rw-r--r--src/libsyntax_ext/lib.rs7
-rw-r--r--src/libsyntax_ext/test.rs11
-rw-r--r--src/libsyntax_ext/test_case.rs7
m---------src/stdarch0
-rw-r--r--src/test/run-pass/allocator/custom-in-block.rs22
-rw-r--r--src/test/run-pass/allocator/custom-in-submodule.rs26
-rw-r--r--src/test/run-pass/consts/const-fn-type-name.rs2
-rw-r--r--src/test/run-pass/generator/size-moved-locals.rs12
-rw-r--r--src/test/run-pass/issues/issue-21058.rs5
-rw-r--r--src/test/run-pass/issues/issue-61894.rs4
-rw-r--r--src/test/run-pass/tydesc-name.rs10
-rw-r--r--src/test/ui/allocator-submodule.rs28
-rw-r--r--src/test/ui/allocator-submodule.stderr8
-rw-r--r--src/test/ui/allocator/allocator-args.rs13
-rw-r--r--src/test/ui/allocator/allocator-args.stderr8
-rw-r--r--src/test/ui/allocator/two-allocators.rs2
-rw-r--r--src/test/ui/allocator/two-allocators.stderr8
-rw-r--r--src/test/ui/associated-const/associated-const-ambiguity-report.stderr2
-rw-r--r--src/test/ui/consts/issue-51559.rs7
-rw-r--r--src/test/ui/consts/issue-51559.stderr11
-rw-r--r--src/test/ui/error-codes/E0034.stderr2
-rw-r--r--src/test/ui/extern/external-doc-error.rs1
-rw-r--r--src/test/ui/extern/external-doc-error.stderr12
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr10
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-test.stderr10
-rw-r--r--src/test/ui/inference/inference_unstable_featured.stderr2
-rw-r--r--src/test/ui/issues/issue-3702-2.stderr2
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr2
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls.rs16
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls.stderr22
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls2.rs16
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr22
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr2
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr2
-rw-r--r--src/test/ui/parser/issue-62881.rs6
-rw-r--r--src/test/ui/parser/issue-62881.stderr29
-rw-r--r--src/test/ui/parser/issue-62895.rs11
-rw-r--r--src/test/ui/parser/issue-62895.stderr49
-rw-r--r--src/test/ui/suggestions/issue-62843.rs5
-rw-r--r--src/test/ui/suggestions/issue-62843.stderr13
-rw-r--r--src/test/ui/traits/trait-alias-ambiguous.stderr2
-rw-r--r--src/tools/tidy/src/features.rs2
98 files changed, 1329 insertions, 1238 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bdc746c0bb0..89932546278 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2752,20 +2752,6 @@ dependencies = [
 ]
 
 [[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"
 dependencies = [
@@ -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",
@@ -2883,7 +2868,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_utils 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -2904,7 +2888,6 @@ dependencies = [
  "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 +2931,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",
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index dc65fb9b797..4e3930c8da7 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -78,8 +78,11 @@ pub fn check(build: &mut Build) {
 
     // We need cmake, but only if we're actually building LLVM or sanitizers.
     let building_llvm = build.hosts.iter()
-        .filter_map(|host| build.config.target_config.get(host))
-        .any(|config| config.llvm_config.is_none());
+        .map(|host| build.config.target_config
+            .get(host)
+            .map(|config| config.llvm_config.is_none())
+            .unwrap_or(true))
+        .any(|build_llvm_ourselves| build_llvm_ourselves);
     if building_llvm || build.config.sanitizers {
         cmd_finder.must_have("cmake");
     }
@@ -106,6 +109,14 @@ pub fn check(build: &mut Build) {
                 build.config.ninja = true;
             }
         }
+
+        if build.config.lldb_enabled {
+            cmd_finder.must_have("swig");
+            let out = output(Command::new("swig").arg("-version"));
+            if !out.contains("SWIG Version 3") && !out.contains("SWIG Version 4") {
+                panic!("Ensure that Swig 3.x.x or 4.x.x is installed.");
+            }
+        }
     }
 
     build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 1d9510c9aac..6e32468b64d 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -183,9 +183,8 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
 
 As designed in [RFC 1990], Rustdoc can read an external file to use as a type's documentation. This
 is useful if certain documentation is so long that it would break the flow of reading the source.
-Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` (where `sometype.md` is
-a file adjacent to the `lib.rs` for the crate) will ask Rustdoc to instead read that file and use it
-as if it were written inline.
+Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` will ask Rustdoc to
+instead read that file and use it as if it were written inline.
 
 [RFC 1990]: https://github.com/rust-lang/rfcs/pull/1990
 
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index bc4ae167984..881d499c074 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 37a1046d094..9a1342c30d5 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/any.rs b/src/libcore/any.rs
index d043ce34eff..f7aef66942d 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -450,3 +450,29 @@ impl TypeId {
         }
     }
 }
+
+/// Returns the name of a type as a string slice.
+///
+/// # Note
+///
+/// This is intended for diagnostic use. The exact contents and format of the
+/// string are not specified, other than being a best-effort description of the
+/// type. For example, `type_name::<Option<String>>()` could return the
+/// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not
+/// `"foobar"`. In addition, the output may change between versions of the
+/// compiler.
+///
+/// The type name should not be considered a unique identifier of a type;
+/// multiple types may share the same type name.
+///
+/// The current implementation uses the same infrastructure as compiler
+/// diagnostics and debuginfo, but this is not guaranteed.
+#[stable(feature = "type_name", since = "1.38.0")]
+pub fn type_name<T: ?Sized>() -> &'static str {
+    #[cfg(bootstrap)]
+    unsafe {
+        intrinsics::type_name::<T>()
+    }
+    #[cfg(not(bootstrap))]
+    intrinsics::type_name::<T>()
+}
diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index 144543be7c4..6ecc0487fae 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array.rs
@@ -81,487 +81,296 @@ impl From<Infallible> for TryFromSliceError {
     }
 }
 
-#[cfg(bootstrap)]
-macro_rules! __impl_slice_eq1 {
-    ($Lhs: ty, $Rhs: ty) => {
-        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
-    };
-    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
-            #[inline]
-            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
-            #[inline]
-            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, const N: usize> AsRef<[T]> for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    #[inline]
+    fn as_ref(&self) -> &[T] {
+        &self[..]
     }
 }
 
-#[cfg(bootstrap)]
-macro_rules! __impl_slice_eq2 {
-    ($Lhs: ty, $Rhs: ty) => {
-        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
-    };
-    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
-        __impl_slice_eq1!($Lhs, $Rhs, $Bound);
-
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
-            #[inline]
-            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
-            #[inline]
-            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, const N: usize> AsMut<[T]> for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    #[inline]
+    fn as_mut(&mut self) -> &mut [T] {
+        &mut self[..]
     }
 }
 
-// macro for implementing n-element array functions and operations
-#[cfg(bootstrap)]
-macro_rules! array_impls {
-    ($($N:expr)+) => {
-        $(
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<T> AsRef<[T]> for [T; $N] {
-                #[inline]
-                fn as_ref(&self) -> &[T] {
-                    &self[..]
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<T> AsMut<[T]> for [T; $N] {
-                #[inline]
-                fn as_mut(&mut self) -> &mut [T] {
-                    &mut self[..]
-                }
-            }
-
-            #[stable(feature = "array_borrow", since = "1.4.0")]
-            impl<T> Borrow<[T]> for [T; $N] {
-                fn borrow(&self) -> &[T] {
-                    self
-                }
-            }
-
-            #[stable(feature = "array_borrow", since = "1.4.0")]
-            impl<T> BorrowMut<[T]> for [T; $N] {
-                fn borrow_mut(&mut self) -> &mut [T] {
-                    self
-                }
-            }
-
-            #[stable(feature = "try_from", since = "1.34.0")]
-            impl<T> TryFrom<&[T]> for [T; $N] where T: Copy {
-                type Error = TryFromSliceError;
-
-                fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> {
-                    <&Self>::try_from(slice).map(|r| *r)
-                }
-            }
-
-            #[stable(feature = "try_from", since = "1.34.0")]
-            impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
-                type Error = TryFromSliceError;
-
-                fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> {
-                    if slice.len() == $N {
-                        let ptr = slice.as_ptr() as *const [T; $N];
-                        unsafe { Ok(&*ptr) }
-                    } else {
-                        Err(TryFromSliceError(()))
-                    }
-                }
-            }
-
-            #[stable(feature = "try_from", since = "1.34.0")]
-            impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
-                type Error = TryFromSliceError;
-
-                fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> {
-                    if slice.len() == $N {
-                        let ptr = slice.as_mut_ptr() as *mut [T; $N];
-                        unsafe { Ok(&mut *ptr) }
-                    } else {
-                        Err(TryFromSliceError(()))
-                    }
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<T: Hash> Hash for [T; $N] {
-                fn hash<H: hash::Hasher>(&self, state: &mut H) {
-                    Hash::hash(&self[..], state)
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    fmt::Debug::fmt(&&self[..], f)
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<'a, T> IntoIterator for &'a [T; $N] {
-                type Item = &'a T;
-                type IntoIter = Iter<'a, T>;
-
-                fn into_iter(self) -> Iter<'a, T> {
-                    self.iter()
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<'a, T> IntoIterator for &'a mut [T; $N] {
-                type Item = &'a mut T;
-                type IntoIter = IterMut<'a, T>;
-
-                fn into_iter(self) -> IterMut<'a, T> {
-                    self.iter_mut()
-                }
-            }
-
-            // NOTE: some less important impls are omitted to reduce code bloat
-            __impl_slice_eq1! { [A; $N], [B; $N] }
-            __impl_slice_eq2! { [A; $N], [B] }
-            __impl_slice_eq2! { [A; $N], &'b [B] }
-            __impl_slice_eq2! { [A; $N], &'b mut [B] }
-            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
-            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<T:Eq> Eq for [T; $N] { }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<T:PartialOrd> PartialOrd for [T; $N] {
-                #[inline]
-                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
-                    PartialOrd::partial_cmp(&&self[..], &&other[..])
-                }
-                #[inline]
-                fn lt(&self, other: &[T; $N]) -> bool {
-                    PartialOrd::lt(&&self[..], &&other[..])
-                }
-                #[inline]
-                fn le(&self, other: &[T; $N]) -> bool {
-                    PartialOrd::le(&&self[..], &&other[..])
-                }
-                #[inline]
-                fn ge(&self, other: &[T; $N]) -> bool {
-                    PartialOrd::ge(&&self[..], &&other[..])
-                }
-                #[inline]
-                fn gt(&self, other: &[T; $N]) -> bool {
-                    PartialOrd::gt(&&self[..], &&other[..])
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<T:Ord> Ord for [T; $N] {
-                #[inline]
-                fn cmp(&self, other: &[T; $N]) -> Ordering {
-                    Ord::cmp(&&self[..], &&other[..])
-                }
-            }
-        )+
+#[stable(feature = "array_borrow", since = "1.4.0")]
+impl<T, const N: usize> Borrow<[T]> for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    fn borrow(&self) -> &[T] {
+        self
     }
 }
 
-#[cfg(not(bootstrap))]
-mod impls_using_const_generics {
-    use super::*;
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T, const N: usize> AsRef<[T]> for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn as_ref(&self) -> &[T] {
-            &self[..]
-        }
+#[stable(feature = "array_borrow", since = "1.4.0")]
+impl<T, const N: usize> BorrowMut<[T]> for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    fn borrow_mut(&mut self) -> &mut [T] {
+        self
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T, const N: usize> AsMut<[T]> for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn as_mut(&mut self) -> &mut [T] {
-            &mut self[..]
-        }
+#[stable(feature = "try_from", since = "1.34.0")]
+impl<T, const N: usize> TryFrom<&[T]> for [T; N]
+where
+    T: Copy,
+    [T; N]: LengthAtMost32,
+{
+    type Error = TryFromSliceError;
+
+    fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
+        <&Self>::try_from(slice).map(|r| *r)
     }
+}
 
-    #[stable(feature = "array_borrow", since = "1.4.0")]
-    impl<T, const N: usize> Borrow<[T]> for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        fn borrow(&self) -> &[T] {
-            self
+#[stable(feature = "try_from", since = "1.34.0")]
+impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    type Error = TryFromSliceError;
+
+    fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
+        if slice.len() == N {
+            let ptr = slice.as_ptr() as *const [T; N];
+            unsafe { Ok(&*ptr) }
+        } else {
+            Err(TryFromSliceError(()))
         }
     }
+}
 
-    #[stable(feature = "array_borrow", since = "1.4.0")]
-    impl<T, const N: usize> BorrowMut<[T]> for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        fn borrow_mut(&mut self) -> &mut [T] {
-            self
+#[stable(feature = "try_from", since = "1.34.0")]
+impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    type Error = TryFromSliceError;
+
+    fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
+        if slice.len() == N {
+            let ptr = slice.as_mut_ptr() as *mut [T; N];
+            unsafe { Ok(&mut *ptr) }
+        } else {
+            Err(TryFromSliceError(()))
         }
     }
+}
 
-    #[stable(feature = "try_from", since = "1.34.0")]
-    impl<T, const N: usize> TryFrom<&[T]> for [T; N]
-    where
-        T: Copy,
-        [T; N]: LengthAtMost32,
-    {
-        type Error = TryFromSliceError;
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Hash, const N: usize> Hash for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    fn hash<H: hash::Hasher>(&self, state: &mut H) {
+        Hash::hash(&self[..], state)
+    }
+}
 
-        fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
-            <&Self>::try_from(slice).map(|r| *r)
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&&self[..], f)
     }
+}
 
-    #[stable(feature = "try_from", since = "1.34.0")]
-    impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        type Error = TryFromSliceError;
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, const N: usize> IntoIterator for &'a [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    type Item = &'a T;
+    type IntoIter = Iter<'a, T>;
 
-        fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
-            if slice.len() == N {
-                let ptr = slice.as_ptr() as *const [T; N];
-                unsafe { Ok(&*ptr) }
-            } else {
-                Err(TryFromSliceError(()))
-            }
-        }
+    fn into_iter(self) -> Iter<'a, T> {
+        self.iter()
     }
+}
 
-    #[stable(feature = "try_from", since = "1.34.0")]
-    impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        type Error = TryFromSliceError;
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    type Item = &'a mut T;
+    type IntoIter = IterMut<'a, T>;
 
-        fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
-            if slice.len() == N {
-                let ptr = slice.as_mut_ptr() as *mut [T; N];
-                unsafe { Ok(&mut *ptr) }
-            } else {
-                Err(TryFromSliceError(()))
-            }
-        }
+    fn into_iter(self) -> IterMut<'a, T> {
+        self.iter_mut()
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: Hash, const N: usize> Hash for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        fn hash<H: hash::Hasher>(&self, state: &mut H) {
-            Hash::hash(&self[..], state)
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, A, B, const N: usize> PartialEq<[B; N]> for [A; N]
+where
+    A: PartialEq<B>,
+    [A; N]: LengthAtMost32,
+    [B; N]: LengthAtMost32,
+{
+    #[inline]
+    fn eq(&self, other: &[B; N]) -> bool {
+        self[..] == other[..]
     }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            fmt::Debug::fmt(&&self[..], f)
-        }
+    #[inline]
+    fn ne(&self, other: &[B; N]) -> bool {
+        self[..] != other[..]
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, T, const N: usize> IntoIterator for &'a [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        type Item = &'a T;
-        type IntoIter = Iter<'a, T>;
-
-        fn into_iter(self) -> Iter<'a, T> {
-            self.iter()
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, A, B, const N: usize> PartialEq<[B]> for [A; N]
+where
+    A: PartialEq<B>,
+    [A; N]: LengthAtMost32,
+{
+    #[inline]
+    fn eq(&self, other: &[B]) -> bool {
+        self[..] == other[..]
     }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        type Item = &'a mut T;
-        type IntoIter = IterMut<'a, T>;
-
-        fn into_iter(self) -> IterMut<'a, T> {
-            self.iter_mut()
-        }
+    #[inline]
+    fn ne(&self, other: &[B]) -> bool {
+        self[..] != other[..]
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, 'b, A, B, const N: usize> PartialEq<[B; N]> for [A; N]
-    where
-        A: PartialEq<B>,
-        [A; N]: LengthAtMost32,
-        [B; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn eq(&self, other: &[B; N]) -> bool {
-            self[..] == other[..]
-        }
-        #[inline]
-        fn ne(&self, other: &[B; N]) -> bool {
-            self[..] != other[..]
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for [B]
+where
+    B: PartialEq<A>,
+    [A; N]: LengthAtMost32,
+{
+    #[inline]
+    fn eq(&self, other: &[A; N]) -> bool {
+        self[..] == other[..]
     }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, 'b, A, B, const N: usize> PartialEq<[B]> for [A; N]
-    where
-        A: PartialEq<B>,
-        [A; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn eq(&self, other: &[B]) -> bool {
-            self[..] == other[..]
-        }
-        #[inline]
-        fn ne(&self, other: &[B]) -> bool {
-            self[..] != other[..]
-        }
+    #[inline]
+    fn ne(&self, other: &[A; N]) -> bool {
+        self[..] != other[..]
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for [B]
-    where
-        B: PartialEq<A>,
-        [A; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn eq(&self, other: &[A; N]) -> bool {
-            self[..] == other[..]
-        }
-        #[inline]
-        fn ne(&self, other: &[A; N]) -> bool {
-            self[..] != other[..]
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N]
+where
+    A: PartialEq<B>,
+    [A; N]: LengthAtMost32,
+{
+    #[inline]
+    fn eq(&self, other: &&'b [B]) -> bool {
+        self[..] == other[..]
     }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, 'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N]
-    where
-        A: PartialEq<B>,
-        [A; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn eq(&self, other: &&'b [B]) -> bool {
-            self[..] == other[..]
-        }
-        #[inline]
-        fn ne(&self, other: &&'b [B]) -> bool {
-            self[..] != other[..]
-        }
+    #[inline]
+    fn ne(&self, other: &&'b [B]) -> bool {
+        self[..] != other[..]
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B]
-    where
-        B: PartialEq<A>,
-        [A; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn eq(&self, other: &[A; N]) -> bool {
-            self[..] == other[..]
-        }
-        #[inline]
-        fn ne(&self, other: &[A; N]) -> bool {
-            self[..] != other[..]
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B]
+where
+    B: PartialEq<A>,
+    [A; N]: LengthAtMost32,
+{
+    #[inline]
+    fn eq(&self, other: &[A; N]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &[A; N]) -> bool {
+        self[..] != other[..]
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, 'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N]
-    where
-        A: PartialEq<B>,
-        [A; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn eq(&self, other: &&'b mut [B]) -> bool {
-            self[..] == other[..]
-        }
-        #[inline]
-        fn ne(&self, other: &&'b mut [B]) -> bool {
-            self[..] != other[..]
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N]
+where
+    A: PartialEq<B>,
+    [A; N]: LengthAtMost32,
+{
+    #[inline]
+    fn eq(&self, other: &&'b mut [B]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &&'b mut [B]) -> bool {
+        self[..] != other[..]
     }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B]
-    where
-        B: PartialEq<A>,
-        [A; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn eq(&self, other: &[A; N]) -> bool {
-            self[..] == other[..]
-        }
-        #[inline]
-        fn ne(&self, other: &[A; N]) -> bool {
-            self[..] != other[..]
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B]
+where
+    B: PartialEq<A>,
+    [A; N]: LengthAtMost32,
+{
+    #[inline]
+    fn eq(&self, other: &[A; N]) -> bool {
+        self[..] == other[..]
+    }
+    #[inline]
+    fn ne(&self, other: &[A; N]) -> bool {
+        self[..] != other[..]
     }
+}
 
-    // NOTE: some less important impls are omitted to reduce code bloat
-    // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
-    // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
+// NOTE: some less important impls are omitted to reduce code bloat
+// __impl_slice_eq2! { [A; $N], &'b [B; $N] }
+// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: Eq, const N: usize> Eq for [T; N] where [T; N]: LengthAtMost32 {}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Eq, const N: usize> Eq for [T; N] where [T; N]: LengthAtMost32 {}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: PartialOrd, const N: usize> PartialOrd for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
-            PartialOrd::partial_cmp(&&self[..], &&other[..])
-        }
-        #[inline]
-        fn lt(&self, other: &[T; N]) -> bool {
-            PartialOrd::lt(&&self[..], &&other[..])
-        }
-        #[inline]
-        fn le(&self, other: &[T; N]) -> bool {
-            PartialOrd::le(&&self[..], &&other[..])
-        }
-        #[inline]
-        fn ge(&self, other: &[T; N]) -> bool {
-            PartialOrd::ge(&&self[..], &&other[..])
-        }
-        #[inline]
-        fn gt(&self, other: &[T; N]) -> bool {
-            PartialOrd::gt(&&self[..], &&other[..])
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: PartialOrd, const N: usize> PartialOrd for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    #[inline]
+    fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&&self[..], &&other[..])
+    }
+    #[inline]
+    fn lt(&self, other: &[T; N]) -> bool {
+        PartialOrd::lt(&&self[..], &&other[..])
+    }
+    #[inline]
+    fn le(&self, other: &[T; N]) -> bool {
+        PartialOrd::le(&&self[..], &&other[..])
     }
+    #[inline]
+    fn ge(&self, other: &[T; N]) -> bool {
+        PartialOrd::ge(&&self[..], &&other[..])
+    }
+    #[inline]
+    fn gt(&self, other: &[T; N]) -> bool {
+        PartialOrd::gt(&&self[..], &&other[..])
+    }
+}
 
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: Ord, const N: usize> Ord for [T; N]
-    where
-        [T; N]: LengthAtMost32,
-    {
-        #[inline]
-        fn cmp(&self, other: &[T; N]) -> Ordering {
-            Ord::cmp(&&self[..], &&other[..])
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Ord, const N: usize> Ord for [T; N]
+where
+    [T; N]: LengthAtMost32,
+{
+    #[inline]
+    fn cmp(&self, other: &[T; N]) -> Ordering {
+        Ord::cmp(&&self[..], &&other[..])
     }
 }
 
@@ -571,10 +380,8 @@ mod impls_using_const_generics {
 )]
 #[unstable(feature = "const_generic_impls_guard", issue = "0",
     reason = "will never be stable, just a temporary step until const generics are stable")]
-#[cfg(not(bootstrap))]
 pub trait LengthAtMost32 {}
 
-#[cfg(not(bootstrap))]
 macro_rules! array_impls {
     ($($N:literal)+) => {
         $(
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index 99f88591eea..aa834db2b9b 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -547,10 +547,10 @@ impl char {
         }
     }
 
-    /// Returns `true` if this `char` satisfies the 'XID_Start' Unicode property, and false
+    /// Returns `true` if this `char` satisfies the `XID_Start` Unicode property, and false
     /// otherwise.
     ///
-    /// 'XID_Start' is a Unicode Derived Property specified in
+    /// `XID_Start` is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to `ID_Start` but modified for closure under `NFKx`.
     #[cfg_attr(bootstrap,
@@ -563,12 +563,12 @@ impl char {
         derived_property::XID_Start(self)
     }
 
-    /// Returns `true` if this `char` satisfies the 'XID_Continue' Unicode property, and false
+    /// Returns `true` if this `char` satisfies the `XID_Continue` Unicode property, and false
     /// otherwise.
     ///
-    /// 'XID_Continue' is a Unicode Derived Property specified in
+    /// `XID_Continue` is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
-    /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
+    /// mostly similar to `ID_Continue` but modified for closure under NFKx.
     #[cfg_attr(bootstrap,
                unstable(feature = "rustc_private",
                         reason = "mainly needed for compiler internals",
@@ -666,7 +666,7 @@ impl char {
     /// Returns `true` if this `char` is alphanumeric.
     ///
     /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories
-    /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
+    /// `Nd`, `Nl`, `No` and the Derived Core Property `Alphabetic`.
     ///
     /// # Examples
     ///
@@ -720,7 +720,7 @@ impl char {
     /// Returns `true` if this `char` is numeric.
     ///
     /// 'Numeric'-ness is defined in terms of the Unicode General Categories
-    /// 'Nd', 'Nl', 'No'.
+    /// `Nd`, `Nl`, `No`.
     ///
     /// # Examples
     ///
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 2b3bad8894e..2bb941b490e 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -74,7 +74,7 @@
 #![feature(concat_idents)]
 #![feature(const_fn)]
 #![feature(const_fn_union)]
-#![cfg_attr(not(bootstrap), feature(const_generics))]
+#![feature(const_generics)]
 #![feature(custom_inner_attributes)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 296bb43f9fa..17781798946 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -1281,6 +1281,13 @@ mod builtin {
     #[rustc_macro_transparency = "semitransparent"]
     pub macro test_case($item:item) { /* compiler built-in */ }
 
+    /// Attribute macro applied to a static to register it as a global allocator.
+    #[stable(feature = "global_allocator", since = "1.28.0")]
+    #[allow_internal_unstable(rustc_attrs)]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro global_allocator($item:item) { /* compiler built-in */ }
+
     /// Derive macro generating an impl of the trait `Clone`.
     #[rustc_builtin_macro]
     #[rustc_macro_transparency = "semitransparent"]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 72552c5a0b0..67e30e7ffcb 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -717,13 +717,12 @@ returning `None` if `rhs == 0` or the division results in overflow.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!((", stringify!($SelfT),
 "::min_value() + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));
 assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None);
 assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -774,14 +773,13 @@ if `rhs == 0` or the division results in overflow.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 use std::", stringify!($SelfT), ";
 
 assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
 assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
 assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1210,11 +1208,10 @@ This function will panic if `rhs` is 0.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
 assert_eq!((-128i8).wrapping_div_euclid(-1), -128);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1269,11 +1266,10 @@ This function will panic if `rhs` is 0.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
 assert_eq!((-128i8).wrapping_rem_euclid(-1), 0);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1566,7 +1562,6 @@ This function will panic if `rhs` is 0.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 use std::", stringify!($SelfT), ";
 
 assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
@@ -1574,7 +1569,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi
 "::MIN, true));
 ```"),
             #[inline]
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
@@ -1636,13 +1631,12 @@ This function will panic if `rhs` is 0.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 use std::", stringify!($SelfT), ";
 
 assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1873,7 +1867,6 @@ This function will panic if `rhs` is 0.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 let a: ", stringify!($SelfT), " = 7; // or any other integer type
 let b = 4;
 
@@ -1882,7 +1875,7 @@ assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1
 assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2
 assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -1913,7 +1906,6 @@ This function will panic if `rhs` is 0.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 let a: ", stringify!($SelfT), " = 7; // or any other integer type
 let b = 4;
 
@@ -1922,7 +1914,7 @@ assert_eq!((-a).rem_euclid(b), 1);
 assert_eq!(a.rem_euclid(-b), 3);
 assert_eq!((-a).rem_euclid(-b), 1);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -2753,11 +2745,10 @@ if `rhs == 0`.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));
 assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -2805,11 +2796,10 @@ if `rhs == 0`.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
 assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -3127,10 +3117,9 @@ is exactly equal to `self.wrapping_div(rhs)`.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -3179,10 +3168,9 @@ is exactly equal to `self.wrapping_rem(rhs)`.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -3448,11 +3436,10 @@ This function will panic if `rhs` is 0.
 Basic usage
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
 ```"),
             #[inline]
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
@@ -3508,11 +3495,10 @@ This function will panic if `rhs` is 0.
 Basic usage
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
 ```"),
             #[inline]
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
@@ -3696,10 +3682,9 @@ is exactly equal to `self / rhs`.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
@@ -3722,10 +3707,9 @@ is exactly equal to `self % rhs`.
 Basic usage:
 
 ```
-#![feature(euclidean_division)]
 assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type
 ```"),
-            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[stable(feature = "euclidean_division", since = "1.38.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs
index c69f5fd9896..b9552eaa1a0 100644
--- a/src/libcore/ops/function.rs
+++ b/src/libcore/ops/function.rs
@@ -137,6 +137,10 @@ pub trait Fn<Args> : FnMut<Args> {
 #[rustc_paren_sugar]
 #[rustc_on_unimplemented(
     on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"),
+    on(
+        all(Args="(char,)", _Self="std::string::String"),
+        note="borrowing the `{Self}` might fix the problem"
+    ),
     message="expected a `{FnMut}<{Args}>` closure, found `{Self}`",
     label="expected an `FnMut<{Args}>` closure, found `{Self}`",
 )]
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index cbb6423d710..505f8b0a261 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -5,7 +5,6 @@
 #![feature(core_private_diy_float)]
 #![feature(debug_map_key_value)]
 #![feature(dec2flt)]
-#![feature(euclidean_division)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
 #![feature(flt2dec)]
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index c7d4fa3aec6..79f60778d3c 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -104,7 +104,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 bb2e3b4ec19..00000000000
--- 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/middle/dead.rs b/src/librustc/middle/dead.rs
index 4c27318c3e1..88de77829a6 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -320,11 +320,6 @@ fn has_allow_dead_code_or_lang_attr(
         return true;
     }
 
-    // Don't lint about global allocators
-    if attr::contains_name(attrs, sym::global_allocator) {
-        return true;
-    }
-
     let def_id = tcx.hir().local_def_id(id);
     let cg_attrs = tcx.codegen_fn_attrs(def_id);
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index c88ca132184..61dac678912 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/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 55e622e46b9..2ffcd0fd4d9 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -34,7 +34,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
     {
         debug!(
             "normalize::<{}>(value={:?}, param_env={:?})",
-            unsafe { ::std::intrinsics::type_name::<T>() },
+            ::std::any::type_name::<T>(),
             value,
             self.param_env,
         );
diff --git a/src/librustc/traits/query/normalize_erasing_regions.rs b/src/librustc/traits/query/normalize_erasing_regions.rs
index 3218ff062ce..d09288461d4 100644
--- a/src/librustc/traits/query/normalize_erasing_regions.rs
+++ b/src/librustc/traits/query/normalize_erasing_regions.rs
@@ -22,7 +22,7 @@ impl<'tcx> TyCtxt<'tcx> {
     {
         debug!(
             "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
-            unsafe { ::std::intrinsics::type_name::<T>() },
+            ::std::any::type_name::<T>(),
             value,
             param_env,
         );
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index b921272856e..1cc083ea93c 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -69,7 +69,7 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M {
         if !tcx.sess.verbose() {
             format!("processing `{}`", tcx.def_path_str(def_id)).into()
         } else {
-            let name = unsafe { ::std::intrinsics::type_name::<M>() };
+            let name = ::std::any::type_name::<M>();
             format!("processing {:?} with query `{}`", def_id, name).into()
         }
     }
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index e788628bc58..f4b99ca3688 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -54,7 +54,7 @@ use rustc_target::spec::PanicStrategy;
 use std::borrow::Cow;
 use std::ops::Deref;
 use std::sync::Arc;
-use std::intrinsics::type_name;
+use std::any::type_name;
 use syntax_pos::{Span, DUMMY_SP};
 use syntax_pos::symbol::InternedString;
 use syntax::attr;
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 211a28fe931..45bc89f5a84 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -1060,7 +1060,7 @@ where
     Q::Value: Encodable,
 {
     let desc = &format!("encode_query_results for {}",
-        unsafe { ::std::intrinsics::type_name::<Q>() });
+        ::std::any::type_name::<Q>());
 
     time_ext(tcx.sess.time_extended(), Some(tcx.sess), desc, || {
         let map = Q::query_cache(tcx).borrow();
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 0c9e31e1ff2..ce9f67db592 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -782,9 +782,9 @@ macro_rules! define_queries_inner {
                         #[cfg(not(debug_assertions))]
                         cache_hits: 0,
                         key_size: mem::size_of::<Q::Key>(),
-                        key_type: unsafe { type_name::<Q::Key>() },
+                        key_type: type_name::<Q::Key>(),
                         value_size: mem::size_of::<Q::Value>(),
-                        value_type: unsafe { type_name::<Q::Value>() },
+                        value_type: type_name::<Q::Value>(),
                         entry_count: map.results.len(),
                     }
                 }
diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml
deleted file mode 100644
index a964f323c9e..00000000000
--- 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_allocator/expand.rs b/src/librustc_allocator/expand.rs
deleted file mode 100644
index af63fffc0f9..00000000000
--- a/src/librustc_allocator/expand.rs
+++ /dev/null
@@ -1,298 +0,0 @@
-use log::debug;
-use rustc::middle::allocator::AllocatorKind;
-use smallvec::{smallvec, SmallVec};
-use syntax::{
-    ast::{
-        self, Arg, Attribute, Crate, Expr, FnHeader, Generics, Ident, Item, ItemKind,
-        Mac, Mod, Mutability, Ty, TyKind, Unsafety, VisibilityKind,
-    },
-    attr,
-    source_map::{
-        respan, ExpnInfo, ExpnKind,
-    },
-    ext::{
-        base::{ExtCtxt, MacroKind, Resolver},
-        build::AstBuilder,
-        expand::ExpansionConfig,
-        hygiene::ExpnId,
-    },
-    mut_visit::{self, MutVisitor},
-    parse::ParseSess,
-    ptr::P,
-    symbol::{kw, sym}
-};
-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,
-) {
-    ExpandAllocatorDirectives {
-        handler,
-        sess,
-        resolver,
-        found: false,
-        crate_name: Some(crate_name),
-        in_submod: -1, // -1 to account for the "root" module
-    }.visit_crate(krate);
-}
-
-struct ExpandAllocatorDirectives<'a> {
-    found: bool,
-    handler: &'a rustc_errors::Handler,
-    sess: &'a ParseSess,
-    resolver: &'a mut dyn Resolver,
-    crate_name: Option<String>,
-
-    // For now, we disallow `global_allocator` in submodules because hygiene is hard. Keep track of
-    // whether we are in a submodule or not. If `in_submod > 0` we are in a submodule.
-    in_submod: isize,
-}
-
-impl MutVisitor for ExpandAllocatorDirectives<'_> {
-    fn flat_map_item(&mut self, item: P<Item>) -> SmallVec<[P<Item>; 1]> {
-        debug!("in submodule {}", self.in_submod);
-
-        if !attr::contains_name(&item.attrs, sym::global_allocator) {
-            return mut_visit::noop_flat_map_item(item, self);
-        }
-
-        match item.node {
-            ItemKind::Static(..) => {}
-            _ => {
-                self.handler
-                    .span_err(item.span, "allocators must be statics");
-                return smallvec![item];
-            }
-        }
-
-        if self.in_submod > 0 {
-            self.handler
-                .span_err(item.span, "`global_allocator` cannot be used in submodules");
-            return smallvec![item];
-        }
-
-        if self.found {
-            self.handler
-                .span_err(item.span, "cannot define more than one `#[global_allocator]`");
-            return smallvec![item];
-        }
-        self.found = true;
-
-        // Create a new expansion for the generated allocator code.
-        let span = item.span.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
-            ExpnKind::Macro(MacroKind::Attr, sym::global_allocator), item.span, self.sess.edition,
-            [sym::rustc_attrs][..].into(),
-        ));
-
-        // Create an expansion config
-        let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap());
-
-        // Generate a bunch of new items using the AllocFnFactory
-        let mut f = AllocFnFactory {
-            span,
-            kind: AllocatorKind::Global,
-            global: item.ident,
-            core: Ident::with_empty_ctxt(sym::core),
-            cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
-        };
-
-        // We will generate a new submodule. To `use` the static from that module, we need to get
-        // the `super::...` path.
-        let super_path = f.cx.path(f.span, vec![Ident::with_empty_ctxt(kw::Super), f.global]);
-
-        // Generate the items in the submodule
-        let mut items = vec![
-            // import `core` to use allocators
-            f.cx.item_extern_crate(f.span, f.core),
-            // `use` the `global_allocator` in `super`
-            f.cx.item_use_simple(
-                f.span,
-                respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
-                super_path,
-            ),
-        ];
-
-        // Add the allocator methods to the submodule
-        items.extend(
-            ALLOCATOR_METHODS
-                .iter()
-                .map(|method| f.allocator_fn(method)),
-        );
-
-        // Generate the submodule itself
-        let name = f.kind.fn_name("allocator_abi");
-        let allocator_abi = Ident::from_str(&name).gensym();
-        let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items);
-        let module = f.cx.monotonic_expander().flat_map_item(module).pop().unwrap();
-
-        // Return the item and new submodule
-        smallvec![item, module]
-    }
-
-    // If we enter a submodule, take note.
-    fn visit_mod(&mut self, m: &mut Mod) {
-        debug!("enter submodule");
-        self.in_submod += 1;
-        mut_visit::noop_visit_mod(m, self);
-        self.in_submod -= 1;
-        debug!("exit submodule");
-    }
-
-    // `visit_mac` is disabled by default. Enable it here.
-    fn visit_mac(&mut self, mac: &mut Mac) {
-        mut_visit::noop_visit_mac(mac, self)
-    }
-}
-
-struct AllocFnFactory<'a> {
-    span: Span,
-    kind: AllocatorKind,
-    global: Ident,
-    core: Ident,
-    cx: ExtCtxt<'a>,
-}
-
-impl AllocFnFactory<'_> {
-    fn allocator_fn(&self, method: &AllocatorMethod) -> P<Item> {
-        let mut abi_args = Vec::new();
-        let mut i = 0;
-        let ref mut mk = || {
-            let name = Ident::from_str(&format!("arg{}", i));
-            i += 1;
-            name
-        };
-        let args = method
-            .inputs
-            .iter()
-            .map(|ty| self.arg_ty(ty, &mut abi_args, mk))
-            .collect();
-        let result = self.call_allocator(method.name, args);
-        let (output_ty, output_expr) = self.ret_ty(&method.output, result);
-        let kind = ItemKind::Fn(
-            self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
-            FnHeader {
-                unsafety: Unsafety::Unsafe,
-                ..FnHeader::default()
-            },
-            Generics::default(),
-            self.cx.block_expr(output_expr),
-        );
-        self.cx.item(
-            self.span,
-            Ident::from_str(&self.kind.fn_name(method.name)),
-            self.attrs(),
-            kind,
-        )
-    }
-
-    fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
-        let method = self.cx.path(
-            self.span,
-            vec![
-                self.core,
-                Ident::from_str("alloc"),
-                Ident::from_str("GlobalAlloc"),
-                Ident::from_str(method),
-            ],
-        );
-        let method = self.cx.expr_path(method);
-        let allocator = self.cx.path_ident(self.span, self.global);
-        let allocator = self.cx.expr_path(allocator);
-        let allocator = self.cx.expr_addr_of(self.span, allocator);
-        args.insert(0, allocator);
-
-        self.cx.expr_call(self.span, method, args)
-    }
-
-    fn attrs(&self) -> Vec<Attribute> {
-        let special = sym::rustc_std_internal_symbol;
-        let special = self.cx.meta_word(self.span, special);
-        vec![self.cx.attribute(self.span, special)]
-    }
-
-    fn arg_ty(
-        &self,
-        ty: &AllocatorTy,
-        args: &mut Vec<Arg>,
-        ident: &mut dyn FnMut() -> Ident,
-    ) -> P<Expr> {
-        match *ty {
-            AllocatorTy::Layout => {
-                let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize));
-                let ty_usize = self.cx.ty_path(usize);
-                let size = ident();
-                let align = ident();
-                args.push(self.cx.arg(self.span, size, ty_usize.clone()));
-                args.push(self.cx.arg(self.span, align, ty_usize));
-
-                let layout_new = self.cx.path(
-                    self.span,
-                    vec![
-                        self.core,
-                        Ident::from_str("alloc"),
-                        Ident::from_str("Layout"),
-                        Ident::from_str("from_size_align_unchecked"),
-                    ],
-                );
-                let layout_new = self.cx.expr_path(layout_new);
-                let size = self.cx.expr_ident(self.span, size);
-                let align = self.cx.expr_ident(self.span, align);
-                let layout = self.cx.expr_call(self.span, layout_new, vec![size, align]);
-                layout
-            }
-
-            AllocatorTy::Ptr => {
-                let ident = ident();
-                args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
-                let arg = self.cx.expr_ident(self.span, ident);
-                self.cx.expr_cast(self.span, arg, self.ptr_u8())
-            }
-
-            AllocatorTy::Usize => {
-                let ident = ident();
-                args.push(self.cx.arg(self.span, ident, self.usize()));
-                self.cx.expr_ident(self.span, ident)
-            }
-
-            AllocatorTy::ResultPtr | AllocatorTy::Unit => {
-                panic!("can't convert AllocatorTy to an argument")
-            }
-        }
-    }
-
-    fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
-        match *ty {
-            AllocatorTy::ResultPtr => {
-                // We're creating:
-                //
-                //      #expr as *mut u8
-
-                let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
-                (self.ptr_u8(), expr)
-            }
-
-            AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),
-
-            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
-                panic!("can't convert `AllocatorTy` to an output")
-            }
-        }
-    }
-
-    fn usize(&self) -> P<Ty> {
-        let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize));
-        self.cx.ty_path(usize)
-    }
-
-    fn ptr_u8(&self) -> P<Ty> {
-        let u8 = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::u8));
-        let ty_u8 = self.cx.ty_path(u8);
-        self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
-    }
-}
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
deleted file mode 100644
index 8d380c47bc4..00000000000
--- a/src/librustc_allocator/lib.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-#![feature(nll)]
-#![feature(rustc_private)]
-
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
-pub mod expand;
-
-pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
-    AllocatorMethod {
-        name: "alloc",
-        inputs: &[AllocatorTy::Layout],
-        output: AllocatorTy::ResultPtr,
-    },
-    AllocatorMethod {
-        name: "dealloc",
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
-        output: AllocatorTy::Unit,
-    },
-    AllocatorMethod {
-        name: "realloc",
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
-        output: AllocatorTy::ResultPtr,
-    },
-    AllocatorMethod {
-        name: "alloc_zeroed",
-        inputs: &[AllocatorTy::Layout],
-        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/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs
index 02a05fd1102..5d43bf6ae28 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 0f0b9f27917..8dd241bd81a 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 90d7320987c..89a6ec27fe5 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -24,7 +24,6 @@ rustc_serialize = { path = "../libserialize", package = "serialize" }
 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 c5553fa93cf..2d9220f897c 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -1,3 +1,4 @@
+use std::collections::hash_map::Entry::*;
 use std::sync::Arc;
 
 use rustc::ty::Instance;
@@ -12,9 +13,8 @@ use rustc::ty::{TyCtxt, SymbolName};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::util::nodemap::{FxHashMap, DefIdMap};
-use rustc_allocator::ALLOCATOR_METHODS;
 use rustc_data_structures::indexed_vec::IndexVec;
-use std::collections::hash_map::Entry::*;
+use syntax::ext::allocator::ALLOCATOR_METHODS;
 
 pub type ExportedSymbols = FxHashMap<
     CrateNum,
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 9d5aaa7655d..9fbb44dcc99 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -3,12 +3,12 @@ use rustc::ty::Ty;
 
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
-use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::{Session, config};
 use rustc::ty::TyCtxt;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use std::sync::Arc;
+use syntax::ext::allocator::AllocatorKind;
 use syntax_pos::symbol::InternedString;
 
 pub trait BackendTypes {
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 3162af5086d..e8c9828a202 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -16,7 +16,6 @@ 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" }
@@ -37,5 +36,4 @@ rustc_interface = { path = "../librustc_interface" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 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 a90254e7e18..4937801d311 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" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 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 b334971353c..1cc7cfda012 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -469,7 +469,7 @@ fn configure_and_expand_inner<'a>(
         util::ReplaceBodyWithLoop::new(sess).visit_crate(&mut krate);
     }
 
-    let (has_proc_macro_decls, has_global_allocator) = time(sess, "AST validation", || {
+    let has_proc_macro_decls = time(sess, "AST validation", || {
         ast_validation::check_crate(sess, &krate)
     });
 
@@ -495,19 +495,6 @@ 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(
-                &sess.parse_sess,
-                &mut resolver,
-                &mut krate,
-                crate_name.to_string(),
-                sess.diagnostic(),
-            )
-        });
-    }
-
     // Done with macro expansion!
 
     if sess.opts.debugging_opts.input_stats {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 4105e030477..b63d14ca949 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -36,10 +36,10 @@ use syntax::tokenstream::{TokenTree, TokenStream};
 use syntax::ast;
 use syntax::ptr::P;
 use syntax::ast::Expr;
-use syntax::attr::{self, HasAttrs};
+use syntax::attr::{self, HasAttrs, AttributeTemplate};
 use syntax::source_map::Spanned;
 use syntax::edition::Edition;
-use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType};
+use syntax::feature_gate::{AttributeGate, AttributeType};
 use syntax::feature_gate::{Stability, deprecated_attributes};
 use syntax_pos::{BytePos, Span, SyntaxContext};
 use syntax::symbol::{Symbol, kw, sym};
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 126cfec157f..3404ec5e173 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,9 +25,9 @@ use std::{cmp, fs};
 
 use syntax::ast;
 use syntax::attr;
+use syntax::ext::allocator::{global_allocator_spans, AllocatorKind};
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
 use syntax::symbol::{Symbol, sym};
-use syntax::visit;
 use syntax::{span_err, span_fatal};
 use syntax_pos::{Span, DUMMY_SP};
 use log::{debug, info, log_enabled};
@@ -888,7 +887,14 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
-        let has_global_allocator = has_global_allocator(krate);
+        let has_global_allocator = match &*global_allocator_spans(krate) {
+            [span1, span2, ..] => {
+                self.sess.struct_span_err(*span2, "cannot define multiple global allocators")
+                         .span_note(*span1, "the previous global allocator is defined here").emit();
+                true
+            }
+            spans => !spans.is_empty()
+        };
         self.sess.has_global_allocator.set(has_global_allocator);
 
         // Check to see if we actually need an allocator. This desire comes
@@ -975,25 +981,8 @@ impl<'a> CrateLoader<'a> {
                            that implements the GlobalAlloc trait.");
         }
         self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib));
-
-        fn has_global_allocator(krate: &ast::Crate) -> bool {
-            struct Finder(bool);
-            let mut f = Finder(false);
-            visit::walk_crate(&mut f, krate);
-            return f.0;
-
-            impl<'ast> visit::Visitor<'ast> for Finder {
-                fn visit_item(&mut self, i: &'ast ast::Item) {
-                    if attr::contains_name(&i.attrs, sym::global_allocator) {
-                        self.0 = true;
-                    }
-                    visit::walk_item(self, i)
-                }
-            }
-        }
     }
 
-
     fn inject_dependency_if(&self,
                             krate: CrateNum,
                             what: &str,
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index b0fe06039f4..8db3ec491df 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -1,6 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(box_patterns)]
+#![feature(crate_visibility_modifier)]
 #![feature(drain_filter)]
 #![feature(in_band_lifetimes)]
 #![feature(libc)]
@@ -8,9 +9,9 @@
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(crate_visibility_modifier)]
-#![feature(specialization)]
 #![feature(rustc_private)]
+#![feature(slice_patterns)]
+#![feature(specialization)]
 
 #![recursion_limit="256"]
 
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 9e23d061453..195a652b0a2 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -127,7 +127,7 @@ impl<'tcx> MirSource<'tcx> {
 /// Generates a default name for the pass based on the name of the
 /// type `T`.
 pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
-    let name = unsafe { ::std::intrinsics::type_name::<T>() };
+    let name = ::std::any::type_name::<T>();
     if let Some(tail) = name.rfind(":") {
         Cow::from(&name[tail+1..])
     } else {
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 56063596299..b550029d978 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -51,7 +51,6 @@ impl OuterImplTrait {
 struct AstValidator<'a> {
     session: &'a Session,
     has_proc_macro_decls: bool,
-    has_global_allocator: bool,
 
     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
     /// Nested `impl Trait` _is_ allowed in associated type position,
@@ -539,10 +538,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             self.has_proc_macro_decls = true;
         }
 
-        if attr::contains_name(&item.attrs, sym::global_allocator) {
-            self.has_global_allocator = true;
-        }
-
         match item.node {
             ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
                 self.invalid_visibility(&item.vis, None);
@@ -848,11 +843,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 }
 
-pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {
+pub fn check_crate(session: &Session, krate: &Crate) -> bool {
     let mut validator = AstValidator {
         session,
         has_proc_macro_decls: false,
-        has_global_allocator: false,
         outer_impl_trait: None,
         is_impl_trait_banned: false,
         is_assoc_ty_bound_banned: false,
@@ -861,5 +855,5 @@ pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {
     };
     visit::walk_crate(&mut validator, krate);
 
-    (validator.has_proc_macro_decls, validator.has_global_allocator)
+    validator.has_proc_macro_decls
 }
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 531ecd11dcb..4d8f5641236 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -71,7 +71,7 @@ pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
         "saturating_add" | "saturating_sub" |
         "rotate_left" | "rotate_right" |
         "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" |
-        "minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64"
+        "minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64" | "type_name"
         => hir::Unsafety::Normal,
         _ => hir::Unsafety::Unsafe,
     }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index cb83630100a..d48ba74f9f2 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -10,7 +10,6 @@ use rustc::hir::{self, ExprKind, Node, QPath};
 use rustc::hir::def::{Res, DefKind};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::hir::map as hir_map;
-use rustc::hir::print;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Obligation;
 use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
@@ -78,6 +77,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         }
 
+        let print_disambiguation_help = |
+            err: &mut DiagnosticBuilder<'_>,
+            trait_name: String,
+        | {
+            err.help(&format!(
+                "to disambiguate the method call, write `{}::{}({}{})` instead",
+                trait_name,
+                item_name,
+                if rcvr_ty.is_region_ptr() && args.is_some() {
+                    if rcvr_ty.is_mutable_pointer() {
+                        "&mut "
+                    } else {
+                        "&"
+                    }
+                } else {
+                    ""
+                },
+                args.map(|arg| arg
+                    .iter()
+                    .map(|arg| self.tcx.sess.source_map().span_to_snippet(arg.span)
+                        .unwrap_or_else(|_| "...".to_owned()))
+                    .collect::<Vec<_>>()
+                    .join(", ")
+                ).unwrap_or_else(|| "...".to_owned())
+            ));
+        };
+
         let report_candidates = |
             span: Span,
             err: &mut DiagnosticBuilder<'_>,
@@ -139,6 +165,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         } else {
                             err.note(&note_str);
                         }
+                        if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
+                            print_disambiguation_help(err, self.tcx.def_path_str(trait_ref.def_id));
+                        }
                     }
                     CandidateSource::TraitSource(trait_did) => {
                         let item = match self.associated_item(
@@ -163,24 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                        "the candidate is defined in the trait `{}`",
                                        self.tcx.def_path_str(trait_did));
                         }
-                        err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
-                                          instead",
-                                          self.tcx.def_path_str(trait_did),
-                                          item_name,
-                                          if rcvr_ty.is_region_ptr() && args.is_some() {
-                                              if rcvr_ty.is_mutable_pointer() {
-                                                  "&mut "
-                                              } else {
-                                                  "&"
-                                              }
-                                          } else {
-                                              ""
-                                          },
-                                          args.map(|arg| arg.iter()
-                                              .map(|arg| print::to_string(print::NO_ANN,
-                                                                          |s| s.print_expr(arg)))
-                                              .collect::<Vec<_>>()
-                                              .join(", ")).unwrap_or_else(|| "...".to_owned())));
+                        print_disambiguation_help(err, self.tcx.def_path_str(trait_did));
                     }
                 }
             }
diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs
index 2def2a455fb..a5f7b4898ae 100644
--- a/src/libserialize/serialize.rs
+++ b/src/libserialize/serialize.rs
@@ -4,8 +4,8 @@
 Core encoding and decoding interfaces.
 */
 
+use std::any;
 use std::borrow::Cow;
-use std::intrinsics;
 use std::marker::PhantomData;
 use std::path;
 use std::rc::Rc;
@@ -849,9 +849,9 @@ pub trait SpecializationError {
 impl<E> SpecializationError for E {
     default fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> E {
         panic!("missing specialization: `<{} as {}<{}>>::{}` not overridden",
-               unsafe { intrinsics::type_name::<S>() },
+               any::type_name::<S>(),
                trait_name,
-               unsafe { intrinsics::type_name::<T>() },
+               any::type_name::<T>(),
                method_name);
     }
 }
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 7254c621611..f649170c403 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -256,7 +256,6 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f32 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
@@ -265,7 +264,7 @@ impl f32 {
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f32) -> f32 {
         let q = (self / rhs).trunc();
         if self % rhs < 0.0 {
@@ -288,7 +287,6 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f32 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.rem_euclid(b), 3.0);
@@ -299,7 +297,7 @@ impl f32 {
     /// assert!((-std::f32::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f32) -> f32 {
         let r = self % rhs;
         if r < 0.0 {
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index f8bb36ad0a8..f61630997dc 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -232,7 +232,6 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f64 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
@@ -241,7 +240,7 @@ impl f64 {
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f64) -> f64 {
         let q = (self / rhs).trunc();
         if self % rhs < 0.0 {
@@ -264,7 +263,6 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f64 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.rem_euclid(b), 3.0);
@@ -275,7 +273,7 @@ impl f64 {
     /// assert!((-std::f64::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f64) -> f64 {
         let r = self % rhs;
         if r < 0.0 {
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index cf8be393a40..0761c50f4b2 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -8,7 +8,8 @@
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
-#[doc(include = "os/raw/char.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
 #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "hexagon",
@@ -32,7 +33,8 @@
                                          target_arch = "powerpc")),
           all(target_os = "fuchsia", target_arch = "aarch64")))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
-#[doc(include = "os/raw/char.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
 #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "hexagon",
@@ -56,37 +58,51 @@
                                              target_arch = "powerpc")),
               all(target_os = "fuchsia", target_arch = "aarch64"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
-#[doc(include = "os/raw/schar.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "schar.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
-#[doc(include = "os/raw/uchar.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
-#[doc(include = "os/raw/short.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "short.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
-#[doc(include = "os/raw/ushort.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
-#[doc(include = "os/raw/int.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "int.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
-#[doc(include = "os/raw/uint.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "uint.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
-#[doc(include = "os/raw/long.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
-#[doc(include = "os/raw/ulong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
-#[doc(include = "os/raw/long.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
-#[doc(include = "os/raw/ulong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
-#[doc(include = "os/raw/longlong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
-#[doc(include = "os/raw/ulonglong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
-#[doc(include = "os/raw/float.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "float.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
-#[doc(include = "os/raw/double.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "double.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;
 
 #[stable(feature = "raw_os", since = "1.1.0")]
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 65fd8c83e1c..d9a3da66a67 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`]. 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,13 @@ 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 memory containing a valid value of `T` - for example,
+/// `&bool` can only point to an allocation containing the integer values `1` (`true`) or `0`
+/// (`false`), but creating a `&bool` that points to an allocation containing
+/// the value `3` causes undefined behaviour.
+/// 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 +1046,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 +1106,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/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index ffb9ce1c81a..aeff57716e8 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -36,7 +36,7 @@ impl WaitTimeoutResult {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///
     ///     // Let's wait 20 milliseconds before notifying the condvar.
     ///     thread::sleep(Duration::from_millis(20));
@@ -48,7 +48,7 @@ impl WaitTimeoutResult {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
     /// loop {
     ///     // Let's put a timeout on the condvar's wait.
@@ -94,7 +94,7 @@ impl WaitTimeoutResult {
 ///
 /// // Inside of our lock, spawn a new thread, and then wait for it to start.
 /// thread::spawn(move|| {
-///     let &(ref lock, ref cvar) = &*pair2;
+///     let (lock, cvar) = &*pair2;
 ///     let mut started = lock.lock().unwrap();
 ///     *started = true;
 ///     // We notify the condvar that the value has changed.
@@ -102,7 +102,7 @@ impl WaitTimeoutResult {
 /// });
 ///
 /// // Wait for the thread to start up.
-/// let &(ref lock, ref cvar) = &*pair;
+/// let (lock, cvar) = &*pair;
 /// let mut started = lock.lock().unwrap();
 /// while !*started {
 ///     started = cvar.wait(started).unwrap();
@@ -180,7 +180,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -188,7 +188,7 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
     /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
@@ -245,7 +245,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -253,7 +253,7 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
     /// ```
@@ -301,7 +301,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -309,7 +309,7 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
     /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// loop {
@@ -374,7 +374,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -382,7 +382,7 @@ impl Condvar {
     /// });
     ///
     /// // wait for the thread to start up
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
     /// // as long as the value inside the `Mutex<bool>` is `false`, we wait
     /// loop {
@@ -449,7 +449,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -457,7 +457,7 @@ impl Condvar {
     /// });
     ///
     /// // wait for the thread to start up
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let result = cvar.wait_timeout_until(
     ///     lock.lock().unwrap(),
     ///     Duration::from_millis(100),
@@ -508,7 +508,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -516,7 +516,7 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
     /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
@@ -548,7 +548,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -556,7 +556,7 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
     /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index b41f1047fcb..dbf31ad0148 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -1,6 +1,9 @@
 //! Parsing and validation of builtin attributes
 
 use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
+use crate::early_buffered_lints::BufferedEarlyLintId;
+use crate::ext::base::ExtCtxt;
+use crate::ext::build::AstBuilder;
 use crate::feature_gate::{Features, GatedCfg};
 use crate::parse::ParseSess;
 
@@ -19,6 +22,27 @@ enum AttrError {
     UnsupportedLiteral(&'static str, /* is_bytestr */ bool),
 }
 
+/// A template that the attribute input must match.
+/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
+#[derive(Clone, Copy)]
+pub struct AttributeTemplate {
+    crate word: bool,
+    crate list: Option<&'static str>,
+    crate name_value_str: Option<&'static str>,
+}
+
+impl AttributeTemplate {
+    /// Checks that the given meta-item is compatible with this template.
+    fn compatible(&self, meta_item_kind: &ast::MetaItemKind) -> bool {
+        match meta_item_kind {
+            ast::MetaItemKind::Word => self.word,
+            ast::MetaItemKind::List(..) => self.list.is_some(),
+            ast::MetaItemKind::NameValue(lit) if lit.node.is_str() => self.name_value_str.is_some(),
+            ast::MetaItemKind::NameValue(..) => false,
+        }
+    }
+}
+
 fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
     let diag = &sess.span_diagnostic;
     match error {
@@ -901,3 +925,76 @@ pub fn find_transparency(
     let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque };
     (transparency.map_or(fallback, |t| t.0), error)
 }
+
+pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
+    // All the built-in macro attributes are "words" at the moment.
+    let template = AttributeTemplate { word: true, list: None, name_value_str: None };
+    let attr = ecx.attribute(meta_item.span, meta_item.clone());
+    check_builtin_attribute(ecx.parse_sess, &attr, name, template);
+}
+
+crate fn check_builtin_attribute(
+    sess: &ParseSess, attr: &ast::Attribute, name: Symbol, template: AttributeTemplate
+) {
+    // Some special attributes like `cfg` must be checked
+    // before the generic check, so we skip them here.
+    let should_skip = |name| name == sym::cfg;
+    // Some of previously accepted forms were used in practice,
+    // report them as warnings for now.
+    let should_warn = |name| name == sym::doc || name == sym::ignore ||
+                             name == sym::inline || name == sym::link ||
+                             name == sym::test || name == sym::bench;
+
+    match attr.parse_meta(sess) {
+        Ok(meta) => if !should_skip(name) && !template.compatible(&meta.node) {
+            let error_msg = format!("malformed `{}` attribute input", name);
+            let mut msg = "attribute must be of the form ".to_owned();
+            let mut suggestions = vec![];
+            let mut first = true;
+            if template.word {
+                first = false;
+                let code = format!("#[{}]", name);
+                msg.push_str(&format!("`{}`", &code));
+                suggestions.push(code);
+            }
+            if let Some(descr) = template.list {
+                if !first {
+                    msg.push_str(" or ");
+                }
+                first = false;
+                let code = format!("#[{}({})]", name, descr);
+                msg.push_str(&format!("`{}`", &code));
+                suggestions.push(code);
+            }
+            if let Some(descr) = template.name_value_str {
+                if !first {
+                    msg.push_str(" or ");
+                }
+                let code = format!("#[{} = \"{}\"]", name, descr);
+                msg.push_str(&format!("`{}`", &code));
+                suggestions.push(code);
+            }
+            if should_warn(name) {
+                sess.buffer_lint(
+                    BufferedEarlyLintId::IllFormedAttributeInput,
+                    meta.span,
+                    ast::CRATE_NODE_ID,
+                    &msg,
+                );
+            } else {
+                sess.span_diagnostic.struct_span_err(meta.span, &error_msg)
+                    .span_suggestions(
+                        meta.span,
+                        if suggestions.len() == 1 {
+                            "must be of the form"
+                        } else {
+                            "the following are the possible correct uses"
+                        },
+                        suggestions.into_iter(),
+                        Applicability::HasPlaceholders,
+                    ).emit();
+            }
+        }
+        Err(mut err) => err.emit(),
+    }
+}
diff --git a/src/libsyntax/ext/allocator.rs b/src/libsyntax/ext/allocator.rs
new file mode 100644
index 00000000000..99aeb5414c5
--- /dev/null
+++ b/src/libsyntax/ext/allocator.rs
@@ -0,0 +1,75 @@
+use crate::{ast, attr, visit};
+use crate::symbol::{sym, Symbol};
+use syntax_pos::Span;
+
+#[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),
+        }
+    }
+}
+
+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 {
+        name: "alloc",
+        inputs: &[AllocatorTy::Layout],
+        output: AllocatorTy::ResultPtr,
+    },
+    AllocatorMethod {
+        name: "dealloc",
+        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
+        output: AllocatorTy::Unit,
+    },
+    AllocatorMethod {
+        name: "realloc",
+        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
+        output: AllocatorTy::ResultPtr,
+    },
+    AllocatorMethod {
+        name: "alloc_zeroed",
+        inputs: &[AllocatorTy::Layout],
+        output: AllocatorTy::ResultPtr,
+    },
+];
+
+pub fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
+    struct Finder { name: Symbol, spans: Vec<Span> }
+    impl<'ast> visit::Visitor<'ast> for Finder {
+        fn visit_item(&mut self, item: &'ast ast::Item) {
+            if item.ident.name == self.name &&
+               attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) {
+                self.spans.push(item.span);
+            }
+            visit::walk_item(self, item)
+        }
+    }
+
+    let name = Symbol::intern(&AllocatorKind::Global.fn_name("alloc"));
+    let mut f = Finder { name, spans: Vec::new() };
+    visit::walk_crate(&mut f, krate);
+    f.spans
+}
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 926c9e88efe..11b7a984aaa 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -1,6 +1,6 @@
 use crate::ast::{self, Attribute, Name, PatKind};
 use crate::attr::{HasAttrs, Stability, Deprecation};
-use crate::source_map::{SourceMap, Spanned, respan};
+use crate::source_map::{SourceMap, Spanned, FileName, respan};
 use crate::edition::Edition;
 use crate::ext::expand::{self, AstFragment, Invocation};
 use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency};
@@ -889,6 +889,31 @@ impl<'a> ExtCtxt<'a> {
     pub fn check_unused_macros(&self) {
         self.resolver.check_unused_macros();
     }
+
+    /// Resolve a path mentioned inside Rust code.
+    ///
+    /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
+    ///
+    /// Returns an absolute path to the file that `path` refers to.
+    pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PathBuf {
+        let path = path.into();
+
+        // Relative paths are resolved relative to the file in which they are found
+        // after macro expansion (that is, they are unhygienic).
+        if !path.is_absolute() {
+            let callsite = span.source_callsite();
+            let mut result = 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),
+            };
+            result.pop();
+            result.push(path);
+            result
+        } else {
+            path
+        }
+    }
 }
 
 /// Extracts a string literal from the macro expanded version of `expr`,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 14d573d07d0..640daaccc3a 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1253,7 +1253,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                         return noop_visit_attribute(at, self);
                     }
 
-                    let filename = self.cx.root_path.join(file.to_string());
+                    let filename = self.cx.resolve_path(&*file.as_str(), it.span());
                     match fs::read_to_string(&filename) {
                         Ok(src) => {
                             let src_interned = Symbol::intern(&src);
@@ -1302,10 +1302,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                                 );
                                 err.span_label(lit.span, "couldn't read file");
 
-                                if e.kind() == ErrorKind::NotFound {
-                                    err.help("external doc paths are relative to the crate root");
-                                }
-
                                 err.emit();
                             }
                         }
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index c2ba8b983f5..ae080c05eec 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -8,11 +8,10 @@ use crate::symbol::Symbol;
 use crate::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,9 +77,9 @@ 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 file = cx.resolve_path(file, sp);
     let directory_ownership = DirectoryOwnership::Owned { relative: None };
-    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
+    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
 
     struct ExpandResult<'a> {
         p: parse::parser::Parser<'a>,
@@ -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.resolve_path(file, sp);
     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.resolve_path(file, sp);
     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/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 43f0eaae7c9..72184b0bd64 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -19,8 +19,7 @@ use crate::ast::{
     self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
     PatKind, RangeEnd,
 };
-use crate::attr;
-use crate::early_buffered_lints::BufferedEarlyLintId;
+use crate::attr::{self, check_builtin_attribute, AttributeTemplate};
 use crate::source_map::Spanned;
 use crate::edition::{ALL_EDITIONS, Edition};
 use crate::visit::{self, FnKind, Visitor};
@@ -906,27 +905,6 @@ pub enum AttributeGate {
     Ungated,
 }
 
-/// A template that the attribute input must match.
-/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
-#[derive(Clone, Copy)]
-pub struct AttributeTemplate {
-    word: bool,
-    list: Option<&'static str>,
-    name_value_str: Option<&'static str>,
-}
-
-impl AttributeTemplate {
-    /// Checks that the given meta-item is compatible with this template.
-    fn compatible(&self, meta_item_kind: &ast::MetaItemKind) -> bool {
-        match meta_item_kind {
-            ast::MetaItemKind::Word => self.word,
-            ast::MetaItemKind::List(..) => self.list.is_some(),
-            ast::MetaItemKind::NameValue(lit) if lit.node.is_str() => self.name_value_str.is_some(),
-            ast::MetaItemKind::NameValue(..) => false,
-        }
-    }
-}
-
 /// A convenience macro for constructing attribute templates.
 /// E.g., `template!(Word, List: "description")` means that the attribute
 /// supports forms `#[attr]` and `#[attr(description)]`.
@@ -1117,7 +1095,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
                                             "the `#[rustc_const_unstable]` attribute \
                                             is an internal feature",
                                             cfg_fn!(rustc_const_unstable))),
-    (sym::global_allocator, Normal, template!(Word), Ungated),
     (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable,
                                             sym::allocator_internals,
                                             "the `#[default_lib_allocator]` \
@@ -1902,70 +1879,6 @@ impl<'a> PostExpansionVisitor<'a> {
             Abi::System => {}
         }
     }
-
-    fn check_builtin_attribute(&mut self, attr: &ast::Attribute, name: Symbol,
-                               template: AttributeTemplate) {
-        // Some special attributes like `cfg` must be checked
-        // before the generic check, so we skip them here.
-        let should_skip = |name| name == sym::cfg;
-        // Some of previously accepted forms were used in practice,
-        // report them as warnings for now.
-        let should_warn = |name| name == sym::doc || name == sym::ignore ||
-                                 name == sym::inline || name == sym::link;
-
-        match attr.parse_meta(self.context.parse_sess) {
-            Ok(meta) => if !should_skip(name) && !template.compatible(&meta.node) {
-                let error_msg = format!("malformed `{}` attribute input", name);
-                let mut msg = "attribute must be of the form ".to_owned();
-                let mut suggestions = vec![];
-                let mut first = true;
-                if template.word {
-                    first = false;
-                    let code = format!("#[{}]", name);
-                    msg.push_str(&format!("`{}`", &code));
-                    suggestions.push(code);
-                }
-                if let Some(descr) = template.list {
-                    if !first {
-                        msg.push_str(" or ");
-                    }
-                    first = false;
-                    let code = format!("#[{}({})]", name, descr);
-                    msg.push_str(&format!("`{}`", &code));
-                    suggestions.push(code);
-                }
-                if let Some(descr) = template.name_value_str {
-                    if !first {
-                        msg.push_str(" or ");
-                    }
-                    let code = format!("#[{} = \"{}\"]", name, descr);
-                    msg.push_str(&format!("`{}`", &code));
-                    suggestions.push(code);
-                }
-                if should_warn(name) {
-                    self.context.parse_sess.buffer_lint(
-                        BufferedEarlyLintId::IllFormedAttributeInput,
-                        meta.span,
-                        ast::CRATE_NODE_ID,
-                        &msg,
-                    );
-                } else {
-                    self.context.parse_sess.span_diagnostic.struct_span_err(meta.span, &error_msg)
-                        .span_suggestions(
-                            meta.span,
-                            if suggestions.len() == 1 {
-                                "must be of the form"
-                            } else {
-                                "the following are the possible correct uses"
-                            },
-                            suggestions.into_iter(),
-                            Applicability::HasPlaceholders,
-                        ).emit();
-                }
-            }
-            Err(mut err) => err.emit(),
-        }
-    }
 }
 
 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -2006,7 +1919,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         match attr_info {
             // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
             Some(&(name, _, template, _)) if name != sym::rustc_dummy =>
-                self.check_builtin_attribute(attr, name, template),
+                check_builtin_attribute(self.context.parse_sess, attr, name, template),
             _ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() {
                 if token == token::Eq {
                     // All key-value attributes are restricted to meta-item syntax.
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 0507a322a5f..75b4e89ec01 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -162,6 +162,7 @@ pub mod print {
 
 pub mod ext {
     pub use syntax_pos::hygiene;
+    pub mod allocator;
     pub mod base;
     pub mod build;
     pub mod derive;
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index da388694637..a5b6f0d6836 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -7671,6 +7671,11 @@ impl<'a> Parser<'a> {
         let ret = f(self);
         let last_token = if self.token_cursor.stack.len() == prev {
             &mut self.token_cursor.frame.last_token
+        } else if self.token_cursor.stack.get(prev).is_none() {
+            // This can happen due to a bad interaction of two unrelated recovery mechanisms with
+            // mismatched delimiters *and* recovery lookahead on the likely typo `pub ident(`
+            // (#62881).
+            return Ok((ret?, TokenStream::new(vec![])));
         } else {
             &mut self.token_cursor.stack[prev].last_token
         };
@@ -7678,7 +7683,15 @@ impl<'a> Parser<'a> {
         // Pull out the tokens that we've collected from the call to `f` above.
         let mut collected_tokens = match *last_token {
             LastToken::Collecting(ref mut v) => mem::take(v),
-            LastToken::Was(_) => panic!("our vector went away?"),
+            LastToken::Was(ref was) => {
+                let msg = format!("our vector went away? - found Was({:?})", was);
+                debug!("collect_tokens: {}", msg);
+                self.sess.span_diagnostic.delay_span_bug(self.token.span, &msg);
+                // This can happen due to a bad interaction of two unrelated recovery mechanisms
+                // with mismatched delimiters *and* recovery lookahead on the likely typo
+                // `pub ident(` (#62895, different but similar to the case above).
+                return Ok((ret?, TokenStream::new(vec![])));
+            }
         };
 
         // If we're not at EOF our current token wasn't actually consumed by
diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs
new file mode 100644
index 00000000000..33072487e19
--- /dev/null
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -0,0 +1,191 @@
+use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafety};
+use syntax::ast::{self, Arg, Attribute, Expr, FnHeader, Generics, Ident};
+use syntax::attr::check_builtin_macro_attribute;
+use syntax::ext::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};
+use syntax::ext::base::{Annotatable, ExtCtxt};
+use syntax::ext::build::AstBuilder;
+use syntax::ext::hygiene::SyntaxContext;
+use syntax::ptr::P;
+use syntax::symbol::{kw, sym, Symbol};
+use syntax_pos::Span;
+
+pub fn expand(
+    ecx: &mut ExtCtxt<'_>,
+    _span: Span,
+    meta_item: &ast::MetaItem,
+    item: Annotatable,
+) -> Vec<Annotatable> {
+    check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
+
+    let not_static = |item: Annotatable| {
+        ecx.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
+        vec![item]
+    };
+    let item = match item {
+        Annotatable::Item(item) => match item.node {
+            ItemKind::Static(..) => item,
+            _ => return not_static(Annotatable::Item(item)),
+        }
+        _ => return not_static(item),
+    };
+
+    // Generate a bunch of new items using the AllocFnFactory
+    let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
+    let f = AllocFnFactory {
+        span,
+        kind: AllocatorKind::Global,
+        global: item.ident,
+        cx: ecx,
+    };
+
+    // Generate item statements for the allocator methods.
+    let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
+
+    // Generate anonymous constant serving as container for the allocator methods.
+    let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
+    let const_body = ecx.expr_block(ecx.block(span, stmts));
+    let const_item =
+        ecx.item_const(span, Ident::with_empty_ctxt(kw::Underscore), const_ty, const_body);
+
+    // Return the original item and the new methods.
+    vec![Annotatable::Item(item), Annotatable::Item(const_item)]
+}
+
+struct AllocFnFactory<'a, 'b> {
+    span: Span,
+    kind: AllocatorKind,
+    global: Ident,
+    cx: &'b ExtCtxt<'a>,
+}
+
+impl AllocFnFactory<'_, '_> {
+    fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
+        let mut abi_args = Vec::new();
+        let mut i = 0;
+        let ref mut mk = || {
+            let name = Ident::from_str(&format!("arg{}", i));
+            i += 1;
+            name
+        };
+        let args = method
+            .inputs
+            .iter()
+            .map(|ty| self.arg_ty(ty, &mut abi_args, mk))
+            .collect();
+        let result = self.call_allocator(method.name, args);
+        let (output_ty, output_expr) = self.ret_ty(&method.output, result);
+        let kind = ItemKind::Fn(
+            self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
+            FnHeader {
+                unsafety: Unsafety::Unsafe,
+                ..FnHeader::default()
+            },
+            Generics::default(),
+            self.cx.block_expr(output_expr),
+        );
+        let item = self.cx.item(
+            self.span,
+            Ident::from_str(&self.kind.fn_name(method.name)),
+            self.attrs(),
+            kind,
+        );
+        self.cx.stmt_item(self.span, item)
+    }
+
+    fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
+        let method = self.cx.std_path(&[
+            Symbol::intern("alloc"),
+            Symbol::intern("GlobalAlloc"),
+            Symbol::intern(method),
+        ]);
+        let method = self.cx.expr_path(self.cx.path(self.span, method));
+        let allocator = self.cx.path_ident(self.span, self.global);
+        let allocator = self.cx.expr_path(allocator);
+        let allocator = self.cx.expr_addr_of(self.span, allocator);
+        args.insert(0, allocator);
+
+        self.cx.expr_call(self.span, method, args)
+    }
+
+    fn attrs(&self) -> Vec<Attribute> {
+        let special = sym::rustc_std_internal_symbol;
+        let special = self.cx.meta_word(self.span, special);
+        vec![self.cx.attribute(self.span, special)]
+    }
+
+    fn arg_ty(
+        &self,
+        ty: &AllocatorTy,
+        args: &mut Vec<Arg>,
+        ident: &mut dyn FnMut() -> Ident,
+    ) -> P<Expr> {
+        match *ty {
+            AllocatorTy::Layout => {
+                let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize));
+                let ty_usize = self.cx.ty_path(usize);
+                let size = ident();
+                let align = ident();
+                args.push(self.cx.arg(self.span, size, ty_usize.clone()));
+                args.push(self.cx.arg(self.span, align, ty_usize));
+
+                let layout_new = self.cx.std_path(&[
+                    Symbol::intern("alloc"),
+                    Symbol::intern("Layout"),
+                    Symbol::intern("from_size_align_unchecked"),
+                ]);
+                let layout_new = self.cx.expr_path(self.cx.path(self.span, layout_new));
+                let size = self.cx.expr_ident(self.span, size);
+                let align = self.cx.expr_ident(self.span, align);
+                let layout = self.cx.expr_call(self.span, layout_new, vec![size, align]);
+                layout
+            }
+
+            AllocatorTy::Ptr => {
+                let ident = ident();
+                args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
+                let arg = self.cx.expr_ident(self.span, ident);
+                self.cx.expr_cast(self.span, arg, self.ptr_u8())
+            }
+
+            AllocatorTy::Usize => {
+                let ident = ident();
+                args.push(self.cx.arg(self.span, ident, self.usize()));
+                self.cx.expr_ident(self.span, ident)
+            }
+
+            AllocatorTy::ResultPtr | AllocatorTy::Unit => {
+                panic!("can't convert AllocatorTy to an argument")
+            }
+        }
+    }
+
+    fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
+        match *ty {
+            AllocatorTy::ResultPtr => {
+                // We're creating:
+                //
+                //      #expr as *mut u8
+
+                let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
+                (self.ptr_u8(), expr)
+            }
+
+            AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),
+
+            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
+                panic!("can't convert `AllocatorTy` to an output")
+            }
+        }
+    }
+
+    fn usize(&self) -> P<Ty> {
+        let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize));
+        self.cx.ty_path(usize)
+    }
+
+    fn ptr_u8(&self) -> P<Ty> {
+        let u8 = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::u8));
+        let ty_u8 = self.cx.ty_path(u8);
+        self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
+    }
+}
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 7de90278ed7..400bfe796bb 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -29,6 +29,7 @@ mod concat_idents;
 mod env;
 mod format;
 mod format_foreign;
+mod global_allocator;
 mod global_asm;
 mod log_syntax;
 mod proc_macro_server;
@@ -151,6 +152,12 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
             SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition
         )
     });
+    register(sym::global_allocator, SyntaxExtension {
+        allow_internal_unstable: Some([sym::rustc_attrs][..].into()),
+        ..SyntaxExtension::default(
+            SyntaxExtensionKind::LegacyAttr(Box::new(global_allocator::expand)), edition
+        )
+    });
 
     let allow_internal_unstable = Some([sym::fmt_internals][..].into());
     register(sym::format_args, SyntaxExtension {
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index f8755a1d1d7..d381c42f9ce 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -1,31 +1,34 @@
 /// The expansion from a test function to the appropriate test struct for libtest
 /// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
 
+use syntax::ast;
+use syntax::attr::{self, check_builtin_macro_attribute};
 use syntax::ext::base::*;
 use syntax::ext::build::AstBuilder;
 use syntax::ext::hygiene::SyntaxContext;
-use syntax::attr;
-use syntax::ast;
 use syntax::print::pprust;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::Span;
+
 use std::iter;
 
 pub fn expand_test(
     cx: &mut ExtCtxt<'_>,
     attr_sp: Span,
-    _meta_item: &ast::MetaItem,
+    meta_item: &ast::MetaItem,
     item: Annotatable,
 ) -> Vec<Annotatable> {
+    check_builtin_macro_attribute(cx, meta_item, sym::test);
     expand_test_or_bench(cx, attr_sp, item, false)
 }
 
 pub fn expand_bench(
     cx: &mut ExtCtxt<'_>,
     attr_sp: Span,
-    _meta_item: &ast::MetaItem,
+    meta_item: &ast::MetaItem,
     item: Annotatable,
 ) -> Vec<Annotatable> {
+    check_builtin_macro_attribute(cx, meta_item, sym::bench);
     expand_test_or_bench(cx, attr_sp, item, true)
 }
 
diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs
index 355f2428e08..ea4a8d541ab 100644
--- a/src/libsyntax_ext/test_case.rs
+++ b/src/libsyntax_ext/test_case.rs
@@ -9,10 +9,11 @@
 // We mark item with an inert attribute "rustc_test_marker" which the test generation
 // logic will pick up on.
 
+use syntax::ast;
+use syntax::attr::check_builtin_macro_attribute;
 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;
@@ -20,9 +21,11 @@ use syntax_pos::Span;
 pub fn expand(
     ecx: &mut ExtCtxt<'_>,
     attr_sp: Span,
-    _meta_item: &ast::MetaItem,
+    meta_item: &ast::MetaItem,
     anno_item: Annotatable
 ) -> Vec<Annotatable> {
+    check_builtin_macro_attribute(ecx, meta_item, sym::test_case);
+
     if !ecx.ecfg.should_test { return vec![]; }
 
     let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
diff --git a/src/stdarch b/src/stdarch
-Subproject b881a2d124cb0eea09d137300eb4a35829b517f
+Subproject 4791ba85e7645c02146dd416288480943670d1c
diff --git a/src/test/run-pass/allocator/custom-in-block.rs b/src/test/run-pass/allocator/custom-in-block.rs
new file mode 100644
index 00000000000..12813a1fc8b
--- /dev/null
+++ b/src/test/run-pass/allocator/custom-in-block.rs
@@ -0,0 +1,22 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+fn main() {
+    #[global_allocator]
+    pub static GLOBAL: A = A(AtomicUsize::new(0));
+
+    let n = GLOBAL.0.load(Ordering::SeqCst);
+    let s = Box::new(0);
+    helper::work_with(&s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+    drop(s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
diff --git a/src/test/run-pass/allocator/custom-in-submodule.rs b/src/test/run-pass/allocator/custom-in-submodule.rs
new file mode 100644
index 00000000000..ea341b1ac14
--- /dev/null
+++ b/src/test/run-pass/allocator/custom-in-submodule.rs
@@ -0,0 +1,26 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+mod submodule {
+    use super::*;
+
+    #[global_allocator]
+    pub static GLOBAL: A = A(AtomicUsize::new(0));
+}
+
+fn main() {
+    let n = submodule::GLOBAL.0.load(Ordering::SeqCst);
+    let s = Box::new(0);
+    helper::work_with(&s);
+    assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 1);
+    drop(s);
+    assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
diff --git a/src/test/run-pass/consts/const-fn-type-name.rs b/src/test/run-pass/consts/const-fn-type-name.rs
index 2ee6415aa68..2bb1aeecf37 100644
--- a/src/test/run-pass/consts/const-fn-type-name.rs
+++ b/src/test/run-pass/consts/const-fn-type-name.rs
@@ -5,7 +5,7 @@
 #![allow(dead_code)]
 
 const fn type_name_wrapper<T>(_: &T) -> &'static str {
-    unsafe { core::intrinsics::type_name::<T>() }
+    core::intrinsics::type_name::<T>()
 }
 
 struct Struct<TA, TB, TC> {
diff --git a/src/test/run-pass/generator/size-moved-locals.rs b/src/test/run-pass/generator/size-moved-locals.rs
index 574442e2574..dbcdfc61ef9 100644
--- a/src/test/run-pass/generator/size-moved-locals.rs
+++ b/src/test/run-pass/generator/size-moved-locals.rs
@@ -56,8 +56,20 @@ fn overlap_move_points() -> impl Generator<Yield = (), Return = ()> {
     }
 }
 
+fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()>{
+    static || {
+        let x = Foo([0; FOO_SIZE]);
+        yield;
+        drop(x);
+        let y = Foo([0; FOO_SIZE]);
+        yield;
+        drop(y);
+    }
+}
+
 fn main() {
     assert_eq!(1028, std::mem::size_of_val(&move_before_yield()));
     assert_eq!(1032, std::mem::size_of_val(&move_before_yield_with_noop()));
     assert_eq!(2056, std::mem::size_of_val(&overlap_move_points()));
+    assert_eq!(1032, std::mem::size_of_val(&overlap_x_and_y()));
 }
diff --git a/src/test/run-pass/issues/issue-21058.rs b/src/test/run-pass/issues/issue-21058.rs
index 3efa94ce683..6facf0b2dd5 100644
--- a/src/test/run-pass/issues/issue-21058.rs
+++ b/src/test/run-pass/issues/issue-21058.rs
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(dead_code)]
-#![feature(core_intrinsics)]
 
 use std::fmt::Debug;
 
@@ -12,7 +11,7 @@ macro_rules! check {
         assert_eq!(type_name_of_val($ty_of), $expected);
     };
     ($ty:ty, $expected:expr) => {
-        assert_eq!(unsafe { std::intrinsics::type_name::<$ty>()}, $expected);
+        assert_eq!(std::any::type_name::<$ty>(), $expected);
     };
 }
 
@@ -50,7 +49,7 @@ fn bar<T: Trait>() {
 }
 
 fn type_name_of_val<T>(_: T) -> &'static str {
-    unsafe { std::intrinsics::type_name::<T>() }
+    std::any::type_name::<T>()
 }
 
 #[derive(Debug)]
diff --git a/src/test/run-pass/issues/issue-61894.rs b/src/test/run-pass/issues/issue-61894.rs
index 9ab969be46a..4d407125299 100644
--- a/src/test/run-pass/issues/issue-61894.rs
+++ b/src/test/run-pass/issues/issue-61894.rs
@@ -1,6 +1,6 @@
 #![feature(core_intrinsics)]
 
-use std::intrinsics::type_name;
+use std::any::type_name;
 
 struct Bar<M>(M);
 
@@ -8,7 +8,7 @@ impl<M> Bar<M> {
     fn foo(&self) -> &'static str {
         fn f() {}
         fn type_name_of<T>(_: T) -> &'static str {
-            unsafe { type_name::<T>() }
+            type_name::<T>()
         }
         type_name_of(f)
     }
diff --git a/src/test/run-pass/tydesc-name.rs b/src/test/run-pass/tydesc-name.rs
index 91578b71d04..d9d947bd4c0 100644
--- a/src/test/run-pass/tydesc-name.rs
+++ b/src/test/run-pass/tydesc-name.rs
@@ -1,16 +1,12 @@
 #![allow(dead_code)]
 
-#![feature(core_intrinsics)]
-
-use std::intrinsics::type_name;
+use std::any::type_name;
 
 struct Foo<T> {
     x: T
 }
 
 pub fn main() {
-    unsafe {
-        assert_eq!(type_name::<isize>(), "isize");
-        assert_eq!(type_name::<Foo<usize>>(), "tydesc_name::Foo<usize>");
-    }
+    assert_eq!(type_name::<isize>(), "isize");
+    assert_eq!(type_name::<Foo<usize>>(), "tydesc_name::Foo<usize>");
 }
diff --git a/src/test/ui/allocator-submodule.rs b/src/test/ui/allocator-submodule.rs
deleted file mode 100644
index 7a8d86b8da1..00000000000
--- a/src/test/ui/allocator-submodule.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Tests that it is possible to create a global allocator in a submodule, rather than in the crate
-// root.
-
-extern crate alloc;
-
-use std::{
-    alloc::{GlobalAlloc, Layout},
-    ptr,
-};
-
-struct MyAlloc;
-
-unsafe impl GlobalAlloc for MyAlloc {
-    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        ptr::null_mut()
-    }
-
-    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {}
-}
-
-mod submod {
-    use super::MyAlloc;
-
-    #[global_allocator]
-    static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator
-}
-
-fn main() {}
diff --git a/src/test/ui/allocator-submodule.stderr b/src/test/ui/allocator-submodule.stderr
deleted file mode 100644
index 91c7c0f6b8e..00000000000
--- a/src/test/ui/allocator-submodule.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: `global_allocator` cannot be used in submodules
-  --> $DIR/allocator-submodule.rs:25:5
-   |
-LL |     static MY_HEAP: MyAlloc = MyAlloc;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/allocator/allocator-args.rs b/src/test/ui/allocator/allocator-args.rs
new file mode 100644
index 00000000000..1033f947c5f
--- /dev/null
+++ b/src/test/ui/allocator/allocator-args.rs
@@ -0,0 +1,13 @@
+use std::alloc::{GlobalAlloc, Layout};
+
+struct A;
+
+unsafe impl GlobalAlloc for A {
+    unsafe fn alloc(&self, _: Layout) -> *mut u8 { panic!() }
+    unsafe fn dealloc(&self, _: *mut u8, _: Layout) { panic!() }
+}
+
+#[global_allocator(malloc)] //~ ERROR malformed `global_allocator` attribute input
+static S: A = A;
+
+fn main() {}
diff --git a/src/test/ui/allocator/allocator-args.stderr b/src/test/ui/allocator/allocator-args.stderr
new file mode 100644
index 00000000000..dfff2a7e709
--- /dev/null
+++ b/src/test/ui/allocator/allocator-args.stderr
@@ -0,0 +1,8 @@
+error: malformed `global_allocator` attribute input
+  --> $DIR/allocator-args.rs:10:1
+   |
+LL | #[global_allocator(malloc)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[global_allocator]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/two-allocators.rs b/src/test/ui/allocator/two-allocators.rs
index 0f81fc41823..aa1291e77ae 100644
--- a/src/test/ui/allocator/two-allocators.rs
+++ b/src/test/ui/allocator/two-allocators.rs
@@ -4,6 +4,6 @@ use std::alloc::System;
 static A: System = System;
 #[global_allocator]
 static B: System = System;
-//~^ ERROR: cannot define more than one `#[global_allocator]`
+//~^ ERROR: cannot define multiple global allocators
 
 fn main() {}
diff --git a/src/test/ui/allocator/two-allocators.stderr b/src/test/ui/allocator/two-allocators.stderr
index 6b0c2b2a25d..ed0aa13eb80 100644
--- a/src/test/ui/allocator/two-allocators.stderr
+++ b/src/test/ui/allocator/two-allocators.stderr
@@ -1,8 +1,14 @@
-error: cannot define more than one `#[global_allocator]`
+error: cannot define multiple global allocators
   --> $DIR/two-allocators.rs:6:1
    |
 LL | static B: System = System;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the previous global allocator is defined here
+  --> $DIR/two-allocators.rs:4:1
+   |
+LL | static A: System = System;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-const/associated-const-ambiguity-report.stderr b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr
index 5f2b9c47e8c..bb217bd182d 100644
--- a/src/test/ui/associated-const/associated-const-ambiguity-report.stderr
+++ b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32`
    |
 LL |     const ID: i32 = 1;
    |     ^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `Foo::ID(...)` instead
 note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32`
   --> $DIR/associated-const-ambiguity-report.rs:14:5
    |
 LL |     const ID: i32 = 3;
    |     ^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `Bar::ID(...)` instead
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/issue-51559.rs b/src/test/ui/consts/issue-51559.rs
new file mode 100644
index 00000000000..42994726938
--- /dev/null
+++ b/src/test/ui/consts/issue-51559.rs
@@ -0,0 +1,7 @@
+#![feature(const_raw_ptr_to_usize_cast)]
+
+const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut ();
+pub const FOO: usize = unsafe { BAR as usize };
+//~^ ERROR it is undefined behavior to use this value
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-51559.stderr b/src/test/ui/consts/issue-51559.stderr
new file mode 100644
index 00000000000..917c54ddaef
--- /dev/null
+++ b/src/test/ui/consts/issue-51559.stderr
@@ -0,0 +1,11 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/issue-51559.rs:4:1
+   |
+LL | pub const FOO: usize = unsafe { BAR as usize };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/error-codes/E0034.stderr b/src/test/ui/error-codes/E0034.stderr
index 816a48f102d..a58d16bfafb 100644
--- a/src/test/ui/error-codes/E0034.stderr
+++ b/src/test/ui/error-codes/E0034.stderr
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Tes
    |
 LL |     fn foo() {}
    |     ^^^^^^^^
+   = help: to disambiguate the method call, write `Trait1::foo(...)` instead
 note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Test`
   --> $DIR/E0034.rs:16:5
    |
 LL |     fn foo() {}
    |     ^^^^^^^^
+   = help: to disambiguate the method call, write `Trait2::foo(...)` instead
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs
index e17dda65568..4e89f7464da 100644
--- a/src/test/ui/extern/external-doc-error.rs
+++ b/src/test/ui/extern/external-doc-error.rs
@@ -4,7 +4,6 @@
 
 #[doc(include = "not-a-file.md")]
 pub struct SomeStruct; //~^ ERROR couldn't read
-                       //~| HELP external doc paths are relative to the crate root
 
 #[doc(include = "auxiliary/invalid-utf8.txt")]
 pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr
index a3be3277de5..b180cd66c52 100644
--- a/src/test/ui/extern/external-doc-error.stderr
+++ b/src/test/ui/extern/external-doc-error.stderr
@@ -3,35 +3,33 @@ error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
    |
 LL | #[doc(include = "not-a-file.md")]
    |                 ^^^^^^^^^^^^^^^ couldn't read file
-   |
-   = help: external doc paths are relative to the crate root
 
 error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
-  --> $DIR/external-doc-error.rs:9:17
+  --> $DIR/external-doc-error.rs:8:17
    |
 LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8
 
 error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:12:7
+  --> $DIR/external-doc-error.rs:11:7
    |
 LL | #[doc(include)]
    |       ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
 
 error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:17:7
+  --> $DIR/external-doc-error.rs:16:7
    |
 LL | #[doc(include("../README.md"))]
    |       ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`
 
 error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:22:7
+  --> $DIR/external-doc-error.rs:21:7
    |
 LL | #[doc(include = 123)]
    |       ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
 
 error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:27:7
+  --> $DIR/external-doc-error.rs:26:7
    |
 LL | #[doc(include(123))]
    |       ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
index 503ef020d96..37b5e792dc2 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
@@ -1,3 +1,13 @@
+warning: attribute must be of the form `#[bench]`
+  --> $DIR/issue-43106-gating-of-bench.rs:15:1
+   |
+LL | #![bench                   = "4100"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(ill_formed_attribute_input)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
 error[E0601]: `main` function not found in crate `issue_43106_gating_of_bench`
    |
    = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-bench.rs`
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
index 2ab35be43c5..dbffabf3e02 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
@@ -1,3 +1,13 @@
+warning: attribute must be of the form `#[test]`
+  --> $DIR/issue-43106-gating-of-test.rs:10:1
+   |
+LL | #![test                    = "4200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(ill_formed_attribute_input)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
 error[E0601]: `main` function not found in crate `issue_43106_gating_of_test`
    |
    = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-test.rs`
diff --git a/src/test/ui/inference/inference_unstable_featured.stderr b/src/test/ui/inference/inference_unstable_featured.stderr
index 08cdb8cc688..b06a6298a57 100644
--- a/src/test/ui/inference/inference_unstable_featured.stderr
+++ b/src/test/ui/inference/inference_unstable_featured.stderr
@@ -5,7 +5,9 @@ LL |     assert_eq!('x'.ipu_flatten(), 0);
    |                    ^^^^^^^^^^^ multiple `ipu_flatten` found
    |
    = note: candidate #1 is defined in an impl of the trait `inference_unstable_iterator::IpuIterator` for the type `char`
+   = help: to disambiguate the method call, write `inference_unstable_iterator::IpuIterator::ipu_flatten('x')` instead
    = note: candidate #2 is defined in an impl of the trait `inference_unstable_itertools::IpuItertools` for the type `char`
+   = help: to disambiguate the method call, write `inference_unstable_itertools::IpuItertools::ipu_flatten('x')` instead
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3702-2.stderr b/src/test/ui/issues/issue-3702-2.stderr
index 347a19b687f..4d0ff750c25 100644
--- a/src/test/ui/issues/issue-3702-2.stderr
+++ b/src/test/ui/issues/issue-3702-2.stderr
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `ToPrimitive` for the type
    |
 LL |     fn to_int(&self) -> isize { 0 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `ToPrimitive::to_int(&self)` instead
 note: candidate #2 is defined in an impl of the trait `Add` for the type `isize`
   --> $DIR/issue-3702-2.rs:14:5
    |
 LL |     fn to_int(&self) -> isize { *self }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `Add::to_int(&self)` instead
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr
index 2b87ddfdf98..9f46a722a50 100644
--- a/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr
+++ b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr
@@ -9,7 +9,9 @@ note: candidate #1 is defined in an impl of the trait `Me2` for the type `usize`
    |
 LL | impl Me2 for usize { fn me(&self) -> usize { *self } }
    |                      ^^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `Me2::me(1_usize)` instead
    = note: candidate #2 is defined in an impl of the trait `ambig_impl_2_lib::Me` for the type `usize`
+   = help: to disambiguate the method call, write `ambig_impl_2_lib::Me::me(1_usize)` instead
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls.rs b/src/test/ui/methods/method-ambig-two-traits-from-impls.rs
new file mode 100644
index 00000000000..22bf8406605
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls.rs
@@ -0,0 +1,16 @@
+trait A { fn foo(self); }
+trait B { fn foo(self); }
+
+struct AB {}
+
+impl A for AB {
+    fn foo(self) {}
+}
+
+impl B for AB {
+    fn foo(self) {}
+}
+
+fn main() {
+    AB {}.foo();  //~ ERROR E0034
+}
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr
new file mode 100644
index 00000000000..0b3724e030f
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr
@@ -0,0 +1,22 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-ambig-two-traits-from-impls.rs:15:11
+   |
+LL |     AB {}.foo();
+   |           ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `A` for the type `AB`
+  --> $DIR/method-ambig-two-traits-from-impls.rs:7:5
+   |
+LL |     fn foo(self) {}
+   |     ^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `A::foo(AB {})` instead
+note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
+  --> $DIR/method-ambig-two-traits-from-impls.rs:11:5
+   |
+LL |     fn foo(self) {}
+   |     ^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `B::foo(AB {})` instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls2.rs b/src/test/ui/methods/method-ambig-two-traits-from-impls2.rs
new file mode 100644
index 00000000000..0a96c1223da
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls2.rs
@@ -0,0 +1,16 @@
+trait A { fn foo(); }
+trait B { fn foo(); }
+
+struct AB {}
+
+impl A for AB {
+    fn foo() {}
+}
+
+impl B for AB {
+    fn foo() {}
+}
+
+fn main() {
+    AB::foo();  //~ ERROR E0034
+}
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr
new file mode 100644
index 00000000000..81c99b33c81
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr
@@ -0,0 +1,22 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-ambig-two-traits-from-impls2.rs:15:5
+   |
+LL |     AB::foo();
+   |     ^^^^^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `A` for the type `AB`
+  --> $DIR/method-ambig-two-traits-from-impls2.rs:7:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^
+   = help: to disambiguate the method call, write `A::foo(...)` instead
+note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
+  --> $DIR/method-ambig-two-traits-from-impls2.rs:11:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^
+   = help: to disambiguate the method call, write `B::foo(...)` instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr
index 5d508d57022..dc8aef25037 100644
--- a/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr
+++ b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `Foo` for the type `usize`
    |
 LL | trait Foo { fn method(&self) {} }
    |             ^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `Foo::method(1_usize)` instead
 note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize`
   --> $DIR/method-ambig-two-traits-with-default-method.rs:6:13
    |
 LL | trait Bar { fn method(&self) {} }
    |             ^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `Bar::method(1_usize)` instead
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index d6fac7025a4..283ef8fcba7 100644
--- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -27,11 +27,13 @@ note: candidate #1 is defined in an impl of the trait `internal::X` for the type
    |
 LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `internal::X::foo(x)` instead
 note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `_`
   --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:70:9
    |
 LL |         fn foo(self) {}
    |         ^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `nuisance_foo::NuisanceFoo::foo(x)` instead
 note: candidate #3 is defined in the trait `FinalFoo`
   --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:57:5
    |
diff --git a/src/test/ui/parser/issue-62881.rs b/src/test/ui/parser/issue-62881.rs
new file mode 100644
index 00000000000..1782c2e375d
--- /dev/null
+++ b/src/test/ui/parser/issue-62881.rs
@@ -0,0 +1,6 @@
+fn main() {}
+
+fn f() -> isize { fn f() -> isize {} pub f<
+//~^ ERROR missing `fn` or `struct` for function or struct definition
+//~| ERROR mismatched types
+//~ ERROR this file contains an un-closed delimiter
diff --git a/src/test/ui/parser/issue-62881.stderr b/src/test/ui/parser/issue-62881.stderr
new file mode 100644
index 00000000000..85c3575fd92
--- /dev/null
+++ b/src/test/ui/parser/issue-62881.stderr
@@ -0,0 +1,29 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/issue-62881.rs:6:53
+   |
+LL | fn f() -> isize { fn f() -> isize {} pub f<
+   |                 - un-closed delimiter
+...
+LL |
+   |                                                     ^
+
+error: missing `fn` or `struct` for function or struct definition
+  --> $DIR/issue-62881.rs:3:41
+   |
+LL | fn f() -> isize { fn f() -> isize {} pub f<
+   |                                         ^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-62881.rs:3:29
+   |
+LL | fn f() -> isize { fn f() -> isize {} pub f<
+   |                      -      ^^^^^ expected isize, found ()
+   |                      |
+   |                      this function's body doesn't return
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-62895.rs b/src/test/ui/parser/issue-62895.rs
new file mode 100644
index 00000000000..53f17405d79
--- /dev/null
+++ b/src/test/ui/parser/issue-62895.rs
@@ -0,0 +1,11 @@
+fn main() {}
+
+fn v() -> isize { //~ ERROR mismatched types
+mod _ { //~ ERROR expected identifier
+pub fn g() -> isizee { //~ ERROR cannot find type `isizee` in this scope
+mod _ { //~ ERROR expected identifier
+pub    g() -> is //~ ERROR missing `fn` for function definition
+(), w20);
+}
+(), w20); //~ ERROR expected item, found `;`
+}
diff --git a/src/test/ui/parser/issue-62895.stderr b/src/test/ui/parser/issue-62895.stderr
new file mode 100644
index 00000000000..7def7b562ca
--- /dev/null
+++ b/src/test/ui/parser/issue-62895.stderr
@@ -0,0 +1,49 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-62895.rs:4:5
+   |
+LL | mod _ {
+   |     ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-62895.rs:6:5
+   |
+LL | mod _ {
+   |     ^ expected identifier, found reserved identifier
+
+error: missing `fn` for function definition
+  --> $DIR/issue-62895.rs:7:4
+   |
+LL | pub    g() -> is
+   |    ^^^^
+help: add `fn` here to parse `g` as a public function
+   |
+LL | pub fn g() -> is
+   |     ^^
+
+error: expected item, found `;`
+  --> $DIR/issue-62895.rs:10:9
+   |
+LL | (), w20);
+   |         ^ help: remove this semicolon
+
+error[E0412]: cannot find type `isizee` in this scope
+  --> $DIR/issue-62895.rs:5:15
+   |
+LL | pub fn g() -> isizee {
+   |               ^^^^^^ help: a builtin type with a similar name exists: `isize`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-62895.rs:3:11
+   |
+LL | fn v() -> isize {
+   |    -      ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0412.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-62843.rs b/src/test/ui/suggestions/issue-62843.rs
new file mode 100644
index 00000000000..d96b12fd15a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-62843.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let line = String::from("abc");
+    let pattern = String::from("bc");
+    println!("{:?}", line.find(pattern)); //~ ERROR E0277
+}
diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr
new file mode 100644
index 00000000000..cc27b5b49b6
--- /dev/null
+++ b/src/test/ui/suggestions/issue-62843.stderr
@@ -0,0 +1,13 @@
+error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `std::string::String`
+  --> $DIR/issue-62843.rs:4:27
+   |
+LL |     println!("{:?}", line.find(pattern));
+   |                           ^^^^ expected an `FnMut<(char,)>` closure, found `std::string::String`
+   |
+   = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String`
+   = note: borrowing the `std::string::String` might fix the problem
+   = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `std::string::String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-alias-ambiguous.stderr b/src/test/ui/traits/trait-alias-ambiguous.stderr
index b7443269b88..cde7dd08249 100644
--- a/src/test/ui/traits/trait-alias-ambiguous.stderr
+++ b/src/test/ui/traits/trait-alias-ambiguous.stderr
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `inner::A` for the type `u
    |
 LL |         fn foo(&self) {}
    |         ^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `inner::A::foo(t)` instead
 note: candidate #2 is defined in an impl of the trait `inner::B` for the type `u8`
   --> $DIR/trait-alias-ambiguous.rs:11:9
    |
 LL |         fn foo(&self) {}
    |         ^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `inner::B::foo(t)` instead
 
 error: aborting due to previous error
 
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 6a728b02f92..335c1aa0175 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -344,7 +344,7 @@ fn get_and_check_lib_features(base_src_path: &Path,
                 Ok((name, f)) => {
                     let mut check_features = |f: &Feature, list: &Features, display: &str| {
                         if let Some(ref s) = list.get(name) {
-                            if f.tracking_issue != s.tracking_issue {
+                            if f.tracking_issue != s.tracking_issue && f.level != Status::Stable {
                                 tidy_error!(bad,
                                             "{}:{}: mismatches the `issue` in {}",
                                             file.display(),