From 0065e33c24213c538ffd76b0cc771e4668819969 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Tue, 8 Sep 2020 11:32:25 +0200
Subject: [PATCH 01/13] rustbuild: don't set PYTHON_EXECUTABLE and WITH_POLLY
 cmake vars since they are no longer supported by llvm

CMake Warning:
  Manually-specified variables were not used by the project:

    PYTHON_EXECUTABLE
    WITH_POLLY
---
 src/bootstrap/native.rs | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index a0c79e38f9d8c..6cd850bc0bfaa 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -169,7 +169,6 @@ impl Step for Llvm {
             .define("LLVM_INCLUDE_TESTS", "OFF")
             .define("LLVM_INCLUDE_DOCS", "OFF")
             .define("LLVM_INCLUDE_BENCHMARKS", "OFF")
-            .define("WITH_POLLY", "OFF")
             .define("LLVM_ENABLE_TERMINFO", "OFF")
             .define("LLVM_ENABLE_LIBEDIT", "OFF")
             .define("LLVM_ENABLE_BINDINGS", "OFF")
@@ -305,10 +304,6 @@ impl Step for Llvm {
             cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES");
         }
 
-        if let Some(ref python) = builder.config.python {
-            cfg.define("PYTHON_EXECUTABLE", python);
-        }
-
         configure_cmake(builder, target, &mut cfg, true);
 
         // FIXME: we don't actually need to build all LLVM tools and all LLVM

From 325acefee485d93c29da6e5641e823dd1d7de059 Mon Sep 17 00:00:00 2001
From: Camelid <camelidcamel@gmail.com>
Date: Tue, 8 Sep 2020 14:36:36 -0700
Subject: [PATCH 02/13] Use intra-doc links in `core::ptr`

The only link that I did not change is a link to a function on the
`pointer` primitive because intra-doc links for the `pointer` primitive
don't work yet (see #63351).
---
 library/core/src/ptr/mod.rs | 77 ++++++++++---------------------------
 1 file changed, 21 insertions(+), 56 deletions(-)

diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 68b5d1df71cb2..219835bfae0f9 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -54,16 +54,9 @@
 //! [aliasing]: ../../nomicon/aliasing.html
 //! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
 //! [ub]: ../../reference/behavior-considered-undefined.html
-//! [null]: ./fn.null.html
 //! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts
-//! [atomic operations]: ../../std/sync/atomic/index.html
-//! [`copy`]: ../../std/ptr/fn.copy.html
+//! [atomic operations]: crate::sync::atomic
 //! [`offset`]: ../../std/primitive.pointer.html#method.offset
-//! [`read_unaligned`]: ./fn.read_unaligned.html
-//! [`write_unaligned`]: ./fn.write_unaligned.html
-//! [`read_volatile`]: ./fn.read_volatile.html
-//! [`write_volatile`]: ./fn.write_volatile.html
-//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -118,9 +111,9 @@ mod mut_ptr;
 /// done automatically by the compiler. This means the fields of packed structs
 /// are not dropped in-place.
 ///
-/// [`ptr::read`]: ../ptr/fn.read.html
-/// [`ptr::read_unaligned`]: ../ptr/fn.read_unaligned.html
-/// [pinned]: ../pin/index.html
+/// [`ptr::read`]: self::read
+/// [`ptr::read_unaligned`]: self::read_unaligned
+/// [pinned]: crate::pin
 ///
 /// # Safety
 ///
@@ -141,9 +134,7 @@ mod mut_ptr;
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`write`]: ../ptr/fn.write.html
+/// [valid]: #safety
 ///
 /// # Examples
 ///
@@ -243,9 +234,9 @@ pub(crate) struct FatPtr<T> {
 /// The `len` argument is the number of **elements**, not the number of bytes.
 ///
 /// This function is safe, but actually using the return value is unsafe.
-/// See the documentation of [`from_raw_parts`] for slice safety requirements.
+/// See the documentation of [`slice::from_raw_parts`] for slice safety requirements.
 ///
-/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html
+/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
 ///
 /// # Examples
 ///
@@ -274,10 +265,9 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
 /// See the documentation of [`slice_from_raw_parts`] for more details.
 ///
 /// This function is safe, but actually using the return value is unsafe.
-/// See the documentation of [`from_raw_parts_mut`] for slice safety requirements.
+/// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements.
 ///
-/// [`slice_from_raw_parts`]: fn.slice_from_raw_parts.html
-/// [`from_raw_parts_mut`]: ../../std/slice/fn.from_raw_parts_mut.html
+/// [`slice::from_raw_parts_mut`]: crate::slice::from_raw_parts_mut
 ///
 /// # Examples
 ///
@@ -316,8 +306,6 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
 ///   overlapping region of memory from `x` will be used. This is demonstrated
 ///   in the second example below.
 ///
-/// [`mem::swap`]: ../mem/fn.swap.html
-///
 /// # Safety
 ///
 /// Behavior is undefined if any of the following conditions are violated:
@@ -328,7 +316,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
 ///
 /// Note that even if `T` has size `0`, the pointers must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
+/// [valid]: #safety
 ///
 /// # Examples
 ///
@@ -406,7 +394,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is `0`,
 /// the pointers must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
+/// [valid]: #safety
 ///
 /// # Examples
 ///
@@ -533,8 +521,6 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
 /// operates on raw pointers instead of references. When references are
 /// available, [`mem::replace`] should be preferred.
 ///
-/// [`mem::replace`]: ../mem/fn.replace.html
-///
 /// # Safety
 ///
 /// Behavior is undefined if any of the following conditions are violated:
@@ -547,7 +533,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
+/// [valid]: #safety
 ///
 /// # Examples
 ///
@@ -682,11 +668,7 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
 /// assert_eq!(s, "bar");
 /// ```
 ///
-/// [`mem::swap`]: ../mem/fn.swap.html
-/// [valid]: ../ptr/index.html#safety
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read_unaligned`]: ./fn.read_unaligned.html
-/// [`write`]: ./fn.write.html
+/// [valid]: #safety
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn read<T>(src: *const T) -> T {
@@ -723,11 +705,8 @@ pub unsafe fn read<T>(src: *const T) -> T {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL.
 ///
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read`]: ./fn.read.html
-/// [`write_unaligned`]: ./fn.write_unaligned.html
-/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
-/// [valid]: ../ptr/index.html#safety
+/// [read-ownership]: read#ownership-of-the-returned-value
+/// [valid]: #safety
 ///
 /// ## On `packed` structs
 ///
@@ -819,8 +798,6 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
 /// This is appropriate for initializing uninitialized memory, or overwriting
 /// memory that has previously been [`read`] from.
 ///
-/// [`read`]: ./fn.read.html
-///
 /// # Safety
 ///
 /// Behavior is undefined if any of the following conditions are violated:
@@ -832,8 +809,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
-/// [`write_unaligned`]: ./fn.write_unaligned.html
+/// [valid]: #safety
 ///
 /// # Examples
 ///
@@ -888,8 +864,6 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
 /// assert_eq!(foo, "bar");
 /// assert_eq!(bar, "foo");
 /// ```
-///
-/// [`mem::swap`]: ../mem/fn.swap.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn write<T>(dst: *mut T, src: T) {
@@ -916,9 +890,6 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 /// This is appropriate for initializing uninitialized memory, or overwriting
 /// memory that has previously been read with [`read_unaligned`].
 ///
-/// [`write`]: ./fn.write.html
-/// [`read_unaligned`]: ./fn.read_unaligned.html
-///
 /// # Safety
 ///
 /// Behavior is undefined if any of the following conditions are violated:
@@ -927,7 +898,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL.
 ///
-/// [valid]: ../ptr/index.html#safety
+/// [valid]: #safety
 ///
 /// ## On `packed` structs
 ///
@@ -1007,8 +978,6 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 /// to not be elided or reordered by the compiler across other volatile
 /// operations.
 ///
-/// [`write_volatile`]: ./fn.write_volatile.html
-///
 /// # Notes
 ///
 /// Rust does not currently have a rigorously and formally defined memory model,
@@ -1041,10 +1010,8 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read`]: ./fn.read.html
-/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
+/// [valid]: #safety
+/// [read-ownership]: read#ownership-of-the-returned-value
 ///
 /// Just like in C, whether an operation is volatile has no bearing whatsoever
 /// on questions involving concurrent access from multiple threads. Volatile
@@ -1089,8 +1056,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 /// Additionally, it does not drop `src`. Semantically, `src` is moved into the
 /// location pointed to by `dst`.
 ///
-/// [`read_volatile`]: ./fn.read_volatile.html
-///
 /// # Notes
 ///
 /// Rust does not currently have a rigorously and formally defined memory model,
@@ -1115,12 +1080,12 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
+/// [valid]: #safety
 ///
 /// Just like in C, whether an operation is volatile has no bearing whatsoever
 /// on questions involving concurrent access from multiple threads. Volatile
 /// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a `write_volatile` and any other operation (reading or writing)
+/// a race between a [`write_volatile`] and any other operation (reading or writing)
 /// on the same location is undefined behavior.
 ///
 /// # Examples

From c19b2370e419c0be7b46cc9ae7767773560a072c Mon Sep 17 00:00:00 2001
From: Rich Kadel <richkadel@google.com>
Date: Tue, 8 Sep 2020 16:08:35 -0700
Subject: [PATCH 03/13] Add -Zgraphviz_dark_mode

Many developers use a dark theme with editors and IDEs, but this
typically doesn't extend to graphviz output.

When I bring up a MIR graphviz document, the white background is
strikingly bright. This new option changes the colors used for graphviz
output to work better in dark-themed UIs.
---
 compiler/rustc_graphviz/src/lib.rs            | 20 +++++++++++--
 .../src/dataflow/framework/engine.rs          |  6 +++-
 compiler/rustc_mir/src/util/graphviz.rs       | 29 ++++++++++++++-----
 compiler/rustc_session/src/options.rs         |  2 ++
 4 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index 4339092b63e85..252e341686541 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -599,6 +599,7 @@ pub enum RenderOption {
     NoNodeStyles,
 
     Monospace,
+    DarkTheme,
 }
 
 /// Returns vec holding all the default render options.
@@ -630,10 +631,23 @@ where
     writeln!(w, "digraph {} {{", g.graph_id().as_slice())?;
 
     // Global graph properties
+    let mut graph_attrs = Vec::new();
+    let mut content_attrs = Vec::new();
     if options.contains(&RenderOption::Monospace) {
-        writeln!(w, r#"    graph[fontname="monospace"];"#)?;
-        writeln!(w, r#"    node[fontname="monospace"];"#)?;
-        writeln!(w, r#"    edge[fontname="monospace"];"#)?;
+        let font = r#"fontname="monospace""#;
+        graph_attrs.push(font);
+        content_attrs.push(font);
+    };
+    if options.contains(&RenderOption::DarkTheme) {
+        graph_attrs.push(r#"bgcolor="black""#);
+        content_attrs.push(r#"color="white""#);
+        content_attrs.push(r#"fontcolor="white""#);
+    }
+    if !(graph_attrs.is_empty() && content_attrs.is_empty()) {
+        writeln!(w, r#"    graph[{}];"#, graph_attrs.join(" "))?;
+        let content_attrs_str = content_attrs.join(" ");
+        writeln!(w, r#"    node[{}];"#, content_attrs_str)?;
+        writeln!(w, r#"    edge[{}];"#, content_attrs_str)?;
     }
 
     for n in g.nodes().iter() {
diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir/src/dataflow/framework/engine.rs
index d3ad42f6bbcce..0b5b437d186aa 100644
--- a/compiler/rustc_mir/src/dataflow/framework/engine.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/engine.rs
@@ -306,7 +306,11 @@ where
     let mut buf = Vec::new();
 
     let graphviz = graphviz::Formatter::new(body, def_id, results, style);
-    dot::render_opts(&graphviz, &mut buf, &[dot::RenderOption::Monospace])?;
+    let mut render_opts = vec![dot::RenderOption::Monospace];
+    if tcx.sess.opts.debugging_opts.graphviz_dark_mode {
+        render_opts.push(dot::RenderOption::DarkTheme);
+    }
+    dot::render_opts(&graphviz, &mut buf, &render_opts)?;
 
     if let Some(parent) = path.parent() {
         fs::create_dir_all(parent)?;
diff --git a/compiler/rustc_mir/src/util/graphviz.rs b/compiler/rustc_mir/src/util/graphviz.rs
index 50193c4a0db7d..bc1e3fa8b2915 100644
--- a/compiler/rustc_mir/src/util/graphviz.rs
+++ b/compiler/rustc_mir/src/util/graphviz.rs
@@ -55,16 +55,28 @@ where
     writeln!(w, "{} {}Mir_{} {{", kind, cluster, def_name)?;
 
     // Global graph properties
-    writeln!(w, r#"    graph [fontname="monospace"];"#)?;
-    writeln!(w, r#"    node [fontname="monospace"];"#)?;
-    writeln!(w, r#"    edge [fontname="monospace"];"#)?;
+    let font = r#"fontname="monospace""#;
+    let mut graph_attrs = vec![font];
+    let mut content_attrs = vec![font];
+
+    let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
+    if dark_mode {
+        graph_attrs.push(r#"bgcolor="black""#);
+        content_attrs.push(r#"color="white""#);
+        content_attrs.push(r#"fontcolor="white""#);
+    }
+
+    writeln!(w, r#"    graph [{}];"#, graph_attrs.join(" "))?;
+    let content_attrs_str = content_attrs.join(" ");
+    writeln!(w, r#"    node [{}];"#, content_attrs_str)?;
+    writeln!(w, r#"    edge [{}];"#, content_attrs_str)?;
 
     // Graph label
     write_graph_label(tcx, def_id, body, w)?;
 
     // Nodes
     for (block, _) in body.basic_blocks().iter_enumerated() {
-        write_node(def_id, block, body, w)?;
+        write_node(def_id, block, body, dark_mode, w)?;
     }
 
     // Edges
@@ -84,6 +96,7 @@ where
 pub fn write_node_label<W: Write, INIT, FINI>(
     block: BasicBlock,
     body: &Body<'_>,
+    dark_mode: bool,
     w: &mut W,
     num_cols: u32,
     init: INIT,
@@ -100,8 +113,9 @@ where
     // Basic block number at the top.
     write!(
         w,
-        r#"<tr><td {attrs} colspan="{colspan}">{blk}</td></tr>"#,
-        attrs = r#"bgcolor="gray" align="center""#,
+        r#"<tr><td bgcolor="{bgcolor}" {attrs} colspan="{colspan}">{blk}</td></tr>"#,
+        bgcolor = if dark_mode { "dimgray" } else { "gray" },
+        attrs = r#"align="center""#,
         colspan = num_cols,
         blk = block.index()
     )?;
@@ -134,11 +148,12 @@ fn write_node<W: Write>(
     def_id: DefId,
     block: BasicBlock,
     body: &Body<'_>,
+    dark_mode: bool,
     w: &mut W,
 ) -> io::Result<()> {
     // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
     write!(w, r#"    {} [shape="none", label=<"#, node(def_id, block))?;
-    write_node_label(block, body, w, 1, |_| Ok(()), |_| Ok(()))?;
+    write_node_label(block, body, dark_mode, w, 1, |_| Ok(()), |_| Ok(()))?;
     // Close the node label and the node itself.
     writeln!(w, ">];")
 }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index ad36fa7698621..f31e0431d0da7 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -907,6 +907,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "force all crates to be `rustc_private` unstable (default: no)"),
     fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
         "set the optimization fuel quota for a crate"),
+    graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED],
+        "use dark-themed colors in graphviz output (default: no)"),
     hir_stats: bool = (false, parse_bool, [UNTRACKED],
         "print some statistics about AST and HIR (default: no)"),
     human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],

From 15ccdeb2248f697c3873a60eea538110ed5b2f8f Mon Sep 17 00:00:00 2001
From: Matt Brubeck <mbrubeck@limpet.net>
Date: Thu, 3 Sep 2020 13:32:53 -0700
Subject: [PATCH 04/13] Update to hashbrown 0.9

---
 Cargo.lock                              |  9 ++++-----
 library/std/Cargo.toml                  |  2 +-
 library/std/src/collections/hash/map.rs | 10 +++++-----
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8deab1deee0d6..b687e714d4fa2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1259,11 +1259,10 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.8.2"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
+checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7"
 dependencies = [
- "autocfg",
  "compiler_builtins",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
@@ -1401,9 +1400,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.5.1"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9"
+checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
 dependencies = [
  "autocfg",
  "hashbrown",
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 9cc6928708008..bfd05db6b1bbe 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -20,7 +20,7 @@ libc = { version = "0.2.74", default-features = false, features = ['rustc-dep-of
 compiler_builtins = { version = "0.1.35" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
-hashbrown = { version = "0.8.1", default-features = false, features = ['rustc-dep-of-std'] }
+hashbrown = { version = "0.9.0", default-features = false, features = ['rustc-dep-of-std'] }
 
 # Dependencies of the `backtrace` crate
 addr2line = { version = "0.13.0", optional = true, default-features = false }
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 57cb179a4244a..56176bc5856f3 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1247,7 +1247,7 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
     /// An occupied entry.
-    Occupied(RawOccupiedEntryMut<'a, K, V>),
+    Occupied(RawOccupiedEntryMut<'a, K, V, S>),
     /// A vacant entry.
     Vacant(RawVacantEntryMut<'a, K, V, S>),
 }
@@ -1255,8 +1255,8 @@ pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
 /// A view into an occupied entry in a `HashMap`.
 /// It is part of the [`RawEntryMut`] enum.
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
-pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> {
-    base: base::RawOccupiedEntryMut<'a, K, V>,
+pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a, S: 'a> {
+    base: base::RawOccupiedEntryMut<'a, K, V, S>,
 }
 
 /// A view into a vacant entry in a `HashMap`.
@@ -1457,7 +1457,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
     }
 }
 
-impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> {
+impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> {
     /// Gets a reference to the key in the entry.
     #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
@@ -1597,7 +1597,7 @@ impl<K: Debug, V: Debug, S> Debug for RawEntryMut<'_, K, V, S> {
 }
 
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
-impl<K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'_, K, V> {
+impl<K: Debug, V: Debug, S> Debug for RawOccupiedEntryMut<'_, K, V, S> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RawOccupiedEntryMut")
             .field("key", self.key())

From ebd15e790aceeaacb01bdd5c4361c5b4be2db237 Mon Sep 17 00:00:00 2001
From: Matt Brubeck <mbrubeck@limpet.net>
Date: Mon, 10 Aug 2020 16:19:54 -0700
Subject: [PATCH 05/13] Implement HashSet in terms of hashbrown::HashSet

---
 library/std/src/collections/hash/map.rs |   2 +-
 library/std/src/collections/hash/set.rs | 109 +++++++++++-------------
 src/etc/gdb_lookup.py                   |   4 +-
 src/etc/gdb_providers.py                |  14 ++-
 src/etc/lldb_lookup.py                  |   2 +-
 src/etc/lldb_providers.py               |  13 ++-
 src/etc/natvis/libstd.natvis            |  18 ++--
 7 files changed, 90 insertions(+), 72 deletions(-)

diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 56176bc5856f3..fc0175332a769 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2698,7 +2698,7 @@ fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K,
 }
 
 #[inline]
-fn map_try_reserve_error(err: hashbrown::TryReserveError) -> TryReserveError {
+pub(super) fn map_try_reserve_error(err: hashbrown::TryReserveError) -> TryReserveError {
     match err {
         hashbrown::TryReserveError::CapacityOverflow => TryReserveError::CapacityOverflow,
         hashbrown::TryReserveError::AllocError { layout } => {
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 8c39725ef3550..f9bc2e933dcf9 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -1,6 +1,8 @@
 #[cfg(test)]
 mod tests;
 
+use hashbrown::hash_set as base;
+
 use crate::borrow::Borrow;
 use crate::collections::TryReserveError;
 use crate::fmt;
@@ -8,7 +10,7 @@ use crate::hash::{BuildHasher, Hash};
 use crate::iter::{Chain, FromIterator, FusedIterator};
 use crate::ops::{BitAnd, BitOr, BitXor, Sub};
 
-use super::map::{self, HashMap, Keys, RandomState};
+use super::map::{map_try_reserve_error, RandomState};
 
 // Future Optimization (FIXME!)
 // ============================
@@ -101,13 +103,14 @@ use super::map::{self, HashMap, Keys, RandomState};
 /// // use the values stored in the set
 /// ```
 ///
+/// [`HashMap`]: crate::collections::HashMap
 /// [`RefCell`]: crate::cell::RefCell
 /// [`Cell`]: crate::cell::Cell
 #[derive(Clone)]
 #[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashSet<T, S = RandomState> {
-    map: HashMap<T, (), S>,
+    base: base::HashSet<T, S>,
 }
 
 impl<T> HashSet<T, RandomState> {
@@ -125,7 +128,7 @@ impl<T> HashSet<T, RandomState> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> HashSet<T, RandomState> {
-        HashSet { map: HashMap::new() }
+        Default::default()
     }
 
     /// Creates an empty `HashSet` with the specified capacity.
@@ -143,7 +146,7 @@ impl<T> HashSet<T, RandomState> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize) -> HashSet<T, RandomState> {
-        HashSet { map: HashMap::with_capacity(capacity) }
+        HashSet { base: base::HashSet::with_capacity_and_hasher(capacity, Default::default()) }
     }
 }
 
@@ -160,7 +163,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> usize {
-        self.map.capacity()
+        self.base.capacity()
     }
 
     /// An iterator visiting all elements in arbitrary order.
@@ -182,7 +185,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<'_, T> {
-        Iter { iter: self.map.keys() }
+        Iter { base: self.base.iter() }
     }
 
     /// Returns the number of elements in the set.
@@ -200,7 +203,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
-        self.map.len()
+        self.base.len()
     }
 
     /// Returns `true` if the set contains no elements.
@@ -218,7 +221,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
-        self.map.is_empty()
+        self.base.is_empty()
     }
 
     /// Clears the set, returning all elements in an iterator.
@@ -241,7 +244,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain(&mut self) -> Drain<'_, T> {
-        Drain { iter: self.map.drain() }
+        Drain { base: self.base.drain() }
     }
 
     /// Clears the set, removing all values.
@@ -259,7 +262,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
-        self.map.clear()
+        self.base.clear()
     }
 
     /// Creates a new empty hash set which will use the given hasher to hash
@@ -288,7 +291,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_hasher(hasher: S) -> HashSet<T, S> {
-        HashSet { map: HashMap::with_hasher(hasher) }
+        HashSet { base: base::HashSet::with_hasher(hasher) }
     }
 
     /// Creates an empty `HashSet` with the specified capacity, using
@@ -318,7 +321,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S> {
-        HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
+        HashSet { base: base::HashSet::with_capacity_and_hasher(capacity, hasher) }
     }
 
     /// Returns a reference to the set's [`BuildHasher`].
@@ -336,7 +339,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
     pub fn hasher(&self) -> &S {
-        self.map.hasher()
+        self.base.hasher()
     }
 }
 
@@ -364,7 +367,7 @@ where
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: usize) {
-        self.map.reserve(additional)
+        self.base.reserve(additional)
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
@@ -387,7 +390,7 @@ where
     #[inline]
     #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
-        self.map.try_reserve(additional)
+        self.base.try_reserve(additional).map_err(map_try_reserve_error)
     }
 
     /// Shrinks the capacity of the set as much as possible. It will drop
@@ -409,7 +412,7 @@ where
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
-        self.map.shrink_to_fit()
+        self.base.shrink_to_fit()
     }
 
     /// Shrinks the capacity of the set with a lower limit. It will drop
@@ -437,7 +440,7 @@ where
     #[inline]
     #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
     pub fn shrink_to(&mut self, min_capacity: usize) {
-        self.map.shrink_to(min_capacity)
+        self.base.shrink_to(min_capacity)
     }
 
     /// Visits the values representing the difference,
@@ -577,7 +580,7 @@ where
         T: Borrow<Q>,
         Q: Hash + Eq,
     {
-        self.map.contains_key(value)
+        self.base.contains(value)
     }
 
     /// Returns a reference to the value in the set, if any, that is equal to the given value.
@@ -602,7 +605,7 @@ where
         T: Borrow<Q>,
         Q: Hash + Eq,
     {
-        self.map.get_key_value(value).map(|(k, _)| k)
+        self.base.get(value)
     }
 
     /// Inserts the given `value` into the set if it is not present, then
@@ -626,7 +629,7 @@ where
     pub fn get_or_insert(&mut self, value: T) -> &T {
         // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
         // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
-        self.map.raw_entry_mut().from_key(&value).or_insert(value, ()).0
+        self.base.get_or_insert(value)
     }
 
     /// Inserts an owned copy of the given `value` into the set if it is not
@@ -658,7 +661,7 @@ where
     {
         // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
         // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
-        self.map.raw_entry_mut().from_key(value).or_insert_with(|| (value.to_owned(), ())).0
+        self.base.get_or_insert_owned(value)
     }
 
     /// Inserts a value computed from `f` into the set if the given `value` is
@@ -691,7 +694,7 @@ where
     {
         // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
         // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
-        self.map.raw_entry_mut().from_key(value).or_insert_with(|| (f(value), ())).0
+        self.base.get_or_insert_with(value, f)
     }
 
     /// Returns `true` if `self` has no elements in common with `other`.
@@ -788,7 +791,7 @@ where
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, value: T) -> bool {
-        self.map.insert(value, ()).is_none()
+        self.base.insert(value)
     }
 
     /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
@@ -809,13 +812,7 @@ where
     #[inline]
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn replace(&mut self, value: T) -> Option<T> {
-        match self.map.entry(value) {
-            map::Entry::Occupied(occupied) => Some(occupied.replace_key()),
-            map::Entry::Vacant(vacant) => {
-                vacant.insert(());
-                None
-            }
-        }
+        self.base.replace(value)
     }
 
     /// Removes a value from the set. Returns whether the value was
@@ -843,7 +840,7 @@ where
         T: Borrow<Q>,
         Q: Hash + Eq,
     {
-        self.map.remove(value).is_some()
+        self.base.remove(value)
     }
 
     /// Removes and returns the value in the set, if any, that is equal to the given one.
@@ -868,7 +865,7 @@ where
         T: Borrow<Q>,
         Q: Hash + Eq,
     {
-        self.map.remove_entry(value).map(|(k, _)| k)
+        self.base.take(value)
     }
 
     /// Retains only the elements specified by the predicate.
@@ -886,11 +883,11 @@ where
     /// assert_eq!(set.len(), 3);
     /// ```
     #[stable(feature = "retain_hash_collection", since = "1.18.0")]
-    pub fn retain<F>(&mut self, mut f: F)
+    pub fn retain<F>(&mut self, f: F)
     where
         F: FnMut(&T) -> bool,
     {
-        self.map.retain(|k, _| f(k));
+        self.base.retain(f)
     }
 }
 
@@ -949,17 +946,17 @@ where
 {
     #[inline]
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
-        self.map.extend(iter.into_iter().map(|k| (k, ())));
+        self.base.extend(iter);
     }
 
     #[inline]
     fn extend_one(&mut self, item: T) {
-        self.map.insert(item, ());
+        self.base.insert(item);
     }
 
     #[inline]
     fn extend_reserve(&mut self, additional: usize) {
-        self.map.extend_reserve(additional);
+        self.base.extend_reserve(additional);
     }
 }
 
@@ -976,7 +973,7 @@ where
 
     #[inline]
     fn extend_one(&mut self, &item: &'a T) {
-        self.map.insert(item, ());
+        self.base.insert(item);
     }
 
     #[inline]
@@ -993,7 +990,7 @@ where
     /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
     #[inline]
     fn default() -> HashSet<T, S> {
-        HashSet { map: HashMap::default() }
+        HashSet { base: Default::default() }
     }
 }
 
@@ -1137,7 +1134,7 @@ where
 /// [`iter`]: HashSet::iter
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a> {
-    iter: Keys<'a, K, ()>,
+    base: base::Iter<'a, K>,
 }
 
 /// An owning iterator over the items of a `HashSet`.
@@ -1148,7 +1145,7 @@ pub struct Iter<'a, K: 'a> {
 /// [`into_iter`]: IntoIterator::into_iter
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K> {
-    iter: map::IntoIter<K, ()>,
+    base: base::IntoIter<K>,
 }
 
 /// A draining iterator over the items of a `HashSet`.
@@ -1159,7 +1156,7 @@ pub struct IntoIter<K> {
 /// [`drain`]: HashSet::drain
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Drain<'a, K: 'a> {
-    iter: map::Drain<'a, K, ()>,
+    base: base::Drain<'a, K>,
 }
 
 /// A lazy iterator producing elements in the intersection of `HashSet`s.
@@ -1250,7 +1247,7 @@ impl<T, S> IntoIterator for HashSet<T, S> {
     /// ```
     #[inline]
     fn into_iter(self) -> IntoIter<T> {
-        IntoIter { iter: self.map.into_iter() }
+        IntoIter { base: self.base.into_iter() }
     }
 }
 
@@ -1258,7 +1255,7 @@ impl<T, S> IntoIterator for HashSet<T, S> {
 impl<K> Clone for Iter<'_, K> {
     #[inline]
     fn clone(&self) -> Self {
-        Iter { iter: self.iter.clone() }
+        Iter { base: self.base.clone() }
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1267,18 +1264,18 @@ impl<'a, K> Iterator for Iter<'a, K> {
 
     #[inline]
     fn next(&mut self) -> Option<&'a K> {
-        self.iter.next()
+        self.base.next()
     }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
+        self.base.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for Iter<'_, K> {
     #[inline]
     fn len(&self) -> usize {
-        self.iter.len()
+        self.base.len()
     }
 }
 #[stable(feature = "fused", since = "1.26.0")]
@@ -1297,18 +1294,18 @@ impl<K> Iterator for IntoIter<K> {
 
     #[inline]
     fn next(&mut self) -> Option<K> {
-        self.iter.next().map(|(k, _)| k)
+        self.base.next()
     }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
+        self.base.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for IntoIter<K> {
     #[inline]
     fn len(&self) -> usize {
-        self.iter.len()
+        self.base.len()
     }
 }
 #[stable(feature = "fused", since = "1.26.0")]
@@ -1317,8 +1314,7 @@ impl<K> FusedIterator for IntoIter<K> {}
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let entries_iter = self.iter.iter().map(|(k, _)| k);
-        f.debug_list().entries(entries_iter).finish()
+        fmt::Debug::fmt(&self.base, f)
     }
 }
 
@@ -1328,18 +1324,18 @@ impl<'a, K> Iterator for Drain<'a, K> {
 
     #[inline]
     fn next(&mut self) -> Option<K> {
-        self.iter.next().map(|(k, _)| k)
+        self.base.next()
     }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
+        self.base.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for Drain<'_, K> {
     #[inline]
     fn len(&self) -> usize {
-        self.iter.len()
+        self.base.len()
     }
 }
 #[stable(feature = "fused", since = "1.26.0")]
@@ -1348,8 +1344,7 @@ impl<K> FusedIterator for Drain<'_, K> {}
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let entries_iter = self.iter.iter().map(|(k, _)| k);
-        f.debug_list().entries(entries_iter).finish()
+        fmt::Debug::fmt(&self.base, f)
     }
 }
 
diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py
index 2a46eaadad6f9..a5a1824c84e78 100644
--- a/src/etc/gdb_lookup.py
+++ b/src/etc/gdb_lookup.py
@@ -69,9 +69,9 @@ def lookup(valobj):
         else:
             return StdOldHashMapProvider(valobj)
     if rust_type == RustType.STD_HASH_SET:
-        hash_map = valobj["map"]
+        hash_map = valobj[valobj.type.fields()[0]]
         if is_hashbrown_hashmap(hash_map):
-            return StdHashMapProvider(hash_map, show_values=False)
+            return StdHashMapProvider(valobj, show_values=False)
         else:
             return StdOldHashMapProvider(hash_map, show_values=False)
 
diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py
index 67f99ec4e40b9..bae51e6f9ee93 100644
--- a/src/etc/gdb_providers.py
+++ b/src/etc/gdb_providers.py
@@ -347,7 +347,7 @@ def __init__(self, valobj, show_values=True):
         self.valobj = valobj
         self.show_values = show_values
 
-        table = self.valobj["base"]["table"]
+        table = self.table()
         capacity = int(table["bucket_mask"]) + 1
         ctrl = table["ctrl"]["pointer"]
 
@@ -368,6 +368,18 @@ def __init__(self, valobj, show_values=True):
             if is_presented:
                 self.valid_indices.append(idx)
 
+    def table(self):
+        if self.show_values:
+            hashbrown_hashmap = self.valobj["base"]
+        elif self.valobj.type.fields()[0].name == "map":
+            # BACKCOMPAT: rust 1.47
+            # HashSet wraps std::collections::HashMap, which wraps hashbrown::HashMap
+            hashbrown_hashmap = self.valobj["map"]["base"]
+        else:
+            # HashSet wraps hashbrown::HashSet, which wraps hashbrown::HashMap
+            hashbrown_hashmap = self.valobj["base"]["map"]
+        return hashbrown_hashmap["table"]
+
     def to_string(self):
         if self.show_values:
             return "HashMap(size={})".format(self.size)
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py
index 13420fbaf0a75..3cee51982ba9f 100644
--- a/src/etc/lldb_lookup.py
+++ b/src/etc/lldb_lookup.py
@@ -94,7 +94,7 @@ def synthetic_lookup(valobj, dict):
     if rust_type == RustType.STD_HASH_SET:
         hash_map = valobj.GetChildAtIndex(0)
         if is_hashbrown_hashmap(hash_map):
-            return StdHashMapSyntheticProvider(hash_map, dict, show_values=False)
+            return StdHashMapSyntheticProvider(valobj, dict, show_values=False)
         else:
             return StdOldHashMapSyntheticProvider(hash_map, dict, show_values=False)
 
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 19da75c35b456..64cb9837943b9 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -526,7 +526,7 @@ def get_child_at_index(self, index):
 
     def update(self):
         # type: () -> None
-        table = self.valobj.GetChildMemberWithName("base").GetChildMemberWithName("table")
+        table = self.table()
         capacity = table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
         ctrl = table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)
 
@@ -552,6 +552,17 @@ def update(self):
             if is_present:
                 self.valid_indices.append(idx)
 
+    def table(self):
+        # type: () -> SBValue
+        if self.show_values:
+            hashbrown_hashmap = self.valobj.GetChildMemberWithName("base")
+        else:
+            # BACKCOMPAT: rust 1.47
+            # HashSet wraps either std HashMap or hashbrown::HashSet, which both
+            # wrap hashbrown::HashMap, so either way we "unwrap" twice.
+            hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0)
+        return hashbrown_hashmap.GetChildMemberWithName("table")
+
     def has_children(self):
         # type: () -> bool
         return True
diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis
index f791979800f19..9550c25f2fcfe 100644
--- a/src/etc/natvis/libstd.natvis
+++ b/src/etc/natvis/libstd.natvis
@@ -5,7 +5,7 @@
 
     Current std impls:
       std::collections::hash::set::HashSet<K, S>      is implemented in terms of...
-      std::collections::hash::map::HashMap<K, V, S>   is implemented in terms of...
+      hashbrown::set::HashSet<K, S>                   is implemented in terms of...
       hashbrown::map::HashMap<K, V, S>                is implemented in terms of...
       hashbrown::raw::RawTable<(K, V)>
 
@@ -50,22 +50,22 @@
   </Type>
 
   <Type Name="std::collections::hash::set::HashSet&lt;*,*&gt;">
-    <DisplayString>{{ size={map.base.table.items} }}</DisplayString>
+    <DisplayString>{{ size={base.map.table.items} }}</DisplayString>
     <Expand>
-      <Item Name="[size]">map.base.table.items</Item>
-      <Item Name="[capacity]">map.base.table.items + map.base.table.growth_left</Item>
-      <Item Name="[state]">map.base.hash_builder</Item>
+      <Item Name="[size]">base.map.table.items</Item>
+      <Item Name="[capacity]">base.map.table.items + base.map.table.growth_left</Item>
+      <Item Name="[state]">base.map.hash_builder</Item>
 
       <CustomListItems>
         <Variable Name="i" InitialValue="0" />
-        <Variable Name="n" InitialValue="map.base.table.items" />
-        <Size>map.base.table.items</Size>
+        <Variable Name="n" InitialValue="base.map.table.items" />
+        <Size>base.map.table.items</Size>
         <Loop>
           <Break Condition="n == 0" />
-          <If Condition="(map.base.table.ctrl.pointer[i] &amp; 0x80) == 0">
+          <If Condition="(base.map.table.ctrl.pointer[i] &amp; 0x80) == 0">
             <!-- Bucket is populated -->
             <Exec>n--</Exec>
-            <Item>(($T1*)map.base.table.ctrl.pointer)[-(i + 1)]</Item>
+            <Item>(($T1*)base.map.table.ctrl.pointer)[-(i + 1)]</Item>
           </If>
           <Exec>i++</Exec>
         </Loop>

From 49aef963d3fb50c6961077cc11c6ce93ee719d73 Mon Sep 17 00:00:00 2001
From: Matt Brubeck <mbrubeck@limpet.net>
Date: Mon, 10 Aug 2020 13:06:48 -0700
Subject: [PATCH 06/13] Add HashMap::drain_filter and HashSet::drain_filter

Implements #59618.
---
 library/std/src/collections/hash/map.rs | 87 +++++++++++++++++++++++++
 library/std/src/collections/hash/set.rs | 84 ++++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index fc0175332a769..1a3a493fbb8f6 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -497,6 +497,50 @@ impl<K, V, S> HashMap<K, V, S> {
         Drain { base: self.base.drain() }
     }
 
+    /// Creates an iterator which uses a closure to determine if an element should be removed.
+    ///
+    /// If the closure returns true, the element is removed from the map and yielded.
+    /// If the closure returns false, or panics, the element remains in the map and will not be
+    /// yielded.
+    ///
+    /// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of
+    /// whether you choose to keep or remove it.
+    ///
+    /// If the iterator is only partially consumed or not consumed at all, each of the remaining
+    /// elements will still be subjected to the closure and removed and dropped if it returns true.
+    ///
+    /// It is unspecified how many more elements will be subjected to the closure
+    /// if a panic occurs in the closure, or a panic occurs while dropping an element,
+    /// or if the `DrainFilter` value is leaked.
+    ///
+    /// # Examples
+    ///
+    /// Splitting a map into even and odd keys, reusing the original map:
+    ///
+    /// ```
+    /// #![feature(hash_drain_filter)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
+    /// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect();
+    ///
+    /// let mut evens = drained.keys().copied().collect::<Vec<_>>();
+    /// let mut odds = map.keys().copied().collect::<Vec<_>>();
+    /// evens.sort();
+    /// odds.sort();
+    ///
+    /// assert_eq!(evens, vec![0, 2, 4, 6]);
+    /// assert_eq!(odds, vec![1, 3, 5, 7]);
+    /// ```
+    #[inline]
+    #[unstable(feature = "hash_drain_filter", issue = "59618")]
+    pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
+    where
+        F: FnMut(&K, &mut V) -> bool,
+    {
+        DrainFilter { base: self.base.drain_filter(pred) }
+    }
+
     /// Clears the map, removing all key-value pairs. Keeps the allocated memory
     /// for reuse.
     ///
@@ -1190,6 +1234,19 @@ impl<'a, K, V> Drain<'a, K, V> {
     }
 }
 
+/// A draining, filtering iterator over the entries of a `HashMap`.
+///
+/// This `struct` is created by the [`drain_filter`] method on [`HashMap`].
+///
+/// [`drain_filter`]: HashMap::drain_filter
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+pub struct DrainFilter<'a, K, V, F>
+where
+    F: FnMut(&K, &mut V) -> bool,
+{
+    base: base::DrainFilter<'a, K, V, F>,
+}
+
 /// A mutable iterator over the values of a `HashMap`.
 ///
 /// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
@@ -1990,6 +2047,36 @@ where
     }
 }
 
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+impl<K, V, F> Iterator for DrainFilter<'_, K, V, F>
+where
+    F: FnMut(&K, &mut V) -> bool,
+{
+    type Item = (K, V);
+
+    #[inline]
+    fn next(&mut self) -> Option<(K, V)> {
+        self.base.next()
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.base.size_hint()
+    }
+}
+
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
+
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+impl<'a, K, V, F> fmt::Debug for DrainFilter<'a, K, V, F>
+where
+    F: FnMut(&K, &mut V) -> bool,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.pad("DrainFilter { .. }")
+    }
+}
+
 impl<'a, K, V> Entry<'a, K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index f9bc2e933dcf9..72f4798b65d66 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -247,6 +247,47 @@ impl<T, S> HashSet<T, S> {
         Drain { base: self.base.drain() }
     }
 
+    /// Creates an iterator which uses a closure to determine if a value should be removed.
+    ///
+    /// If the closure returns true, then the value is removed and yielded.
+    /// If the closure returns false, the value will remain in the list and will not be yielded
+    /// by the iterator.
+    ///
+    /// If the iterator is only partially consumed or not consumed at all, each of the remaining
+    /// values will still be subjected to the closure and removed and dropped if it returns true.
+    ///
+    /// It is unspecified how many more values will be subjected to the closure
+    /// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the
+    /// `DrainFilter` itself is leaked.
+    ///
+    /// # Examples
+    ///
+    /// Splitting a set into even and odd values, reusing the original set:
+    ///
+    /// ```
+    /// #![feature(hash_drain_filter)]
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set: HashSet<i32> = (0..8).collect();
+    /// let drained: HashSet<i32> = set.drain_filter(|v| v % 2 == 0).collect();
+    ///
+    /// let mut evens = drained.into_iter().collect::<Vec<_>>();
+    /// let mut odds = set.into_iter().collect::<Vec<_>>();
+    /// evens.sort();
+    /// odds.sort();
+    ///
+    /// assert_eq!(evens, vec![0, 2, 4, 6]);
+    /// assert_eq!(odds, vec![1, 3, 5, 7]);
+    /// ```
+    #[inline]
+    #[unstable(feature = "hash_drain_filter", issue = "59618")]
+    pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F>
+    where
+        F: FnMut(&T) -> bool,
+    {
+        DrainFilter { base: self.base.drain_filter(pred) }
+    }
+
     /// Clears the set, removing all values.
     ///
     /// # Examples
@@ -1159,6 +1200,19 @@ pub struct Drain<'a, K: 'a> {
     base: base::Drain<'a, K>,
 }
 
+/// A draining, filtering iterator over the items of a `HashSet`.
+///
+/// This `struct` is created by the [`drain_filter`] method on [`HashSet`].
+///
+/// [`drain_filter`]: HashSet::drain_filter
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+pub struct DrainFilter<'a, K, F>
+where
+    F: FnMut(&K) -> bool,
+{
+    base: base::DrainFilter<'a, K, F>,
+}
+
 /// A lazy iterator producing elements in the intersection of `HashSet`s.
 ///
 /// This `struct` is created by the [`intersection`] method on [`HashSet`].
@@ -1348,6 +1402,36 @@ impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
     }
 }
 
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+impl<K, F> Iterator for DrainFilter<'_, K, F>
+where
+    F: FnMut(&K) -> bool,
+{
+    type Item = K;
+
+    #[inline]
+    fn next(&mut self) -> Option<K> {
+        self.base.next()
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.base.size_hint()
+    }
+}
+
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+impl<K, F> FusedIterator for DrainFilter<'_, K, F> where F: FnMut(&K) -> bool {}
+
+#[unstable(feature = "hash_drain_filter", issue = "59618")]
+impl<'a, K, F> fmt::Debug for DrainFilter<'a, K, F>
+where
+    F: FnMut(&K) -> bool,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.pad("DrainFilter { .. }")
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Clone for Intersection<'_, T, S> {
     #[inline]

From fb1fab5a67955240330038414c23d912766ddeaf Mon Sep 17 00:00:00 2001
From: Matt Brubeck <mbrubeck@limpet.net>
Date: Mon, 7 Sep 2020 10:07:15 -0700
Subject: [PATCH 07/13] Tests for HashMap/HashSet::drain_filter

---
 library/std/src/collections/hash/map/tests.rs | 161 ++++++++++++++++++
 library/std/src/collections/hash/set/tests.rs |  71 ++++++++
 2 files changed, 232 insertions(+)

diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs
index 4283d80b78e64..467968354e25d 100644
--- a/library/std/src/collections/hash/map/tests.rs
+++ b/library/std/src/collections/hash/map/tests.rs
@@ -924,3 +924,164 @@ fn test_raw_entry() {
         }
     }
 }
+
+mod test_drain_filter {
+    use super::*;
+
+    use crate::panic::{catch_unwind, AssertUnwindSafe};
+    use crate::sync::atomic::{AtomicUsize, Ordering};
+
+    trait EqSorted: Iterator {
+        fn eq_sorted<I: IntoIterator<Item = Self::Item>>(self, other: I) -> bool;
+    }
+
+    impl<T: Iterator> EqSorted for T
+    where
+        T::Item: Eq + Ord,
+    {
+        fn eq_sorted<I: IntoIterator<Item = Self::Item>>(self, other: I) -> bool {
+            let mut v: Vec<_> = self.collect();
+            v.sort_unstable();
+            v.into_iter().eq(other)
+        }
+    }
+
+    #[test]
+    fn empty() {
+        let mut map: HashMap<i32, i32> = HashMap::new();
+        map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn consuming_nothing() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: HashMap<_, _> = pairs.collect();
+        assert!(map.drain_filter(|_, _| false).eq_sorted(crate::iter::empty()));
+        assert_eq!(map.len(), 3);
+    }
+
+    #[test]
+    fn consuming_all() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: HashMap<_, _> = pairs.clone().collect();
+        assert!(map.drain_filter(|_, _| true).eq_sorted(pairs));
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn mutating_and_keeping() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: HashMap<_, _> = pairs.collect();
+        assert!(
+            map.drain_filter(|_, v| {
+                *v += 6;
+                false
+            })
+            .eq_sorted(crate::iter::empty())
+        );
+        assert!(map.keys().copied().eq_sorted(0..3));
+        assert!(map.values().copied().eq_sorted(6..9));
+    }
+
+    #[test]
+    fn mutating_and_removing() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: HashMap<_, _> = pairs.collect();
+        assert!(
+            map.drain_filter(|_, v| {
+                *v += 6;
+                true
+            })
+            .eq_sorted((0..3).map(|i| (i, i + 6)))
+        );
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn drop_panic_leak() {
+        static PREDS: AtomicUsize = AtomicUsize::new(0);
+        static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+        struct D;
+        impl Drop for D {
+            fn drop(&mut self) {
+                if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+                    panic!("panic in `drop`");
+                }
+            }
+        }
+
+        let mut map = (0..3).map(|i| (i, D)).collect::<HashMap<_, _>>();
+
+        catch_unwind(move || {
+            drop(map.drain_filter(|_, _| {
+                PREDS.fetch_add(1, Ordering::SeqCst);
+                true
+            }))
+        })
+        .unwrap_err();
+
+        assert_eq!(PREDS.load(Ordering::SeqCst), 3);
+        assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+    }
+
+    #[test]
+    fn pred_panic_leak() {
+        static PREDS: AtomicUsize = AtomicUsize::new(0);
+        static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+        struct D;
+        impl Drop for D {
+            fn drop(&mut self) {
+                DROPS.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+
+        let mut map = (0..3).map(|i| (i, D)).collect::<HashMap<_, _>>();
+
+        catch_unwind(AssertUnwindSafe(|| {
+            drop(map.drain_filter(|_, _| match PREDS.fetch_add(1, Ordering::SeqCst) {
+                0 => true,
+                _ => panic!(),
+            }))
+        }))
+        .unwrap_err();
+
+        assert_eq!(PREDS.load(Ordering::SeqCst), 2);
+        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+        assert_eq!(map.len(), 2);
+    }
+
+    // Same as above, but attempt to use the iterator again after the panic in the predicate
+    #[test]
+    fn pred_panic_reuse() {
+        static PREDS: AtomicUsize = AtomicUsize::new(0);
+        static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+        struct D;
+        impl Drop for D {
+            fn drop(&mut self) {
+                DROPS.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+
+        let mut map = (0..3).map(|i| (i, D)).collect::<HashMap<_, _>>();
+
+        {
+            let mut it = map.drain_filter(|_, _| match PREDS.fetch_add(1, Ordering::SeqCst) {
+                0 => true,
+                _ => panic!(),
+            });
+            catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
+            // Iterator behaviour after a panic is explicitly unspecified,
+            // so this is just the current implementation:
+            let result = catch_unwind(AssertUnwindSafe(|| it.next()));
+            assert!(result.is_err());
+        }
+
+        assert_eq!(PREDS.load(Ordering::SeqCst), 3);
+        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+        assert_eq!(map.len(), 2);
+    }
+}
diff --git a/library/std/src/collections/hash/set/tests.rs b/library/std/src/collections/hash/set/tests.rs
index 3582390cee4bc..40f8467fd93fd 100644
--- a/library/std/src/collections/hash/set/tests.rs
+++ b/library/std/src/collections/hash/set/tests.rs
@@ -1,6 +1,9 @@
 use super::super::map::RandomState;
 use super::HashSet;
 
+use crate::panic::{catch_unwind, AssertUnwindSafe};
+use crate::sync::atomic::{AtomicU32, Ordering};
+
 #[test]
 fn test_zero_capacities() {
     type HS = HashSet<i32>;
@@ -413,3 +416,71 @@ fn test_retain() {
     assert!(set.contains(&4));
     assert!(set.contains(&6));
 }
+
+#[test]
+fn test_drain_filter() {
+    let mut x: HashSet<_> = [1].iter().copied().collect();
+    let mut y: HashSet<_> = [1].iter().copied().collect();
+
+    x.drain_filter(|_| true);
+    y.drain_filter(|_| false);
+    assert_eq!(x.len(), 0);
+    assert_eq!(y.len(), 1);
+}
+
+#[test]
+fn test_drain_filter_drop_panic_leak() {
+    static PREDS: AtomicU32 = AtomicU32::new(0);
+    static DROPS: AtomicU32 = AtomicU32::new(0);
+
+    #[derive(PartialEq, Eq, PartialOrd, Hash)]
+    struct D(i32);
+    impl Drop for D {
+        fn drop(&mut self) {
+            if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut set = (0..3).map(|i| D(i)).collect::<HashSet<_>>();
+
+    catch_unwind(move || {
+        drop(set.drain_filter(|_| {
+            PREDS.fetch_add(1, Ordering::SeqCst);
+            true
+        }))
+    })
+    .ok();
+
+    assert_eq!(PREDS.load(Ordering::SeqCst), 3);
+    assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+}
+
+#[test]
+fn test_drain_filter_pred_panic_leak() {
+    static PREDS: AtomicU32 = AtomicU32::new(0);
+    static DROPS: AtomicU32 = AtomicU32::new(0);
+
+    #[derive(PartialEq, Eq, PartialOrd, Hash)]
+    struct D;
+    impl Drop for D {
+        fn drop(&mut self) {
+            DROPS.fetch_add(1, Ordering::SeqCst);
+        }
+    }
+
+    let mut set: HashSet<_> = (0..3).map(|_| D).collect();
+
+    catch_unwind(AssertUnwindSafe(|| {
+        drop(set.drain_filter(|_| match PREDS.fetch_add(1, Ordering::SeqCst) {
+            0 => true,
+            _ => panic!(),
+        }))
+    }))
+    .ok();
+
+    assert_eq!(PREDS.load(Ordering::SeqCst), 1);
+    assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+    assert_eq!(set.len(), 0);
+}

From d24026bb6dbf33f022b9dd1daffeeab2c9f7d117 Mon Sep 17 00:00:00 2001
From: Camelid <camelidcamel@gmail.com>
Date: Tue, 8 Sep 2020 19:24:57 -0700
Subject: [PATCH 08/13] Fix broken link

`write` is ambiguous because there's also a macro called `write`.

Also removed unnecessary and potentially confusing link to a function in
its own docs.
---
 library/core/src/ptr/mod.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 219835bfae0f9..eb31c739e834e 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -129,7 +129,7 @@ mod mut_ptr;
 /// Additionally, if `T` is not [`Copy`], using the pointed-to value after
 /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
 /// foo` counts as a use because it will cause the value to be dropped
-/// again. [`write`] can be used to overwrite data without causing it to be
+/// again. [`write()`] can be used to overwrite data without causing it to be
 /// dropped.
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
@@ -639,7 +639,7 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
 /// `*src` can violate memory safety. Note that assigning to `*src` counts as a
 /// use because it will attempt to drop the value at `*src`.
 ///
-/// [`write`] can be used to overwrite data without causing it to be dropped.
+/// [`write()`] can be used to overwrite data without causing it to be dropped.
 ///
 /// ```
 /// use std::ptr;
@@ -878,7 +878,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 /// Overwrites a memory location with the given value without reading or
 /// dropping the old value.
 ///
-/// Unlike [`write`], the pointer may be unaligned.
+/// Unlike [`write()`], the pointer may be unaligned.
 ///
 /// `write_unaligned` does not drop the contents of `dst`. This is safe, but it
 /// could leak allocations or resources, so care should be taken not to overwrite
@@ -1085,7 +1085,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 /// Just like in C, whether an operation is volatile has no bearing whatsoever
 /// on questions involving concurrent access from multiple threads. Volatile
 /// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a [`write_volatile`] and any other operation (reading or writing)
+/// a race between a `write_volatile` and any other operation (reading or writing)
 /// on the same location is undefined behavior.
 ///
 /// # Examples

From 10d3f8a484a812db995198f17b17462718f477bc Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sun, 26 Jul 2020 20:11:30 +0300
Subject: [PATCH 09/13] Move `rustllvm` into `rustc_llvm`

---
 .gitignore                                       |  1 -
 compiler/rustc_codegen_llvm/Cargo.toml           |  2 +-
 compiler/rustc_codegen_llvm/src/llvm/ffi.rs      |  4 ++--
 .../rustc_llvm}/Cargo.toml                       |  5 +----
 .../rustc_llvm}/build.rs                         | 16 ++++++++--------
 .../rustc_llvm/llvm-wrapper}/.editorconfig       |  0
 .../rustc_llvm/llvm-wrapper}/ArchiveWrapper.cpp  |  2 +-
 .../llvm-wrapper}/CoverageMappingWrapper.cpp     |  2 +-
 .../rustc_llvm/llvm-wrapper/LLVMWrapper.h        |  0
 .../rustc_llvm/llvm-wrapper}/Linker.cpp          |  2 +-
 .../rustc_llvm/llvm-wrapper}/PassWrapper.cpp     |  2 +-
 .../rustc_llvm/llvm-wrapper}/README              |  0
 .../rustc_llvm/llvm-wrapper}/RustWrapper.cpp     |  2 +-
 .../rustc_llvm/src}/lib.rs                       |  0
 config.toml.example                              |  2 +-
 src/bootstrap/builder.rs                         |  6 +++---
 src/bootstrap/compile.rs                         |  4 ++--
 17 files changed, 23 insertions(+), 27 deletions(-)
 rename {src/librustc_llvm => compiler/rustc_llvm}/Cargo.toml (77%)
 rename {src/librustc_llvm => compiler/rustc_llvm}/build.rs (96%)
 rename {src/rustllvm => compiler/rustc_llvm/llvm-wrapper}/.editorconfig (100%)
 rename {src/rustllvm => compiler/rustc_llvm/llvm-wrapper}/ArchiveWrapper.cpp (99%)
 rename {src/rustllvm => compiler/rustc_llvm/llvm-wrapper}/CoverageMappingWrapper.cpp (98%)
 rename src/rustllvm/rustllvm.h => compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h (100%)
 rename {src/rustllvm => compiler/rustc_llvm/llvm-wrapper}/Linker.cpp (97%)
 rename {src/rustllvm => compiler/rustc_llvm/llvm-wrapper}/PassWrapper.cpp (99%)
 rename {src/rustllvm => compiler/rustc_llvm/llvm-wrapper}/README (100%)
 rename {src/rustllvm => compiler/rustc_llvm/llvm-wrapper}/RustWrapper.cpp (99%)
 rename {src/librustc_llvm => compiler/rustc_llvm/src}/lib.rs (100%)

diff --git a/.gitignore b/.gitignore
index 856ff7dbb0f33..1c50d9b054ddc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,7 +33,6 @@ __pycache__/
 /mingw-build/
 # Created by default with `src/ci/docker/run.sh`:
 /obj/
-/rustllvm/
 /unicode-downloads
 /target
 # Generated by compiletest for incremental:
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 38f552558c839..04792b334d553 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -25,7 +25,7 @@ rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_incremental = { path = "../rustc_incremental" }
 rustc_index = { path = "../rustc_index" }
-rustc_llvm = { path = "../../src/librustc_llvm" }
+rustc_llvm = { path = "../rustc_llvm" }
 rustc_session = { path = "../rustc_session" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 32822eba930c6..4942c997682d8 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -96,7 +96,7 @@ pub enum DLLStorageClass {
     DllExport = 2, // Function to be accessible from DLL.
 }
 
-/// Matches LLVMRustAttribute in rustllvm.h
+/// Matches LLVMRustAttribute in LLVMWrapper.h
 /// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
 /// though it is not ABI compatible (since it's a C++ enum)
 #[repr(C)]
@@ -1705,7 +1705,7 @@ extern "C" {
         PM: &PassManager<'_>,
     );
 
-    // Stuff that's in rustllvm/ because it's not upstream yet.
+    // Stuff that's in llvm-wrapper/ because it's not upstream yet.
 
     /// Opens an object file.
     pub fn LLVMCreateObjectFile(
diff --git a/src/librustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
similarity index 77%
rename from src/librustc_llvm/Cargo.toml
rename to compiler/rustc_llvm/Cargo.toml
index 7120f2e991acd..ee83689f0a469 100644
--- a/src/librustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -4,9 +4,6 @@ name = "rustc_llvm"
 version = "0.0.0"
 edition = "2018"
 
-[lib]
-path = "lib.rs"
-
 [features]
 static-libstdcpp = []
 emscripten = []
@@ -15,5 +12,5 @@ emscripten = []
 libc = "0.2.73"
 
 [build-dependencies]
-build_helper = { path = "../build_helper" }
+build_helper = { path = "../../src/build_helper" }
 cc = "1.0.58"
diff --git a/src/librustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
similarity index 96%
rename from src/librustc_llvm/build.rs
rename to compiler/rustc_llvm/build.rs
index 306ffbf5daab4..7f1e5cf336ac4 100644
--- a/src/librustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -175,15 +175,15 @@ fn main() {
         cfg.debug(false);
     }
 
-    build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm"));
-    cfg.file("../rustllvm/PassWrapper.cpp")
-        .file("../rustllvm/RustWrapper.cpp")
-        .file("../rustllvm/ArchiveWrapper.cpp")
-        .file("../rustllvm/CoverageMappingWrapper.cpp")
-        .file("../rustllvm/Linker.cpp")
+    build_helper::rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper"));
+    cfg.file("llvm-wrapper/PassWrapper.cpp")
+        .file("llvm-wrapper/RustWrapper.cpp")
+        .file("llvm-wrapper/ArchiveWrapper.cpp")
+        .file("llvm-wrapper/CoverageMappingWrapper.cpp")
+        .file("llvm-wrapper/Linker.cpp")
         .cpp(true)
         .cpp_link_stdlib(None) // we handle this below
-        .compile("rustllvm");
+        .compile("llvm-wrapper");
 
     let (llvm_kind, llvm_link_arg) = detect_llvm_link();
 
@@ -259,7 +259,7 @@ fn main() {
     }
 
     // Some LLVM linker flags (-L and -l) may be needed even when linking
-    // librustc_llvm, for example when using static libc++, we may need to
+    // rustc_llvm, for example when using static libc++, we may need to
     // manually specify the library search path and -ldl -lpthread as link
     // dependencies.
     let llvm_linker_flags = tracked_env_var_os("LLVM_LINKER_FLAGS");
diff --git a/src/rustllvm/.editorconfig b/compiler/rustc_llvm/llvm-wrapper/.editorconfig
similarity index 100%
rename from src/rustllvm/.editorconfig
rename to compiler/rustc_llvm/llvm-wrapper/.editorconfig
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
similarity index 99%
rename from src/rustllvm/ArchiveWrapper.cpp
rename to compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
index 9ce614fda5752..2797fe8df4a8e 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
@@ -1,4 +1,4 @@
-#include "rustllvm.h"
+#include "LLVMWrapper.h"
 
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ArchiveWriter.h"
diff --git a/src/rustllvm/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
similarity index 98%
rename from src/rustllvm/CoverageMappingWrapper.cpp
rename to compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index 81aba0cbf7d42..2b1143a4ecff5 100644
--- a/src/rustllvm/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -1,4 +1,4 @@
-#include "rustllvm.h"
+#include "LLVMWrapper.h"
 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
 #include "llvm/ProfileData/InstrProf.h"
diff --git a/src/rustllvm/rustllvm.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
similarity index 100%
rename from src/rustllvm/rustllvm.h
rename to compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
diff --git a/src/rustllvm/Linker.cpp b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp
similarity index 97%
rename from src/rustllvm/Linker.cpp
rename to compiler/rustc_llvm/llvm-wrapper/Linker.cpp
index 69176f9cb1f6d..8766e96f086d2 100644
--- a/src/rustllvm/Linker.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp
@@ -1,6 +1,6 @@
 #include "llvm/Linker/Linker.h"
 
-#include "rustllvm.h"
+#include "LLVMWrapper.h"
 
 using namespace llvm;
 
diff --git a/src/rustllvm/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
similarity index 99%
rename from src/rustllvm/PassWrapper.cpp
rename to compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 76fe5e7f769f7..7b1c3f9ba2c68 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -3,7 +3,7 @@
 #include <vector>
 #include <set>
 
-#include "rustllvm.h"
+#include "LLVMWrapper.h"
 
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
diff --git a/src/rustllvm/README b/compiler/rustc_llvm/llvm-wrapper/README
similarity index 100%
rename from src/rustllvm/README
rename to compiler/rustc_llvm/llvm-wrapper/README
diff --git a/src/rustllvm/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
similarity index 99%
rename from src/rustllvm/RustWrapper.cpp
rename to compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 9d90b0dfe0702..e85a9b7638004 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1,4 +1,4 @@
-#include "rustllvm.h"
+#include "LLVMWrapper.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
diff --git a/src/librustc_llvm/lib.rs b/compiler/rustc_llvm/src/lib.rs
similarity index 100%
rename from src/librustc_llvm/lib.rs
rename to compiler/rustc_llvm/src/lib.rs
diff --git a/config.toml.example b/config.toml.example
index 9abb8add785a9..0f25d311ec5d2 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -45,7 +45,7 @@
 # this flag will indicate that this version check should not be done.
 #version-check = true
 
-# Link libstdc++ statically into the librustc_llvm instead of relying on a
+# Link libstdc++ statically into the rustc_llvm instead of relying on a
 # dynamic version to be available.
 #static-libstdcpp = false
 
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 01dbb48354825..d2baf4a1d1e6a 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -812,7 +812,7 @@ impl<'a> Builder<'a> {
             format!("CARGO_PROFILE_{}_{}", profile, name)
         };
 
-        // See comment in librustc_llvm/build.rs for why this is necessary, largely llvm-config
+        // See comment in rustc_llvm/build.rs for why this is necessary, largely llvm-config
         // needs to not accidentally link to libLLVM in stage0/lib.
         cargo.env("REAL_LIBRARY_PATH_VAR", &util::dylib_path_var());
         if let Some(e) = env::var_os(util::dylib_path_var()) {
@@ -829,9 +829,9 @@ impl<'a> Builder<'a> {
         // scripts can do less work (i.e. not building/requiring LLVM).
         if cmd == "check" || cmd == "clippy" || cmd == "fix" {
             // If we've not yet built LLVM, or it's stale, then bust
-            // the librustc_llvm cache. That will always work, even though it
+            // the rustc_llvm cache. That will always work, even though it
             // may mean that on the next non-check build we'll need to rebuild
-            // librustc_llvm. But if LLVM is stale, that'll be a tiny amount
+            // rustc_llvm. But if LLVM is stale, that'll be a tiny amount
             // of work comparitively, and we'd likely need to rebuild it anyway,
             // so that's okay.
             if crate::native::prebuilt_llvm_config(self, target).is_err() {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 7814ca8e5bbce..9d314e8452b9c 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -560,7 +560,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
     }
 
     // Pass down configuration from the LLVM build into the build of
-    // librustc_llvm and librustc_codegen_llvm.
+    // rustc_llvm and rustc_codegen_llvm.
     //
     // Note that this is disabled if LLVM itself is disabled or we're in a check
     // build. If we are in a check build we still go ahead here presuming we've
@@ -579,7 +579,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
         if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
             cargo.env("CFG_LLVM_ROOT", s);
         }
-        // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm.
+        // Some LLVM linker flags (-L and -l) may be needed to link rustc_llvm.
         if let Some(ref s) = builder.config.llvm_ldflags {
             cargo.env("LLVM_LINKER_FLAGS", s);
         }

From 884a1b4b9b358fcb2c12dab0aac5671c8534b29d Mon Sep 17 00:00:00 2001
From: Camelid <camelidcamel@gmail.com>
Date: Wed, 9 Sep 2020 13:42:57 -0700
Subject: [PATCH 10/13] Fix anchor links

#safety -> self#safety
---
 library/core/src/ptr/mod.rs | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index eb31c739e834e..92c4f2ccfe8a0 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -134,7 +134,7 @@ mod mut_ptr;
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// # Examples
 ///
@@ -316,7 +316,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
 ///
 /// Note that even if `T` has size `0`, the pointers must be non-NULL and properly aligned.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// # Examples
 ///
@@ -394,7 +394,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is `0`,
 /// the pointers must be non-NULL and properly aligned.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// # Examples
 ///
@@ -533,7 +533,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// # Examples
 ///
@@ -668,7 +668,7 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
 /// assert_eq!(s, "bar");
 /// ```
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn read<T>(src: *const T) -> T {
@@ -706,7 +706,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
 /// Note that even if `T` has size `0`, the pointer must be non-NULL.
 ///
 /// [read-ownership]: read#ownership-of-the-returned-value
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// ## On `packed` structs
 ///
@@ -809,7 +809,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// # Examples
 ///
@@ -898,7 +898,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// ## On `packed` structs
 ///
@@ -1010,7 +1010,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 /// [read-ownership]: read#ownership-of-the-returned-value
 ///
 /// Just like in C, whether an operation is volatile has no bearing whatsoever
@@ -1080,7 +1080,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 ///
 /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: #safety
+/// [valid]: self#safety
 ///
 /// Just like in C, whether an operation is volatile has no bearing whatsoever
 /// on questions involving concurrent access from multiple threads. Volatile

From f7aee330c70ef787d2224adb49804343978dd145 Mon Sep 17 00:00:00 2001
From: Rich Kadel <richkadel@google.com>
Date: Wed, 9 Sep 2020 14:49:32 -0700
Subject: [PATCH 11/13] Also fixed monospace font for d3-graphviz engine

VS code graphviz extensions use d3-graphviz, which supports `Courier`
fontname but does not support `monospace`. This caused graphs to render
poorly because the text sizes were wrong.
---
 compiler/rustc_graphviz/src/lib.rs           | 2 +-
 compiler/rustc_mir/src/util/graphviz.rs      | 2 +-
 src/test/mir-opt/graphviz.main.mir_map.0.dot | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index 252e341686541..29ec3572016d7 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -634,7 +634,7 @@ where
     let mut graph_attrs = Vec::new();
     let mut content_attrs = Vec::new();
     if options.contains(&RenderOption::Monospace) {
-        let font = r#"fontname="monospace""#;
+        let font = r#"fontname="Courier, monospace""#;
         graph_attrs.push(font);
         content_attrs.push(font);
     };
diff --git a/compiler/rustc_mir/src/util/graphviz.rs b/compiler/rustc_mir/src/util/graphviz.rs
index bc1e3fa8b2915..e89c943770638 100644
--- a/compiler/rustc_mir/src/util/graphviz.rs
+++ b/compiler/rustc_mir/src/util/graphviz.rs
@@ -55,7 +55,7 @@ where
     writeln!(w, "{} {}Mir_{} {{", kind, cluster, def_name)?;
 
     // Global graph properties
-    let font = r#"fontname="monospace""#;
+    let font = r#"fontname="Courier, monospace""#;
     let mut graph_attrs = vec![font];
     let mut content_attrs = vec![font];
 
diff --git a/src/test/mir-opt/graphviz.main.mir_map.0.dot b/src/test/mir-opt/graphviz.main.mir_map.0.dot
index f5d8b84812a3e..df4f11f0f2169 100644
--- a/src/test/mir-opt/graphviz.main.mir_map.0.dot
+++ b/src/test/mir-opt/graphviz.main.mir_map.0.dot
@@ -1,7 +1,7 @@
 digraph Mir_0_3 {
-    graph [fontname="monospace"];
-    node [fontname="monospace"];
-    edge [fontname="monospace"];
+    graph [fontname="Courier, monospace"];
+    node [fontname="Courier, monospace"];
+    edge [fontname="Courier, monospace"];
     label=<fn main() -&gt; ()<br align="left"/>>;
     bb0__0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = const ()<br/></td></tr><tr><td align="left">goto</td></tr></table>>];
     bb1__0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left">resume</td></tr></table>>];

From f42dac0ce04e372d413dcc374f2e0cf1e40dff6a Mon Sep 17 00:00:00 2001
From: Stein Somers <git@steinsomers.be>
Date: Thu, 23 Jul 2020 20:15:47 +0200
Subject: [PATCH 12/13] Document btree's unwrap_unchecked

---
 library/alloc/src/collections/btree/mod.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs
index 6c8a588eb58f3..1a836f11499ec 100644
--- a/library/alloc/src/collections/btree/mod.rs
+++ b/library/alloc/src/collections/btree/mod.rs
@@ -13,6 +13,9 @@ trait Recover<Q: ?Sized> {
     fn replace(&mut self, key: Self::Key) -> Option<Self::Key>;
 }
 
+/// Same purpose as `Option::unwrap` but doesn't always guarantee a panic
+/// if the option contains no value.
+/// SAFETY: the caller must ensure that the option contains a value.
 #[inline(always)]
 pub unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T {
     val.unwrap_or_else(|| {

From fdff7defc9a21fc63a1586efab87694723144793 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@google.com>
Date: Thu, 10 Sep 2020 02:18:46 +0000
Subject: [PATCH 13/13] Revert "Rollup merge of #76285 -
 matklad:censor-spacing, r=petrochenkov"

This reverts commit 85cee57fd791d670d92dc61e0ad71594128dd45a, reversing
changes made to b4d387302416c90a3f70211770292d8d8ab5e07d.
---
 compiler/rustc_ast/src/tokenstream.rs         |  4 ++--
 .../rustc_expand/src/proc_macro_server.rs     | 22 +++++--------------
 compiler/rustc_parse/src/lexer/tokentrees.rs  |  5 ++++-
 compiler/rustc_parse/src/parser/mod.rs        | 10 ++++-----
 4 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index fb98f55a2154a..151acddae840e 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -403,8 +403,8 @@ impl Cursor {
         self.index = index;
     }
 
-    pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
-        self.stream.0[self.index..].get(n).map(|(tree, _)| tree)
+    pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
+        self.stream.0[self.index..].get(n).map(|(tree, _)| tree.clone())
     }
 }
 
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 765871a6396f3..39c82f97e0a39 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -47,26 +47,15 @@ impl ToInternal<token::DelimToken> for Delimiter {
     }
 }
 
-impl
-    FromInternal<(
-        TreeAndJoint,
-        Option<&'_ tokenstream::TokenTree>,
-        &'_ ParseSess,
-        &'_ mut Vec<Self>,
-    )> for TokenTree<Group, Punct, Ident, Literal>
+impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
+    for TokenTree<Group, Punct, Ident, Literal>
 {
     fn from_internal(
-        ((tree, is_joint), look_ahead, sess, stack): (
-            TreeAndJoint,
-            Option<&tokenstream::TokenTree>,
-            &ParseSess,
-            &mut Vec<Self>,
-        ),
+        ((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>),
     ) -> Self {
         use rustc_ast::token::*;
 
-        let joint = is_joint == Joint
-            && matches!(look_ahead, Some(tokenstream::TokenTree::Token(t)) if t.is_op());
+        let joint = is_joint == Joint;
         let Token { kind, span } = match tree {
             tokenstream::TokenTree::Delimited(span, delim, tts) => {
                 let delimiter = Delimiter::from_internal(delim);
@@ -456,8 +445,7 @@ impl server::TokenStreamIter for Rustc<'_> {
         loop {
             let tree = iter.stack.pop().or_else(|| {
                 let next = iter.cursor.next_with_joint()?;
-                let lookahead = iter.cursor.look_ahead(0);
-                Some(TokenTree::from_internal((next, lookahead, self.sess, &mut iter.stack)))
+                Some(TokenTree::from_internal((next, self.sess, &mut iter.stack)))
             })?;
             // A hack used to pass AST fragments to attribute and derive macros
             // as a single nonterminal token instead of a token stream.
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index fb27ccfbd9429..d5977ca3c7d2f 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -262,7 +262,10 @@ impl<'a> TokenTreesReader<'a> {
             }
             _ => {
                 let tt = TokenTree::Token(self.token.take());
-                let is_joint = self.bump();
+                let mut is_joint = self.bump();
+                if !self.token.is_op() {
+                    is_joint = NonJoint;
+                }
                 Ok((tt, is_joint))
             }
         }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 1b2067f8f256b..84edfecad192f 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -822,15 +822,15 @@ impl<'a> Parser<'a> {
         }
 
         let frame = &self.token_cursor.frame;
-        match frame.tree_cursor.look_ahead(dist - 1) {
+        looker(&match frame.tree_cursor.look_ahead(dist - 1) {
             Some(tree) => match tree {
-                TokenTree::Token(token) => looker(token),
+                TokenTree::Token(token) => token,
                 TokenTree::Delimited(dspan, delim, _) => {
-                    looker(&Token::new(token::OpenDelim(delim.clone()), dspan.open))
+                    Token::new(token::OpenDelim(delim), dspan.open)
                 }
             },
-            None => looker(&Token::new(token::CloseDelim(frame.delim), frame.span.close)),
-        }
+            None => Token::new(token::CloseDelim(frame.delim), frame.span.close),
+        })
     }
 
     /// Returns whether any of the given keywords are `dist` tokens ahead of the current one.