From a838a708e3239af7f9cbf0a79be10d495759e63c Mon Sep 17 00:00:00 2001
From: Nicolas Nattis <nicolas.nattis@gmail.com>
Date: Sat, 12 Sep 2020 13:53:30 -0300
Subject: [PATCH 01/34] Add a spin loop hint for Arc::downgrade

---
 library/alloc/src/lib.rs  | 1 +
 library/alloc/src/sync.rs | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 755a21934f0c5..8083fa5ba3e08 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -116,6 +116,7 @@
 #![feature(raw_ref_op)]
 #![feature(rustc_attrs)]
 #![feature(receiver_trait)]
+#![feature(renamed_spin_loop)]
 #![feature(min_specialization)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 6a240fbb42a99..f2609e58c1463 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -11,6 +11,7 @@ use core::convert::{From, TryFrom};
 use core::fmt;
 use core::hash::{Hash, Hasher};
 use core::intrinsics::abort;
+use core::hint;
 use core::iter;
 use core::marker::{PhantomData, Unpin, Unsize};
 use core::mem::{self, align_of_val, size_of_val};
@@ -764,6 +765,7 @@ impl<T: ?Sized> Arc<T> {
         loop {
             // check if the weak counter is currently "locked"; if so, spin.
             if cur == usize::MAX {
+                hint::spin_loop();
                 cur = this.inner().weak.load(Relaxed);
                 continue;
             }

From b58db1b7a122f4b45eec51cc72d5b1708cdb7a4f Mon Sep 17 00:00:00 2001
From: Nicolas Nattis <nicolas.nattis@gmail.com>
Date: Sat, 12 Sep 2020 15:32:12 -0300
Subject: [PATCH 02/34] Formatting

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

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index f2609e58c1463..762997bccd09a 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -10,8 +10,8 @@ use core::cmp::Ordering;
 use core::convert::{From, TryFrom};
 use core::fmt;
 use core::hash::{Hash, Hasher};
-use core::intrinsics::abort;
 use core::hint;
+use core::intrinsics::abort;
 use core::iter;
 use core::marker::{PhantomData, Unpin, Unsize};
 use core::mem::{self, align_of_val, size_of_val};

From 16e10bf81ee73f61cf813acef3d5dbbce4f66da2 Mon Sep 17 00:00:00 2001
From: Francesca Lovebloom <francesca@brainiumstudios.com>
Date: Wed, 7 Oct 2020 15:46:05 -0700
Subject: [PATCH 03/34] Revert "Allow dynamic linking for iOS/tvOS targets."

This reverts commit 56e115a2627ba8bdd2e66c759457af96b2b0286a.
---
 compiler/rustc_target/src/spec/apple_sdk_base.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
index e34277d5af04c..1b17c2c278f9a 100644
--- a/compiler/rustc_target/src/spec/apple_sdk_base.rs
+++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs
@@ -34,6 +34,7 @@ fn link_env_remove(arch: Arch) -> Vec<String> {
 pub fn opts(arch: Arch) -> TargetOptions {
     TargetOptions {
         cpu: target_cpu(arch),
+        dynamic_linking: false,
         executables: true,
         link_env_remove: link_env_remove(arch),
         has_elf_tls: false,

From 16d65d04322de4a00327dfe26b4af6bd3e4187c8 Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Tue, 6 Oct 2020 11:39:59 +0200
Subject: [PATCH 04/34] revise Hermit's mutex interface to support the
 behaviour of StaticMutex

rust-lang/rust#77147 simplifies things by splitting this Mutex type
into two types matching the two use cases: StaticMutex and MovableMutex.
To support the behavior of StaticMutex, we move part of the mutex
implementation into libstd.
---
 library/std/src/sys/hermit/mutex.rs | 190 ++++++++++++++++++++++++++--
 1 file changed, 182 insertions(+), 8 deletions(-)

diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index 3d4813209cbc4..511a5100ac625 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -1,9 +1,161 @@
+use crate::cell::UnsafeCell;
+use crate::collections::VecDeque;
 use crate::ffi::c_void;
+use crate::ops::{Deref, DerefMut, Drop};
 use crate::ptr;
+use crate::sync::atomic::{AtomicUsize, Ordering, spin_loop_hint};
 use crate::sys::hermit::abi;
 
+/// This type provides a lock based on busy waiting to realize mutual exclusion
+///
+/// # Description
+///
+/// This structure behaves a lot like a common mutex. There are some differences:
+///
+/// - By using busy waiting, it can be used outside the runtime.
+/// - It is a so called ticket lock (https://en.wikipedia.org/wiki/Ticket_lock)
+///   and completly fair.
+#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
+#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
+struct Spinlock<T: ?Sized> {
+    queue: AtomicUsize,
+    dequeue: AtomicUsize,
+    data: UnsafeCell<T>,
+}
+
+unsafe impl<T: ?Sized + Send> Sync for Spinlock<T> {}
+unsafe impl<T: ?Sized + Send> Send for Spinlock<T> {}
+
+/// A guard to which the protected data can be accessed
+///
+/// When the guard falls out of scope it will release the lock.
+struct SpinlockGuard<'a, T: ?Sized + 'a> {
+    dequeue: &'a AtomicUsize,
+    data: &'a mut T,
+}
+
+impl<T> Spinlock<T> {
+    pub const fn new(user_data: T) -> Spinlock<T> {
+        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
+    }
+
+    #[inline]
+    fn obtain_lock(&self) {
+        let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
+        while self.dequeue.load(Ordering::SeqCst) != ticket {
+            spin_loop_hint();
+        }
+    }
+
+    #[inline]
+    pub unsafe fn lock(&self) -> SpinlockGuard<'_, T> {
+        self.obtain_lock();
+        SpinlockGuard {
+            dequeue: &self.dequeue,
+            data: &mut *self.data.get(),
+        }
+    }
+}
+
+impl<T: ?Sized + Default> Default for Spinlock<T> {
+    fn default() -> Spinlock<T> {
+        Spinlock::new(Default::default())
+    }
+}
+
+impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &*self.data
+    }
+}
+
+impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut *self.data
+    }
+}
+
+impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
+    /// The dropping of the SpinlockGuard will release the lock it was created from.
+    fn drop(&mut self) {
+        self.dequeue.fetch_add(1, Ordering::SeqCst);
+    }
+}
+
+/// Realize a priority queue for tasks
+struct PriorityQueue {
+    queues: [Option<VecDeque<abi::Tid>>; abi::NO_PRIORITIES],
+    prio_bitmap: u64,
+}
+
+impl PriorityQueue {
+    pub const fn new() -> PriorityQueue {
+        PriorityQueue {
+            queues: [
+                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+                None, None, None,
+            ],
+            prio_bitmap: 0,
+        }
+    }
+
+    /// Add a task handle by its priority to the queue
+    pub fn push(&mut self, prio: abi::Priority, id: abi::Tid) {
+        let i: usize = prio.into().into();
+        self.prio_bitmap |= (1 << i) as u64;
+        if let Some(queue) = &mut self.queues[i] {
+            queue.push_back(id);
+        } else {
+            let mut queue = VecDeque::new();
+            queue.push_back(id);
+            self.queues[i] = Some(queue);
+        }
+    }
+
+    fn pop_from_queue(&mut self, queue_index: usize) -> Option<abi::Tid> {
+        if let Some(queue) = &mut self.queues[queue_index] {
+            let id = queue.pop_front();
+
+            if queue.is_empty() {
+                self.prio_bitmap &= !(1 << queue_index as u64);
+            }
+
+            id
+        } else {
+            None
+        }
+    }
+
+    /// Pop the task handle with the highest priority from the queue
+    pub fn pop(&mut self) -> Option<abi::Tid> {
+        for i in 0..abi::NO_PRIORITIES {
+            if self.prio_bitmap & (1 << i) != 0 {
+                return self.pop_from_queue(i);
+            }
+        }
+
+        None
+    }
+}
+
+struct MutexInner {
+    locked: bool,
+    blocked_task: PriorityQueue,
+}
+
+impl MutexInner {
+    pub const fn new() -> MutexInner {
+        MutexInner {
+            locked: false,
+            blocked_task: PriorityQueue::new(),
+        }
+    }
+}
+
 pub struct Mutex {
-    inner: *const c_void,
+    inner: Spinlock<MutexInner>,
 }
 
 unsafe impl Send for Mutex {}
@@ -11,33 +163,55 @@ unsafe impl Sync for Mutex {}
 
 impl Mutex {
     pub const fn new() -> Mutex {
-        Mutex { inner: ptr::null() }
+        Mutex {
+            inner: Spinlock::new(MutexInner::new()),
+        }
     }
 
     #[inline]
     pub unsafe fn init(&mut self) {
-        let _ = abi::sem_init(&mut self.inner as *mut *const c_void, 1);
+        self.inner = Spinlock::new(MutexInner::new());
     }
 
     #[inline]
     pub unsafe fn lock(&self) {
-        let _ = abi::sem_timedwait(self.inner, 0);
+        loop {
+            let mut guard = self.inner.lock();
+            if guard.locked == false {
+                guard.locked = true;
+                return;
+            } else {
+                let prio = abi::get_priority();
+                let id = abi::getpid();
+
+                guard.blocked_task.push(prio, id);
+                abi::block_current_task();
+                drop(guard);
+                abi::yield_now();
+            }
+        }
     }
 
     #[inline]
     pub unsafe fn unlock(&self) {
-        let _ = abi::sem_post(self.inner);
+        let mut guard = self.inner.lock();
+        guard.locked = false;
+        if let Some(tid) = guard.blocked_task.pop() {
+            abi::wakeup_task(tid);
+        }
     }
 
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        let result = abi::sem_trywait(self.inner);
-        result == 0
+        let mut guard = self.inner.lock();
+        if guard.locked == false {
+            guard.locked = true;
+        }
+        guard.locked
     }
 
     #[inline]
     pub unsafe fn destroy(&self) {
-        let _ = abi::sem_destroy(self.inner);
     }
 }
 

From 98fcc3fbc7b2f3420d393b8916746002d501401c Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Tue, 6 Oct 2020 11:42:57 +0200
Subject: [PATCH 05/34] using the latest version of libhermit-rs

---
 Cargo.lock             | 4 ++--
 library/std/Cargo.toml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ec4f3091d2da2..493c184313cb1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1328,9 +1328,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.15"
+version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
+checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
 dependencies = [
  "compiler_builtins",
  "libc",
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index c08828bc0cde9..98d955efb2899 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -42,7 +42,7 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
 fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 
 [target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies]
-hermit-abi = { version = "0.1.15", features = ['rustc-dep-of-std'] }
+hermit-abi = { version = "0.1.17", features = ['rustc-dep-of-std'] }
 
 [target.wasm32-wasi.dependencies]
 wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }

From d560b50d87c05ea5a8e6186c05a50ecd828eaaae Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Tue, 6 Oct 2020 12:12:15 +0200
Subject: [PATCH 06/34] revise code to pass the format check

---
 library/std/src/sys/hermit/mutex.rs | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index 511a5100ac625..bd9a9023396b4 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -3,7 +3,7 @@ use crate::collections::VecDeque;
 use crate::ffi::c_void;
 use crate::ops::{Deref, DerefMut, Drop};
 use crate::ptr;
-use crate::sync::atomic::{AtomicUsize, Ordering, spin_loop_hint};
+use crate::sync::atomic::{spin_loop_hint, AtomicUsize, Ordering};
 use crate::sys::hermit::abi;
 
 /// This type provides a lock based on busy waiting to realize mutual exclusion
@@ -50,10 +50,7 @@ impl<T> Spinlock<T> {
     #[inline]
     pub unsafe fn lock(&self) -> SpinlockGuard<'_, T> {
         self.obtain_lock();
-        SpinlockGuard {
-            dequeue: &self.dequeue,
-            data: &mut *self.data.get(),
-        }
+        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
     }
 }
 
@@ -147,10 +144,7 @@ struct MutexInner {
 
 impl MutexInner {
     pub const fn new() -> MutexInner {
-        MutexInner {
-            locked: false,
-            blocked_task: PriorityQueue::new(),
-        }
+        MutexInner { locked: false, blocked_task: PriorityQueue::new() }
     }
 }
 
@@ -163,9 +157,7 @@ unsafe impl Sync for Mutex {}
 
 impl Mutex {
     pub const fn new() -> Mutex {
-        Mutex {
-            inner: Spinlock::new(MutexInner::new()),
-        }
+        Mutex { inner: Spinlock::new(MutexInner::new()) }
     }
 
     #[inline]
@@ -211,8 +203,7 @@ impl Mutex {
     }
 
     #[inline]
-    pub unsafe fn destroy(&self) {
-    }
+    pub unsafe fn destroy(&self) {}
 }
 
 pub struct ReentrantMutex {

From 986c1fc053828a051c9fd888cbf49393f276f4f5 Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Wed, 7 Oct 2020 10:39:22 +0200
Subject: [PATCH 07/34] revise comments and descriptions of the helper
 functions

---
 library/std/src/sys/hermit/mutex.rs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index bd9a9023396b4..1bf142ec683d5 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -13,8 +13,7 @@ use crate::sys::hermit::abi;
 /// This structure behaves a lot like a common mutex. There are some differences:
 ///
 /// - By using busy waiting, it can be used outside the runtime.
-/// - It is a so called ticket lock (https://en.wikipedia.org/wiki/Ticket_lock)
-///   and completly fair.
+/// - It is a so called ticket lock and is completly fair.
 #[cfg_attr(target_arch = "x86_64", repr(align(128)))]
 #[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
 struct Spinlock<T: ?Sized> {
@@ -98,7 +97,7 @@ impl PriorityQueue {
         }
     }
 
-    /// Add a task handle by its priority to the queue
+    /// Add a task id by its priority to the queue
     pub fn push(&mut self, prio: abi::Priority, id: abi::Tid) {
         let i: usize = prio.into().into();
         self.prio_bitmap |= (1 << i) as u64;

From d6e955f3bfd0a47240879549dc2fb3284dfe08e4 Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Fri, 9 Oct 2020 06:42:19 +0200
Subject: [PATCH 08/34] fix typos in new method

---
 library/std/src/sys/hermit/mutex.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index 1bf142ec683d5..c3f88ada0f4bc 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -35,7 +35,11 @@ struct SpinlockGuard<'a, T: ?Sized + 'a> {
 
 impl<T> Spinlock<T> {
     pub const fn new(user_data: T) -> Spinlock<T> {
-        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
+        Spinlock {
+           queue: AtomicUsize::new(0),
+           dequeue: AtomicUsize::new(1),
+	   data: UnsafeCell::new(user_data),
+        }
     }
 
     #[inline]

From 530f5754664699dee29bde6cfa99aaf861499544 Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Fri, 9 Oct 2020 07:26:48 +0200
Subject: [PATCH 09/34] revise code to pass the format check

---
 library/std/src/sys/hermit/mutex.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index c3f88ada0f4bc..e9222f34b89b4 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -36,9 +36,9 @@ struct SpinlockGuard<'a, T: ?Sized + 'a> {
 impl<T> Spinlock<T> {
     pub const fn new(user_data: T) -> Spinlock<T> {
         Spinlock {
-           queue: AtomicUsize::new(0),
-           dequeue: AtomicUsize::new(1),
-	   data: UnsafeCell::new(user_data),
+            queue: AtomicUsize::new(0),
+            dequeue: AtomicUsize::new(1),
+            data: UnsafeCell::new(user_data),
         }
     }
 

From 8d8a290c691db7a8ee566edbd485a729eb41d4ba Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Fri, 9 Oct 2020 08:25:19 +0200
Subject: [PATCH 10/34] add hermit to the list of omit OS

---
 library/std/src/sys/mod.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 7b5fac922d08a..b4628b649117e 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -89,6 +89,7 @@ cfg_if::cfg_if! {
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use self::ext as windows_ext;
     } else if #[cfg(any(target_os = "cloudabi",
+                        target_os = "hermit",
                         target_arch = "wasm32",
                         all(target_vendor = "fortanix", target_env = "sgx")))] {
         // On CloudABI and wasm right now the shim below doesn't compile, so

From 33fd08b61f57cde81bf01964b2fc4d2dca0e4d3f Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Mon, 12 Oct 2020 06:51:52 +0200
Subject: [PATCH 11/34] remove obsolete function diverge

---
 library/std/src/sys/hermit/fs.rs      |   4 -
 library/std/src/sys/hermit/process.rs | 149 --------------------------
 2 files changed, 153 deletions(-)
 delete mode 100644 library/std/src/sys/hermit/process.rs

diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 82ccab1462ba8..829d4c943f11b 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -334,10 +334,6 @@ impl File {
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
         Err(Error::from_raw_os_error(22))
     }
-
-    pub fn diverge(&self) -> ! {
-        loop {}
-    }
 }
 
 impl DirBuilder {
diff --git a/library/std/src/sys/hermit/process.rs b/library/std/src/sys/hermit/process.rs
deleted file mode 100644
index 4702e5c549228..0000000000000
--- a/library/std/src/sys/hermit/process.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io;
-use crate::sys::fs::File;
-use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
-
-pub use crate::ffi::OsString as EnvKey;
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    env: CommandEnv,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-}
-
-impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
-    }
-
-    pub fn arg(&mut self, _arg: &OsStr) {}
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, _dir: &OsStr) {}
-
-    pub fn stdin(&mut self, _stdin: Stdio) {}
-
-    pub fn stdout(&mut self, _stdout: Stdio) {}
-
-    pub fn stderr(&mut self, _stderr: Stdio) {}
-
-    pub fn spawn(
-        &mut self,
-        _default: Stdio,
-        _needs_stdin: bool,
-    ) -> io::Result<(Process, StdioPipes)> {
-        unsupported()
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        pipe.diverge()
-    }
-}
-
-impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-pub struct ExitStatus(Void);
-
-impl ExitStatus {
-    pub fn success(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        match self.0 {}
-    }
-}
-
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        match self.0 {}
-    }
-}
-
-impl Copy for ExitStatus {}
-
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for ExitStatus {}
-
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-pub struct Process(Void);
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        match self.0 {}
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
-    }
-}

From 30c3dadb4da44c950f79e9772b36bbaf2660bb0e Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Mon, 12 Oct 2020 06:53:06 +0200
Subject: [PATCH 12/34] reuse implementation of the system provider
 "unsupported"

---
 library/std/src/sys/hermit/mod.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index 8eaf07e52d69a..af05310a8d3ab 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -31,6 +31,7 @@ pub mod net;
 pub mod os;
 pub mod path;
 pub mod pipe;
+#[path = "../unsupported/process.rs"]
 pub mod process;
 pub mod rwlock;
 pub mod stack_overflow;

From 1741e5b8f581960a6e9cb9f0b8261b5f0c26e92d Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Mon, 12 Oct 2020 06:54:48 +0200
Subject: [PATCH 13/34] define required type 'MovableMutex'

---
 library/std/src/sys/hermit/mutex.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index e9222f34b89b4..e12c2f4e00c50 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -155,6 +155,8 @@ pub struct Mutex {
     inner: Spinlock<MutexInner>,
 }
 
+pub type MovableMutex = Mutex;
+
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 

From bc6b2ac449a0f6d9a8bd87788a0eae9516cb58ce Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Tue, 13 Oct 2020 12:06:48 +0200
Subject: [PATCH 14/34] move __rg_oom to the libos to avoid duplicated symbols

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

diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 4646d4a833525..850451bb29e12 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -372,7 +372,7 @@ pub fn handle_alloc_error(layout: Layout) -> ! {
     unsafe { oom_impl(layout) }
 }
 
-#[cfg(not(any(test, bootstrap)))]
+#[cfg(not(any(target_os="hermit", test, bootstrap)))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
 #[unstable(feature = "alloc_internals", issue = "none")]

From 77d98316f489f4490459b3dcf12d14f45caf1286 Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Tue, 13 Oct 2020 12:22:18 +0200
Subject: [PATCH 15/34] minor changes to pass the format check

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

diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 850451bb29e12..1ea34be71dd3b 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -372,7 +372,7 @@ pub fn handle_alloc_error(layout: Layout) -> ! {
     unsafe { oom_impl(layout) }
 }
 
-#[cfg(not(any(target_os="hermit", test, bootstrap)))]
+#[cfg(not(any(target_os = "hermit", test, bootstrap)))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
 #[unstable(feature = "alloc_internals", issue = "none")]

From bf268fe928eae8d85a868ccdbcc086ea033ae51c Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Tue, 13 Oct 2020 23:25:42 +0200
Subject: [PATCH 16/34] box mutex to get a movable mutex

the commit avoid an alignement issue in Mutex implementation
---
 library/std/src/sys/hermit/mutex.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index e12c2f4e00c50..f988a019cfedb 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -155,7 +155,7 @@ pub struct Mutex {
     inner: Spinlock<MutexInner>,
 }
 
-pub type MovableMutex = Mutex;
+pub type MovableMutex = Box<Mutex>;
 
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}

From b62b352f4779072c07c110a63fd83afa9508b9e9 Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Mon, 19 Oct 2020 10:02:51 -0700
Subject: [PATCH 17/34] Check for exhaustion in RangeInclusive::contains

When a range has finished iteration, `is_empty` returns true, so it
should also be the case that `contains` returns false.
---
 library/core/src/ops/range.rs | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 4423cfc27dd17..1da186d9fbb24 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -479,13 +479,23 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
     /// assert!(!(0.0..=f32::NAN).contains(&0.0));
     /// assert!(!(f32::NAN..=1.0).contains(&1.0));
     /// ```
+    ///
+    /// This method always returns `false` after iteration has finished:
+    ///
+    /// ```
+    /// let mut r = 3..=5;
+    /// assert!(r.contains(&3) && r.contains(&5));
+    /// for _ in r.by_ref() {}
+    /// // Precise field values are unspecified here
+    /// assert!(!r.contains(&3) && !r.contains(&5));
+    /// ```
     #[stable(feature = "range_contains", since = "1.35.0")]
     pub fn contains<U>(&self, item: &U) -> bool
     where
         Idx: PartialOrd<U>,
         U: ?Sized + PartialOrd<Idx>,
     {
-        <Self as RangeBounds<Idx>>::contains(self, item)
+        !self.exhausted && <Self as RangeBounds<Idx>>::contains(self, item)
     }
 
     /// Returns `true` if the range contains no items.

From 9fd79a39044be777a39604856d0a276484d6480f Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Mon, 19 Oct 2020 13:46:30 -0700
Subject: [PATCH 18/34] make exhausted RangeInclusive::end_bound return
 Excluded(end)

---
 library/core/src/ops/range.rs | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 1da186d9fbb24..084ddffab0b7a 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -495,7 +495,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
         Idx: PartialOrd<U>,
         U: ?Sized + PartialOrd<Idx>,
     {
-        !self.exhausted && <Self as RangeBounds<Idx>>::contains(self, item)
+        <Self as RangeBounds<Idx>>::contains(self, item)
     }
 
     /// Returns `true` if the range contains no items.
@@ -891,7 +891,13 @@ impl<T> RangeBounds<T> for RangeInclusive<T> {
         Included(&self.start)
     }
     fn end_bound(&self) -> Bound<&T> {
-        Included(&self.end)
+        if self.exhausted {
+            // When the iterator is exhausted, we usually have start == end,
+            // but we want the range to appear empty, containing nothing.
+            Excluded(&self.end)
+        } else {
+            Included(&self.end)
+        }
     }
 }
 

From a9470d0522368f67d8aaa551318e3feb2d18e790 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Wed, 21 Oct 2020 00:00:00 +0000
Subject: [PATCH 19/34] Simplify assert terminator only if condition evaluates
 to expected value

---
 compiler/rustc_mir/src/transform/simplify_branches.rs | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/simplify_branches.rs b/compiler/rustc_mir/src/transform/simplify_branches.rs
index 5f63c03993d3a..a9a45e61a38cb 100644
--- a/compiler/rustc_mir/src/transform/simplify_branches.rs
+++ b/compiler/rustc_mir/src/transform/simplify_branches.rs
@@ -49,9 +49,10 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches {
                 }
                 TerminatorKind::Assert {
                     target, cond: Operand::Constant(ref c), expected, ..
-                } if (c.literal.try_eval_bool(tcx, param_env) == Some(true)) == expected => {
-                    TerminatorKind::Goto { target }
-                }
+                } => match c.literal.try_eval_bool(tcx, param_env) {
+                    Some(v) if v == expected => TerminatorKind::Goto { target },
+                    _ => continue,
+                },
                 TerminatorKind::FalseEdge { real_target, .. } => {
                     TerminatorKind::Goto { target: real_target }
                 }

From 9202fbdbdbd60adb62839c3230738274e30f15fc Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Tue, 20 Oct 2020 17:18:08 -0700
Subject: [PATCH 20/34] Check for exhaustion in SliceIndex for RangeInclusive

---
 library/alloc/tests/str.rs      | 29 +++++++++++++++++++++++++++++
 library/core/src/ops/range.rs   | 14 ++++++++++++++
 library/core/src/slice/index.rs | 16 ++++++----------
 library/core/src/str/traits.rs  | 16 ++++++----------
 library/core/tests/slice.rs     | 30 ++++++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index ed8ee2d8823c0..834dd4656ff76 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -529,6 +529,13 @@ mod slice_index {
             message: "out of bounds";
         }
 
+        in mod rangeinclusive_len {
+            data: "abcdef";
+            good: data[0..=5] == "abcdef";
+            bad: data[0..=6];
+            message: "out of bounds";
+        }
+
         in mod range_len_len {
             data: "abcdef";
             good: data[6..6] == "";
@@ -544,6 +551,28 @@ mod slice_index {
         }
     }
 
+    panic_cases! {
+        in mod rangeinclusive_exhausted {
+            data: "abcdef";
+
+            good: data[0..=5] == "abcdef";
+            good: data[{
+                let mut iter = 0..=5;
+                iter.by_ref().count(); // exhaust it
+                iter
+            }] == "";
+
+            // 0..=6 is out of bounds before exhaustion, so it
+            // stands to reason that it still would be after.
+            bad: data[{
+                let mut iter = 0..=6;
+                iter.by_ref().count(); // exhaust it
+                iter
+            }];
+            message: "out of bounds";
+        }
+    }
+
     panic_cases! {
         in mod range_neg_width {
             data: "abcdef";
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 084ddffab0b7a..1d67e65e51f5f 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -446,6 +446,20 @@ impl<Idx> RangeInclusive<Idx> {
     }
 }
 
+impl RangeInclusive<usize> {
+    /// Converts to an exclusive `Range` for `SliceIndex` implementations.
+    /// The caller is responsible for dealing with `end == usize::MAX`.
+    #[inline]
+    pub(crate) fn into_slice_range(self) -> Range<usize> {
+        // If we're not exhausted, we want to simply slice `start..end + 1`.
+        // If we are exhausted, then slicing with `end + 1..end + 1` gives us an
+        // empty range that is still subject to bounds-checks for that endpoint.
+        let exclusive_end = self.end + 1;
+        let start = if self.exhausted { exclusive_end } else { self.start };
+        start..exclusive_end
+    }
+}
+
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index f1f21c1d24b0b..660c8a2da5da0 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -376,28 +376,24 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&[T]> {
-        if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) }
+        if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        if *self.end() == usize::MAX {
-            None
-        } else {
-            (*self.start()..self.end() + 1).get_mut(slice)
-        }
+        if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
     }
 
     #[inline]
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
-        unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
+        unsafe { self.into_slice_range().get_unchecked(slice) }
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
-        unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
+        unsafe { self.into_slice_range().get_unchecked_mut(slice) }
     }
 
     #[inline]
@@ -405,7 +401,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
         if *self.end() == usize::MAX {
             slice_end_index_overflow_fail();
         }
-        (*self.start()..self.end() + 1).index(slice)
+        self.into_slice_range().index(slice)
     }
 
     #[inline]
@@ -413,7 +409,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
         if *self.end() == usize::MAX {
             slice_end_index_overflow_fail();
         }
-        (*self.start()..self.end() + 1).index_mut(slice)
+        self.into_slice_range().index_mut(slice)
     }
 }
 
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 4f8aa246e5232..f363541431100 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -398,39 +398,35 @@ unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
-        if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) }
+        if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
     }
     #[inline]
     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
-        if *self.end() == usize::MAX {
-            None
-        } else {
-            (*self.start()..self.end() + 1).get_mut(slice)
-        }
+        if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
     }
     #[inline]
     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
         // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
-        unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
+        unsafe { self.into_slice_range().get_unchecked(slice) }
     }
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
         // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
-        unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
+        unsafe { self.into_slice_range().get_unchecked_mut(slice) }
     }
     #[inline]
     fn index(self, slice: &str) -> &Self::Output {
         if *self.end() == usize::MAX {
             str_index_overflow_fail();
         }
-        (*self.start()..self.end() + 1).index(slice)
+        self.into_slice_range().index(slice)
     }
     #[inline]
     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
         if *self.end() == usize::MAX {
             str_index_overflow_fail();
         }
-        (*self.start()..self.end() + 1).index_mut(slice)
+        self.into_slice_range().index_mut(slice)
     }
 }
 
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index ac5c9353ccb46..9ccc5a08dcbea 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -1341,6 +1341,14 @@ mod slice_index {
             message: "out of range";
         }
 
+        in mod rangeinclusive_len {
+            data: [0, 1, 2, 3, 4, 5];
+
+            good: data[0..=5] == [0, 1, 2, 3, 4, 5];
+            bad: data[0..=6];
+            message: "out of range";
+        }
+
         in mod range_len_len {
             data: [0, 1, 2, 3, 4, 5];
 
@@ -1358,6 +1366,28 @@ mod slice_index {
         }
     }
 
+    panic_cases! {
+        in mod rangeinclusive_exhausted {
+            data: [0, 1, 2, 3, 4, 5];
+
+            good: data[0..=5] == [0, 1, 2, 3, 4, 5];
+            good: data[{
+                let mut iter = 0..=5;
+                iter.by_ref().count(); // exhaust it
+                iter
+            }] == [];
+
+            // 0..=6 is out of range before exhaustion, so it
+            // stands to reason that it still would be after.
+            bad: data[{
+                let mut iter = 0..=6;
+                iter.by_ref().count(); // exhaust it
+                iter
+            }];
+            message: "out of range";
+        }
+    }
+
     panic_cases! {
         in mod range_neg_width {
             data: [0, 1, 2, 3, 4, 5];

From 40ab18d97dab9df68418d19ef8a40c3218142d5f Mon Sep 17 00:00:00 2001
From: Bastian Kauschke <bastian_kauschke@hotmail.de>
Date: Thu, 22 Oct 2020 23:07:48 +0200
Subject: [PATCH 21/34] improve const infer error

---
 compiler/rustc_middle/src/infer/unify_key.rs     | 16 +++++-----------
 .../ui/const-generics/infer/issue-77092.stderr   |  2 +-
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 4d884dde39387..cf5e99845d189 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -176,17 +176,17 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
     type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>);
 
     fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
-        let (val, span) = match (value1.val, value2.val) {
+        let (val, origin) = match (value1.val, value2.val) {
             (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
                 bug!("equating two const variables, both of which have known values")
             }
 
             // If one side is known, prefer that one.
             (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => {
-                (value1.val, value1.origin.span)
+                (value1.val, value1.origin)
             }
             (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => {
-                (value2.val, value2.origin.span)
+                (value2.val, value2.origin)
             }
 
             // If both sides are *unknown*, it hardly matters, does it?
@@ -200,17 +200,11 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
                 // universe is the minimum of the two universes, because that is
                 // the one which contains the fewest names in scope.
                 let universe = cmp::min(universe1, universe2);
-                (ConstVariableValue::Unknown { universe }, value1.origin.span)
+                (ConstVariableValue::Unknown { universe }, value1.origin)
             }
         };
 
-        Ok(ConstVarValue {
-            origin: ConstVariableOrigin {
-                kind: ConstVariableOriginKind::ConstInference,
-                span: span,
-            },
-            val,
-        })
+        Ok(ConstVarValue { origin, val })
     }
 }
 
diff --git a/src/test/ui/const-generics/infer/issue-77092.stderr b/src/test/ui/const-generics/infer/issue-77092.stderr
index e84ff8baeea53..63facbf3b8c0f 100644
--- a/src/test/ui/const-generics/infer/issue-77092.stderr
+++ b/src/test/ui/const-generics/infer/issue-77092.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
   --> $DIR/issue-77092.rs:13:26
    |
 LL |         println!("{:?}", take_array_from_mut(&mut arr, i));
-   |                          ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{_: usize}`
+   |                          ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `take_array_from_mut`
 
 error: aborting due to previous error
 

From 9775ac60dcc92dbb04861863a69eacfafeea5c4c Mon Sep 17 00:00:00 2001
From: Camelid <camelidcamel@gmail.com>
Date: Thu, 22 Oct 2020 14:22:09 -0700
Subject: [PATCH 22/34] Document inline-const in the Unstable Book

---
 .../src/language-features/inline-const.md     | 45 +++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 src/doc/unstable-book/src/language-features/inline-const.md

diff --git a/src/doc/unstable-book/src/language-features/inline-const.md b/src/doc/unstable-book/src/language-features/inline-const.md
new file mode 100644
index 0000000000000..00e1c79ca3ff3
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/inline-const.md
@@ -0,0 +1,45 @@
+# `inline_const`
+
+The tracking issue for this feature is: [#76001]
+
+------
+
+This feature allows you to use inline constant expressions. For example, you can
+turn this code:
+
+```rust
+# fn add_one(x: i32) -> i32 { x + 1 }
+const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4;
+
+fn main() {
+    let x = add_one(MY_COMPUTATION);
+}
+```
+
+into this code:
+
+```rust
+#![feature(inline_const)]
+
+# fn add_one(x: i32) -> i32 { x + 1 }
+fn main() {
+    let x = add_one(const { 1 + 2 * 3 / 4 });
+}
+```
+
+You can also use inline constant expressions in patterns:
+
+```rust
+#![feature(inline_const)]
+
+const fn one() -> i32 { 1 }
+
+let some_int = 3;
+match some_int {
+    const { 1 + 2 } => println!("Matched 1 + 2"),
+    const { one() } => println!("Matched const fn returning 1"),
+    _ => println!("Didn't match anything :("),
+}
+```
+
+[#76001]: https://github.com/rust-lang/rust/issues/76001

From 09135e4e758c6fb5a3ca91924a78521f749acda9 Mon Sep 17 00:00:00 2001
From: Yuki Okushi <huyuumi.dev@gmail.com>
Date: Fri, 23 Oct 2020 16:09:17 +0900
Subject: [PATCH 23/34] Add regression test for issue-77475

---
 src/test/ui/macros/issue-77475.rs | 10 ++++++++++
 1 file changed, 10 insertions(+)
 create mode 100644 src/test/ui/macros/issue-77475.rs

diff --git a/src/test/ui/macros/issue-77475.rs b/src/test/ui/macros/issue-77475.rs
new file mode 100644
index 0000000000000..7b32a33ea4f17
--- /dev/null
+++ b/src/test/ui/macros/issue-77475.rs
@@ -0,0 +1,10 @@
+// check-pass
+// Regression test of #77475, this used to be ICE.
+
+#![feature(decl_macro)]
+
+use crate as _;
+
+pub macro ice(){}
+
+fn main() {}

From e1c524cd457bd02435a47214052320f8d4bfa999 Mon Sep 17 00:00:00 2001
From: Bastian Kauschke <bastian_kauschke@hotmail.de>
Date: Fri, 23 Oct 2020 09:33:47 +0200
Subject: [PATCH 24/34] review

---
 compiler/rustc_middle/src/infer/unify_key.rs | 21 +++++++++-----------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index cf5e99845d189..16e9aafb25a54 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -175,19 +175,15 @@ impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
     type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>);
 
-    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
-        let (val, origin) = match (value1.val, value2.val) {
+    fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> {
+        Ok(match (value1.val, value2.val) {
             (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
                 bug!("equating two const variables, both of which have known values")
             }
 
             // If one side is known, prefer that one.
-            (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => {
-                (value1.val, value1.origin)
-            }
-            (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => {
-                (value2.val, value2.origin)
-            }
+            (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1,
+            (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2,
 
             // If both sides are *unknown*, it hardly matters, does it?
             (
@@ -200,11 +196,12 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
                 // universe is the minimum of the two universes, because that is
                 // the one which contains the fewest names in scope.
                 let universe = cmp::min(universe1, universe2);
-                (ConstVariableValue::Unknown { universe }, value1.origin)
+                ConstVarValue {
+                    val: ConstVariableValue::Unknown { universe },
+                    origin: value1.origin,
+                }
             }
-        };
-
-        Ok(ConstVarValue { origin, val })
+        })
     }
 }
 

From 9b90e1762e6cb21baa504a27530b9aa404fbe3ac Mon Sep 17 00:00:00 2001
From: Canop <cano.petrole@gmail.com>
Date: Thu, 1 Oct 2020 11:13:38 +0200
Subject: [PATCH 25/34] add `insert` and `insert_with` to `Option`

This removes a cause of `unwrap` and code complexity.

This allows replacing

```
option_value = Some(build());
option_value.as_mut().unwrap()
```

with

```
option_value.insert(build())
```

or

```
option_value.insert_with(build)
```

It's also useful in contexts not requiring the mutability of the reference.

Here's a typical cache example:

```
let checked_cache = cache.as_ref().filter(|e| e.is_valid());
let content = match checked_cache {
	Some(e) => &e.content,
	None => {
	    cache = Some(compute_cache_entry());
	    // unwrap is OK because we just filled the option
	    &cache.as_ref().unwrap().content
	}
};
```

It can be changed into

```
let checked_cache = cache.as_ref().filter(|e| e.is_valid());
let content = match checked_cache {
	Some(e) => &e.content,
	None => &cache.insert_with(compute_cache_entry).content,
};
```
---
 library/core/src/option.rs | 46 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 825144e5a6fbe..394be746ec2fa 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -562,6 +562,52 @@ impl<T> Option<T> {
         }
     }
 
+    /////////////////////////////////////////////////////////////////////////
+    // Setting a new value
+    /////////////////////////////////////////////////////////////////////////
+
+    /// Inserts `v` into the option then returns a mutable reference
+    /// to the contained value.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(option_insert)]
+    ///
+    /// let mut o = None;
+    /// let v = o.insert(3);
+    /// assert_eq!(*v, 3);
+    /// ```
+    #[inline]
+    #[unstable(feature = "option_insert", reason = "new API", issue = "none")]
+    pub fn insert(&mut self, v: T) -> &mut T {
+        self.insert_with(|| v)
+    }
+
+    /// Inserts a value computed from `f` into the option, then returns a
+    /// mutable reference to the contained value.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(option_insert)]
+    ///
+    /// let mut o = None;
+    /// let v = o.insert_with(|| 3);
+    /// assert_eq!(*v, 3);
+    /// ```
+    #[inline]
+    #[unstable(feature = "option_insert", reason = "new API", issue = "none")]
+    pub fn insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
+        *self = Some(f());
+
+        match *self {
+            Some(ref mut v) => v,
+            // SAFETY: the code above just filled the option
+            None => unsafe { hint::unreachable_unchecked() },
+        }
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Iterator constructors
     /////////////////////////////////////////////////////////////////////////

From e8df2a426959fa3ff4f65eae85e618394bf27e28 Mon Sep 17 00:00:00 2001
From: Canop <cano.petrole@gmail.com>
Date: Thu, 1 Oct 2020 13:24:33 +0200
Subject: [PATCH 26/34] remove `option.insert_with`

`option.insert` covers both needs anyway, `insert_with` is
redundant.
---
 library/core/src/option.rs | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 394be746ec2fa..64541da300e86 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -581,25 +581,7 @@ impl<T> Option<T> {
     #[inline]
     #[unstable(feature = "option_insert", reason = "new API", issue = "none")]
     pub fn insert(&mut self, v: T) -> &mut T {
-        self.insert_with(|| v)
-    }
-
-    /// Inserts a value computed from `f` into the option, then returns a
-    /// mutable reference to the contained value.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// #![feature(option_insert)]
-    ///
-    /// let mut o = None;
-    /// let v = o.insert_with(|| 3);
-    /// assert_eq!(*v, 3);
-    /// ```
-    #[inline]
-    #[unstable(feature = "option_insert", reason = "new API", issue = "none")]
-    pub fn insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
-        *self = Some(f());
+        *self = Some(v);
 
         match *self {
             Some(ref mut v) => v,

From 60a96cae336b621be3a5e01cf6c87649b327f836 Mon Sep 17 00:00:00 2001
From: Canop <cano.petrole@gmail.com>
Date: Thu, 1 Oct 2020 16:05:01 +0200
Subject: [PATCH 27/34] more tests in option.insert, code cleaning in option

Code cleaning made according to suggestions in discussion
on PR ##77392 impacts insert, get_or_insert and get_or_insert_with.
---
 library/core/src/option.rs | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 64541da300e86..65575f4c41bad 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -574,17 +574,22 @@ impl<T> Option<T> {
     /// ```
     /// #![feature(option_insert)]
     ///
-    /// let mut o = None;
-    /// let v = o.insert(3);
-    /// assert_eq!(*v, 3);
+    /// let mut opt = None;
+    /// let val = opt.insert(1);
+    /// assert_eq!(*val, 1);
+    /// assert_eq!(opt.unwrap(), 1);
+    /// let val = opt.insert(2);
+    /// assert_eq!(*val, 2);
+    /// *val = 3;
+    /// assert_eq!(opt.unwrap(), 3);
     /// ```
     #[inline]
-    #[unstable(feature = "option_insert", reason = "new API", issue = "none")]
-    pub fn insert(&mut self, v: T) -> &mut T {
-        *self = Some(v);
+    #[unstable(feature = "option_insert", reason = "newly added", issue = "none")]
+    pub fn insert(&mut self, val: T) -> &mut T {
+        *self = Some(val);
 
-        match *self {
-            Some(ref mut v) => v,
+        match self {
+            Some(v) => v,
             // SAFETY: the code above just filled the option
             None => unsafe { hint::unreachable_unchecked() },
         }
@@ -839,8 +844,8 @@ impl<T> Option<T> {
     /// ```
     #[inline]
     #[stable(feature = "option_entry", since = "1.20.0")]
-    pub fn get_or_insert(&mut self, v: T) -> &mut T {
-        self.get_or_insert_with(|| v)
+    pub fn get_or_insert(&mut self, val: T) -> &mut T {
+        self.get_or_insert_with(|| val)
     }
 
     /// Inserts a value computed from `f` into the option if it is [`None`], then
@@ -867,8 +872,8 @@ impl<T> Option<T> {
             *self = Some(f());
         }
 
-        match *self {
-            Some(ref mut v) => v,
+        match self {
+            Some(v) => v,
             // SAFETY: a `None` variant for `self` would have been replaced by a `Some`
             // variant in the code above.
             None => unsafe { hint::unreachable_unchecked() },

From cc8b77a7cf0e1179b148a70c8f760a7ba3c1debd Mon Sep 17 00:00:00 2001
From: Canop <cano.petrole@gmail.com>
Date: Sat, 3 Oct 2020 10:29:11 +0200
Subject: [PATCH 28/34] fix naming unconsistency between function doc and
 prototype

---
 library/core/src/option.rs | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 65575f4c41bad..8fd3bfe77b800 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -566,8 +566,7 @@ impl<T> Option<T> {
     // Setting a new value
     /////////////////////////////////////////////////////////////////////////
 
-    /// Inserts `v` into the option then returns a mutable reference
-    /// to the contained value.
+    /// Inserts `value` into the option then returns a mutable reference to it.
     ///
     /// # Example
     ///
@@ -585,8 +584,8 @@ impl<T> Option<T> {
     /// ```
     #[inline]
     #[unstable(feature = "option_insert", reason = "newly added", issue = "none")]
-    pub fn insert(&mut self, val: T) -> &mut T {
-        *self = Some(val);
+    pub fn insert(&mut self, value: T) -> &mut T {
+        *self = Some(value);
 
         match self {
             Some(v) => v,
@@ -825,7 +824,7 @@ impl<T> Option<T> {
     // Entry-like operations to insert if None and return a reference
     /////////////////////////////////////////////////////////////////////////
 
-    /// Inserts `v` into the option if it is [`None`], then
+    /// Inserts `value` into the option if it is [`None`], then
     /// returns a mutable reference to the contained value.
     ///
     /// # Examples
@@ -844,12 +843,12 @@ impl<T> Option<T> {
     /// ```
     #[inline]
     #[stable(feature = "option_entry", since = "1.20.0")]
-    pub fn get_or_insert(&mut self, val: T) -> &mut T {
-        self.get_or_insert_with(|| val)
+    pub fn get_or_insert(&mut self, value: T) -> &mut T {
+        self.get_or_insert_with(|| value)
     }
 
-    /// Inserts a value computed from `f` into the option if it is [`None`], then
-    /// returns a mutable reference to the contained value.
+    /// Inserts a value computed from `f` into the option if it is [`None`],
+    /// then returns a mutable reference to the contained value.
     ///
     /// # Examples
     ///

From 39557799c763d75b58cbd7235af49a29c4d1212c Mon Sep 17 00:00:00 2001
From: Canop <cano.petrole@gmail.com>
Date: Fri, 23 Oct 2020 11:08:09 +0200
Subject: [PATCH 29/34] Update library/core/src/option.rs

Co-authored-by: Mara Bos <m-ou.se@m-ou.se>
---
 library/core/src/option.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 8fd3bfe77b800..4e8a74d9162a5 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -568,6 +568,8 @@ impl<T> Option<T> {
 
     /// Inserts `value` into the option then returns a mutable reference to it.
     ///
+    /// If the option already contains a value, the old value is dropped.
+    ///
     /// # Example
     ///
     /// ```

From 415a8e526d0e99f0e85e3b06bad9d2f2867910c5 Mon Sep 17 00:00:00 2001
From: Canop <cano.petrole@gmail.com>
Date: Fri, 23 Oct 2020 11:09:15 +0200
Subject: [PATCH 30/34] Update library/core/src/option.rs

Co-authored-by: Ivan Tham <pickfire@riseup.net>
---
 library/core/src/option.rs | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 4e8a74d9162a5..a3d20f016fd98 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -562,10 +562,6 @@ impl<T> Option<T> {
         }
     }
 
-    /////////////////////////////////////////////////////////////////////////
-    // Setting a new value
-    /////////////////////////////////////////////////////////////////////////
-
     /// Inserts `value` into the option then returns a mutable reference to it.
     ///
     /// If the option already contains a value, the old value is dropped.

From 216d0fe36466ce9307a643a67afa41ebfb8c43dd Mon Sep 17 00:00:00 2001
From: Canop <cano.petrole@gmail.com>
Date: Fri, 23 Oct 2020 11:44:58 +0200
Subject: [PATCH 31/34] add tracking issue number to option_insert feature gate

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

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index a3d20f016fd98..3daf26208b937 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -581,7 +581,7 @@ impl<T> Option<T> {
     /// assert_eq!(opt.unwrap(), 3);
     /// ```
     #[inline]
-    #[unstable(feature = "option_insert", reason = "newly added", issue = "none")]
+    #[unstable(feature = "option_insert", reason = "newly added", issue = "78271")]
     pub fn insert(&mut self, value: T) -> &mut T {
         *self = Some(value);
 

From efedcb23447a805fad841c4e38d5dea0d53ec3c7 Mon Sep 17 00:00:00 2001
From: Eduardo Pinho <enet4mikeenet@gmail.com>
Date: Fri, 23 Oct 2020 12:13:07 +0100
Subject: [PATCH 32/34] Update description of Empty Enum for accuracy

An empty enum is similar to the never type `!`, rather than the unit type `()`.
---
 library/std/src/keyword_docs.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index a4bbb18da5983..9b704ee9ecab2 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -346,7 +346,7 @@ mod else_keyword {}
 /// When data follows along with a variant, such as with rust's built-in [`Option`] type, the data
 /// is added as the type describes, for example `Option::Some(123)`. The same follows with
 /// struct-like variants, with things looking like `ComplexEnum::LotsOfThings { usual_struct_stuff:
-/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to () in that they cannot be
+/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to [`!`] in that they cannot be
 /// instantiated at all, and are used mainly to mess with the type system in interesting ways.
 ///
 /// For more information, take a look at the [Rust Book] or the [Reference]
@@ -354,6 +354,7 @@ mod else_keyword {}
 /// [ADT]: https://en.wikipedia.org/wiki/Algebraic_data_type
 /// [Rust Book]: ../book/ch06-01-defining-an-enum.html
 /// [Reference]: ../reference/items/enumerations.html
+/// [`!`]: primitive.never.html
 mod enum_keyword {}
 
 #[doc(keyword = "extern")]

From 972d9e886ca8787b2b4223bd39a76ff0250dfcaf Mon Sep 17 00:00:00 2001
From: Bastian Kauschke <bastian_kauschke@hotmail.de>
Date: Fri, 23 Oct 2020 13:58:32 +0200
Subject: [PATCH 33/34] move `visit_predicate` into `TypeVisitor`

---
 compiler/rustc_middle/src/ty/fold.rs             | 11 +++++------
 compiler/rustc_middle/src/ty/structural_impls.rs | 10 ----------
 2 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 5524d91a6d533..0e5e22dcaae9f 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -30,8 +30,6 @@
 //!
 //! These methods return true to indicate that the visitor has found what it is
 //! looking for, and does not need to visit anything else.
-
-use crate::ty::structural_impls::PredicateVisitor;
 use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -211,6 +209,10 @@ pub trait TypeVisitor<'tcx>: Sized {
     fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
         c.super_visit_with(self)
     }
+
+    fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> bool {
+        p.super_visit_with(self)
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -868,9 +870,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
             _ => ct.super_visit_with(self),
         }
     }
-}
 
-impl<'tcx> PredicateVisitor<'tcx> for HasEscapingVarsVisitor {
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
         predicate.inner.outer_exclusive_binder > self.outer_index
     }
@@ -903,9 +903,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
         debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
         flags.intersects(self.flags)
     }
-}
 
-impl<'tcx> PredicateVisitor<'tcx> for HasTypeFlagsVisitor {
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
         debug!(
             "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
@@ -914,6 +912,7 @@ impl<'tcx> PredicateVisitor<'tcx> for HasTypeFlagsVisitor {
         predicate.inner.flags.intersects(self.flags)
     }
 }
+
 /// Collects all the late-bound regions at the innermost binding level
 /// into a hash set.
 struct LateBoundRegionsCollector {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index d9ec6bb20fda8..53521d0e9f332 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -1040,16 +1040,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
     }
 }
 
-pub(super) trait PredicateVisitor<'tcx>: TypeVisitor<'tcx> {
-    fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool;
-}
-
-impl<T: TypeVisitor<'tcx>> PredicateVisitor<'tcx> for T {
-    default fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
-        predicate.super_visit_with(self)
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         fold_list(*self, folder, |tcx, v| tcx.intern_predicates(v))

From a0ce1e095e0d89d35ff3de20541dd4faf79607da Mon Sep 17 00:00:00 2001
From: nasso <nassomails@gmail.com>
Date: Fri, 23 Oct 2020 18:58:42 +0200
Subject: [PATCH 34/34] Always store Rustdoc theme when it's changed

---
 src/librustdoc/html/static/storage.js | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
index a027d6845ea21..ef734f260afd5 100644
--- a/src/librustdoc/html/static/storage.js
+++ b/src/librustdoc/html/static/storage.js
@@ -94,6 +94,12 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
     var fullNewTheme = newTheme + resourcesSuffix + ".css";
     var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
 
+    // If this new value comes from a system setting or from the previously
+    // saved theme, no need to save it.
+    if (saveTheme === true) {
+        updateLocalStorage("rustdoc-theme", newTheme);
+    }
+
     if (styleElem.href === newHref) {
         return;
     }
@@ -112,11 +118,6 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
     });
     if (found === true) {
         styleElem.href = newHref;
-        // If this new value comes from a system setting or from the previously
-        // saved theme, no need to save it.
-        if (saveTheme === true) {
-            updateLocalStorage("rustdoc-theme", newTheme);
-        }
     }
 }