From c71f5232d812fb17c87650a84c19cd12647e6907 Mon Sep 17 00:00:00 2001
From: Camelid <camelidcamel@gmail.com>
Date: Sat, 26 Dec 2020 10:09:41 -0800
Subject: [PATCH 01/17] Clarify what `Cell::replace` returns

---
 library/core/src/cell.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index c5ab7a39ff0ca..bccc34bf44074 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -374,7 +374,7 @@ impl<T> Cell<T> {
         }
     }
 
-    /// Replaces the contained value, and returns it.
+    /// Replaces the contained value with `val`, and returns the old contained value.
     ///
     /// # Examples
     ///

From 14e23f117ec984434f30e51ebd5e183a3f0533c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= <mockersf@gmail.com>
Date: Tue, 9 Mar 2021 21:26:07 +0100
Subject: [PATCH 02/17] convert slice doc link to intra-doc links

---
 library/alloc/src/slice.rs    |  10 ++--
 library/core/src/slice/mod.rs | 107 +++++++++++++++++-----------------
 2 files changed, 58 insertions(+), 59 deletions(-)

diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 0c911cea1bb1e..8cd4ef7a14e81 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -231,7 +231,7 @@ impl<T> [T] {
     ///
     /// When applicable, unstable sorting is preferred because it is generally faster than stable
     /// sorting and it doesn't allocate auxiliary memory.
-    /// See [`sort_unstable`](#method.sort_unstable).
+    /// See [`sort_unstable`](slice::sort_unstable).
     ///
     /// # Current implementation
     ///
@@ -282,7 +282,7 @@ impl<T> [T] {
     ///
     /// When applicable, unstable sorting is preferred because it is generally faster than stable
     /// sorting and it doesn't allocate auxiliary memory.
-    /// See [`sort_unstable_by`](#method.sort_unstable_by).
+    /// See [`sort_unstable_by`](slice::sort_unstable_by).
     ///
     /// # Current implementation
     ///
@@ -320,12 +320,12 @@ impl<T> [T] {
     /// worst-case, where the key function is *O*(*m*).
     ///
     /// For expensive key functions (e.g. functions that are not simple property accesses or
-    /// basic operations), [`sort_by_cached_key`](#method.sort_by_cached_key) is likely to be
+    /// basic operations), [`sort_by_cached_key`](slice::sort_by_cached_key) is likely to be
     /// significantly faster, as it does not recompute element keys.
     ///
     /// When applicable, unstable sorting is preferred because it is generally faster than stable
     /// sorting and it doesn't allocate auxiliary memory.
-    /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key).
+    /// See [`sort_unstable_by_key`](slice::sort_unstable_by_key).
     ///
     /// # Current implementation
     ///
@@ -363,7 +363,7 @@ impl<T> [T] {
     /// worst-case, where the key function is *O*(*m*).
     ///
     /// For simple key functions (e.g., functions that are property accesses or
-    /// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be
+    /// basic operations), [`sort_by_key`](slice::sort_by_key) is likely to be
     /// faster.
     ///
     /// # Current implementation
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 5510bb0257e34..674780a170ecc 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -308,7 +308,7 @@ impl<T> [T] {
     /// Returns a mutable reference to an element or subslice depending on the
     /// type of index (see [`get`]) or `None` if the index is out of bounds.
     ///
-    /// [`get`]: #method.get
+    /// [`get`]: slice::get
     ///
     /// # Examples
     ///
@@ -339,7 +339,7 @@ impl<T> [T] {
     /// Calling this method with an out-of-bounds index is *[undefined behavior]*
     /// even if the resulting reference is not used.
     ///
-    /// [`get`]: #method.get
+    /// [`get`]: slice::get
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     ///
     /// # Examples
@@ -373,7 +373,7 @@ impl<T> [T] {
     /// Calling this method with an out-of-bounds index is *[undefined behavior]*
     /// even if the resulting reference is not used.
     ///
-    /// [`get_mut`]: #method.get_mut
+    /// [`get_mut`]: slice::get_mut
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     ///
     /// # Examples
@@ -424,7 +424,7 @@ impl<T> [T] {
     /// }
     /// ```
     ///
-    /// [`as_mut_ptr`]: #method.as_mut_ptr
+    /// [`as_mut_ptr`]: slice::as_mut_ptr
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
     #[inline]
@@ -487,7 +487,7 @@ impl<T> [T] {
     /// assert!(!a.as_ptr_range().contains(&y));
     /// ```
     ///
-    /// [`as_ptr`]: #method.as_ptr
+    /// [`as_ptr`]: slice::as_ptr
     #[stable(feature = "slice_ptr_range", since = "1.48.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
@@ -529,7 +529,7 @@ impl<T> [T] {
     /// use two pointers to refer to a range of elements in memory, as is
     /// common in C++.
     ///
-    /// [`as_mut_ptr`]: #method.as_mut_ptr
+    /// [`as_mut_ptr`]: slice::as_mut_ptr
     #[stable(feature = "slice_ptr_range", since = "1.48.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
@@ -780,8 +780,8 @@ impl<T> [T] {
     /// assert!(iter.next().is_none());
     /// ```
     ///
-    /// [`chunks_exact`]: #method.chunks_exact
-    /// [`rchunks`]: #method.rchunks
+    /// [`chunks_exact`]: slice::chunks_exact
+    /// [`rchunks`]: slice::rchunks
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> {
@@ -818,8 +818,8 @@ impl<T> [T] {
     /// assert_eq!(v, &[1, 1, 2, 2, 3]);
     /// ```
     ///
-    /// [`chunks_exact_mut`]: #method.chunks_exact_mut
-    /// [`rchunks_mut`]: #method.rchunks_mut
+    /// [`chunks_exact_mut`]: slice::chunks_exact_mut
+    /// [`rchunks_mut`]: slice::rchunks_mut
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> {
@@ -855,8 +855,8 @@ impl<T> [T] {
     /// assert_eq!(iter.remainder(), &['m']);
     /// ```
     ///
-    /// [`chunks`]: #method.chunks
-    /// [`rchunks_exact`]: #method.rchunks_exact
+    /// [`chunks`]: slice::chunks
+    /// [`rchunks_exact`]: slice::rchunks_exact
     #[stable(feature = "chunks_exact", since = "1.31.0")]
     #[inline]
     pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
@@ -897,8 +897,8 @@ impl<T> [T] {
     /// assert_eq!(v, &[1, 1, 2, 2, 0]);
     /// ```
     ///
-    /// [`chunks_mut`]: #method.chunks_mut
-    /// [`rchunks_exact_mut`]: #method.rchunks_exact_mut
+    /// [`chunks_mut`]: slice::chunks_mut
+    /// [`rchunks_exact_mut`]: slice::rchunks_exact_mut
     #[stable(feature = "chunks_exact", since = "1.31.0")]
     #[inline]
     pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
@@ -1032,7 +1032,7 @@ impl<T> [T] {
     /// assert_eq!(iter.remainder(), &['m']);
     /// ```
     ///
-    /// [`chunks_exact`]: #method.chunks_exact
+    /// [`chunks_exact`]: slice::chunks_exact
     #[unstable(feature = "array_chunks", issue = "74985")]
     #[inline]
     pub fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
@@ -1182,7 +1182,7 @@ impl<T> [T] {
     /// assert_eq!(v, &[1, 1, 2, 2, 0]);
     /// ```
     ///
-    /// [`chunks_exact_mut`]: #method.chunks_exact_mut
+    /// [`chunks_exact_mut`]: slice::chunks_exact_mut
     #[unstable(feature = "array_chunks", issue = "74985")]
     #[inline]
     pub fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> {
@@ -1214,7 +1214,7 @@ impl<T> [T] {
     /// assert!(iter.next().is_none());
     /// ```
     ///
-    /// [`windows`]: #method.windows
+    /// [`windows`]: slice::windows
     #[unstable(feature = "array_windows", issue = "75027")]
     #[inline]
     pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
@@ -1247,8 +1247,8 @@ impl<T> [T] {
     /// assert!(iter.next().is_none());
     /// ```
     ///
-    /// [`rchunks_exact`]: #method.rchunks_exact
-    /// [`chunks`]: #method.chunks
+    /// [`rchunks_exact`]: slice::rchunks_exact
+    /// [`chunks`]: slice::chunks
     #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {
@@ -1285,8 +1285,8 @@ impl<T> [T] {
     /// assert_eq!(v, &[3, 2, 2, 1, 1]);
     /// ```
     ///
-    /// [`rchunks_exact_mut`]: #method.rchunks_exact_mut
-    /// [`chunks_mut`]: #method.chunks_mut
+    /// [`rchunks_exact_mut`]: slice::rchunks_exact_mut
+    /// [`chunks_mut`]: slice::chunks_mut
     #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> {
@@ -1323,9 +1323,9 @@ impl<T> [T] {
     /// assert_eq!(iter.remainder(), &['l']);
     /// ```
     ///
-    /// [`chunks`]: #method.chunks
-    /// [`rchunks`]: #method.rchunks
-    /// [`chunks_exact`]: #method.chunks_exact
+    /// [`chunks`]: slice::chunks
+    /// [`rchunks`]: slice::rchunks
+    /// [`chunks_exact`]: slice::chunks_exact
     #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {
@@ -1366,9 +1366,9 @@ impl<T> [T] {
     /// assert_eq!(v, &[0, 2, 2, 1, 1]);
     /// ```
     ///
-    /// [`chunks_mut`]: #method.chunks_mut
-    /// [`rchunks_mut`]: #method.rchunks_mut
-    /// [`chunks_exact_mut`]: #method.chunks_exact_mut
+    /// [`chunks_mut`]: slice::chunks_mut
+    /// [`rchunks_mut`]: slice::rchunks_mut
+    /// [`chunks_exact_mut`]: slice::chunks_exact_mut
     #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {
@@ -1552,7 +1552,7 @@ impl<T> [T] {
     /// even if the resulting reference is not used. The caller has to ensure that
     /// `0 <= mid <= self.len()`.
     ///
-    /// [`split_at`]: #method.split_at
+    /// [`split_at`]: slice::split_at
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     ///
     /// # Examples
@@ -1601,7 +1601,7 @@ impl<T> [T] {
     /// even if the resulting reference is not used. The caller has to ensure that
     /// `0 <= mid <= self.len()`.
     ///
-    /// [`split_at_mut`]: #method.split_at_mut
+    /// [`split_at_mut`]: slice::split_at_mut
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     ///
     /// # Examples
@@ -2103,9 +2103,9 @@ impl<T> [T] {
     ///
     /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`].
     ///
-    /// [`binary_search_by`]: #method.binary_search_by
-    /// [`binary_search_by_key`]: #method.binary_search_by_key
-    /// [`partition_point`]: #method.partition_point
+    /// [`binary_search_by`]: slice::binary_search_by
+    /// [`binary_search_by_key`]: slice::binary_search_by_key
+    /// [`partition_point`]: slice::partition_point
     ///
     /// # Examples
     ///
@@ -2156,9 +2156,9 @@ impl<T> [T] {
     ///
     /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`].
     ///
-    /// [`binary_search`]: #method.binary_search
-    /// [`binary_search_by_key`]: #method.binary_search_by_key
-    /// [`partition_point`]: #method.partition_point
+    /// [`binary_search`]: slice::binary_search
+    /// [`binary_search_by_key`]: slice::binary_search_by_key
+    /// [`partition_point`]: slice::partition_point
     ///
     /// # Examples
     ///
@@ -2215,7 +2215,7 @@ impl<T> [T] {
     /// Binary searches this sorted slice with a key extraction function.
     ///
     /// Assumes that the slice is sorted by the key, for instance with
-    /// [`sort_by_key`] using the same key extraction function.
+    /// `sort_by_key` using the same key extraction function.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2225,10 +2225,9 @@ impl<T> [T] {
     ///
     /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`].
     ///
-    /// [`sort_by_key`]: #method.sort_by_key
-    /// [`binary_search`]: #method.binary_search
-    /// [`binary_search_by`]: #method.binary_search_by
-    /// [`partition_point`]: #method.partition_point
+    /// [`binary_search`]: slice::binary_search
+    /// [`binary_search_by`]: slice::binary_search_by
+    /// [`partition_point`]: slice::partition_point
     ///
     /// # Examples
     ///
@@ -2446,7 +2445,7 @@ impl<T> [T] {
     /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
     /// used for [`sort_unstable`].
     ///
-    /// [`sort_unstable`]: #method.sort_unstable
+    /// [`sort_unstable`]: slice::sort_unstable
     ///
     /// # Panics
     ///
@@ -2494,7 +2493,7 @@ impl<T> [T] {
     /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
     /// used for [`sort_unstable`].
     ///
-    /// [`sort_unstable`]: #method.sort_unstable
+    /// [`sort_unstable`]: slice::sort_unstable
     ///
     /// # Panics
     ///
@@ -2546,7 +2545,7 @@ impl<T> [T] {
     /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
     /// used for [`sort_unstable`].
     ///
-    /// [`sort_unstable`]: #method.sort_unstable
+    /// [`sort_unstable`]: slice::sort_unstable
     ///
     /// # Panics
     ///
@@ -2883,7 +2882,7 @@ impl<T> [T] {
     /// trait to generate values, you can pass [`Default::default`] as the
     /// argument.
     ///
-    /// [`fill`]: #method.fill
+    /// [`fill`]: slice::fill
     ///
     /// # Examples
     ///
@@ -2956,8 +2955,8 @@ impl<T> [T] {
     /// assert_eq!(slice, [4, 5, 3, 4, 5]);
     /// ```
     ///
-    /// [`copy_from_slice`]: #method.copy_from_slice
-    /// [`split_at_mut`]: #method.split_at_mut
+    /// [`copy_from_slice`]: slice::copy_from_slice
+    /// [`split_at_mut`]: slice::split_at_mut
     #[stable(feature = "clone_from_slice", since = "1.7.0")]
     pub fn clone_from_slice(&mut self, src: &[T])
     where
@@ -3018,8 +3017,8 @@ impl<T> [T] {
     /// assert_eq!(slice, [4, 5, 3, 4, 5]);
     /// ```
     ///
-    /// [`clone_from_slice`]: #method.clone_from_slice
-    /// [`split_at_mut`]: #method.split_at_mut
+    /// [`clone_from_slice`]: slice::clone_from_slice
+    /// [`split_at_mut`]: slice::split_at_mut
     #[doc(alias = "memcpy")]
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     pub fn copy_from_slice(&mut self, src: &[T])
@@ -3136,7 +3135,7 @@ impl<T> [T] {
     /// assert_eq!(slice, [4, 5, 3, 1, 2]);
     /// ```
     ///
-    /// [`split_at_mut`]: #method.split_at_mut
+    /// [`split_at_mut`]: slice::split_at_mut
     #[stable(feature = "swap_with_slice", since = "1.27.0")]
     pub fn swap_with_slice(&mut self, other: &mut [T]) {
         assert!(self.len() == other.len(), "destination and source slices have different lengths");
@@ -3380,7 +3379,7 @@ impl<T> [T] {
     /// function to determine the ordering of two elements. Apart from that, it's equivalent to
     /// [`is_sorted`]; see its documentation for more information.
     ///
-    /// [`is_sorted`]: #method.is_sorted
+    /// [`is_sorted`]: slice::is_sorted
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
     pub fn is_sorted_by<F>(&self, mut compare: F) -> bool
     where
@@ -3395,7 +3394,7 @@ impl<T> [T] {
     /// elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see its
     /// documentation for more information.
     ///
-    /// [`is_sorted`]: #method.is_sorted
+    /// [`is_sorted`]: slice::is_sorted
     ///
     /// # Examples
     ///
@@ -3429,9 +3428,9 @@ impl<T> [T] {
     ///
     /// See also [`binary_search`], [`binary_search_by`], and [`binary_search_by_key`].
     ///
-    /// [`binary_search`]: #method.binary_search
-    /// [`binary_search_by`]: #method.binary_search_by
-    /// [`binary_search_by_key`]: #method.binary_search_by_key
+    /// [`binary_search`]: slice::binary_search
+    /// [`binary_search_by`]: slice::binary_search_by
+    /// [`binary_search_by_key`]: slice::binary_search_by_key
     ///
     /// # Examples
     ///

From a6624d3c984bc00b2f4e0eed292409e8d013dfde Mon Sep 17 00:00:00 2001
From: Erin Power <erin.power@embark-studios.com>
Date: Wed, 10 Mar 2021 07:54:26 +0100
Subject: [PATCH 03/17] Add spirv extension handling in compiletest

---
 src/tools/compiletest/src/runtest.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 9a82591e5a75a..8290711418e63 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2069,6 +2069,8 @@ impl<'test> TestCx<'test> {
             f = f.with_extra_extension("js");
         } else if self.config.target.contains("wasm32") {
             f = f.with_extra_extension("wasm");
+        } else if self.config.target.contains("spirv") {
+            f = f.with_extra_extension("spv");
         } else if !env::consts::EXE_SUFFIX.is_empty() {
             f = f.with_extra_extension(env::consts::EXE_SUFFIX);
         }

From 3a3e7ebdf0fd4813ebdebe652a5d025a45976f33 Mon Sep 17 00:00:00 2001
From: Trevor Spiteri <tspiteri@ieee.org>
Date: Wed, 10 Mar 2021 08:41:53 +0100
Subject: [PATCH 04/17] update MSYS2 link in README

Now https://msys2.github.io/ redirects to https://www.msys2.org/, so
the README might just link to that immediately.
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index cc073875cde57..5ec94e189f835 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,7 @@ build.
 
 [MSYS2][msys2] can be used to easily build Rust on Windows:
 
-[msys2]: https://msys2.github.io/
+[msys2]: https://www.msys2.org/
 
 1. Grab the latest [MSYS2 installer][msys2] and go through the installer.
 

From a4d7046714731987d079da9b99769a60da246fc9 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Wed, 10 Mar 2021 16:40:27 +0100
Subject: [PATCH 05/17] Fix "run" button position in error index

---
 src/doc/rust.css                       | 1 +
 src/librustdoc/html/static/rustdoc.css | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/doc/rust.css b/src/doc/rust.css
index ff18e1a8f51cc..06f4df9a9b6da 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -332,6 +332,7 @@ table th {
 
 /* Code snippets */
 
+.example-wrap { position: relative; }
 pre.rust { position: relative; }
 a.test-arrow {
 	background-color: rgba(78, 139, 202, 0.2);
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 94c231cb33a8b..7393abfdd9eb5 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -347,10 +347,10 @@ nav.sub {
 .rustdoc:not(.source) .example-wrap {
 	display: inline-flex;
 	margin-bottom: 10px;
-	position: relative;
 }
 
 .example-wrap {
+	position: relative;
 	width: 100%;
 }
 

From 0d0715350717f7aa308fbe7473b863b95f6198f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= <mockersf@gmail.com>
Date: Wed, 10 Mar 2021 18:18:28 +0100
Subject: [PATCH 06/17] add back sort_by_key link, allow linter and add comment

---
 library/core/src/slice/mod.rs | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 674780a170ecc..e35f3e52aa0be 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -2215,7 +2215,7 @@ impl<T> [T] {
     /// Binary searches this sorted slice with a key extraction function.
     ///
     /// Assumes that the slice is sorted by the key, for instance with
-    /// `sort_by_key` using the same key extraction function.
+    /// [`sort_by_key`] using the same key extraction function.
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
@@ -2225,6 +2225,7 @@ impl<T> [T] {
     ///
     /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`].
     ///
+    /// [`sort_by_key`]: slice::sort_by_key
     /// [`binary_search`]: slice::binary_search
     /// [`binary_search_by`]: slice::binary_search_by
     /// [`partition_point`]: slice::partition_point
@@ -2247,6 +2248,10 @@ impl<T> [T] {
     /// let r = s.binary_search_by_key(&1, |&(a, b)| b);
     /// assert!(match r { Ok(1..=4) => true, _ => false, });
     /// ```
+    // Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is
+    // in crate `alloc`, and as such doesn't exists yet when building `core`
+    // links to downstream crate: https://github.com/rust-lang/rust/issues/74481
+    #[cfg_attr(not(bootstrap), allow(rustdoc::broken_intra_doc_links))]
     #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
     #[inline]
     pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>

From 06669056b53e00c53ff6d787e706c393a469eb78 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= <mockersf@gmail.com>
Date: Wed, 10 Mar 2021 18:18:56 +0100
Subject: [PATCH 07/17] remove slice linkcheck exceptions

---
 src/tools/linkchecker/main.rs | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 01e067ea0b803..f6875e0036f67 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -33,11 +33,6 @@ use crate::Redirect::*;
 // are cases where that does not work
 // [(generated_documentation_page, &[broken_links])]
 const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
-    // These are methods on slice, and `Self` does not work on primitive impls
-    // in intra-doc links (primitive impls are weird)
-    // https://github.com/rust-lang/rust/issues/62834 is necessary to be
-    // able to link to slices
-    ("std/io/struct.IoSlice.html", &["#method.as_mut_ptr", "#method.sort_by_key"]),
     // These try to link to std::collections, but are defined in alloc
     // https://github.com/rust-lang/rust/issues/74481
     ("std/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]),

From 232b9f1641097763ef40fedccf442f2119958608 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= <mockersf@gmail.com>
Date: Wed, 10 Mar 2021 18:32:55 +0100
Subject: [PATCH 08/17] apply review

---
 library/core/src/slice/mod.rs | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index e35f3e52aa0be..417a106b99a2e 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -2249,9 +2249,11 @@ impl<T> [T] {
     /// assert!(match r { Ok(1..=4) => true, _ => false, });
     /// ```
     // Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is
-    // in crate `alloc`, and as such doesn't exists yet when building `core`
-    // links to downstream crate: https://github.com/rust-lang/rust/issues/74481
+    // in crate `alloc`, and as such doesn't exists yet when building `core`.
+    // links to downstream crate: #74481. Since primitives are only documented in
+    // libstd (#73423), this never leads to broken links in practice.
     #[cfg_attr(not(bootstrap), allow(rustdoc::broken_intra_doc_links))]
+    #[cfg_attr(bootstrap, allow(broken_intra_doc_links))]
     #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
     #[inline]
     pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>

From 9925ecb3928417b4401e81a2a7cde6de114aa26f Mon Sep 17 00:00:00 2001
From: Nixon Enraght-Moony <nixon.emoony@gmail.com>
Date: Fri, 26 Feb 2021 22:55:08 +0000
Subject: [PATCH 09/17] Add reexport tests

---
 src/test/rustdoc-json/reexport/glob_extern.rs | 17 ++++++++++++
 .../rustdoc-json/reexport/glob_private.rs     | 27 +++++++++++++++++++
 .../rustdoc-json/reexport/rename_public.rs    | 17 ++++++++++++
 .../rustdoc-json/reexport/simple_private.rs   | 13 +++++++++
 .../rustdoc-json/reexport/simple_public.rs    | 18 +++++++++++++
 5 files changed, 92 insertions(+)
 create mode 100644 src/test/rustdoc-json/reexport/glob_extern.rs
 create mode 100644 src/test/rustdoc-json/reexport/glob_private.rs
 create mode 100644 src/test/rustdoc-json/reexport/rename_public.rs
 create mode 100644 src/test/rustdoc-json/reexport/simple_private.rs
 create mode 100644 src/test/rustdoc-json/reexport/simple_public.rs

diff --git a/src/test/rustdoc-json/reexport/glob_extern.rs b/src/test/rustdoc-json/reexport/glob_extern.rs
new file mode 100644
index 0000000000000..831c185f6b136
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/glob_extern.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @!has glob_extern.json "$.index[*][?(@.name=='mod1')]"
+mod mod1 {
+    extern "C" {
+        // @set public_fn_id = - "$.index[*][?(@.name=='public_fn')].id"
+        pub fn public_fn();
+        // @!has - "$.index[*][?(@.name=='private_fn')]"
+        fn private_fn();
+    }
+}
+
+// @has - "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $public_fn_id
+pub use mod1::*;
diff --git a/src/test/rustdoc-json/reexport/glob_private.rs b/src/test/rustdoc-json/reexport/glob_private.rs
new file mode 100644
index 0000000000000..e907de9236776
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/glob_private.rs
@@ -0,0 +1,27 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @!has glob_private.json "$.index[*][?(@.name=='mod1')]"
+mod mod1 {
+    // @!has - "$.index[*][?(@.name=='mod2')]"
+    mod mod2 {
+        // @set m2pub_id = - "$.index[*][?(@.name=='Mod2Public')].id"
+        pub struct Mod2Public;
+
+        // @!has - "$.index[*][?(@.name=='Mod2Private')]"
+        struct Mod2Private;
+    }
+    pub use self::mod2::*;
+
+    // @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id"
+    pub struct Mod1Public;
+
+    // @!has - "$.index[*][?(@.name=='Mod1Private')]"
+    struct Mod1Private;
+}
+pub use mod1::*;
+
+// @has - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $m2pub_id
+// @has - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $m1pub_id
diff --git a/src/test/rustdoc-json/reexport/rename_public.rs b/src/test/rustdoc-json/reexport/rename_public.rs
new file mode 100644
index 0000000000000..8c2d7200d0c01
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/rename_public.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @set inner_id = rename_public.json "$.index[*][?(@.name=='inner')].id"
+// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id
+pub mod inner {
+    // @set public_id = - "$.index[*][?(@.name=='Public')].id"
+    // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    pub struct Public;
+}
+// @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id"
+// @!has - "$.index[*][?(@.inner.name=='Public')]"
+// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $import_id
+// @is - "$.index[*][?(@.inner.name=='NewName')].inner.span" \"inner::Public\"
+pub use inner::Public as NewName;
diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs
new file mode 100644
index 0000000000000..658b121e6ce97
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/simple_private.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @!has simple_private.json "$.index[*][?(@.name=='inner')]"
+mod inner {
+    // @set pub_id = - "$.index[*][?(@.name=='Public')].id"
+    pub struct Public;
+}
+
+// @has - "$.index[*][?(@.name=='simple_private')].inner.items[*]" $pub_id
+pub use inner::Public;
diff --git a/src/test/rustdoc-json/reexport/simple_public.rs b/src/test/rustdoc-json/reexport/simple_public.rs
new file mode 100644
index 0000000000000..0c97a2e7b40a2
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/simple_public.rs
@@ -0,0 +1,18 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @set inner_id = simple_public.json "$.index[*][?(@.name=='inner')].id"
+// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $inner_id
+pub mod inner {
+
+    // @set public_id = - "$.index[*][?(@.name=='Public')].id"
+    // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    pub struct Public;
+}
+
+// @set import_id = - "$.index[*][?(@.inner.name=='Public')].id"
+// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id
+// @is - "$.index[*][?(@.inner.name=='Public')].inner.span" \"inner::Public\"
+pub use inner::Public;

From 5f24798b9e228438973a8abeee1a2d5ea016f335 Mon Sep 17 00:00:00 2001
From: Nixon Enraght-Moony <nixon.emoony@gmail.com>
Date: Fri, 26 Feb 2021 22:55:28 +0000
Subject: [PATCH 10/17] Improve some jsondocck errors

---
 src/tools/jsondocck/src/main.rs | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index 5020a4917a00a..bcb3f6922efaa 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -205,7 +205,21 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
                     let val = cache.get_value(&command.args[0])?;
                     let results = select(&val, &command.args[1]).unwrap();
                     let pat = string_to_value(&command.args[2], cache);
-                    results.contains(&pat.as_ref())
+                    let has = results.contains(&pat.as_ref());
+                    // Give better error for when @has check fails
+                    if !command.negated && !has {
+                        return Err(CkError::FailedCheck(
+                            format!(
+                                "{} matched to {:?} but didn't have {:?}",
+                                &command.args[1],
+                                results,
+                                pat.as_ref()
+                            ),
+                            command,
+                        ));
+                    } else {
+                        has
+                    }
                 }
                 _ => unreachable!(),
             }
@@ -233,7 +247,13 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
             assert_eq!(command.args[1], "=", "Expected an `=`");
             let val = cache.get_value(&command.args[2])?;
             let results = select(&val, &command.args[3]).unwrap();
-            assert_eq!(results.len(), 1);
+            assert_eq!(
+                results.len(),
+                1,
+                "Didn't get 1 result for `{}`: got {:?}",
+                command.args[3],
+                results
+            );
             match results.len() {
                 0 => false,
                 1 => {

From 68f50c8025a61e6c27dd9d713b25d9a9e46dc98e Mon Sep 17 00:00:00 2001
From: Camelid <camelidcamel@gmail.com>
Date: Wed, 10 Mar 2021 18:28:05 -0800
Subject: [PATCH 11/17] Ignore Vim swap files

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index 3b2e8bd86a11c..3f77e6884b90f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@
 # configure your local ignore list.
 # FIXME: This needs cleanup.
 *~
+*.swp
+*.swo
 .#*
 .DS_Store
 .cproject

From 3934dd1b3e7514959202de6ca0d2636bcae21830 Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Wed, 10 Mar 2021 19:31:49 -0700
Subject: [PATCH 12/17] rustdoc: tweak the search index format

This essentially switches search-index.js from a "array of struct"
to a "struct of array" format, like this:

    {
    "doc": "Crate documentation",
    "t": [ 1, 1, 2, 3, ... ],
    "n": [ "Something", "SomethingElse", "whatever", "do_stuff", ... ],
    "q": [ "a::b", "", "", "", ... ],
    "d": [ "A Struct That Does Something", "Another Struct", "a function", "another function", ... ],
    "i": [ 0, 0, 1, 1, ... ],
    "f": [ null, null, [], [], ... ],
    "p": ...,
    "a": ...
    }

So `{ty: 1, name: "Something", path: "a::b", desc: "A Struct That Does Something", parent_idx: 0, search_type: null}` is the first item.

This makes the uncompressed version smaller, but it really shows on the
compressed version:

    notriddle:rust$ wc -c new-search-index1.52.0.js
    2622427 new-search-index1.52.0.js
    notriddle:rust$ wc -c old-search-index1.52.0.js
    2725046 old-search-index1.52.0.js
    notriddle:rust$ gzip new-search-index1.52.0.js
    notriddle:rust$ gzip old-search-index1.52.0.js
    notriddle:rust$ wc -c new-search-index1.52.0.js.gz
    239385 new-search-index1.52.0.js.gz
    notriddle:rust$ wc -c old-search-index1.52.0.js.gz
    296328 old-search-index1.52.0.js.gz
    notriddle:rust$

That's a 4% improvement on the uncompressed version (fewer `[]`),
and 20% improvement after gzipping it, thanks to putting like-typed
data next to each other. Any compression algorithm based on a sliding
window will probably show this kind of improvement.
---
 src/librustdoc/html/render/cache.rs | 60 ++++++++++++++++++++++++++---
 src/librustdoc/html/render/mod.rs   | 17 --------
 src/librustdoc/html/static/main.js  | 39 ++++++++++---------
 3 files changed, 74 insertions(+), 42 deletions(-)

diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index a21cf5266fe1f..56fee2c9fec2d 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -4,7 +4,7 @@ use std::path::Path;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{sym, Symbol};
-use serde::Serialize;
+use serde::ser::{Serialize, SerializeStruct, Serializer};
 
 use crate::clean::types::{
     FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, TypeKind, WherePredicate,
@@ -133,21 +133,69 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
         .map(|module| module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)))
         .unwrap_or_default();
 
-    #[derive(Serialize)]
     struct CrateData<'a> {
         doc: String,
-        #[serde(rename = "i")]
         items: Vec<&'a IndexItem>,
-        #[serde(rename = "p")]
         paths: Vec<(ItemType, String)>,
         // The String is alias name and the vec is the list of the elements with this alias.
         //
         // To be noted: the `usize` elements are indexes to `items`.
-        #[serde(rename = "a")]
-        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
         aliases: &'a BTreeMap<String, Vec<usize>>,
     }
 
+    impl<'a> Serialize for CrateData<'a> {
+        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            let has_aliases = !self.aliases.is_empty();
+            let mut crate_data =
+                serializer.serialize_struct("CrateData", if has_aliases { 9 } else { 8 })?;
+            crate_data.serialize_field("doc", &self.doc)?;
+            crate_data.serialize_field(
+                "t",
+                &self.items.iter().map(|item| &item.ty).collect::<Vec<_>>(),
+            )?;
+            crate_data.serialize_field(
+                "n",
+                &self.items.iter().map(|item| &item.name).collect::<Vec<_>>(),
+            )?;
+            crate_data.serialize_field(
+                "q",
+                &self.items.iter().map(|item| &item.path).collect::<Vec<_>>(),
+            )?;
+            crate_data.serialize_field(
+                "d",
+                &self.items.iter().map(|item| &item.desc).collect::<Vec<_>>(),
+            )?;
+            crate_data.serialize_field(
+                "i",
+                &self
+                    .items
+                    .iter()
+                    .map(|item| {
+                        assert_eq!(
+                            item.parent.is_some(),
+                            item.parent_idx.is_some(),
+                            "`{}` is missing idx",
+                            item.name
+                        );
+                        item.parent_idx.map(|x| x + 1).unwrap_or(0)
+                    })
+                    .collect::<Vec<_>>(),
+            )?;
+            crate_data.serialize_field(
+                "f",
+                &self.items.iter().map(|item| &item.search_type).collect::<Vec<_>>(),
+            )?;
+            crate_data.serialize_field("p", &self.paths)?;
+            if has_aliases {
+                crate_data.serialize_field("a", &self.aliases)?;
+            }
+            crate_data.end()
+        }
+    }
+
     // Collect the index into a string
     format!(
         r#""{}":{}"#,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a4621fb8ed555..66c47f14655ba 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -166,23 +166,6 @@ crate struct IndexItem {
     crate search_type: Option<IndexItemFunctionType>,
 }
 
-impl Serialize for IndexItem {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        assert_eq!(
-            self.parent.is_some(),
-            self.parent_idx.is_some(),
-            "`{}` is missing idx",
-            self.name
-        );
-
-        (self.ty, &self.name, &self.path, &self.desc, self.parent_idx, &self.search_type)
-            .serialize(serializer)
-    }
-}
-
 /// A type used for the search index.
 #[derive(Debug)]
 crate struct RenderType {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 42519d596225b..ac2da5f779bd1 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1847,13 +1847,18 @@ function defocusSearchBar() {
                 });
                 currentIndex += 1;
 
-                // an array of [(Number) item type,
-                //              (String) name,
-                //              (String) full path or empty string for previous path,
-                //              (String) description,
-                //              (Number | null) the parent path index to `paths`]
-                //              (Object | null) the type of the function (if any)
-                var items = rawSearchIndex[crate].i;
+                // an array of (Number) item types
+                var itemTypes = rawSearchIndex[crate].t;
+                // an array of (String) item names
+                var itemNames = rawSearchIndex[crate].n;
+                // an array of (String) full paths (or empty string for previous path)
+                var itemPaths = rawSearchIndex[crate].q;
+                // an array of (String) descriptions
+                var itemDescs = rawSearchIndex[crate].d;
+                // an array of (Number) the parent path index + 1 to `paths`, or 0 if none
+                var itemParentIdxs = rawSearchIndex[crate].i;
+                // an array of (Object | null) the type of the function, if any
+                var itemFunctionSearchTypes = rawSearchIndex[crate].f;
                 // an array of [(Number) item type,
                 //              (String) name]
                 var paths = rawSearchIndex[crate].p;
@@ -1867,28 +1872,24 @@ function defocusSearchBar() {
                     paths[i] = {ty: paths[i][0], name: paths[i][1]};
                 }
 
-                // convert `items` into an object form, and construct word indices.
+                // convert `item*` into an object form, and construct word indices.
                 //
                 // before any analysis is performed lets gather the search terms to
                 // search against apart from the rest of the data.  This is a quick
                 // operation that is cached for the life of the page state so that
                 // all other search operations have access to this cached data for
                 // faster analysis operations
-                len = items.length;
+                len = itemTypes.length;
                 var lastPath = "";
                 for (i = 0; i < len; ++i) {
-                    var rawRow = items[i];
-                    if (!rawRow[2]) {
-                        rawRow[2] = lastPath;
-                    }
                     var row = {
                         crate: crate,
-                        ty: rawRow[0],
-                        name: rawRow[1],
-                        path: rawRow[2],
-                        desc: rawRow[3],
-                        parent: paths[rawRow[4]],
-                        type: rawRow[5],
+                        ty: itemTypes[i],
+                        name: itemNames[i],
+                        path: itemPaths[i] ? itemPaths[i] : lastPath,
+                        desc: itemDescs[i],
+                        parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
+                        type: itemFunctionSearchTypes[i],
                     };
                     searchIndex.push(row);
                     if (typeof row.name === "string") {

From 00c08727c888e493baf2fa625970a357fe998414 Mon Sep 17 00:00:00 2001
From: hyd-dev <yd-huang@outlook.com>
Date: Thu, 11 Mar 2021 18:03:32 +0800
Subject: [PATCH 13/17] Adjust some `#[cfg]`s to take non-Unix non-Windows
 operating systems into account

---
 compiler/rustc_codegen_ssa/src/back/link.rs | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index caa6a6a8e3a26..b11821b7db0a2 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -711,7 +711,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
             status.signal() == Some(libc::SIGILL)
         }
 
-        #[cfg(windows)]
+        #[cfg(not(unix))]
         fn is_illegal_instruction(_status: &ExitStatus) -> bool {
             false
         }
@@ -1198,7 +1198,7 @@ fn exec_linker(
     flush_linked_file(&output, out_filename)?;
     return output;
 
-    #[cfg(unix)]
+    #[cfg(not(windows))]
     fn flush_linked_file(_: &io::Result<Output>, _: &Path) -> io::Result<()> {
         Ok(())
     }
@@ -1238,6 +1238,11 @@ fn exec_linker(
         err.raw_os_error() == Some(ERROR_FILENAME_EXCED_RANGE)
     }
 
+    #[cfg(not(any(unix, windows)))]
+    fn command_line_too_big(_: &io::Error) -> bool {
+        false
+    }
+
     struct Escape<'a> {
         arg: &'a str,
         is_like_msvc: bool,

From c69b108d2ab3c2b99b784590be34efcf89ec789a Mon Sep 17 00:00:00 2001
From: Oli Scherer <github35764891676564198441@oli-obk.de>
Date: Thu, 11 Mar 2021 14:56:03 +0000
Subject: [PATCH 14/17] Reintroduce accidentally deleted assertions.

These were removed in https://github.com/rust-lang/rust/pull/50198
---
 compiler/rustc_mir_build/src/thir/constant.rs | 25 +++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index 969f7d1e3a458..ac93d042970f2 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -1,3 +1,4 @@
+use rustc_apfloat::Float;
 use rustc_ast as ast;
 use rustc_middle::mir::interpret::{
     Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
@@ -61,20 +62,40 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result<ConstVa
     use rustc_apfloat::ieee::{Double, Single};
     let scalar = match fty {
         ty::FloatTy::F32 => {
-            num.parse::<f32>().map_err(|_| ())?;
+            let rust_f = num.parse::<f32>().map_err(|_| ())?;
             let mut f = num.parse::<Single>().unwrap_or_else(|e| {
                 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
             });
+            assert!(
+                u128::from(rust_f.to_bits()) == f.to_bits(),
+                "apfloat::ieee::Single gave different result for `{}`: \
+                 {}({:#x}) vs Rust's {}({:#x})",
+                rust_f,
+                f,
+                f.to_bits(),
+                Single::from_bits(rust_f.to_bits().into()),
+                rust_f.to_bits()
+            );
             if neg {
                 f = -f;
             }
             Scalar::from_f32(f)
         }
         ty::FloatTy::F64 => {
-            num.parse::<f64>().map_err(|_| ())?;
+            let rust_f = num.parse::<f64>().map_err(|_| ())?;
             let mut f = num.parse::<Double>().unwrap_or_else(|e| {
                 panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
             });
+            assert!(
+                u128::from(rust_f.to_bits()) == f.to_bits(),
+                "apfloat::ieee::Double gave different result for `{}`: \
+                 {}({:#x}) vs Rust's {}({:#x})",
+                rust_f,
+                f,
+                f.to_bits(),
+                Double::from_bits(rust_f.to_bits().into()),
+                rust_f.to_bits()
+            );
             if neg {
                 f = -f;
             }

From ae5cc8a75b78f4b3449704ce9a7d35b13a30408a Mon Sep 17 00:00:00 2001
From: Igor Matuszewski <xanewok@gmail.com>
Date: Thu, 11 Mar 2021 19:01:01 +0100
Subject: [PATCH 15/17] Update RLS

---
 src/tools/rls | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/rls b/src/tools/rls
index 3bd7215d48ba0..fd1df1554a22a 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 3bd7215d48ba05f18401cc340ae8d71af002ba6d
+Subproject commit fd1df1554a22accde727e8c4bdeb2a065627d10c

From 2a3442825335fe55ba30ef000f472bffb0ee9fe9 Mon Sep 17 00:00:00 2001
From: LeSeulArtichaut <leseulartichaut@gmail.com>
Date: Sun, 7 Mar 2021 15:09:00 +0100
Subject: [PATCH 16/17] Make THIR data structures public

---
 compiler/rustc_mir_build/src/build/mod.rs     |  3 +-
 compiler/rustc_mir_build/src/lib.rs           |  2 +-
 compiler/rustc_mir_build/src/thir/cx/mod.rs   |  2 +-
 compiler/rustc_mir_build/src/thir/mod.rs      | 79 ++++++++++---------
 .../rustc_mir_build/src/thir/pattern/mod.rs   | 38 ++++-----
 5 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b633fe32674be..9c83c0d09aa8e 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,7 +1,6 @@
 use crate::build;
 use crate::build::scope::DropKind;
-use crate::thir::cx::build_thir;
-use crate::thir::{Arena, BindingMode, Expr, LintLevel, Pat, PatKind};
+use crate::thir::{build_thir, Arena, BindingMode, Expr, LintLevel, Pat, PatKind};
 use rustc_attr::{self as attr, UnwindAttr};
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 0866892265bd9..b1591d8ba35f4 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -20,7 +20,7 @@ extern crate rustc_middle;
 
 mod build;
 mod lints;
-mod thir;
+pub mod thir;
 
 use rustc_middle::ty::query::Providers;
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 66c11ea95286d..fe8a58c008872 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -14,7 +14,7 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-crate fn build_thir<'thir, 'tcx>(
+pub fn build_thir<'thir, 'tcx>(
     tcx: TyCtxt<'tcx>,
     owner_def: ty::WithOptConstParam<LocalDefId>,
     arena: &'thir Arena<'thir, 'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs
index 27a7e99951c3b..0c9df32c18803 100644
--- a/compiler/rustc_mir_build/src/thir/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/mod.rs
@@ -18,36 +18,37 @@ use rustc_target::abi::VariantIdx;
 use rustc_target::asm::InlineAsmRegOrRegClass;
 
 crate mod constant;
+
 crate mod cx;
+pub use cx::build_thir;
 
 crate mod pattern;
-crate use self::pattern::PatTyProj;
-crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
+pub use self::pattern::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
 
 mod arena;
-crate use arena::Arena;
+pub use arena::Arena;
 
 mod util;
 
 #[derive(Copy, Clone, Debug)]
-crate enum LintLevel {
+pub enum LintLevel {
     Inherited,
     Explicit(hir::HirId),
 }
 
 #[derive(Debug)]
-crate struct Block<'thir, 'tcx> {
-    crate targeted_by_break: bool,
-    crate region_scope: region::Scope,
-    crate opt_destruction_scope: Option<region::Scope>,
-    crate span: Span,
-    crate stmts: &'thir [Stmt<'thir, 'tcx>],
-    crate expr: Option<&'thir Expr<'thir, 'tcx>>,
-    crate safety_mode: BlockSafety,
+pub struct Block<'thir, 'tcx> {
+    pub targeted_by_break: bool,
+    pub region_scope: region::Scope,
+    pub opt_destruction_scope: Option<region::Scope>,
+    pub span: Span,
+    pub stmts: &'thir [Stmt<'thir, 'tcx>],
+    pub expr: Option<&'thir Expr<'thir, 'tcx>>,
+    pub safety_mode: BlockSafety,
 }
 
 #[derive(Copy, Clone, Debug)]
-crate enum BlockSafety {
+pub enum BlockSafety {
     Safe,
     ExplicitUnsafe(hir::HirId),
     PushUnsafe,
@@ -55,13 +56,13 @@ crate enum BlockSafety {
 }
 
 #[derive(Debug)]
-crate struct Stmt<'thir, 'tcx> {
-    crate kind: StmtKind<'thir, 'tcx>,
-    crate opt_destruction_scope: Option<region::Scope>,
+pub struct Stmt<'thir, 'tcx> {
+    pub kind: StmtKind<'thir, 'tcx>,
+    pub opt_destruction_scope: Option<region::Scope>,
 }
 
 #[derive(Debug)]
-crate enum StmtKind<'thir, 'tcx> {
+pub enum StmtKind<'thir, 'tcx> {
     Expr {
         /// scope for this statement; may be used as lifetime of temporaries
         scope: region::Scope,
@@ -111,23 +112,23 @@ rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144);
 /// example, method calls and overloaded operators are absent: they are
 /// expected to be converted into `Expr::Call` instances.
 #[derive(Debug)]
-crate struct Expr<'thir, 'tcx> {
+pub struct Expr<'thir, 'tcx> {
     /// type of this expression
-    crate ty: Ty<'tcx>,
+    pub ty: Ty<'tcx>,
 
     /// lifetime of this expression if it should be spilled into a
     /// temporary; should be None only if in a constant context
-    crate temp_lifetime: Option<region::Scope>,
+    pub temp_lifetime: Option<region::Scope>,
 
     /// span of the expression in the source
-    crate span: Span,
+    pub span: Span,
 
     /// kind of expression
-    crate kind: ExprKind<'thir, 'tcx>,
+    pub kind: ExprKind<'thir, 'tcx>,
 }
 
 #[derive(Debug)]
-crate enum ExprKind<'thir, 'tcx> {
+pub enum ExprKind<'thir, 'tcx> {
     Scope {
         region_scope: region::Scope,
         lint_level: LintLevel,
@@ -316,41 +317,41 @@ crate enum ExprKind<'thir, 'tcx> {
 }
 
 #[derive(Debug)]
-crate struct FieldExpr<'thir, 'tcx> {
-    crate name: Field,
-    crate expr: &'thir Expr<'thir, 'tcx>,
+pub struct FieldExpr<'thir, 'tcx> {
+    pub name: Field,
+    pub expr: &'thir Expr<'thir, 'tcx>,
 }
 
 #[derive(Debug)]
-crate struct FruInfo<'thir, 'tcx> {
-    crate base: &'thir Expr<'thir, 'tcx>,
-    crate field_types: &'thir [Ty<'tcx>],
+pub struct FruInfo<'thir, 'tcx> {
+    pub base: &'thir Expr<'thir, 'tcx>,
+    pub field_types: &'thir [Ty<'tcx>],
 }
 
 #[derive(Debug)]
-crate struct Arm<'thir, 'tcx> {
-    crate pattern: Pat<'tcx>,
-    crate guard: Option<Guard<'thir, 'tcx>>,
-    crate body: &'thir Expr<'thir, 'tcx>,
-    crate lint_level: LintLevel,
-    crate scope: region::Scope,
-    crate span: Span,
+pub struct Arm<'thir, 'tcx> {
+    pub pattern: Pat<'tcx>,
+    pub guard: Option<Guard<'thir, 'tcx>>,
+    pub body: &'thir Expr<'thir, 'tcx>,
+    pub lint_level: LintLevel,
+    pub scope: region::Scope,
+    pub span: Span,
 }
 
 #[derive(Debug)]
-crate enum Guard<'thir, 'tcx> {
+pub enum Guard<'thir, 'tcx> {
     If(&'thir Expr<'thir, 'tcx>),
     IfLet(Pat<'tcx>, &'thir Expr<'thir, 'tcx>),
 }
 
 #[derive(Copy, Clone, Debug)]
-crate enum LogicalOp {
+pub enum LogicalOp {
     And,
     Or,
 }
 
 #[derive(Debug)]
-crate enum InlineAsmOperand<'thir, 'tcx> {
+pub enum InlineAsmOperand<'thir, 'tcx> {
     In {
         reg: InlineAsmRegOrRegClass,
         expr: &'thir Expr<'thir, 'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 6e29e60b3034d..9ac79a37ac690 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -40,22 +40,22 @@ crate enum PatternError {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-crate enum BindingMode {
+pub enum BindingMode {
     ByValue,
     ByRef(BorrowKind),
 }
 
 #[derive(Clone, Debug, PartialEq)]
-crate struct FieldPat<'tcx> {
-    crate field: Field,
-    crate pattern: Pat<'tcx>,
+pub struct FieldPat<'tcx> {
+    pub field: Field,
+    pub pattern: Pat<'tcx>,
 }
 
 #[derive(Clone, Debug, PartialEq)]
-crate struct Pat<'tcx> {
-    crate ty: Ty<'tcx>,
-    crate span: Span,
-    crate kind: Box<PatKind<'tcx>>,
+pub struct Pat<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub span: Span,
+    pub kind: Box<PatKind<'tcx>>,
 }
 
 impl<'tcx> Pat<'tcx> {
@@ -65,8 +65,8 @@ impl<'tcx> Pat<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-crate struct PatTyProj<'tcx> {
-    crate user_ty: CanonicalUserType<'tcx>,
+pub struct PatTyProj<'tcx> {
+    pub user_ty: CanonicalUserType<'tcx>,
 }
 
 impl<'tcx> PatTyProj<'tcx> {
@@ -92,8 +92,8 @@ impl<'tcx> PatTyProj<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-crate struct Ascription<'tcx> {
-    crate user_ty: PatTyProj<'tcx>,
+pub struct Ascription<'tcx> {
+    pub user_ty: PatTyProj<'tcx>,
     /// Variance to use when relating the type `user_ty` to the **type of the value being
     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
     /// have a type that is some subtype of the ascribed type.
@@ -112,12 +112,12 @@ crate struct Ascription<'tcx> {
     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
     /// of the old type-check for now. See #57280 for details.
-    crate variance: ty::Variance,
-    crate user_ty_span: Span,
+    pub variance: ty::Variance,
+    pub user_ty_span: Span,
 }
 
 #[derive(Clone, Debug, PartialEq)]
-crate enum PatKind<'tcx> {
+pub enum PatKind<'tcx> {
     Wild,
 
     AscribeUserType {
@@ -195,10 +195,10 @@ crate enum PatKind<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-crate struct PatRange<'tcx> {
-    crate lo: &'tcx ty::Const<'tcx>,
-    crate hi: &'tcx ty::Const<'tcx>,
-    crate end: RangeEnd,
+pub struct PatRange<'tcx> {
+    pub lo: &'tcx ty::Const<'tcx>,
+    pub hi: &'tcx ty::Const<'tcx>,
+    pub end: RangeEnd,
 }
 
 impl<'tcx> fmt::Display for Pat<'tcx> {

From 6bf41476465278b82ad875ee15d88f371e51b1dc Mon Sep 17 00:00:00 2001
From: LeSeulArtichaut <leseulartichaut@gmail.com>
Date: Sun, 7 Mar 2021 15:09:39 +0100
Subject: [PATCH 17/17] Add `-Z unpretty` flag for the THIR

---
 Cargo.lock                           |  2 ++
 compiler/rustc_driver/Cargo.toml     |  2 ++
 compiler/rustc_driver/src/pretty.rs  | 17 +++++++++++++++++
 compiler/rustc_session/src/config.rs |  4 ++++
 4 files changed, 25 insertions(+)

diff --git a/Cargo.lock b/Cargo.lock
index 25039b5cbd92a..2c9eaebb5fdc2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3870,6 +3870,7 @@ dependencies = [
  "rustc_metadata",
  "rustc_middle",
  "rustc_mir",
+ "rustc_mir_build",
  "rustc_parse",
  "rustc_plugin_impl",
  "rustc_save_analysis",
@@ -3877,6 +3878,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_typeck",
  "tracing",
  "tracing-subscriber",
  "tracing-tree",
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index 93c6ec04e4fd6..c521f2041d891 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -34,6 +34,8 @@ rustc_interface = { path = "../rustc_interface" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
+rustc_mir_build = { path = "../rustc_mir_build" }
+rustc_typeck = { path = "../rustc_typeck" }
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index 38c493a920d26..5512bd74453e5 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -9,12 +9,14 @@ use rustc_hir_pretty as pprust_hir;
 use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_mir::util::{write_mir_graphviz, write_mir_pretty};
+use rustc_mir_build::thir;
 use rustc_session::config::{Input, PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::FileName;
 
 use std::cell::Cell;
+use std::fmt::Write;
 use std::path::Path;
 
 pub use self::PpMode::*;
@@ -469,6 +471,21 @@ pub fn print_after_hir_lowering<'tcx>(
             format!("{:#?}", krate)
         }),
 
+        ThirTree => {
+            let mut out = String::new();
+            abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess);
+            debug!("pretty printing THIR tree");
+            for did in tcx.body_owners() {
+                let hir = tcx.hir();
+                let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(did)));
+                let arena = thir::Arena::default();
+                let thir =
+                    thir::build_thir(tcx, ty::WithOptConstParam::unknown(did), &arena, &body.value);
+                let _ = writeln!(out, "{:?}:\n{:#?}\n", did, thir);
+            }
+            out
+        }
+
         _ => unreachable!(),
     };
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index f25828e21618f..c1be90efc7299 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2074,6 +2074,7 @@ fn parse_pretty(
             ("hir,identified", true) => Hir(PpHirMode::Identified),
             ("hir,typed", true) => Hir(PpHirMode::Typed),
             ("hir-tree", true) => HirTree,
+            ("thir-tree", true) => ThirTree,
             ("mir", true) => Mir,
             ("mir-cfg", true) => MirCFG,
             _ => {
@@ -2265,6 +2266,8 @@ pub enum PpMode {
     Hir(PpHirMode),
     /// `-Zunpretty=hir-tree`
     HirTree,
+    /// `-Zunpretty=thir-tree`
+    ThirTree,
     /// `-Zunpretty=mir`
     Mir,
     /// `-Zunpretty=mir-cfg`
@@ -2282,6 +2285,7 @@ impl PpMode {
             | AstTree(PpAstTreeMode::Expanded)
             | Hir(_)
             | HirTree
+            | ThirTree
             | Mir
             | MirCFG => true,
         }