From aa40c028fcb20a47fb214fea2899ff9a8ae88840 Mon Sep 17 00:00:00 2001
From: Arkadiusz Piekarz <piekarzarkadiusz@gmail.com>
Date: Wed, 26 Aug 2020 22:03:29 +0200
Subject: [PATCH 01/21] Unstable Book: add links to tracking issues for FFI
 features

---
 src/doc/unstable-book/src/language-features/ffi-const.md | 5 +++++
 src/doc/unstable-book/src/language-features/ffi-pure.md  | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/src/doc/unstable-book/src/language-features/ffi-const.md b/src/doc/unstable-book/src/language-features/ffi-const.md
index 9a1ced4033b22..24a304437542d 100644
--- a/src/doc/unstable-book/src/language-features/ffi-const.md
+++ b/src/doc/unstable-book/src/language-features/ffi-const.md
@@ -1,5 +1,9 @@
 # `ffi_const`
 
+The tracking issue for this feature is: [#58328]
+
+------
+
 The `#[ffi_const]` attribute applies clang's `const` attribute to foreign
 functions declarations.
 
@@ -42,6 +46,7 @@ implemented in this way on all of them. It is therefore also worth verifying
 that the semantics of the C toolchain used to compile the binary being linked
 against are compatible with those of the `#[ffi_const]`.
 
+[#58328]: https://github.com/rust-lang/rust/issues/58328
 [ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacgigch.html
 [GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
 [IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_const.htm
diff --git a/src/doc/unstable-book/src/language-features/ffi-pure.md b/src/doc/unstable-book/src/language-features/ffi-pure.md
index 7bfd7a378f00b..4aef4eeab5532 100644
--- a/src/doc/unstable-book/src/language-features/ffi-pure.md
+++ b/src/doc/unstable-book/src/language-features/ffi-pure.md
@@ -1,5 +1,9 @@
 # `ffi_pure`
 
+The tracking issue for this feature is: [#58329]
+
+------
+
 The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign
 functions declarations.
 
@@ -46,6 +50,7 @@ that the semantics of the C toolchain used to compile the binary being linked
 against are compatible with those of the `#[ffi_pure]`.
 
 
+[#58329]: https://github.com/rust-lang/rust/issues/58329
 [ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html
 [GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
 [IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm

From f03d0b38d6a33a64307d83f8ddd3df8ef57ca537 Mon Sep 17 00:00:00 2001
From: mental32 <m3nta1@yahoo.com>
Date: Thu, 27 Aug 2020 19:19:29 +0100
Subject: [PATCH 02/21] `impl Rc::new_cyclic`

---
 library/alloc/src/rc.rs       | 34 ++++++++++++++++++
 library/alloc/src/rc/tests.rs | 66 +++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+)

diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 1046397f4be60..76266d77bb0d2 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -325,6 +325,40 @@ impl<T> Rc<T> {
         )
     }
 
+    /// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
+    /// to upgrade the weak reference before this function retuns will result
+    /// in a `None` value. However, the weak reference may be cloned freely and
+    /// stored for use at a later time.
+    #[inline]
+    #[unstable(feature = "arc_new_cyclic", issue = "75861")]
+    pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
+        let uninit_ptr: NonNull<_> = Box::leak(box RcBox {
+            strong: Cell::new(0),
+            weak: Cell::new(1),
+            value: mem::MaybeUninit::<T>::uninit(),
+        })
+        .into();
+
+        let init_ptr: NonNull<RcBox<T>> = uninit_ptr.cast();
+
+        let weak = Weak { ptr: init_ptr };
+
+        let data = data_fn(&weak);
+
+        unsafe {
+            let inner = init_ptr.as_ptr();
+            ptr::write(&raw mut (*inner).value, data);
+
+            let prev_value = (*inner).strong.get();
+            debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
+            (*inner).strong.set(1);
+        }
+
+        let strong = Rc::from_inner(init_ptr);
+        mem::forget(weak);
+        strong
+    }
+
     /// Constructs a new `Rc` with uninitialized contents.
     ///
     /// # Examples
diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs
index e88385faf4fd4..fed48a59f809e 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloc/src/rc/tests.rs
@@ -434,3 +434,69 @@ fn test_array_from_slice() {
     let a: Result<Rc<[u32; 2]>, _> = r.clone().try_into();
     assert!(a.is_err());
 }
+
+#[test]
+fn test_rc_cyclic_with_zero_refs() {
+    struct ZeroRefs {
+        inner: Weak<ZeroRefs>,
+    }
+
+    let zero_refs = Rc::new_cyclic(|inner| {
+        assert_eq!(inner.strong_count(), 0);
+        assert!(inner.upgrade().is_none());
+        ZeroRefs { inner: Weak::new() }
+    });
+
+    assert_eq!(Rc::strong_count(&zero_refs), 1);
+    assert_eq!(Rc::weak_count(&zero_refs), 0);
+    assert_eq!(zero_refs.inner.strong_count(), 0);
+    assert_eq!(zero_refs.inner.weak_count(), 0);
+}
+
+#[test]
+fn test_rc_cyclic_with_one_ref() {
+    struct OneRef {
+        inner: Weak<OneRef>,
+    }
+
+    let one_ref = Rc::new_cyclic(|inner| {
+        assert_eq!(inner.strong_count(), 0);
+        assert!(inner.upgrade().is_none());
+        OneRef { inner: inner.clone() }
+    });
+
+    assert_eq!(Rc::strong_count(&one_ref), 1);
+    assert_eq!(Rc::weak_count(&one_ref), 1);
+
+    let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap();
+    assert!(Rc::ptr_eq(&one_ref, &one_ref2));
+
+    assert_eq!(one_ref.inner.strong_count(), 2);
+    assert_eq!(one_ref.inner.weak_count(), 1);
+}
+
+#[test]
+fn test_rc_cyclic_with_two_ref() {
+    struct TwoRefs {
+        inner: Weak<TwoRefs>,
+        inner1: Weak<TwoRefs>,
+    }
+
+    let two_refs = Rc::new_cyclic(|inner| {
+        assert_eq!(inner.strong_count(), 0);
+        assert!(inner.upgrade().is_none());
+        TwoRefs { inner: inner.clone(), inner1: inner.clone() }
+    });
+
+    assert_eq!(Rc::strong_count(&two_refs), 1);
+    assert_eq!(Rc::weak_count(&two_refs), 2);
+
+    let two_ref3 = Weak::upgrade(&two_refs.inner).unwrap();
+    assert!(Rc::ptr_eq(&two_refs, &two_ref3));
+
+    let two_ref2 = Weak::upgrade(&two_refs.inner1).unwrap();
+    assert!(Rc::ptr_eq(&two_refs, &two_ref2));
+
+    assert_eq!(Rc::strong_count(&two_refs), 3);
+    assert_eq!(Rc::weak_count(&two_refs), 2);
+}

From 42fb27001e07e832cb40604c7daeaa6aada07675 Mon Sep 17 00:00:00 2001
From: mental <m3nta1@yahoo.com>
Date: Sat, 29 Aug 2020 07:39:03 +0100
Subject: [PATCH 03/21] typo

Co-authored-by: Andrew Hickman <andrew.hickman1@sky.com>
---
 library/alloc/src/rc.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 76266d77bb0d2..7dbdc8f6017fe 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -326,7 +326,7 @@ impl<T> Rc<T> {
     }
 
     /// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
-    /// to upgrade the weak reference before this function retuns will result
+    /// to upgrade the weak reference before this function returns will result
     /// in a `None` value. However, the weak reference may be cloned freely and
     /// stored for use at a later time.
     #[inline]

From bb5e79cbd11dbb8aa91840108b67085e5d5d04f8 Mon Sep 17 00:00:00 2001
From: Ivan Tham <pickfire@riseup.net>
Date: Sat, 29 Aug 2020 18:47:11 +0800
Subject: [PATCH 04/21] Link vec doc to & reference

It is not always obvious that people could see the docs for `&`
especially for beginners, it also helps learnability.
---
 library/alloc/src/vec.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index b4ad238680f79..5e6493c27ae0f 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -159,7 +159,7 @@ use crate::raw_vec::RawVec;
 /// # Slicing
 ///
 /// A `Vec` can be mutable. Slices, on the other hand, are read-only objects.
-/// To get a slice, use `&`. Example:
+/// To get a slice, use [`&`][prim@reference]. Example:
 ///
 /// ```
 /// fn read_slice(slice: &[usize]) {

From 20a68666d89a85e14021f656233a086e46ff8a34 Mon Sep 17 00:00:00 2001
From: Ivan Tham <pickfire@riseup.net>
Date: Sun, 30 Aug 2020 09:17:22 +0800
Subject: [PATCH 05/21] Try removing [prim@reference]

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

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index 5e6493c27ae0f..35d64d85010c3 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -159,7 +159,7 @@ use crate::raw_vec::RawVec;
 /// # Slicing
 ///
 /// A `Vec` can be mutable. Slices, on the other hand, are read-only objects.
-/// To get a slice, use [`&`][prim@reference]. Example:
+/// To get a slice, use [`&`]. Example:
 ///
 /// ```
 /// fn read_slice(slice: &[usize]) {

From 81e85ce76d6630a8f87f81df2470e76fbe73de7d Mon Sep 17 00:00:00 2001
From: Alexis Bourget <alexis.bourget@gmail.com>
Date: Sun, 30 Aug 2020 21:59:43 +0200
Subject: [PATCH 06/21] Move to Arc::clone(&x) over x.clone() in library/std

---
 library/std/src/collections/hash/map.rs |  4 ++--
 library/std/src/sync/barrier.rs         |  4 ++--
 library/std/src/sync/condvar.rs         | 18 +++++++++---------
 library/std/src/sync/mutex.rs           |  8 ++++----
 library/std/src/sync/rwlock.rs          |  4 ++--
 library/std/src/sys_common/poison.rs    |  4 ++--
 6 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 70f7214e2f1d7..56f63002b7f11 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2381,7 +2381,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// use std::rc::Rc;
     ///
     /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// let mut known_strings: Vec<Rc<String>> = Vec::new();
+    /// let known_strings: Vec<Rc<String>> = Vec::new();
     ///
     /// // Initialise known strings, run program, etc.
     ///
@@ -2389,7 +2389,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
     ///     for s in known_strings {
-    ///         if let Entry::Occupied(entry) = map.entry(s.clone()) {
+    ///         if let Entry::Occupied(entry) = map.entry(Rc::clone(s)) {
     ///             // Replaces the entry's key with our version of it in `known_strings`.
     ///             entry.replace_key();
     ///         }
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index 23c989fd2fdfb..61f097ccf250c 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -13,7 +13,7 @@ use crate::sync::{Condvar, Mutex};
 /// let mut handles = Vec::with_capacity(10);
 /// let barrier = Arc::new(Barrier::new(10));
 /// for _ in 0..10 {
-///     let c = barrier.clone();
+///     let c = Arc::clone(&barrier);
 ///     // The same messages will be printed together.
 ///     // You will NOT see any interleaving.
 ///     handles.push(thread::spawn(move|| {
@@ -110,7 +110,7 @@ impl Barrier {
     /// let mut handles = Vec::with_capacity(10);
     /// let barrier = Arc::new(Barrier::new(10));
     /// for _ in 0..10 {
-    ///     let c = barrier.clone();
+    ///     let c = Arc::clone(&barrier);
     ///     // The same messages will be printed together.
     ///     // You will NOT see any interleaving.
     ///     handles.push(thread::spawn(move|| {
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 4efd86aa3ede8..1fbcb0ac08e0f 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -33,7 +33,7 @@ impl WaitTimeoutResult {
     /// use std::time::Duration;
     ///
     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move || {
     ///     let (lock, cvar) = &*pair2;
@@ -90,7 +90,7 @@ impl WaitTimeoutResult {
 /// use std::thread;
 ///
 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
-/// let pair2 = pair.clone();
+/// let pair2 = Arc::clone(&pair);
 ///
 /// // Inside of our lock, spawn a new thread, and then wait for it to start.
 /// thread::spawn(move|| {
@@ -173,7 +173,7 @@ impl Condvar {
     /// use std::thread;
     ///
     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
@@ -229,7 +229,7 @@ impl Condvar {
     /// use std::thread;
     ///
     /// let pair = Arc::new((Mutex::new(true), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
@@ -288,7 +288,7 @@ impl Condvar {
     /// use std::thread;
     ///
     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
@@ -360,7 +360,7 @@ impl Condvar {
     /// use std::time::Duration;
     ///
     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
@@ -429,7 +429,7 @@ impl Condvar {
     /// use std::time::Duration;
     ///
     /// let pair = Arc::new((Mutex::new(true), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
@@ -493,7 +493,7 @@ impl Condvar {
     /// use std::thread;
     ///
     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
@@ -533,7 +533,7 @@ impl Condvar {
     /// use std::thread;
     ///
     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    /// let pair2 = pair.clone();
+    /// let pair2 = Arc::clone(&pair);
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index d7a4f00305c71..39a5a455fe4d5 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -85,7 +85,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 /// use std::thread;
 ///
 /// let lock = Arc::new(Mutex::new(0_u32));
-/// let lock2 = lock.clone();
+/// let lock2 = Arc::clone(&lock);
 ///
 /// let _ = thread::spawn(move || -> () {
 ///     // This thread will acquire the mutex first, unwrapping the result of
@@ -256,7 +256,7 @@ impl<T: ?Sized> Mutex<T> {
     /// use std::thread;
     ///
     /// let mutex = Arc::new(Mutex::new(0));
-    /// let c_mutex = mutex.clone();
+    /// let c_mutex = Arc::clone(&mutex);
     ///
     /// thread::spawn(move || {
     ///     *c_mutex.lock().unwrap() = 10;
@@ -292,7 +292,7 @@ impl<T: ?Sized> Mutex<T> {
     /// use std::thread;
     ///
     /// let mutex = Arc::new(Mutex::new(0));
-    /// let c_mutex = mutex.clone();
+    /// let c_mutex = Arc::clone(&mutex);
     ///
     /// thread::spawn(move || {
     ///     let mut lock = c_mutex.try_lock();
@@ -328,7 +328,7 @@ impl<T: ?Sized> Mutex<T> {
     /// use std::thread;
     ///
     /// let mutex = Arc::new(Mutex::new(0));
-    /// let c_mutex = mutex.clone();
+    /// let c_mutex = Arc::clone(&mutex);
     ///
     /// let _ = thread::spawn(move || {
     ///     let _lock = c_mutex.lock().unwrap();
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 586093c916dea..b7f135f5c8af4 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -162,7 +162,7 @@ impl<T: ?Sized> RwLock<T> {
     /// use std::thread;
     ///
     /// let lock = Arc::new(RwLock::new(1));
-    /// let c_lock = lock.clone();
+    /// let c_lock = Arc::clone(&lock);
     ///
     /// let n = lock.read().unwrap();
     /// assert_eq!(*n, 1);
@@ -318,7 +318,7 @@ impl<T: ?Sized> RwLock<T> {
     /// use std::thread;
     ///
     /// let lock = Arc::new(RwLock::new(0));
-    /// let c_lock = lock.clone();
+    /// let c_lock = Arc::clone(&lock);
     ///
     /// let _ = thread::spawn(move || {
     ///     let _lock = c_lock.write().unwrap();
diff --git a/library/std/src/sys_common/poison.rs b/library/std/src/sys_common/poison.rs
index 3f079da9098c7..2ab2c700a1bf1 100644
--- a/library/std/src/sys_common/poison.rs
+++ b/library/std/src/sys_common/poison.rs
@@ -65,7 +65,7 @@ pub struct Guard {
 /// let mutex = Arc::new(Mutex::new(1));
 ///
 /// // poison the mutex
-/// let c_mutex = mutex.clone();
+/// let c_mutex = Arc::clone(&mutex);
 /// let _ = thread::spawn(move || {
 ///     let mut data = c_mutex.lock().unwrap();
 ///     *data = 2;
@@ -168,7 +168,7 @@ impl<T> PoisonError<T> {
     /// let mutex = Arc::new(Mutex::new(HashSet::new()));
     ///
     /// // poison the mutex
-    /// let c_mutex = mutex.clone();
+    /// let c_mutex = Arc::clone(&mutex);
     /// let _ = thread::spawn(move || {
     ///     let mut data = c_mutex.lock().unwrap();
     ///     data.insert(10);

From 6b75e3d11b89671df0a3f284252584414bfe17d9 Mon Sep 17 00:00:00 2001
From: Alexis Bourget <alexis.bourget@gmail.com>
Date: Sun, 30 Aug 2020 22:14:17 +0200
Subject: [PATCH 07/21] Move to Arc::clone(&x) over x.clone() in library/core

---
 library/core/src/pin.rs         | 2 +-
 library/core/src/sync/atomic.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 8f60c4787d459..fc17f64879a50 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -541,7 +541,7 @@ impl<P: Deref> Pin<P> {
     /// use std::pin::Pin;
     ///
     /// fn move_pinned_rc<T>(mut x: Rc<T>) {
-    ///     let pinned = unsafe { Pin::new_unchecked(x.clone()) };
+    ///     let pinned = unsafe { Pin::new_unchecked(Rc::clone(&x)) };
     ///     {
     ///         let p: Pin<&T> = pinned.as_ref();
     ///         // This should mean the pointee can never move again.
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 1aec7e1b5f871..38eabaaa396e0 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -76,7 +76,7 @@
 //! fn main() {
 //!     let spinlock = Arc::new(AtomicUsize::new(1));
 //!
-//!     let spinlock_clone = spinlock.clone();
+//!     let spinlock_clone = Arc::clone(&spinlock);
 //!     let thread = thread::spawn(move|| {
 //!         spinlock_clone.store(0, Ordering::SeqCst);
 //!     });

From 0f301e8bb40aaf7cbfefb8c16ce3b0a112c6d5c1 Mon Sep 17 00:00:00 2001
From: mental <m3nta1@yahoo.com>
Date: Tue, 1 Sep 2020 09:46:48 +0100
Subject: [PATCH 08/21] Removed [inline] and copied over comments from
 Arc::new_cyclic

---
 library/alloc/src/rc.rs | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 7dbdc8f6017fe..1a2dfd2888261 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -329,9 +329,10 @@ impl<T> Rc<T> {
     /// to upgrade the weak reference before this function returns will result
     /// in a `None` value. However, the weak reference may be cloned freely and
     /// stored for use at a later time.
-    #[inline]
     #[unstable(feature = "arc_new_cyclic", issue = "75861")]
     pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
+        // Construct the inner in the "uninitialized" state with a single
+        // weak reference.
         let uninit_ptr: NonNull<_> = Box::leak(box RcBox {
             strong: Cell::new(0),
             weak: Cell::new(1),
@@ -343,6 +344,12 @@ impl<T> Rc<T> {
 
         let weak = Weak { ptr: init_ptr };
 
+        // It's important we don't give up ownership of the weak pointer, or
+        // else the memory might be freed by the time `data_fn` returns. If
+        // we really wanted to pass ownership, we could create an additional
+        // weak pointer for ourselves, but this would result in additional
+        // updates to the weak reference count which might not be necessary
+        // otherwise.
         let data = data_fn(&weak);
 
         unsafe {
@@ -355,6 +362,9 @@ impl<T> Rc<T> {
         }
 
         let strong = Rc::from_inner(init_ptr);
+
+        // Strong references should collectively own a shared weak reference,
+        // so don't run the destructor for our old weak reference.
         mem::forget(weak);
         strong
     }

From 8783c62f0c8641ef56094fae13e2fed193b60d1f Mon Sep 17 00:00:00 2001
From: Camelid <37223377+camelid@users.noreply.github.com>
Date: Tue, 1 Sep 2020 17:48:15 -0700
Subject: [PATCH 09/21] Add missing link in README

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

diff --git a/README.md b/README.md
index a7e23d8ac2caa..6cf9577d3330e 100644
--- a/README.md
+++ b/README.md
@@ -243,6 +243,8 @@ The Rust community congregates in a few places:
 If you are interested in contributing to the Rust project, please take a look
 at the [Getting Started][gettingstarted] guide in the [rustc-dev-guide].
 
+[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org
+
 ## License
 
 Rust is primarily distributed under the terms of both the MIT license

From 3e29fdb0fb3be5a35d3e2d55d902be8b4ecbe7bb Mon Sep 17 00:00:00 2001
From: Rune Tynan <runetynan@gmail.com>
Date: Thu, 3 Sep 2020 01:37:40 -0400
Subject: [PATCH 10/21] Remove a number of vec UI tests, make them unit tests
 in the alloc library

---
 library/alloc/tests/vec.rs                | 53 +++++++++++++++++++++++
 src/test/ui/array-slice-vec/vec-concat.rs | 14 ------
 src/test/ui/array-slice-vec/vec-growth.rs | 16 -------
 src/test/ui/array-slice-vec/vec-push.rs   |  3 --
 src/test/ui/array-slice-vec/vec-slice.rs  |  9 ----
 src/test/ui/array-slice-vec/vec-to_str.rs |  5 ---
 src/test/ui/array-slice-vec/vec.rs        | 15 -------
 7 files changed, 53 insertions(+), 62 deletions(-)
 delete mode 100644 src/test/ui/array-slice-vec/vec-concat.rs
 delete mode 100644 src/test/ui/array-slice-vec/vec-growth.rs
 delete mode 100644 src/test/ui/array-slice-vec/vec-push.rs
 delete mode 100644 src/test/ui/array-slice-vec/vec-slice.rs
 delete mode 100644 src/test/ui/array-slice-vec/vec.rs

diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index ffff543b07fe5..b422960c19982 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -72,6 +72,39 @@ fn test_zst_capacity() {
     assert_eq!(Vec::<()>::new().capacity(), usize::MAX);
 }
 
+#[test]
+fn test_indexing() {
+    let v: Vec<isize> = vec![10, 20];
+    assert_eq!(v[0], 10);
+    assert_eq!(v[1], 20);
+    let mut x: usize = 0;
+    assert_eq!(v[x], 10);
+    assert_eq!(v[x + 1], 20);
+    x = x + 1;
+    assert_eq!(v[x], 20);
+    assert_eq!(v[x - 1], 10);
+}
+
+#[test]
+fn test_debug_fmt() {
+    let vec1: Vec<isize> = vec![];
+    assert_eq!("[]", format!("{:?}", vec1));
+
+    let vec2 = vec![0, 1];
+    assert_eq!("[0, 1]", format!("{:?}", vec2));
+}
+
+#[test]
+fn test_push() {
+    let mut v = vec![];
+    v.push(1);
+    assert_eq!(v, [1]);
+    v.push(2);
+    assert_eq!(v, [1, 2]);
+    v.push(3);
+    assert_eq!(v, [1, 2, 3]);
+}
+
 #[test]
 fn test_extend() {
     let mut v = Vec::new();
@@ -117,6 +150,18 @@ fn test_extend() {
     assert_eq!(count_x, 1);
 }
 
+#[test]
+fn test_extend_from_slice() {
+    let a: Vec<isize> = vec![1, 2, 3, 4, 5];
+    let b: Vec<isize> = vec![6, 7, 8, 9, 0];
+
+    let mut v: Vec<isize> = a;
+
+    v.extend_from_slice(&b);
+
+    assert_eq!(v, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
+}
+
 #[test]
 fn test_extend_ref() {
     let mut v = vec![1, 2];
@@ -132,6 +177,14 @@ fn test_extend_ref() {
     assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
 }
 
+#[test]
+fn test_slice_from_ref() {
+    let values = vec![1, 2, 3, 4, 5];
+    let slice = &values[1..3];
+
+    assert_eq!(slice, [2, 3]);
+}
+
 #[test]
 fn test_slice_from_mut() {
     let mut values = vec![1, 2, 3, 4, 5];
diff --git a/src/test/ui/array-slice-vec/vec-concat.rs b/src/test/ui/array-slice-vec/vec-concat.rs
deleted file mode 100644
index 1f493679b7947..0000000000000
--- a/src/test/ui/array-slice-vec/vec-concat.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-
-use std::vec;
-
-pub fn main() {
-    let a: Vec<isize> = vec![1, 2, 3, 4, 5];
-    let b: Vec<isize> = vec![6, 7, 8, 9, 0];
-    let mut v: Vec<isize> = a;
-    v.extend_from_slice(&b);
-    println!("{}", v[9]);
-    assert_eq!(v[0], 1);
-    assert_eq!(v[7], 8);
-    assert_eq!(v[9], 0);
-}
diff --git a/src/test/ui/array-slice-vec/vec-growth.rs b/src/test/ui/array-slice-vec/vec-growth.rs
deleted file mode 100644
index b09f08bb85a82..0000000000000
--- a/src/test/ui/array-slice-vec/vec-growth.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-
-
-
-pub fn main() {
-    let mut v = vec![1];
-    v.push(2);
-    v.push(3);
-    v.push(4);
-    v.push(5);
-    assert_eq!(v[0], 1);
-    assert_eq!(v[1], 2);
-    assert_eq!(v[2], 3);
-    assert_eq!(v[3], 4);
-    assert_eq!(v[4], 5);
-}
diff --git a/src/test/ui/array-slice-vec/vec-push.rs b/src/test/ui/array-slice-vec/vec-push.rs
deleted file mode 100644
index 466ab3fab1cab..0000000000000
--- a/src/test/ui/array-slice-vec/vec-push.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-// run-pass
-
-pub fn main() { let mut v = vec![1, 2, 3]; v.push(1); }
diff --git a/src/test/ui/array-slice-vec/vec-slice.rs b/src/test/ui/array-slice-vec/vec-slice.rs
deleted file mode 100644
index 1f090ddd9c97d..0000000000000
--- a/src/test/ui/array-slice-vec/vec-slice.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-
-
-pub fn main() {
-    let  v = vec![1,2,3,4,5];
-    let v2 = &v[1..3];
-    assert_eq!(v2[0], 2);
-    assert_eq!(v2[1], 3);
-}
diff --git a/src/test/ui/array-slice-vec/vec-to_str.rs b/src/test/ui/array-slice-vec/vec-to_str.rs
index a11cfc8e9b5c9..fbff19b862283 100644
--- a/src/test/ui/array-slice-vec/vec-to_str.rs
+++ b/src/test/ui/array-slice-vec/vec-to_str.rs
@@ -2,11 +2,6 @@
 
 
 pub fn main() {
-    assert_eq!(format!("{:?}", vec![0, 1]), "[0, 1]".to_string());
-
-    let foo = vec![3, 4];
     let bar: &[isize] = &[4, 5];
-
-    assert_eq!(format!("{:?}", foo), "[3, 4]");
     assert_eq!(format!("{:?}", bar), "[4, 5]");
 }
diff --git a/src/test/ui/array-slice-vec/vec.rs b/src/test/ui/array-slice-vec/vec.rs
deleted file mode 100644
index e76c1ab440e6e..0000000000000
--- a/src/test/ui/array-slice-vec/vec.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-
-
-pub fn main() {
-    let v: Vec<isize> = vec![10, 20];
-    assert_eq!(v[0], 10);
-    assert_eq!(v[1], 20);
-    let mut x: usize = 0;
-    assert_eq!(v[x], 10);
-    assert_eq!(v[x + 1], 20);
-    x = x + 1;
-    assert_eq!(v[x], 20);
-    assert_eq!(v[x - 1], 10);
-}

From 791f93c796f7b4f0346eee276baf6e31ed3c81ea Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Wed, 2 Sep 2020 23:39:50 -0700
Subject: [PATCH 11/21] Allow try blocks as the argument to return expressions

Fixes 76271
---
 compiler/rustc_ast/src/token.rs              |  1 +
 src/test/ui/try-block/try-block-in-return.rs | 12 ++++++++++++
 2 files changed, 13 insertions(+)
 create mode 100644 src/test/ui/try-block/try-block-in-return.rs

diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index c6cc890b47f79..f3da0ec130a52 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -173,6 +173,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
             kw::Move,
             kw::Return,
             kw::True,
+            kw::Try,
             kw::Unsafe,
             kw::While,
             kw::Yield,
diff --git a/src/test/ui/try-block/try-block-in-return.rs b/src/test/ui/try-block/try-block-in-return.rs
new file mode 100644
index 0000000000000..a15bfeef1c12d
--- /dev/null
+++ b/src/test/ui/try-block/try-block-in-return.rs
@@ -0,0 +1,12 @@
+// run-pass
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn issue_76271() -> Option<i32> {
+    return try { 4 }
+}
+
+fn main() {
+    assert_eq!(issue_76271(), Some(4));
+}

From 4231fbc0a8cb4b2b0df431d8ffcf308f837e07e3 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Thu, 3 Sep 2020 15:37:03 +0200
Subject: [PATCH 12/21] Condense StringReader's API to a single function

---
 compiler/rustc_parse/src/lexer/mod.rs         | 45 +++++++------------
 compiler/rustc_parse/src/lexer/tokentrees.rs  |  2 +-
 .../rustc_parse/src/lexer/unicode_chars.rs    |  2 +-
 compiler/rustc_parse/src/lib.rs               |  9 +++-
 4 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 034442b798b29..8099b8a24658d 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,22 +1,19 @@
 use rustc_ast::ast::AttrStyle;
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
-use rustc_ast::tokenstream::IsJoint;
-use rustc_data_structures::sync::Lrc;
-use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError};
-use rustc_lexer::Base;
-use rustc_lexer::{unescape, RawStrError};
+use rustc_ast::tokenstream::{IsJoint, TokenStream};
+use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
+use rustc_lexer::unescape::{self, Mode};
+use rustc_lexer::{Base, DocStyle, RawStrError};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{BytePos, Pos, Span};
 
-use std::char;
 use tracing::debug;
 
 mod tokentrees;
 mod unescape_error_reporting;
 mod unicode_chars;
 
-use rustc_lexer::{unescape::Mode, DocStyle};
 use unescape_error_reporting::{emit_unescape_error, push_escaped_char};
 
 #[derive(Clone, Debug)]
@@ -28,7 +25,17 @@ pub struct UnmatchedBrace {
     pub candidate_span: Option<Span>,
 }
 
-crate struct StringReader<'a> {
+crate fn parse_token_trees<'a>(
+    sess: &'a ParseSess,
+    src: &'a str,
+    start_pos: BytePos,
+    override_span: Option<Span>,
+) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+    StringReader { sess, start_pos, pos: start_pos, end_src_index: src.len(), src, override_span }
+        .into_token_trees()
+}
+
+struct StringReader<'a> {
     sess: &'a ParseSess,
     /// Initial position, read-only.
     start_pos: BytePos,
@@ -37,31 +44,11 @@ crate struct StringReader<'a> {
     /// Stop reading src at this index.
     end_src_index: usize,
     /// Source text to tokenize.
-    src: Lrc<String>,
+    src: &'a str,
     override_span: Option<Span>,
 }
 
 impl<'a> StringReader<'a> {
-    crate fn new(
-        sess: &'a ParseSess,
-        source_file: Lrc<rustc_span::SourceFile>,
-        override_span: Option<Span>,
-    ) -> Self {
-        let src = source_file.src.clone().unwrap_or_else(|| {
-            sess.span_diagnostic
-                .bug(&format!("cannot lex `source_file` without source: {}", source_file.name));
-        });
-
-        StringReader {
-            sess,
-            start_pos: source_file.start_pos,
-            pos: source_file.start_pos,
-            end_src_index: src.len(),
-            src,
-            override_span,
-        }
-    }
-
     fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
         self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi))
     }
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index d5977ca3c7d2f..357b10ab89d41 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -12,7 +12,7 @@ use rustc_errors::PResult;
 use rustc_span::Span;
 
 impl<'a> StringReader<'a> {
-    crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+    pub(super) fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
         let mut tt_reader = TokenTreesReader {
             string_reader: self,
             token: Token::dummy(),
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index 8dc0db01ecb51..40e2e34aa0589 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -332,7 +332,7 @@ const ASCII_ARRAY: &[(char, &str, Option<token::TokenKind>)] = &[
     ('"', "Quotation Mark", None),
 ];
 
-crate fn check_for_substitution<'a>(
+pub(super) fn check_for_substitution<'a>(
     reader: &StringReader<'a>,
     pos: BytePos,
     ch: char,
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 462279b0a9e03..b804e8a825f37 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -200,8 +200,13 @@ pub fn maybe_file_to_stream(
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
 ) -> Result<(TokenStream, Vec<lexer::UnmatchedBrace>), Vec<Diagnostic>> {
-    let srdr = lexer::StringReader::new(sess, source_file, override_span);
-    let (token_trees, unmatched_braces) = srdr.into_token_trees();
+    let src = source_file.src.as_ref().unwrap_or_else(|| {
+        sess.span_diagnostic
+            .bug(&format!("cannot lex `source_file` without source: {}", source_file.name));
+    });
+
+    let (token_trees, unmatched_braces) =
+        lexer::parse_token_trees(sess, src.as_str(), source_file.start_pos, override_span);
 
     match token_trees {
         Ok(stream) => Ok((stream, unmatched_braces)),

From 4df64905ea74f9732cb1448c14f72b17d3f32abc Mon Sep 17 00:00:00 2001
From: Ivan Tham <pickfire@riseup.net>
Date: Thu, 3 Sep 2020 23:02:27 +0800
Subject: [PATCH 13/21] Link & primitive using relative link

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

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index 35d64d85010c3..43a0b048b47cc 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -287,6 +287,7 @@ use crate::raw_vec::RawVec;
 /// [`insert`]: Vec::insert
 /// [`reserve`]: Vec::reserve
 /// [owned slice]: Box
+/// [`&`]: ../../std/primitive.reference.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")]
 pub struct Vec<T> {

From ccf41dd5eb42730b1de6a4bc9d95c03dca0a8143 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Thu, 3 Sep 2020 17:21:53 +0200
Subject: [PATCH 14/21] Rename IsJoint -> Spacing

To match better naming from proc-macro
---
 compiler/rustc_ast/src/attr/mod.rs            | 16 ++++----
 compiler/rustc_ast/src/tokenstream.rs         | 41 +++++++++----------
 compiler/rustc_expand/src/mbe/transcribe.rs   |  4 +-
 .../rustc_expand/src/proc_macro_server.rs     | 12 +++---
 compiler/rustc_parse/src/lexer/mod.rs         | 14 +++----
 compiler/rustc_parse/src/lexer/tokentrees.rs  | 22 +++++-----
 compiler/rustc_parse/src/lib.rs               |  4 +-
 compiler/rustc_parse/src/parser/mod.rs        | 10 ++---
 .../ast-json/ast-json-noexpand-output.stdout  |  2 +-
 src/test/ui/ast-json/ast-json-output.stdout   |  2 +-
 10 files changed, 62 insertions(+), 65 deletions(-)

diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 12d6f7cc33ddc..d819e3cb8152e 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -8,7 +8,7 @@ use crate::ast::{Path, PathSegment};
 use crate::mut_visit::visit_clobber;
 use crate::ptr::P;
 use crate::token::{self, CommentKind, Token};
-use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
+use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::source_map::{BytePos, Spanned};
@@ -361,7 +361,7 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
 }
 
 impl MetaItem {
-    fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
+    fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
         let mut idents = vec![];
         let mut last_pos = BytePos(0 as u32);
         for (i, segment) in self.path.segments.iter().enumerate() {
@@ -374,7 +374,7 @@ impl MetaItem {
             idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
             last_pos = segment.ident.span.hi();
         }
-        idents.extend(self.kind.token_trees_and_joints(self.span));
+        idents.extend(self.kind.token_trees_and_spacings(self.span));
         idents
     }
 
@@ -447,7 +447,7 @@ impl MetaItemKind {
                     if i > 0 {
                         tts.push(TokenTree::token(token::Comma, span).into());
                     }
-                    tts.extend(item.token_trees_and_joints())
+                    tts.extend(item.token_trees_and_spacings())
                 }
                 MacArgs::Delimited(
                     DelimSpan::from_single(span),
@@ -458,7 +458,7 @@ impl MetaItemKind {
         }
     }
 
-    fn token_trees_and_joints(&self, span: Span) -> Vec<TreeAndJoint> {
+    fn token_trees_and_spacings(&self, span: Span) -> Vec<TreeAndSpacing> {
         match *self {
             MetaItemKind::Word => vec![],
             MetaItemKind::NameValue(ref lit) => {
@@ -470,7 +470,7 @@ impl MetaItemKind {
                     if i > 0 {
                         tokens.push(TokenTree::token(token::Comma, span).into());
                     }
-                    tokens.extend(item.token_trees_and_joints())
+                    tokens.extend(item.token_trees_and_spacings())
                 }
                 vec![
                     TokenTree::Delimited(
@@ -553,9 +553,9 @@ impl NestedMetaItem {
         }
     }
 
-    fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
+    fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
         match *self {
-            NestedMetaItem::MetaItem(ref item) => item.token_trees_and_joints(),
+            NestedMetaItem::MetaItem(ref item) => item.token_trees_and_spacings(),
             NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()],
         }
     }
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 151acddae840e..f201f0b5c6643 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -83,7 +83,7 @@ impl TokenTree {
     }
 
     pub fn joint(self) -> TokenStream {
-        TokenStream::new(vec![(self, Joint)])
+        TokenStream::new(vec![(self, Spacing::Joint)])
     }
 
     pub fn token(kind: TokenKind, span: Span) -> TokenTree {
@@ -125,22 +125,20 @@ where
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
 #[derive(Clone, Debug, Default, Encodable, Decodable)]
-pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
+pub struct TokenStream(pub Lrc<Vec<TreeAndSpacing>>);
 
-pub type TreeAndJoint = (TokenTree, IsJoint);
+pub type TreeAndSpacing = (TokenTree, Spacing);
 
 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
 rustc_data_structures::static_assert_size!(TokenStream, 8);
 
 #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
-pub enum IsJoint {
+pub enum Spacing {
+    Alone,
     Joint,
-    NonJoint,
 }
 
-use IsJoint::*;
-
 impl TokenStream {
     /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
     /// separating the two arguments with a comma for diagnostic suggestions.
@@ -153,7 +151,7 @@ impl TokenStream {
                 let sp = match (&ts, &next) {
                     (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue,
                     (
-                        (TokenTree::Token(token_left), NonJoint),
+                        (TokenTree::Token(token_left), Spacing::Alone),
                         (TokenTree::Token(token_right), _),
                     ) if ((token_left.is_ident() && !token_left.is_reserved_ident())
                         || token_left.is_lit())
@@ -162,11 +160,11 @@ impl TokenStream {
                     {
                         token_left.span
                     }
-                    ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(),
+                    ((TokenTree::Delimited(sp, ..), Spacing::Alone), _) => sp.entire(),
                     _ => continue,
                 };
                 let sp = sp.shrink_to_hi();
-                let comma = (TokenTree::token(token::Comma, sp), NonJoint);
+                let comma = (TokenTree::token(token::Comma, sp), Spacing::Alone);
                 suggestion = Some((pos, comma, sp));
             }
         }
@@ -184,19 +182,19 @@ impl TokenStream {
 
 impl From<TokenTree> for TokenStream {
     fn from(tree: TokenTree) -> TokenStream {
-        TokenStream::new(vec![(tree, NonJoint)])
+        TokenStream::new(vec![(tree, Spacing::Alone)])
     }
 }
 
-impl From<TokenTree> for TreeAndJoint {
-    fn from(tree: TokenTree) -> TreeAndJoint {
-        (tree, NonJoint)
+impl From<TokenTree> for TreeAndSpacing {
+    fn from(tree: TokenTree) -> TreeAndSpacing {
+        (tree, Spacing::Alone)
     }
 }
 
 impl iter::FromIterator<TokenTree> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
-        TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TreeAndJoint>>())
+        TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TreeAndSpacing>>())
     }
 }
 
@@ -209,7 +207,7 @@ impl PartialEq<TokenStream> for TokenStream {
 }
 
 impl TokenStream {
-    pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
+    pub fn new(streams: Vec<TreeAndSpacing>) -> TokenStream {
         TokenStream(Lrc::new(streams))
     }
 
@@ -320,11 +318,11 @@ impl TokenStreamBuilder {
         // If `self` is not empty and the last tree within the last stream is a
         // token tree marked with `Joint`...
         if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut() {
-            if let Some((TokenTree::Token(last_token), Joint)) = last_stream_lrc.last() {
+            if let Some((TokenTree::Token(last_token), Spacing::Joint)) = last_stream_lrc.last() {
                 // ...and `stream` is not empty and the first tree within it is
                 // a token tree...
                 let TokenStream(ref mut stream_lrc) = stream;
-                if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() {
+                if let Some((TokenTree::Token(token), spacing)) = stream_lrc.first() {
                     // ...and the two tokens can be glued together...
                     if let Some(glued_tok) = last_token.glue(&token) {
                         // ...then do so, by overwriting the last token
@@ -337,8 +335,7 @@ impl TokenStreamBuilder {
                         // Overwrite the last token tree with the merged
                         // token.
                         let last_vec_mut = Lrc::make_mut(last_stream_lrc);
-                        *last_vec_mut.last_mut().unwrap() =
-                            (TokenTree::Token(glued_tok), *is_joint);
+                        *last_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
 
                         // Remove the first token tree from `stream`. (This
                         // is almost always the only tree in `stream`.)
@@ -375,7 +372,7 @@ impl Iterator for Cursor {
     type Item = TokenTree;
 
     fn next(&mut self) -> Option<TokenTree> {
-        self.next_with_joint().map(|(tree, _)| tree)
+        self.next_with_spacing().map(|(tree, _)| tree)
     }
 }
 
@@ -384,7 +381,7 @@ impl Cursor {
         Cursor { stream, index: 0 }
     }
 
-    pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
+    pub fn next_with_spacing(&mut self) -> Option<TreeAndSpacing> {
         if self.index < self.stream.len() {
             self.index += 1;
             Some(self.stream.0[self.index - 1].clone())
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b908a12c1fc9e..0e5c5fe4d4473 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -4,7 +4,7 @@ use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
 
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::token::{self, NtTT, Token};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
+use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_ast::MacCall;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -111,7 +111,7 @@ pub(super) fn transcribe<'a>(
     //
     // Thus, if we try to pop the `result_stack` and it is empty, we have reached the top-level
     // again, and we are done transcribing.
-    let mut result: Vec<TreeAndJoint> = Vec::new();
+    let mut result: Vec<TreeAndSpacing> = Vec::new();
     let mut result_stack = Vec::new();
     let mut marker = Marker(cx.current_expansion.id, transparency);
 
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 39c82f97e0a39..ec41fd7a3eebe 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -2,7 +2,7 @@ use crate::base::ExtCtxt;
 
 use rustc_ast as ast;
 use rustc_ast::token;
-use rustc_ast::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
+use rustc_ast::tokenstream::{self, DelimSpan, Spacing::*, TokenStream, TreeAndSpacing};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::Diagnostic;
@@ -47,15 +47,15 @@ impl ToInternal<token::DelimToken> for Delimiter {
     }
 }
 
-impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
+impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
     for TokenTree<Group, Punct, Ident, Literal>
 {
     fn from_internal(
-        ((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>),
+        ((tree, spacing), sess, stack): (TreeAndSpacing, &ParseSess, &mut Vec<Self>),
     ) -> Self {
         use rustc_ast::token::*;
 
-        let joint = is_joint == Joint;
+        let joint = spacing == Joint;
         let Token { kind, span } = match tree {
             tokenstream::TokenTree::Delimited(span, delim, tts) => {
                 let delimiter = Delimiter::from_internal(delim);
@@ -261,7 +261,7 @@ impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
         };
 
         let tree = tokenstream::TokenTree::token(kind, span);
-        TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
+        TokenStream::new(vec![(tree, if joint { Joint } else { Alone })])
     }
 }
 
@@ -444,7 +444,7 @@ impl server::TokenStreamIter for Rustc<'_> {
     ) -> Option<TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
         loop {
             let tree = iter.stack.pop().or_else(|| {
-                let next = iter.cursor.next_with_joint()?;
+                let next = iter.cursor.next_with_spacing()?;
                 Some(TokenTree::from_internal((next, self.sess, &mut iter.stack)))
             })?;
             // A hack used to pass AST fragments to attribute and derive macros
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 8099b8a24658d..32b124970cf7c 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,6 +1,6 @@
 use rustc_ast::ast::AttrStyle;
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
-use rustc_ast::tokenstream::{IsJoint, TokenStream};
+use rustc_ast::tokenstream::{Spacing, TokenStream};
 use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
@@ -54,8 +54,8 @@ impl<'a> StringReader<'a> {
     }
 
     /// Returns the next token, and info about preceding whitespace, if any.
-    fn next_token(&mut self) -> (IsJoint, Token) {
-        let mut is_joint = IsJoint::Joint;
+    fn next_token(&mut self) -> (Spacing, Token) {
+        let mut spacing = Spacing::Joint;
 
         // Skip `#!` at the start of the file
         let start_src_index = self.src_index(self.pos);
@@ -64,7 +64,7 @@ impl<'a> StringReader<'a> {
         if is_beginning_of_file {
             if let Some(shebang_len) = rustc_lexer::strip_shebang(text) {
                 self.pos = self.pos + BytePos::from_usize(shebang_len);
-                is_joint = IsJoint::NonJoint;
+                spacing = Spacing::Alone;
             }
         }
 
@@ -75,7 +75,7 @@ impl<'a> StringReader<'a> {
 
             if text.is_empty() {
                 let span = self.mk_sp(self.pos, self.pos);
-                return (is_joint, Token::new(token::Eof, span));
+                return (spacing, Token::new(token::Eof, span));
             }
 
             let token = rustc_lexer::first_token(text);
@@ -88,9 +88,9 @@ impl<'a> StringReader<'a> {
             match self.cook_lexer_token(token.kind, start) {
                 Some(kind) => {
                     let span = self.mk_sp(start, self.pos);
-                    return (is_joint, Token::new(kind, span));
+                    return (spacing, Token::new(kind, span));
                 }
-                None => is_joint = IsJoint::NonJoint,
+                None => spacing = Spacing::Alone,
             }
         }
     }
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 357b10ab89d41..0f364bffb134e 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -3,8 +3,8 @@ use super::{StringReader, UnmatchedBrace};
 use rustc_ast::token::{self, DelimToken, Token};
 use rustc_ast::tokenstream::{
     DelimSpan,
-    IsJoint::{self, *},
-    TokenStream, TokenTree, TreeAndJoint,
+    Spacing::{self, *},
+    TokenStream, TokenTree, TreeAndSpacing,
 };
 use rustc_ast_pretty::pprust::token_to_string;
 use rustc_data_structures::fx::FxHashMap;
@@ -77,7 +77,7 @@ impl<'a> TokenTreesReader<'a> {
         }
     }
 
-    fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
+    fn parse_token_tree(&mut self) -> PResult<'a, TreeAndSpacing> {
         let sm = self.string_reader.sess.source_map();
 
         match self.token.kind {
@@ -262,29 +262,29 @@ impl<'a> TokenTreesReader<'a> {
             }
             _ => {
                 let tt = TokenTree::Token(self.token.take());
-                let mut is_joint = self.bump();
+                let mut spacing = self.bump();
                 if !self.token.is_op() {
-                    is_joint = NonJoint;
+                    spacing = Alone;
                 }
-                Ok((tt, is_joint))
+                Ok((tt, spacing))
             }
         }
     }
 
-    fn bump(&mut self) -> IsJoint {
-        let (joint_to_prev, token) = self.string_reader.next_token();
+    fn bump(&mut self) -> Spacing {
+        let (spacing, token) = self.string_reader.next_token();
         self.token = token;
-        joint_to_prev
+        spacing
     }
 }
 
 #[derive(Default)]
 struct TokenStreamBuilder {
-    buf: Vec<TreeAndJoint>,
+    buf: Vec<TreeAndSpacing>,
 }
 
 impl TokenStreamBuilder {
-    fn push(&mut self, (tree, joint): TreeAndJoint) {
+    fn push(&mut self, (tree, joint): TreeAndSpacing) {
         if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() {
             if let TokenTree::Token(token) = &tree {
                 if let Some(glued) = prev_token.glue(token) {
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index b804e8a825f37..e7fd74f551aaa 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -8,7 +8,7 @@
 
 use rustc_ast as ast;
 use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{self, IsJoint, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{self, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diagnostic, FatalError, Level, PResult};
@@ -437,7 +437,7 @@ pub fn tokenstream_probably_equal_for_proc_macro(
             // issue #75734 tracks resolving this.
             nt_to_tokenstream(nt, sess, *span).into_trees()
         } else {
-            TokenStream::new(vec![(tree, IsJoint::NonJoint)]).into_trees()
+            TokenStream::new(vec![(tree, Spacing::Alone)]).into_trees()
         }
     };
 
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 84edfecad192f..d22d08cd14438 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -15,7 +15,7 @@ pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, DelimToken, Token, TokenKind};
-use rustc_ast::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndJoint};
+use rustc_ast::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_ast::DUMMY_NODE_ID;
 use rustc_ast::{self as ast, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
 use rustc_ast::{Async, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, VisibilityKind};
@@ -118,7 +118,7 @@ impl<'a> Drop for Parser<'a> {
 struct TokenCursor {
     frame: TokenCursorFrame,
     stack: Vec<TokenCursorFrame>,
-    cur_token: Option<TreeAndJoint>,
+    cur_token: Option<TreeAndSpacing>,
     collecting: Option<Collecting>,
 }
 
@@ -136,7 +136,7 @@ struct TokenCursorFrame {
 struct Collecting {
     /// Holds the current tokens captured during the most
     /// recent call to `collect_tokens`
-    buf: Vec<TreeAndJoint>,
+    buf: Vec<TreeAndSpacing>,
     /// The depth of the `TokenCursor` stack at the time
     /// collection was started. When we encounter a `TokenTree::Delimited`,
     /// we want to record the `TokenTree::Delimited` itself,
@@ -167,7 +167,7 @@ impl TokenCursor {
             let tree = if !self.frame.open_delim {
                 self.frame.open_delim = true;
                 TokenTree::open_tt(self.frame.span, self.frame.delim).into()
-            } else if let Some(tree) = self.frame.tree_cursor.next_with_joint() {
+            } else if let Some(tree) = self.frame.tree_cursor.next_with_spacing() {
                 tree
             } else if !self.frame.close_delim {
                 self.frame.close_delim = true;
@@ -1154,7 +1154,7 @@ impl<'a> Parser<'a> {
         f: impl FnOnce(&mut Self) -> PResult<'a, R>,
     ) -> PResult<'a, (R, TokenStream)> {
         // Record all tokens we parse when parsing this item.
-        let tokens: Vec<TreeAndJoint> = self.token_cursor.cur_token.clone().into_iter().collect();
+        let tokens: Vec<TreeAndSpacing> = self.token_cursor.cur_token.clone().into_iter().collect();
         debug!("collect_tokens: starting with {:?}", tokens);
 
         // We need special handling for the case where `collect_tokens` is called
diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
index d0942f78bb86c..031c0d0cae51c 100644
--- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout
+++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout
index dc06fd74a4bb5..9b3b6870cbe7e 100644
--- a/src/test/ui/ast-json/ast-json-output.stdout
+++ b/src/test/ui/ast-json/ast-json-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}

From c6ab3ff19aed41d8a451d16c9a63bc06ecb0a9c4 Mon Sep 17 00:00:00 2001
From: kadmin <julianknodt@gmail.com>
Date: Sun, 16 Aug 2020 03:01:38 +0000
Subject: [PATCH 15/21] Add test for checking if-let or-patterns

---
 src/test/mir-opt/issues/issue-75439.rs        | 21 +++++
 ...e_75439.foo.MatchBranchSimplification.diff | 87 +++++++++++++++++++
 2 files changed, 108 insertions(+)
 create mode 100644 src/test/mir-opt/issues/issue-75439.rs
 create mode 100644 src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff

diff --git a/src/test/mir-opt/issues/issue-75439.rs b/src/test/mir-opt/issues/issue-75439.rs
new file mode 100644
index 0000000000000..44d6bc619d3bb
--- /dev/null
+++ b/src/test/mir-opt/issues/issue-75439.rs
@@ -0,0 +1,21 @@
+// EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff
+
+#![feature(const_fn_transmute)]
+#![feature(or_patterns)]
+
+use std::mem::transmute;
+
+pub fn foo(bytes: [u8; 16]) -> Option<[u8; 4]> {
+    // big endian `u32`s
+    let dwords: [u32; 4] = unsafe { transmute(bytes) };
+    const FF: u32 = 0x0000_ffff_u32.to_be();
+    if let [0, 0, 0 | FF, ip] = dwords {
+        Some(unsafe { transmute(ip) })
+    } else {
+        None
+    }
+}
+
+fn main() {
+  let _ = foo([0; 16]);
+}
diff --git a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
new file mode 100644
index 0000000000000..5b90df660a517
--- /dev/null
+++ b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -0,0 +1,87 @@
+- // MIR for `foo` before MatchBranchSimplification
++ // MIR for `foo` after MatchBranchSimplification
+  
+  fn foo(_1: [u8; 16]) -> std::option::Option<[u8; 4]> {
+      debug bytes => _1;                   // in scope 0 at $DIR/issue-75439.rs:8:12: 8:17
+      let mut _0: std::option::Option<[u8; 4]>; // return place in scope 0 at $DIR/issue-75439.rs:8:32: 8:47
+      let _2: [u32; 4];                    // in scope 0 at $DIR/issue-75439.rs:10:9: 10:15
+      let mut _3: [u8; 16];                // in scope 0 at $DIR/issue-75439.rs:10:47: 10:52
+      let mut _5: [u8; 4];                 // in scope 0 at $DIR/issue-75439.rs:13:14: 13:38
+      let mut _6: u32;                     // in scope 0 at $DIR/issue-75439.rs:13:33: 13:35
+      scope 1 {
+          debug dwords => _2;              // in scope 1 at $DIR/issue-75439.rs:10:9: 10:15
+          let _4: u32;                     // in scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          scope 3 {
+              debug ip => _4;              // in scope 3 at $DIR/issue-75439.rs:12:27: 12:29
+              scope 4 {
+              }
+          }
+      }
+      scope 2 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/issue-75439.rs:10:9: 10:15
+          StorageLive(_3);                 // scope 2 at $DIR/issue-75439.rs:10:47: 10:52
+          _3 = _1;                         // scope 2 at $DIR/issue-75439.rs:10:47: 10:52
+          _2 = std::intrinsics::transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue-75439.rs:10:37: 10:53
+                                           // mir::Constant
+                                           // + span: $DIR/issue-75439.rs:10:37: 10:46
+                                           // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {std::intrinsics::transmute::<[u8; 16], [u32; 4]>}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          StorageDead(_3);                 // scope 2 at $DIR/issue-75439.rs:10:52: 10:53
+          switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:13: 12:14
+      }
+  
+      bb2: {
+          switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:16: 12:17
+      }
+  
+      bb3: {
+          switchInt(_2[2 of 4]) -> [0_u32: bb6, 4294901760_u32: bb7, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:19: 12:20
+      }
+  
+      bb4: {
+          discriminant(_0) = 0;            // scope 1 at $DIR/issue-75439.rs:15:9: 15:13
+          goto -> bb9;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb5: {
+          StorageLive(_5);                 // scope 3 at $DIR/issue-75439.rs:13:14: 13:38
+          StorageLive(_6);                 // scope 4 at $DIR/issue-75439.rs:13:33: 13:35
+          _6 = _4;                         // scope 4 at $DIR/issue-75439.rs:13:33: 13:35
+          _5 = std::intrinsics::transmute::<u32, [u8; 4]>(move _6) -> bb8; // scope 4 at $DIR/issue-75439.rs:13:23: 13:36
+                                           // mir::Constant
+                                           // + span: $DIR/issue-75439.rs:13:23: 13:32
+                                           // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {std::intrinsics::transmute::<u32, [u8; 4]>}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb6: {
+          StorageLive(_4);                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          _4 = _2[3 of 4];                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          goto -> bb5;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb7: {
+          StorageLive(_4);                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          _4 = _2[3 of 4];                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          goto -> bb5;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb8: {
+          StorageDead(_6);                 // scope 4 at $DIR/issue-75439.rs:13:35: 13:36
+          ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue-75439.rs:13:9: 13:39
+          discriminant(_0) = 1;            // scope 3 at $DIR/issue-75439.rs:13:9: 13:39
+          StorageDead(_5);                 // scope 3 at $DIR/issue-75439.rs:13:38: 13:39
+          StorageDead(_4);                 // scope 1 at $DIR/issue-75439.rs:14:5: 14:6
+          goto -> bb9;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb9: {
+          StorageDead(_2);                 // scope 0 at $DIR/issue-75439.rs:17:1: 17:2
+          return;                          // scope 0 at $DIR/issue-75439.rs:17:2: 17:2
+      }
+  }
+  

From 2278c7255a1423b12d0efee3de43b23fa0d5b892 Mon Sep 17 00:00:00 2001
From: Rune Tynan <runetynan@gmail.com>
Date: Thu, 3 Sep 2020 15:43:07 -0400
Subject: [PATCH 16/21] Remove vec-to_str.rs, merge the remaining test in with
 vec

---
 library/alloc/tests/vec.rs                | 3 +++
 src/test/ui/array-slice-vec/vec-to_str.rs | 7 -------
 2 files changed, 3 insertions(+), 7 deletions(-)
 delete mode 100644 src/test/ui/array-slice-vec/vec-to_str.rs

diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index b422960c19982..f1c6af46d3103 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -92,6 +92,9 @@ fn test_debug_fmt() {
 
     let vec2 = vec![0, 1];
     assert_eq!("[0, 1]", format!("{:?}", vec2));
+
+    let slice: &[isize] = &[4, 5];
+    assert_eq!("[4, 5]", format!("{:?}", slice));
 }
 
 #[test]
diff --git a/src/test/ui/array-slice-vec/vec-to_str.rs b/src/test/ui/array-slice-vec/vec-to_str.rs
deleted file mode 100644
index fbff19b862283..0000000000000
--- a/src/test/ui/array-slice-vec/vec-to_str.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-
-
-pub fn main() {
-    let bar: &[isize] = &[4, 5];
-    assert_eq!(format!("{:?}", bar), "[4, 5]");
-}

From a2e077e405f9538b42d32e18082d50d0102d2334 Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Thu, 3 Sep 2020 23:17:21 +0200
Subject: [PATCH 17/21] Make `Ipv4Addr` and `Ipv6Addr` const tests unit tests
 under `library`

These tests are about the standard library, not the compiler itself, thus should live in `library`, see #76268.
---
 library/std/src/net/ip/tests.rs    | 109 +++++++++++++++++++++++++++++
 src/test/ui/consts/std/net/ipv4.rs |  58 ---------------
 src/test/ui/consts/std/net/ipv6.rs |  53 --------------
 3 files changed, 109 insertions(+), 111 deletions(-)
 delete mode 100644 src/test/ui/consts/std/net/ipv4.rs
 delete mode 100644 src/test/ui/consts/std/net/ipv6.rs

diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs
index a2fba4b4cca95..76a0ae8b9454d 100644
--- a/library/std/src/net/ip/tests.rs
+++ b/library/std/src/net/ip/tests.rs
@@ -809,3 +809,112 @@ fn is_v6() {
     assert!(!ip.is_ipv4());
     assert!(ip.is_ipv6());
 }
+
+#[test]
+fn ipv4_const() {
+    // test that the methods of `Ipv4Addr` are usable in a const context
+
+    const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
+    assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
+
+    const OCTETS: [u8; 4] = IP_ADDRESS.octets();
+    assert_eq!(OCTETS, [127, 0, 0, 1]);
+
+    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+    assert!(!IS_UNSPECIFIED);
+
+    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+    assert!(IS_LOOPBACK);
+
+    const IS_PRIVATE: bool = IP_ADDRESS.is_private();
+    assert!(!IS_PRIVATE);
+
+    const IS_LINK_LOCAL: bool = IP_ADDRESS.is_link_local();
+    assert!(!IS_LINK_LOCAL);
+
+    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+    assert!(!IS_GLOBAL);
+
+    const IS_SHARED: bool = IP_ADDRESS.is_shared();
+    assert!(!IS_SHARED);
+
+    const IS_IETF_PROTOCOL_ASSIGNMENT: bool = IP_ADDRESS.is_ietf_protocol_assignment();
+    assert!(!IS_IETF_PROTOCOL_ASSIGNMENT);
+
+    const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
+    assert!(!IS_BENCHMARKING);
+
+    const IS_RESERVED: bool = IP_ADDRESS.is_reserved();
+    assert!(!IS_RESERVED);
+
+    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+    assert!(!IS_MULTICAST);
+
+    const IS_BROADCAST: bool = IP_ADDRESS.is_broadcast();
+    assert!(!IS_BROADCAST);
+
+    const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
+    assert!(!IS_DOCUMENTATION);
+
+    const IP_V6_COMPATIBLE: Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
+    assert_eq!(
+        IP_V6_COMPATIBLE,
+        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1])
+    );
+
+    const IP_V6_MAPPED: Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
+    assert_eq!(
+        IP_V6_MAPPED,
+        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1])
+    );
+}
+
+#[test]
+fn ipv6_const() {
+    // test that the methods of `Ipv6Addr` are usable in a const context
+
+    const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+    assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
+
+    const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
+    assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
+
+    const OCTETS: [u8; 16] = IP_ADDRESS.octets();
+    assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+
+    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+    assert!(!IS_UNSPECIFIED);
+
+    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+    assert!(IS_LOOPBACK);
+
+    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+    assert!(!IS_GLOBAL);
+
+    const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local();
+    assert!(!IS_UNIQUE_LOCAL);
+
+    const IS_UNICAST_LINK_LOCAL_STRICT: bool = IP_ADDRESS.is_unicast_link_local_strict();
+    assert!(!IS_UNICAST_LINK_LOCAL_STRICT);
+
+    const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local();
+    assert!(!IS_UNICAST_LINK_LOCAL);
+
+    const IS_UNICAST_SITE_LOCAL: bool = IP_ADDRESS.is_unicast_site_local();
+    assert!(!IS_UNICAST_SITE_LOCAL);
+
+    const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
+    assert!(!IS_DOCUMENTATION);
+
+    const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global();
+    assert!(!IS_UNICAST_GLOBAL);
+
+    const MULTICAST_SCOPE: Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
+    assert_eq!(MULTICAST_SCOPE, None);
+
+    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+    assert!(!IS_MULTICAST);
+
+    const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
+    assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
+}
diff --git a/src/test/ui/consts/std/net/ipv4.rs b/src/test/ui/consts/std/net/ipv4.rs
deleted file mode 100644
index 8c676999ae734..0000000000000
--- a/src/test/ui/consts/std/net/ipv4.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// run-pass
-
-#![feature(ip)]
-#![feature(const_ipv4)]
-
-use std::net::{Ipv4Addr, Ipv6Addr};
-
-fn main() {
-    const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
-    assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
-
-    const OCTETS: [u8; 4] = IP_ADDRESS.octets();
-    assert_eq!(OCTETS, [127, 0, 0, 1]);
-
-    const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
-    assert!(!IS_UNSPECIFIED);
-
-    const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
-    assert!(IS_LOOPBACK);
-
-    const IS_PRIVATE : bool = IP_ADDRESS.is_private();
-    assert!(!IS_PRIVATE);
-
-    const IS_LINK_LOCAL : bool = IP_ADDRESS.is_link_local();
-    assert!(!IS_LINK_LOCAL);
-
-    const IS_GLOBAL : bool = IP_ADDRESS.is_global();
-    assert!(!IS_GLOBAL);
-
-    const IS_SHARED : bool = IP_ADDRESS.is_shared();
-    assert!(!IS_SHARED);
-
-    const IS_IETF_PROTOCOL_ASSIGNMENT : bool = IP_ADDRESS.is_ietf_protocol_assignment();
-    assert!(!IS_IETF_PROTOCOL_ASSIGNMENT);
-
-    const IS_BENCHMARKING : bool = IP_ADDRESS.is_benchmarking();
-    assert!(!IS_BENCHMARKING);
-
-    const IS_RESERVED : bool = IP_ADDRESS.is_reserved();
-    assert!(!IS_RESERVED);
-
-    const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
-    assert!(!IS_MULTICAST);
-
-    const IS_BROADCAST : bool = IP_ADDRESS.is_broadcast();
-    assert!(!IS_BROADCAST);
-
-    const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
-    assert!(!IS_DOCUMENTATION);
-
-    const IP_V6_COMPATIBLE : Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
-    assert_eq!(IP_V6_COMPATIBLE,
-        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1]));
-
-    const IP_V6_MAPPED : Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
-    assert_eq!(IP_V6_MAPPED,
-        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1]));
-}
diff --git a/src/test/ui/consts/std/net/ipv6.rs b/src/test/ui/consts/std/net/ipv6.rs
deleted file mode 100644
index e3841c38c2231..0000000000000
--- a/src/test/ui/consts/std/net/ipv6.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-// run-pass
-
-#![feature(ip)]
-#![feature(const_ipv6)]
-
-use std::net::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
-
-fn main() {
-    const IP_ADDRESS : Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
-    assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
-
-    const SEGMENTS : [u16; 8] = IP_ADDRESS.segments();
-    assert_eq!(SEGMENTS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 1]);
-
-    const OCTETS : [u8; 16] = IP_ADDRESS.octets();
-    assert_eq!(OCTETS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0, 0, 1]);
-
-    const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
-    assert!(!IS_UNSPECIFIED);
-
-    const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
-    assert!(IS_LOOPBACK);
-
-    const IS_GLOBAL : bool = IP_ADDRESS.is_global();
-    assert!(!IS_GLOBAL);
-
-    const IS_UNIQUE_LOCAL : bool = IP_ADDRESS.is_unique_local();
-    assert!(!IS_UNIQUE_LOCAL);
-
-    const IS_UNICAST_LINK_LOCAL_STRICT : bool = IP_ADDRESS.is_unicast_link_local_strict();
-    assert!(!IS_UNICAST_LINK_LOCAL_STRICT);
-
-    const IS_UNICAST_LINK_LOCAL : bool = IP_ADDRESS.is_unicast_link_local();
-    assert!(!IS_UNICAST_LINK_LOCAL);
-
-    const IS_UNICAST_SITE_LOCAL : bool = IP_ADDRESS.is_unicast_site_local();
-    assert!(!IS_UNICAST_SITE_LOCAL);
-
-    const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
-    assert!(!IS_DOCUMENTATION);
-
-    const IS_UNICAST_GLOBAL : bool = IP_ADDRESS.is_unicast_global();
-    assert!(!IS_UNICAST_GLOBAL);
-
-    const MULTICAST_SCOPE : Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
-    assert_eq!(MULTICAST_SCOPE, None);
-
-    const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
-    assert!(!IS_MULTICAST);
-
-    const IP_V4 : Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
-    assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
-}

From 8c93125c17aeb9e9252054d4ddd0095ff4e60a2e Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Thu, 3 Sep 2020 18:03:33 -0400
Subject: [PATCH 18/21] Address review comments on `Peekable::next_if`

---
 library/core/src/iter/adapters/mod.rs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index f32c3963abea2..46dc77ba35c1a 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -1628,7 +1628,7 @@ impl<I: Iterator> Peekable<I> {
         self.peeked.get_or_insert_with(|| iter.next()).as_ref()
     }
 
-    /// Consume the next value of this iterator if a condition is true.
+    /// Consume and return the next value of this iterator if a condition is true.
     ///
     /// If `func` returns `true` for the next value of this iterator, consume and return it.
     /// Otherwise, return `None`.
@@ -1668,7 +1668,7 @@ impl<I: Iterator> Peekable<I> {
         }
     }
 
-    /// Consume the next item if it is equal to `expected`.
+    /// Consume and return the next item if it is equal to `expected`.
     ///
     /// # Example
     /// Consume a number if it's equal to 0.
@@ -1683,10 +1683,10 @@ impl<I: Iterator> Peekable<I> {
     /// assert_eq!(iter.next(), Some(1));
     /// ```
     #[unstable(feature = "peekable_next_if", issue = "72480")]
-    pub fn next_if_eq<R>(&mut self, expected: &R) -> Option<I::Item>
+    pub fn next_if_eq<T>(&mut self, expected: &T) -> Option<I::Item>
     where
-        R: ?Sized,
-        I::Item: PartialEq<R>,
+        T: ?Sized,
+        I::Item: PartialEq<T>,
     {
         self.next_if(|next| next == expected)
     }

From 7b823df489e89d0ba3f6acd1cb788d3d8fbbf1e7 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Thu, 3 Sep 2020 18:08:25 -0400
Subject: [PATCH 19/21] Link to `#capacity-and-reallocation` when using
 with_capacity

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

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index 27eefb0584216..a9215eb2dbc1b 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -119,6 +119,9 @@ use crate::raw_vec::RawVec;
 /// assert_eq!(vec, [0, 0, 0, 0, 0]);
 /// ```
 ///
+/// For more information, see
+/// [Capacity and Reallocation](#capacity-and-reallocation).
+///
 /// Use a `Vec<T>` as an efficient stack:
 ///
 /// ```

From 538e198193451e680cc95b66c82baac3ac687c8c Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Fri, 4 Sep 2020 02:35:27 +0200
Subject: [PATCH 20/21] Move various ui const tests to `library`

Move:
 - `src\test\ui\consts\const-nonzero.rs` to `library\core`
 - `src\test\ui\consts\ascii.rs` to `library\core`
 - `src\test\ui\consts\cow-is-borrowed` to `library\alloc`

Part of #76268
---
 library/alloc/tests/borrow.rs         | 13 +++++++++++++
 library/alloc/tests/lib.rs            |  1 +
 library/core/tests/ascii.rs           | 11 +++++++++++
 library/core/tests/nonzero.rs         | 17 +++++++++++++++++
 src/test/ui/consts/const-nonzero.rs   | 16 ----------------
 src/test/ui/consts/cow-is-borrowed.rs | 15 ---------------
 src/test/ui/consts/is_ascii.rs        | 15 ---------------
 7 files changed, 42 insertions(+), 46 deletions(-)
 delete mode 100644 src/test/ui/consts/const-nonzero.rs
 delete mode 100644 src/test/ui/consts/cow-is-borrowed.rs
 delete mode 100644 src/test/ui/consts/is_ascii.rs

diff --git a/library/alloc/tests/borrow.rs b/library/alloc/tests/borrow.rs
index 8bfcf323f674a..57976aa6cdfdf 100644
--- a/library/alloc/tests/borrow.rs
+++ b/library/alloc/tests/borrow.rs
@@ -45,3 +45,16 @@ fn test_from_cow_path() {
     let path = Path::new("hello");
     test_from_cow!(path: &Path);
 }
+
+#[test]
+fn cow_const() {
+    // test that the methods of `Cow` are usable in a const context
+
+    const COW: Cow<'_, str> = Cow::Borrowed("moo");
+
+    const IS_BORROWED: bool = COW.is_borrowed();
+    assert!(IS_BORROWED);
+
+    const IS_OWNED: bool = COW.is_owned();
+    assert!(!IS_OWNED);
+}
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index b1513d1b05655..590639d983481 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -1,5 +1,6 @@
 #![feature(allocator_api)]
 #![feature(box_syntax)]
+#![feature(cow_is_borrowed)]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
 #![feature(new_uninit)]
diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs
index 0b97508394789..3244bbc2d670d 100644
--- a/library/core/tests/ascii.rs
+++ b/library/core/tests/ascii.rs
@@ -397,3 +397,14 @@ fn test_is_ascii_align_size_thoroughly() {
         }
     }
 }
+
+#[test]
+fn ascii_const() {
+    // test that the `is_ascii` methods of `char` and `u8` are usable in a const context
+
+    const CHAR_IS_ASCII: bool = 'a'.is_ascii();
+    assert!(CHAR_IS_ASCII);
+
+    const BYTE_IS_ASCII: bool = 97u8.is_ascii();
+    assert!(BYTE_IS_ASCII);
+}
diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs
index 48aec6d718d3d..825e5e63b59bc 100644
--- a/library/core/tests/nonzero.rs
+++ b/library/core/tests/nonzero.rs
@@ -195,3 +195,20 @@ fn test_nonzero_from_int_on_err() {
     assert!(NonZeroI8::try_from(0).is_err());
     assert!(NonZeroI32::try_from(0).is_err());
 }
+
+#[test]
+fn nonzero_const() {
+    // test that the methods of `NonZeroX>` are usable in a const context
+    // Note: only tests NonZero8
+
+    const NONZERO: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) };
+
+    const GET: u8 = NONZERO.get();
+    assert_eq!(GET, 5);
+
+    const ZERO: Option<NonZeroU8> = NonZeroU8::new(0);
+    assert!(ZERO.is_none());
+
+    const ONE: Option<NonZeroU8> = NonZeroU8::new(1);
+    assert!(ONE.is_some());
+}
diff --git a/src/test/ui/consts/const-nonzero.rs b/src/test/ui/consts/const-nonzero.rs
deleted file mode 100644
index cf6f8c8d69a26..0000000000000
--- a/src/test/ui/consts/const-nonzero.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-
-use std::num::NonZeroU8;
-
-const X: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) };
-const Y: u8 = X.get();
-
-const ZERO: Option<NonZeroU8> = NonZeroU8::new(0);
-const ONE: Option<NonZeroU8> = NonZeroU8::new(1);
-
-fn main() {
-    assert_eq!(Y, 5);
-
-    assert!(ZERO.is_none());
-    assert_eq!(ONE.unwrap().get(), 1);
-}
diff --git a/src/test/ui/consts/cow-is-borrowed.rs b/src/test/ui/consts/cow-is-borrowed.rs
deleted file mode 100644
index adebe20f5a255..0000000000000
--- a/src/test/ui/consts/cow-is-borrowed.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![feature(cow_is_borrowed)]
-
-use std::borrow::Cow;
-
-fn main() {
-    const COW: Cow<str> = Cow::Borrowed("moo");
-
-    const IS_BORROWED: bool = COW.is_borrowed();
-    assert!(IS_BORROWED);
-
-    const IS_OWNED: bool = COW.is_owned();
-    assert!(!IS_OWNED);
-}
diff --git a/src/test/ui/consts/is_ascii.rs b/src/test/ui/consts/is_ascii.rs
deleted file mode 100644
index d8424549f93e6..0000000000000
--- a/src/test/ui/consts/is_ascii.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-static X: bool = 'a'.is_ascii();
-static Y: bool = 'รค'.is_ascii();
-
-static BX: bool = b'a'.is_ascii();
-static BY: bool = 192u8.is_ascii();
-
-fn main() {
-    assert!(X);
-    assert!(!Y);
-
-    assert!(BX);
-    assert!(!BY);
-}

From 85146b9db7bf5de79684f8595ad49c33e436d1ae Mon Sep 17 00:00:00 2001
From: Ivan Tham <pickfire@riseup.net>
Date: Fri, 4 Sep 2020 09:50:50 +0800
Subject: [PATCH 21/21] Add slice primitive link to vec

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

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index 43a0b048b47cc..a132cf17dff4a 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -159,7 +159,7 @@ use crate::raw_vec::RawVec;
 /// # Slicing
 ///
 /// A `Vec` can be mutable. Slices, on the other hand, are read-only objects.
-/// To get a slice, use [`&`]. Example:
+/// To get a [slice], use [`&`]. Example:
 ///
 /// ```
 /// fn read_slice(slice: &[usize]) {
@@ -287,6 +287,7 @@ use crate::raw_vec::RawVec;
 /// [`insert`]: Vec::insert
 /// [`reserve`]: Vec::reserve
 /// [owned slice]: Box
+/// [slice]: ../../std/primitive.slice.html
 /// [`&`]: ../../std/primitive.reference.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")]