From 3f5f54cd8bf73e7a271955582834fda9e707429d Mon Sep 17 00:00:00 2001
From: Adam Gemmell <adam.gemmell@arm.com>
Date: Wed, 28 Apr 2021 17:54:44 +0100
Subject: [PATCH 01/26] Update list of allowed aarch64 features

These features were recently added to std_detect. Features not supported
by LLVM 9, the current minimum version for Rust, are commented.
---
 compiler/rustc_codegen_llvm/src/llvm_util.rs  |  6 ++
 .../rustc_codegen_ssa/src/target_features.rs  | 77 ++++++++++++++++++-
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index b44553e4f6d3b..f0a2c91c01851 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -152,6 +152,12 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
         ("x86", "avx512vpclmulqdq") => "vpclmulqdq",
         ("aarch64", "fp") => "fp-armv8",
         ("aarch64", "fp16") => "fullfp16",
+        ("aarch64", "fhm") => "fp16fml",
+        ("aarch64", "lse2") => "outline-atomics",
+        ("aarch64", "rcpc2") => "rcpc-immo",
+        ("aarch64", "dpb") => "ccpp",
+        ("aarch64", "dpb2") => "ccdp",
+        ("aarch64", "fcma") => "complxnum",
         (_, s) => s,
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 4e987908b4ea7..aa415754dadb0 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -33,22 +33,95 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("thumb-mode", Some(sym::arm_target_feature)),
 ];
 
+// Commented features are not available in LLVM 9.0, or have since been renamed
 const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
-    ("fp", Some(sym::aarch64_target_feature)),
+    // FEAT_AdvSimd
     ("neon", Some(sym::aarch64_target_feature)),
+    // FEAT_FP
+    ("fp", Some(sym::aarch64_target_feature)),
+    // FEAT_FP16
+    ("fp16", Some(sym::aarch64_target_feature)),
+    // FEAT_SVE
     ("sve", Some(sym::aarch64_target_feature)),
+    // FEAT_CRC
     ("crc", Some(sym::aarch64_target_feature)),
+    // Cryptographic extension
     ("crypto", Some(sym::aarch64_target_feature)),
+    // FEAT_RAS
     ("ras", Some(sym::aarch64_target_feature)),
+    // FEAT_LSE
     ("lse", Some(sym::aarch64_target_feature)),
+    // FEAT_LSE2
+    // ("lse2", Some(sym::aarch64_target_feature)),
+    // FEAT_RDM
     ("rdm", Some(sym::aarch64_target_feature)),
-    ("fp16", Some(sym::aarch64_target_feature)),
+    // FEAT_RCPC
     ("rcpc", Some(sym::aarch64_target_feature)),
+    // FEAT_RCPC2
+    ("rcpc2", Some(sym::aarch64_target_feature)),
+    // FEAT_DotProd
     ("dotprod", Some(sym::aarch64_target_feature)),
+    // FEAT_TME
     ("tme", Some(sym::aarch64_target_feature)),
+    // FEAT_FHM
+    ("fhm", Some(sym::aarch64_target_feature)),
+    // FEAT_DIT
+    ("dit", Some(sym::aarch64_target_feature)),
+    // FEAT_FLAGM
+    // ("flagm", Some(sym::aarch64_target_feature)),
+    // FEAT_SSBS
+    ("ssbs", Some(sym::aarch64_target_feature)),
+    // FEAT_SB
+    ("sb", Some(sym::aarch64_target_feature)),
+    // FEAT_PAUTH
+    // ("pauth", Some(sym::aarch64_target_feature)),
+    // FEAT_DPB
+    ("dpb", Some(sym::aarch64_target_feature)),
+    // FEAT_DPB2
+    ("dpb2", Some(sym::aarch64_target_feature)),
+    // FEAT_SVE2
+    ("sve2", Some(sym::aarch64_target_feature)),
+    // FEAT_SVE2_AES
+    ("sve2-aes", Some(sym::aarch64_target_feature)),
+    // FEAT_SVE2_SM4
+    ("sve2-sm4", Some(sym::aarch64_target_feature)),
+    // FEAT_SVE2_SHA3
+    ("sve2-sha3", Some(sym::aarch64_target_feature)),
+    // FEAT_SVE2_BitPerm
+    ("sve2-bitperm", Some(sym::aarch64_target_feature)),
+    // FEAT_FRINTTS
+    ("fptoint", Some(sym::aarch64_target_feature)),
+    // FEAT_I8MM
+    // ("i8mm", Some(sym::aarch64_target_feature)),
+    // FEAT_F32MM
+    // ("f32mm", Some(sym::aarch64_target_feature)),
+    // FEAT_F64MM
+    // ("f64mm", Some(sym::aarch64_target_feature)),
+    // FEAT_BF16
+    // ("bf16", Some(sym::aarch64_target_feature)),
+    // FEAT_RAND
+    ("rand", Some(sym::aarch64_target_feature)),
+    // FEAT_BTI
+    ("bti", Some(sym::aarch64_target_feature)),
+    // FEAT_MTE
+    ("mte", Some(sym::aarch64_target_feature)),
+    // FEAT_JSCVT
+    ("jsconv", Some(sym::aarch64_target_feature)),
+    // FEAT_FCMA
+    ("fcma", Some(sym::aarch64_target_feature)),
+    // FEAT_SHA1 & FEAT_SHA256
+    ("sha2", Some(sym::aarch64_target_feature)),
+    // FEAT_SHA512 & FEAT_SHA3
+    ("sha3", Some(sym::aarch64_target_feature)),
+    // FEAT_SM3 & FEAT_SM4
+    ("sm4", Some(sym::aarch64_target_feature)),
     ("v8.1a", Some(sym::aarch64_target_feature)),
     ("v8.2a", Some(sym::aarch64_target_feature)),
     ("v8.3a", Some(sym::aarch64_target_feature)),
+    ("v8.4a", Some(sym::aarch64_target_feature)),
+    ("v8.5a", Some(sym::aarch64_target_feature)),
+    // ("v8.6a", Some(sym::aarch64_target_feature)),
+    // ("v8.7a", Some(sym::aarch64_target_feature)),
 ];
 
 const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[

From 5353c5c3fb7ebc4fb12ca3488c555ee3006c8325 Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Fri, 14 May 2021 03:54:46 +0200
Subject: [PATCH 02/26] Move `std::memchr` to `sys_common`

---
 library/std/src/ffi/c_str.rs                     | 2 +-
 library/std/src/io/buffered/linewritershim.rs    | 2 +-
 library/std/src/io/mod.rs                        | 2 +-
 library/std/src/lib.rs                           | 1 -
 library/std/src/sys/hermit/os.rs                 | 2 +-
 library/std/src/sys/unix/os.rs                   | 2 +-
 library/std/src/{ => sys_common}/memchr.rs       | 6 ++++--
 library/std/src/{ => sys_common}/memchr/tests.rs | 0
 library/std/src/sys_common/mod.rs                | 1 +
 9 files changed, 10 insertions(+), 8 deletions(-)
 rename library/std/src/{ => sys_common}/memchr.rs (92%)
 rename library/std/src/{ => sys_common}/memchr/tests.rs (100%)

diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 2f9845d7536cd..a828a57fc8fb5 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -10,7 +10,6 @@ use crate::error::Error;
 use crate::fmt::{self, Write};
 use crate::io;
 use crate::mem;
-use crate::memchr;
 use crate::num::NonZeroU8;
 use crate::ops;
 use crate::os::raw::c_char;
@@ -20,6 +19,7 @@ use crate::slice;
 use crate::str::{self, Utf8Error};
 use crate::sync::Arc;
 use crate::sys;
+use crate::sys_common::memchr;
 
 /// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
 /// middle.
diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs
index d0c859d2e0c87..0175d2693e894 100644
--- a/library/std/src/io/buffered/linewritershim.rs
+++ b/library/std/src/io/buffered/linewritershim.rs
@@ -1,5 +1,5 @@
 use crate::io::{self, BufWriter, IoSlice, Write};
-use crate::memchr;
+use crate::sys_common::memchr;
 
 /// Private helper struct for implementing the line-buffered writing logic.
 /// This shim temporarily wraps a BufWriter, and uses its internals to
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 9f43379aff787..47a414fad391a 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -253,12 +253,12 @@ mod tests;
 
 use crate::cmp;
 use crate::fmt;
-use crate::memchr;
 use crate::ops::{Deref, DerefMut};
 use crate::ptr;
 use crate::slice;
 use crate::str;
 use crate::sys;
+use crate::sys_common::memchr;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::buffered::IntoInnerError;
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5f89ac059fd2d..3b86025cbba30 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -530,7 +530,6 @@ mod sys;
 pub mod alloc;
 
 // Private support modules
-mod memchr;
 mod panicking;
 
 // The runtime entry point and a few unstable public functions used by the
diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs
index 81cd68a74e665..40bd393098f57 100644
--- a/library/std/src/sys/hermit/os.rs
+++ b/library/std/src/sys/hermit/os.rs
@@ -4,11 +4,11 @@ use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
-use crate::memchr;
 use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sync::Mutex;
 use crate::sys::hermit::abi;
+use crate::sys::memchr;
 use crate::sys::unsupported;
 use crate::sys_common::os_str_bytes::*;
 use crate::vec;
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 51c3e5d175cca..bbc4691d963c6 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -13,13 +13,13 @@ use crate::fmt;
 use crate::io;
 use crate::iter;
 use crate::mem;
-use crate::memchr;
 use crate::path::{self, PathBuf};
 use crate::ptr;
 use crate::slice;
 use crate::str;
 use crate::sys::cvt;
 use crate::sys::fd;
+use crate::sys::memchr;
 use crate::sys::rwlock::{RWLockReadGuard, StaticRWLock};
 use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard};
 use crate::vec;
diff --git a/library/std/src/memchr.rs b/library/std/src/sys_common/memchr.rs
similarity index 92%
rename from library/std/src/memchr.rs
rename to library/std/src/sys_common/memchr.rs
index 86a08f75a8d48..b219e87891264 100644
--- a/library/std/src/memchr.rs
+++ b/library/std/src/sys_common/memchr.rs
@@ -1,6 +1,8 @@
 // Original implementation taken from rust-memchr.
 // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
 
+use crate::sys::memchr as sys;
+
 #[cfg(test)]
 mod tests;
 
@@ -25,7 +27,7 @@ mod tests;
 /// ```
 #[inline]
 pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    crate::sys::memchr::memchr(needle, haystack)
+    sys::memchr(needle, haystack)
 }
 
 /// A safe interface to `memrchr`.
@@ -45,5 +47,5 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 /// ```
 #[inline]
 pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    crate::sys::memchr::memrchr(needle, haystack)
+    sys::memrchr(needle, haystack)
 }
diff --git a/library/std/src/memchr/tests.rs b/library/std/src/sys_common/memchr/tests.rs
similarity index 100%
rename from library/std/src/memchr/tests.rs
rename to library/std/src/sys_common/memchr/tests.rs
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 7fa6977f2af26..5d2136ae74488 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -25,6 +25,7 @@ pub mod bytestring;
 pub mod condvar;
 pub mod fs;
 pub mod io;
+pub mod memchr;
 pub mod mutex;
 // `doc` is required because `sys/mod.rs` imports `unix/ext/mod.rs` on Windows
 // when generating documentation.

From 67e8f1230745785bc08ec4d3d882f61b1d3516af Mon Sep 17 00:00:00 2001
From: Alan Egerton <eggyal@gmail.com>
Date: Fri, 14 May 2021 13:28:56 +0100
Subject: [PATCH 03/26] Expose `Concurrent` (private type in public i'face)

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

diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 9adc099aaa566..bda5ed888d7e1 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -49,7 +49,7 @@ pub mod test {
         cli::{parse_opts, TestOpts},
         filter_tests,
         helpers::metrics::{Metric, MetricMap},
-        options::{Options, RunIgnored, RunStrategy, ShouldPanic},
+        options::{Concurrent, Options, RunIgnored, RunStrategy, ShouldPanic},
         run_test, test_main, test_main_static,
         test_result::{TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk},
         time::{TestExecTime, TestTimeOptions},

From f054ce394695ae8dc9cfa6db426bf1dbed483c2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= <lnicola@dend.ro>
Date: Mon, 17 May 2021 09:56:57 +0300
Subject: [PATCH 04/26] :arrow_up: rust-analyzer

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

diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
index fd109fb587904..b82458818d44d 160000
--- a/src/tools/rust-analyzer
+++ b/src/tools/rust-analyzer
@@ -1 +1 @@
-Subproject commit fd109fb587904cfecc1149e068814bfd38feb83c
+Subproject commit b82458818d44dfe5b4b5db38d8113e3f3194506e

From 445658ba6d00ae8fbbd7705ec1b1cf19b92d1ad2 Mon Sep 17 00:00:00 2001
From: Augie Fackler <augie@google.com>
Date: Mon, 17 May 2021 14:12:38 -0400
Subject: [PATCH 05/26] PassWrapper: update for LLVM change D102093

In https://reviews.llvm.org/D102093 lots of things stopped taking the
DebugLogging boolean parameter. Mercifully we appear to always set
DebugPassManager to false, so I don't think we're losing anything by not
passing this parameter.
---
 compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 65a988629c3b2..3cbdd9598cc2d 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -789,16 +789,23 @@ LLVMRustOptimizeWithNewPassManager(
     PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse);
   }
 
-#if LLVM_VERSION_GE(12, 0)
+#if LLVM_VERSION_GE(12, 0) && !LLVM_VERSION_GE(13,0)
   PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC);
 #else
   PassBuilder PB(TM, PTO, PGOOpt, &PIC);
 #endif
 
+#if LLVM_VERSION_GE(13, 0)
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+#else
   LoopAnalysisManager LAM(DebugPassManager);
   FunctionAnalysisManager FAM(DebugPassManager);
   CGSCCAnalysisManager CGAM(DebugPassManager);
   ModuleAnalysisManager MAM(DebugPassManager);
+#endif
 
   FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
 
@@ -935,7 +942,11 @@ LLVMRustOptimizeWithNewPassManager(
     }
   }
 
+#if LLVM_VERSION_GE(13, 0)
+  ModulePassManager MPM;
+#else
   ModulePassManager MPM(DebugPassManager);
+#endif
   bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
   if (!NoPrepopulatePasses) {
     if (OptLevel == PassBuilder::OptimizationLevel::O0) {

From d730cc66460c1cad2f7c5d1951a06666bb8b78de Mon Sep 17 00:00:00 2001
From: Mateusz Gacek <96mateusz.gacek@gmail.com>
Date: Tue, 18 May 2021 15:33:38 +0200
Subject: [PATCH 06/26] Add diagnostic item to `CStr`

---
 compiler/rustc_span/src/symbol.rs | 1 +
 library/std/src/ffi/c_str.rs      | 1 +
 2 files changed, 2 insertions(+)

diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 03a8f2be1561c..a5dc67854883e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -131,6 +131,7 @@ symbols! {
         BinaryHeap,
         Borrow,
         C,
+        CStr,
         CString,
         Center,
         Clone,
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 2f9845d7536cd..302f12af6a0fe 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -185,6 +185,7 @@ pub struct CString {
 ///
 /// [`&str`]: prim@str
 #[derive(Hash)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")]
 #[stable(feature = "rust1", since = "1.0.0")]
 // FIXME:
 // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies

From 24480ded58c9867439cfabba4198e1877c1fd166 Mon Sep 17 00:00:00 2001
From: Jacob Hoffman-Andrews <github@hoffman-andrews.com>
Date: Mon, 10 May 2021 16:41:41 -0700
Subject: [PATCH 07/26] Add method-toggle to <details> for methods.

The makes the code for handling "auto-hide" settings more consistent.
---
 src/librustdoc/html/render/mod.rs  |  9 ++++++---
 src/librustdoc/html/static/main.js | 16 ++++------------
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a288b43722ad4..318e1b44f8683 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1352,8 +1352,11 @@ fn render_impl(
         }
         let w = if short_documented && trait_.is_some() { interesting } else { boring };
 
-        if !doc_buffer.is_empty() {
-            w.write_str("<details class=\"rustdoc-toggle\" open><summary>");
+        let toggled = !doc_buffer.is_empty();
+        if toggled {
+            let method_toggle_class =
+                if item_type == ItemType::Method { " method-toggle" } else { "" };
+            write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class);
         }
         match *item.kind {
             clean::MethodItem(..) | clean::TyMethodItem(_) => {
@@ -1453,7 +1456,7 @@ fn render_impl(
         }
 
         w.push_buffer(info_buffer);
-        if !doc_buffer.is_empty() {
+        if toggled {
             w.write_str("</summary>");
             w.push_buffer(doc_buffer);
             w.push_str("</details>");
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 307ce9ac3752c..83e6a529b0aa4 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -924,24 +924,16 @@ function hideThemeButtonState() {
             });
         }
 
-        if (hideMethodDocs) {
-            onEachLazy(document.getElementsByClassName("method"), function(e) {
-                var toggle = e.parentNode;
-                if (toggle) {
-                    toggle = toggle.parentNode;
-                }
-                if (toggle && toggle.tagName === "DETAILS") {
-                    toggle.open = false;
-                }
-            });
-        }
-
         onEachLazy(document.getElementsByTagName("details"), function (e) {
             var showLargeItem = !hideLargeItemContents && hasClass(e, "type-contents-toggle");
             var showImplementor = !hideImplementors && hasClass(e, "implementors-toggle");
             if (showLargeItem || showImplementor) {
                 e.open = true;
             }
+            if (hideMethodDocs && hasClass(e, "method-toggle")) {
+                e.open = false;
+            }
+
         });
 
         var currentType = document.getElementsByClassName("type-decl")[0];

From f9752b493086fd3063c9aef83d2622d322bbc51c Mon Sep 17 00:00:00 2001
From: Frank Steffahn <frank.steffahn@stu.uni-kiel.de>
Date: Wed, 19 May 2021 12:33:10 +0200
Subject: [PATCH 08/26] Fix UB in documented example for `ptr::swap`

---
 library/core/src/ptr/mod.rs | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 2c324b15a1a1a..214d7c8bc1560 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -342,10 +342,12 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
 /// ```
 /// use std::ptr;
 ///
-/// let mut array = [0, 1, 2, 3];
+/// let mut array: [i32; 4] = [0, 1, 2, 3];
+///
+/// let array_ptr: *mut i32 = array.as_mut_ptr();
 ///
-/// let x = array[0..].as_mut_ptr() as *mut [u32; 3]; // this is `array[0..3]`
-/// let y = array[1..].as_mut_ptr() as *mut [u32; 3]; // this is `array[1..4]`
+/// let x = array_ptr as *mut [i32; 3]; // this is `array[0..3]`
+/// let y = unsafe { array_ptr.add(1) } as *mut [i32; 3]; // this is `array[1..4]`
 ///
 /// unsafe {
 ///     ptr::swap(x, y);

From 5b0908587e5e549051bcc6294b034049421de4f8 Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Thu, 29 Apr 2021 15:57:05 +0200
Subject: [PATCH 09/26] Introduce `sys_common::rt::rterr!`

---
 library/std/src/sys_common/rt.rs | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/library/std/src/sys_common/rt.rs b/library/std/src/sys_common/rt.rs
index c70f2ecc04e3a..9ce6aa7c36963 100644
--- a/library/std/src/sys_common/rt.rs
+++ b/library/std/src/sys_common/rt.rs
@@ -1,4 +1,5 @@
 #![deny(unsafe_op_in_unsafe_fn)]
+#![allow(unused_macros)]
 
 use crate::sync::Once;
 use crate::sys;
@@ -38,6 +39,14 @@ pub fn cleanup() {
     });
 }
 
+macro_rules! rterr {
+    ($($t:tt)*) => {
+        if let Some(mut out) = crate::sys::stdio::panic_output() {
+            let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
+        }
+    }
+}
+
 macro_rules! rtabort {
     ($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*)))
 }
@@ -50,7 +59,6 @@ macro_rules! rtassert {
     };
 }
 
-#[allow(unused_macros)] // not used on all platforms
 macro_rules! rtunwrap {
     ($ok:ident, $e:expr) => {
         match $e {

From b987f74f05b3fbeb81eed27c43678dc71cdab8cf Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Thu, 29 Apr 2021 15:59:05 +0200
Subject: [PATCH 10/26] Remove `sys_common::util::abort`

---
 library/std/src/sys_common/rt.rs   |  7 ++++++-
 library/std/src/sys_common/util.rs | 10 ----------
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/library/std/src/sys_common/rt.rs b/library/std/src/sys_common/rt.rs
index 9ce6aa7c36963..e4c9b60594ef7 100644
--- a/library/std/src/sys_common/rt.rs
+++ b/library/std/src/sys_common/rt.rs
@@ -48,7 +48,12 @@ macro_rules! rterr {
 }
 
 macro_rules! rtabort {
-    ($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*)))
+    ($($t:tt)*) => {
+        {
+            rterr!("fatal runtime error: {}\n", format_args!($($t)*));
+            crate::sys::abort_internal();
+        }
+    }
 }
 
 macro_rules! rtassert {
diff --git a/library/std/src/sys_common/util.rs b/library/std/src/sys_common/util.rs
index 9f7c3bd87952f..b8cae26d04c58 100644
--- a/library/std/src/sys_common/util.rs
+++ b/library/std/src/sys_common/util.rs
@@ -9,16 +9,6 @@ pub fn dumb_print(args: fmt::Arguments<'_>) {
     }
 }
 
-// Other platforms should use the appropriate platform-specific mechanism for
-// aborting the process.  If no platform-specific mechanism is available,
-// crate::intrinsics::abort() may be used instead.  The above implementations cover
-// all targets currently supported by libstd.
-
-pub fn abort(args: fmt::Arguments<'_>) -> ! {
-    dumb_print(format_args!("fatal runtime error: {}\n", args));
-    crate::sys::abort_internal();
-}
-
 #[allow(dead_code)] // stack overflow detection not enabled on all platforms
 pub unsafe fn report_overflow() {
     dumb_print(format_args!(

From 236705f3c30905623f97dc8887c83db520eb27c1 Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Thu, 29 Apr 2021 16:05:10 +0200
Subject: [PATCH 11/26] Replace `sys_common::util::report_overflow` with
 `rterr!`

---
 library/std/src/sys/unix/stack_overflow.rs    | 8 +++++---
 library/std/src/sys/windows/stack_overflow.rs | 7 +++++--
 library/std/src/sys_common/util.rs            | 9 ---------
 3 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs
index 2a487fff54ae7..72fd48278bc16 100644
--- a/library/std/src/sys/unix/stack_overflow.rs
+++ b/library/std/src/sys/unix/stack_overflow.rs
@@ -42,6 +42,7 @@ mod imp {
     use crate::io;
     use crate::mem;
     use crate::ptr;
+    use crate::thread;
 
     use libc::MAP_FAILED;
     use libc::{mmap, munmap};
@@ -95,15 +96,16 @@ mod imp {
         info: *mut libc::siginfo_t,
         _data: *mut libc::c_void,
     ) {
-        use crate::sys_common::util::report_overflow;
-
         let guard = thread_info::stack_guard().unwrap_or(0..0);
         let addr = siginfo_si_addr(info);
 
         // If the faulting address is within the guard page, then we print a
         // message saying so and abort.
         if guard.start <= addr && addr < guard.end {
-            report_overflow();
+            rterr!(
+                "\nthread '{}' has overflowed its stack\n",
+                thread::current().name().unwrap_or("<unknown>")
+            );
             rtabort!("stack overflow");
         } else {
             // Unregister ourselves by reverting back to the default behavior.
diff --git a/library/std/src/sys/windows/stack_overflow.rs b/library/std/src/sys/windows/stack_overflow.rs
index 39efb778207fc..24ba35ad17e63 100644
--- a/library/std/src/sys/windows/stack_overflow.rs
+++ b/library/std/src/sys/windows/stack_overflow.rs
@@ -1,7 +1,7 @@
 #![cfg_attr(test, allow(dead_code))]
 
 use crate::sys::c;
-use crate::sys_common::util::report_overflow;
+use crate::thread;
 
 pub struct Handler;
 
@@ -24,7 +24,10 @@ extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -
         let code = rec.ExceptionCode;
 
         if code == c::EXCEPTION_STACK_OVERFLOW {
-            report_overflow();
+            rterr!(
+                "\nthread '{}' has overflowed its stack\n",
+                thread::current().name().unwrap_or("<unknown>")
+            );
         }
         c::EXCEPTION_CONTINUE_SEARCH
     }
diff --git a/library/std/src/sys_common/util.rs b/library/std/src/sys_common/util.rs
index b8cae26d04c58..f7072cc501103 100644
--- a/library/std/src/sys_common/util.rs
+++ b/library/std/src/sys_common/util.rs
@@ -1,18 +1,9 @@
 use crate::fmt;
 use crate::io::prelude::*;
 use crate::sys::stdio::panic_output;
-use crate::thread;
 
 pub fn dumb_print(args: fmt::Arguments<'_>) {
     if let Some(mut out) = panic_output() {
         let _ = out.write_fmt(args);
     }
 }
-
-#[allow(dead_code)] // stack overflow detection not enabled on all platforms
-pub unsafe fn report_overflow() {
-    dumb_print(format_args!(
-        "\nthread '{}' has overflowed its stack\n",
-        thread::current().name().unwrap_or("<unknown>")
-    ));
-}

From 6145051eeebeba030cef3aa01a99683b84ff24fc Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Thu, 29 Apr 2021 16:10:32 +0200
Subject: [PATCH 12/26] Replace `sys_common::util::dumb_print` with `rterr!`

---
 library/std/src/alloc.rs           |  4 +---
 library/std/src/panicking.rs       | 10 +++++-----
 library/std/src/sys_common/mod.rs  |  1 -
 library/std/src/sys_common/util.rs |  9 ---------
 4 files changed, 6 insertions(+), 18 deletions(-)
 delete mode 100644 library/std/src/sys_common/util.rs

diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 843ef09a5842f..9e9052ff92e1b 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -63,8 +63,6 @@ use core::ptr::NonNull;
 use core::sync::atomic::{AtomicPtr, Ordering};
 use core::{mem, ptr};
 
-use crate::sys_common::util::dumb_print;
-
 #[stable(feature = "alloc_module", since = "1.28.0")]
 #[doc(inline)]
 pub use alloc_crate::alloc::*;
@@ -317,7 +315,7 @@ pub fn take_alloc_error_hook() -> fn(Layout) {
 }
 
 fn default_alloc_error_hook(layout: Layout) {
-    dumb_print(format_args!("memory allocation of {} bytes failed\n", layout.size()));
+    rterr!("memory allocation of {} bytes failed\n", layout.size());
 }
 
 #[cfg(not(test))]
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index a8410bea7342b..9091151518579 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -20,7 +20,7 @@ use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::stdio::panic_output;
 use crate::sys_common::backtrace::{self, RustBacktrace};
 use crate::sys_common::rwlock::RWLock;
-use crate::sys_common::{thread_info, util};
+use crate::sys_common::thread_info;
 use crate::thread;
 
 #[cfg(not(test))]
@@ -596,15 +596,15 @@ fn rust_panic_with_hook(
         if panics > 2 {
             // Don't try to print the message in this case
             // - perhaps that is causing the recursive panics.
-            util::dumb_print(format_args!("thread panicked while processing panic. aborting.\n"));
+            rterr!("thread panicked while processing panic. aborting.\n");
         } else {
             // Unfortunately, this does not print a backtrace, because creating
             // a `Backtrace` will allocate, which we must to avoid here.
             let panicinfo = PanicInfo::internal_constructor(message, location);
-            util::dumb_print(format_args!(
+            rterr!(
                 "{}\npanicked after panic::always_abort(), aborting.\n",
                 panicinfo
-            ));
+            );
         }
         intrinsics::abort()
     }
@@ -637,7 +637,7 @@ fn rust_panic_with_hook(
         // have limited options. Currently our preference is to
         // just abort. In the future we may consider resuming
         // unwinding or otherwise exiting the thread cleanly.
-        util::dumb_print(format_args!("thread panicked while panicking. aborting.\n"));
+        rterr!("thread panicked while panicking. aborting.\n");
         intrinsics::abort()
     }
 
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 7fa6977f2af26..4ef0e72adf020 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -40,7 +40,6 @@ pub mod thread_info;
 pub mod thread_local_dtor;
 pub mod thread_local_key;
 pub mod thread_parker;
-pub mod util;
 pub mod wtf8;
 
 cfg_if::cfg_if! {
diff --git a/library/std/src/sys_common/util.rs b/library/std/src/sys_common/util.rs
deleted file mode 100644
index f7072cc501103..0000000000000
--- a/library/std/src/sys_common/util.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use crate::fmt;
-use crate::io::prelude::*;
-use crate::sys::stdio::panic_output;
-
-pub fn dumb_print(args: fmt::Arguments<'_>) {
-    if let Some(mut out) = panic_output() {
-        let _ = out.write_fmt(args);
-    }
-}

From ec32bcf3fdb4fd3e36a48a5e9c11df0f3f7cd222 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Wed, 19 May 2021 15:37:10 +0200
Subject: [PATCH 13/26] Fix invalid CSS rules for a:hover

---
 src/librustdoc/html/static/themes/ayu.css   | 7 ++-----
 src/librustdoc/html/static/themes/dark.css  | 4 ++--
 src/librustdoc/html/static/themes/light.css | 4 ++--
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
index 989ea7140c587..e59909ffdf05e 100644
--- a/src/librustdoc/html/static/themes/ayu.css
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -151,17 +151,14 @@ pre, .rustdoc.source .example-wrap {
 	color: #c5c5c5;
 }
 
-.content a:hover {
+.search-results a:hover {
 	background-color: #777;
 }
 
-.content a:focus {
+.search-results a:focus {
 	color: #000 !important;
 	background-color: #c6afb3;
 }
-.content a:focus {
-	color: #000 !important;
-}
 .search-results a {
 	color: #0096cf;
 }
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index e6bd16ddd11b8..a2bcb43f44e6f 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -109,11 +109,11 @@ pre, .rustdoc.source .example-wrap {
 	color: #ddd;
 }
 
-.content a:hover {
+.search-results a:hover {
 	background-color: #777;
 }
 
-.content a:focus {
+.search-results a:focus {
 	color: #eee !important;
 	background-color: #616161;
 }
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 5481b348aa26f..2ad3551d900ea 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -109,11 +109,11 @@ pre, .rustdoc.source .example-wrap {
 	color: #4E4C4C;
 }
 
-.content a:hover {
+.search-results a:hover {
 	background-color: #ddd;
 }
 
-.content a:focus {
+.search-results a:focus {
 	color: #000 !important;
 	background-color: #ccc;
 }

From 4ff5ab52966203b8ad8da96f897566e4a218308a Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Thu, 6 May 2021 14:03:50 +0200
Subject: [PATCH 14/26] Rename `rterr` to `rtprintpanic`

---
 library/std/src/alloc.rs                      | 2 +-
 library/std/src/panicking.rs                  | 9 +++------
 library/std/src/sys/unix/stack_overflow.rs    | 2 +-
 library/std/src/sys/windows/stack_overflow.rs | 2 +-
 library/std/src/sys_common/rt.rs              | 8 ++++++--
 5 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 9e9052ff92e1b..8ee55234cea43 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -315,7 +315,7 @@ pub fn take_alloc_error_hook() -> fn(Layout) {
 }
 
 fn default_alloc_error_hook(layout: Layout) {
-    rterr!("memory allocation of {} bytes failed\n", layout.size());
+    rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
 }
 
 #[cfg(not(test))]
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 9091151518579..02957e75a7409 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -596,15 +596,12 @@ fn rust_panic_with_hook(
         if panics > 2 {
             // Don't try to print the message in this case
             // - perhaps that is causing the recursive panics.
-            rterr!("thread panicked while processing panic. aborting.\n");
+            rtprintpanic!("thread panicked while processing panic. aborting.\n");
         } else {
             // Unfortunately, this does not print a backtrace, because creating
             // a `Backtrace` will allocate, which we must to avoid here.
             let panicinfo = PanicInfo::internal_constructor(message, location);
-            rterr!(
-                "{}\npanicked after panic::always_abort(), aborting.\n",
-                panicinfo
-            );
+            rtprintpanic!("{}\npanicked after panic::always_abort(), aborting.\n", panicinfo);
         }
         intrinsics::abort()
     }
@@ -637,7 +634,7 @@ fn rust_panic_with_hook(
         // have limited options. Currently our preference is to
         // just abort. In the future we may consider resuming
         // unwinding or otherwise exiting the thread cleanly.
-        rterr!("thread panicked while panicking. aborting.\n");
+        rtprintpanic!("thread panicked while panicking. aborting.\n");
         intrinsics::abort()
     }
 
diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs
index 72fd48278bc16..81f47a779d33b 100644
--- a/library/std/src/sys/unix/stack_overflow.rs
+++ b/library/std/src/sys/unix/stack_overflow.rs
@@ -102,7 +102,7 @@ mod imp {
         // If the faulting address is within the guard page, then we print a
         // message saying so and abort.
         if guard.start <= addr && addr < guard.end {
-            rterr!(
+            rtprintpanic!(
                 "\nthread '{}' has overflowed its stack\n",
                 thread::current().name().unwrap_or("<unknown>")
             );
diff --git a/library/std/src/sys/windows/stack_overflow.rs b/library/std/src/sys/windows/stack_overflow.rs
index 24ba35ad17e63..755dc0a6c8b47 100644
--- a/library/std/src/sys/windows/stack_overflow.rs
+++ b/library/std/src/sys/windows/stack_overflow.rs
@@ -24,7 +24,7 @@ extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -
         let code = rec.ExceptionCode;
 
         if code == c::EXCEPTION_STACK_OVERFLOW {
-            rterr!(
+            rtprintpanic!(
                 "\nthread '{}' has overflowed its stack\n",
                 thread::current().name().unwrap_or("<unknown>")
             );
diff --git a/library/std/src/sys_common/rt.rs b/library/std/src/sys_common/rt.rs
index e4c9b60594ef7..02013ecc4ced6 100644
--- a/library/std/src/sys_common/rt.rs
+++ b/library/std/src/sys_common/rt.rs
@@ -39,7 +39,11 @@ pub fn cleanup() {
     });
 }
 
-macro_rules! rterr {
+// Prints to the "panic output", depending on the platform this may be:
+// - the standard error output
+// - some dedicated platform specific output
+// - nothing (so this macro is a no-op)
+macro_rules! rtprintpanic {
     ($($t:tt)*) => {
         if let Some(mut out) = crate::sys::stdio::panic_output() {
             let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
@@ -50,7 +54,7 @@ macro_rules! rterr {
 macro_rules! rtabort {
     ($($t:tt)*) => {
         {
-            rterr!("fatal runtime error: {}\n", format_args!($($t)*));
+            rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*));
             crate::sys::abort_internal();
         }
     }

From 50a9f008f266bc7e81926309e3a0a2e36860a305 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Wed, 19 May 2021 16:37:17 +0200
Subject: [PATCH 15/26] CTFE Machine: do not expose Allocation

---
 compiler/rustc_mir/src/interpret/machine.rs |  7 ++++---
 compiler/rustc_mir/src/interpret/memory.rs  | 13 +++++++------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs
index e6b3b1daf5a79..e7d7c38cc8ffd 100644
--- a/compiler/rustc_mir/src/interpret/machine.rs
+++ b/compiler/rustc_mir/src/interpret/machine.rs
@@ -313,7 +313,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     #[inline(always)]
     fn memory_read(
         _memory_extra: &Self::MemoryExtra,
-        _alloc: &Allocation<Self::PointerTag, Self::AllocExtra>,
+        _alloc_extra: &Self::AllocExtra,
         _ptr: Pointer<Self::PointerTag>,
         _size: Size,
     ) -> InterpResult<'tcx> {
@@ -324,7 +324,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     #[inline(always)]
     fn memory_written(
         _memory_extra: &mut Self::MemoryExtra,
-        _alloc: &mut Allocation<Self::PointerTag, Self::AllocExtra>,
+        _alloc_extra: &mut Self::AllocExtra,
         _ptr: Pointer<Self::PointerTag>,
         _size: Size,
     ) -> InterpResult<'tcx> {
@@ -335,8 +335,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
     #[inline(always)]
     fn memory_deallocated(
         _memory_extra: &mut Self::MemoryExtra,
-        _alloc: &mut Allocation<Self::PointerTag, Self::AllocExtra>,
+        _alloc_extra: &mut Self::AllocExtra,
         _ptr: Pointer<Self::PointerTag>,
+        _size: Size,
     ) -> InterpResult<'tcx> {
         Ok(())
     }
diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs
index 37aaa834aff1c..7fb7c51b0b5bc 100644
--- a/compiler/rustc_mir/src/interpret/memory.rs
+++ b/compiler/rustc_mir/src/interpret/memory.rs
@@ -343,10 +343,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         }
 
         // Let the machine take some extra action
-        M::memory_deallocated(&mut self.extra, &mut alloc, ptr)?;
+        let size = alloc.size();
+        M::memory_deallocated(&mut self.extra, &mut alloc.extra, ptr, size)?;
 
         // Don't forget to remember size and align of this now-dead allocation
-        let old = self.dead_alloc_map.insert(ptr.alloc_id, (alloc.size(), alloc.align));
+        let old = self.dead_alloc_map.insert(ptr.alloc_id, (size, alloc.align));
         if old.is_some() {
             bug!("Nothing can be deallocated twice");
         }
@@ -591,7 +592,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             },
         )?;
         if let Some((ptr, alloc)) = ptr_and_alloc {
-            M::memory_read(&self.extra, alloc, ptr, size)?;
+            M::memory_read(&self.extra, &alloc.extra, ptr, size)?;
             let range = alloc_range(ptr.offset, size);
             Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id: ptr.alloc_id }))
         } else {
@@ -660,7 +661,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             // FIXME: can we somehow avoid looking up the allocation twice here?
             // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
             let (alloc, extra) = self.get_raw_mut(ptr.alloc_id)?;
-            M::memory_written(extra, alloc, ptr, size)?;
+            M::memory_written(extra, &mut alloc.extra, ptr, size)?;
             let range = alloc_range(ptr.offset, size);
             Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id: ptr.alloc_id }))
         } else {
@@ -1029,7 +1030,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             Some(src_ptr) => src_ptr,
         };
         let src_alloc = self.get_raw(src.alloc_id)?;
-        M::memory_read(&self.extra, src_alloc, src, size)?;
+        M::memory_read(&self.extra, &src_alloc.extra, src, size)?;
         // We need the `dest` ptr for the next operation, so we get it now.
         // We already did the source checks and called the hooks so we are good to return early.
         let dest = match dest {
@@ -1058,7 +1059,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
         // Destination alloc preparations and access hooks.
         let (dest_alloc, extra) = self.get_raw_mut(dest.alloc_id)?;
-        M::memory_written(extra, dest_alloc, dest, size * num_copies)?;
+        M::memory_written(extra, &mut dest_alloc.extra, dest, size * num_copies)?;
         let dest_bytes = dest_alloc
             .get_bytes_mut_ptr(&tcx, alloc_range(dest.offset, size * num_copies))
             .as_mut_ptr();

From 523b4d149966a284101cc823167e637b6be9a10a Mon Sep 17 00:00:00 2001
From: Adam Gemmell <adam.gemmell@arm.com>
Date: Wed, 19 May 2021 16:11:11 +0100
Subject: [PATCH 16/26] Remove LSE2

---
 compiler/rustc_codegen_llvm/src/llvm_util.rs      | 1 -
 compiler/rustc_codegen_ssa/src/target_features.rs | 4 +---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index f0a2c91c01851..c734d3e0af93d 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -153,7 +153,6 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
         ("aarch64", "fp") => "fp-armv8",
         ("aarch64", "fp16") => "fullfp16",
         ("aarch64", "fhm") => "fp16fml",
-        ("aarch64", "lse2") => "outline-atomics",
         ("aarch64", "rcpc2") => "rcpc-immo",
         ("aarch64", "dpb") => "ccpp",
         ("aarch64", "dpb2") => "ccdp",
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index aa415754dadb0..5a8f0b6d6dbad 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -33,7 +33,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("thumb-mode", Some(sym::arm_target_feature)),
 ];
 
-// Commented features are not available in LLVM 9.0, or have since been renamed
+// Commented features are not available in LLVM 10.0, or have since been renamed
 const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // FEAT_AdvSimd
     ("neon", Some(sym::aarch64_target_feature)),
@@ -51,8 +51,6 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("ras", Some(sym::aarch64_target_feature)),
     // FEAT_LSE
     ("lse", Some(sym::aarch64_target_feature)),
-    // FEAT_LSE2
-    // ("lse2", Some(sym::aarch64_target_feature)),
     // FEAT_RDM
     ("rdm", Some(sym::aarch64_target_feature)),
     // FEAT_RCPC

From c71e58d432447d29cbcb99b19b48e43a9913dcc1 Mon Sep 17 00:00:00 2001
From: Adam Gemmell <adam.gemmell@arm.com>
Date: Wed, 19 May 2021 16:12:30 +0100
Subject: [PATCH 17/26] Rename fptoint to frintts

---
 compiler/rustc_codegen_llvm/src/llvm_util.rs      | 1 +
 compiler/rustc_codegen_ssa/src/target_features.rs | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index c734d3e0af93d..6394f15f6a92d 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -156,6 +156,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
         ("aarch64", "rcpc2") => "rcpc-immo",
         ("aarch64", "dpb") => "ccpp",
         ("aarch64", "dpb2") => "ccdp",
+        ("aarch64", "frintts") => "fptoint",
         ("aarch64", "fcma") => "complxnum",
         (_, s) => s,
     }
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 5a8f0b6d6dbad..646f21fa10fbb 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -88,7 +88,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // FEAT_SVE2_BitPerm
     ("sve2-bitperm", Some(sym::aarch64_target_feature)),
     // FEAT_FRINTTS
-    ("fptoint", Some(sym::aarch64_target_feature)),
+    ("frintts", Some(sym::aarch64_target_feature)),
     // FEAT_I8MM
     // ("i8mm", Some(sym::aarch64_target_feature)),
     // FEAT_F32MM

From 904467a926f20d189203d119af57ae3861d2b56c Mon Sep 17 00:00:00 2001
From: Adam Gemmell <adam.gemmell@arm.com>
Date: Wed, 19 May 2021 16:13:23 +0100
Subject: [PATCH 18/26] Ensure all crypto components (AES, PMULL, SHA1/2) are
 available on arm/aarch64

---
 compiler/rustc_codegen_ssa/src/target_features.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 646f21fa10fbb..98d550d732fe2 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -17,6 +17,8 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("neon", Some(sym::arm_target_feature)),
     ("crc", Some(sym::arm_target_feature)),
     ("crypto", Some(sym::arm_target_feature)),
+    ("aes", Some(sym::arm_target_feature)),
+    ("sha2", Some(sym::arm_target_feature)),
     ("v5te", Some(sym::arm_target_feature)),
     ("v6", Some(sym::arm_target_feature)),
     ("v6k", Some(sym::arm_target_feature)),
@@ -107,6 +109,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("jsconv", Some(sym::aarch64_target_feature)),
     // FEAT_FCMA
     ("fcma", Some(sym::aarch64_target_feature)),
+    // FEAT_AES
+    ("aes", Some(sym::aarch64_target_feature)),
     // FEAT_SHA1 & FEAT_SHA256
     ("sha2", Some(sym::aarch64_target_feature)),
     // FEAT_SHA512 & FEAT_SHA3

From d3737a66074945f65858086609cd51377c14559b Mon Sep 17 00:00:00 2001
From: Adam Gemmell <adam.gemmell@arm.com>
Date: Wed, 19 May 2021 16:13:52 +0100
Subject: [PATCH 19/26] Remove test for crypto feature ahead of its removal

---
 library/std/tests/run-time-detect.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs
index 61a04c467224b..c7107b5d0a3ef 100644
--- a/library/std/tests/run-time-detect.rs
+++ b/library/std/tests/run-time-detect.rs
@@ -27,7 +27,6 @@ fn aarch64_linux() {
     println!("asimd: {}", is_aarch64_feature_detected!("asimd"));
     println!("sve: {}", is_aarch64_feature_detected!("sve"));
     println!("crc: {}", is_aarch64_feature_detected!("crc"));
-    println!("crypto: {}", is_aarch64_feature_detected!("crypto"));
     println!("lse: {}", is_aarch64_feature_detected!("lse"));
     println!("rdm: {}", is_aarch64_feature_detected!("rdm"));
     println!("rcpc: {}", is_aarch64_feature_detected!("rcpc"));

From f06126506077ba535bc36f73bb531651c284c154 Mon Sep 17 00:00:00 2001
From: Chris Denton <christophersdenton@gmail.com>
Date: Wed, 17 Mar 2021 03:52:02 +0000
Subject: [PATCH 20/26] Move the implementation of `Path::exists` to
 `sys_common::fs` so platforms can specialize it

---
 library/std/src/fs.rs                 | 26 ++++++++++++++++++++++++++
 library/std/src/path.rs               |  6 +-----
 library/std/src/sys/hermit/fs.rs      |  2 +-
 library/std/src/sys/unix/fs.rs        |  2 +-
 library/std/src/sys/unsupported/fs.rs |  4 ++++
 library/std/src/sys/wasi/fs.rs        |  2 +-
 library/std/src/sys/windows/fs.rs     |  1 +
 library/std/src/sys_common/fs.rs      |  8 ++++++++
 8 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index e6120b8ee31c2..a1636e2f604cf 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2208,3 +2208,29 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
         &mut self.inner
     }
 }
+
+/// Returns `Ok(true)` if the path points at an existing entity.
+///
+/// This function will traverse symbolic links to query information about the
+/// destination file. In case of broken symbolic links this will return `Ok(false)`.
+///
+/// As opposed to the `exists()` method, this one doesn't silently ignore errors
+/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
+/// denied on some of the parent directories.)
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(path_try_exists)]
+/// use std::fs;
+///
+/// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt"));
+/// assert!(fs::try_exists("/root/secret_file.txt").is_err());
+/// ```
+// FIXME: stabilization should modify documentation of `exists()` to recommend this method
+// instead.
+#[unstable(feature = "path_try_exists", issue = "83186")]
+#[inline]
+pub fn try_exists<P: AsRef<Path>>(path: P) -> io::Result<bool> {
+    fs_imp::try_exists(path.as_ref())
+}
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index cbe14767bd3e7..9c5615f58c436 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2507,11 +2507,7 @@ impl Path {
     #[unstable(feature = "path_try_exists", issue = "83186")]
     #[inline]
     pub fn try_exists(&self) -> io::Result<bool> {
-        match fs::metadata(self) {
-            Ok(_) => Ok(true),
-            Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
-            Err(error) => Err(error),
-        }
+        fs::try_exists(self)
     }
 
     /// Returns `true` if the path exists on disk and is pointing at a regular file.
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 5b3f2fa4e8275..76ea70d997f5d 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -12,7 +12,7 @@ use crate::sys::time::SystemTime;
 use crate::sys::unsupported;
 use crate::sys_common::os_str_bytes::OsStrExt;
 
-pub use crate::sys_common::fs::copy;
+pub use crate::sys_common::fs::{copy, try_exists};
 //pub use crate::sys_common::fs::remove_dir_all;
 
 fn cstr(path: &Path) -> io::Result<CString> {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 79617aa77b7b2..ef14865fbcd39 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -48,7 +48,7 @@ use libc::{
     dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, readdir64_r, stat64,
 };
 
-pub use crate::sys_common::fs::remove_dir_all;
+pub use crate::sys_common::fs::{remove_dir_all, try_exists};
 
 pub struct File(FileDesc);
 
diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs
index cd533761e3732..1ec16a1acb375 100644
--- a/library/std/src/sys/unsupported/fs.rs
+++ b/library/std/src/sys/unsupported/fs.rs
@@ -275,6 +275,10 @@ pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
     unsupported()
 }
 
+pub fn try_exists(_path: &Path) -> io::Result<()> {
+    unsupported()
+}
+
 pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
     unsupported()
 }
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index ed0f03e4b710b..45e38f68b8c37 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -14,7 +14,7 @@ use crate::sys::time::SystemTime;
 use crate::sys::unsupported;
 use crate::sys_common::FromInner;
 
-pub use crate::sys_common::fs::remove_dir_all;
+pub use crate::sys_common::fs::{remove_dir_all, try_exists};
 
 pub struct File {
     fd: WasiFd,
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 8e6bd76f85f06..36b395507b129 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -11,6 +11,7 @@ use crate::sync::Arc;
 use crate::sys::handle::Handle;
 use crate::sys::time::SystemTime;
 use crate::sys::{c, cvt};
+pub use crate::sys_common::fs::try_exists;
 use crate::sys_common::FromInner;
 
 use super::to_u16s;
diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs
index 30908824dd663..309f5483874e0 100644
--- a/library/std/src/sys_common/fs.rs
+++ b/library/std/src/sys_common/fs.rs
@@ -41,3 +41,11 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
     }
     fs::remove_dir(path)
 }
+
+pub fn try_exists(path: &Path) -> io::Result<bool> {
+    match fs::metadata(path) {
+        Ok(_) => Ok(true),
+        Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
+        Err(error) => Err(error),
+    }
+}

From 5d7c75a19f5bed05e565979f35d5fa5a09471217 Mon Sep 17 00:00:00 2001
From: Chris Denton <christophersdenton@gmail.com>
Date: Tue, 18 May 2021 04:18:46 +0100
Subject: [PATCH 21/26] Windows implementation of `fs::try_exists`

---
 library/std/src/sys/windows/c.rs  |  1 +
 library/std/src/sys/windows/fs.rs | 30 +++++++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index e91c489361ea6..50d6e8cf27a40 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -173,6 +173,7 @@ pub const ERROR_INVALID_HANDLE: DWORD = 6;
 pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8;
 pub const ERROR_OUTOFMEMORY: DWORD = 14;
 pub const ERROR_NO_MORE_FILES: DWORD = 18;
+pub const ERROR_SHARING_VIOLATION: u32 = 32;
 pub const ERROR_HANDLE_EOF: DWORD = 38;
 pub const ERROR_FILE_EXISTS: DWORD = 80;
 pub const ERROR_INVALID_PARAMETER: DWORD = 87;
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 36b395507b129..2b6143de96056 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -11,7 +11,6 @@ use crate::sync::Arc;
 use crate::sys::handle::Handle;
 use crate::sys::time::SystemTime;
 use crate::sys::{c, cvt};
-pub use crate::sys_common::fs::try_exists;
 use crate::sys_common::FromInner;
 
 use super::to_u16s;
@@ -945,3 +944,32 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
         .map(drop)
     }
 }
+
+// Try to see if a file exists but, unlike `exists`, report I/O errors.
+pub fn try_exists(path: &Path) -> io::Result<bool> {
+    // Open the file to ensure any symlinks are followed to their target.
+    let mut opts = OpenOptions::new();
+    // No read, write, etc access rights are needed.
+    opts.access_mode(0);
+    // Backup semantics enables opening directories as well as files.
+    opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
+    match File::open(path, &opts) {
+        Err(e) => match e.kind() {
+            // The file definitely does not exist
+            io::ErrorKind::NotFound => Ok(false),
+
+            // `ERROR_SHARING_VIOLATION` means that the file has been locked by
+            // another process. This is often temporary so we simply report it
+            // as the file existing.
+            io::ErrorKind::Other if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => {
+                Ok(true)
+            }
+            // Other errors such as `ERROR_ACCESS_DENIED` may indicate that the
+            // file exists. However, these types of errors are usually more
+            // permanent so we report them here.
+            _ => Err(e),
+        },
+        // The file was opened successfully therefore it must exist,
+        Ok(_) => Ok(true),
+    }
+}

From 39441bb2c1030884d0f1d200de0a65b146ba6b6d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Thu, 29 Apr 2021 11:10:14 -0700
Subject: [PATCH 22/26] Make a ui test to take the role of libproc_macro
 #[test] tests

---
 src/test/ui/proc-macro/auxiliary/api/mod.rs | 16 ++++++++++++++++
 src/test/ui/proc-macro/test.rs              | 12 ++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 src/test/ui/proc-macro/auxiliary/api/mod.rs
 create mode 100644 src/test/ui/proc-macro/test.rs

diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs
new file mode 100644
index 0000000000000..72b02ad554e52
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs
@@ -0,0 +1,16 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![crate_name = "proc_macro_api_tests"]
+#![deny(dead_code)] // catch if a test function is never called
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn run(input: TokenStream) -> TokenStream {
+    assert!(input.is_empty());
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/test.rs b/src/test/ui/proc-macro/test.rs
new file mode 100644
index 0000000000000..c96aa73175f2c
--- /dev/null
+++ b/src/test/ui/proc-macro/test.rs
@@ -0,0 +1,12 @@
+// check-pass
+// aux-build:api/mod.rs
+
+//! This is for everything that *would* be a #[test] inside of libproc_macro,
+//! except for the fact that proc_macro objects are not capable of existing
+//! inside of an ordinary Rust test execution, only inside a macro.
+
+extern crate proc_macro_api_tests;
+
+proc_macro_api_tests::run!();
+
+fn main() {}

From 3c16c0e1df61755db2267897392529eb9451aa62 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Thu, 29 Apr 2021 11:17:44 -0700
Subject: [PATCH 23/26] Move proc_macro tests to ui test

---
 .../test/ui/proc-macro/auxiliary/api/cmp.rs              | 9 +++++----
 src/test/ui/proc-macro/auxiliary/api/mod.rs              | 4 ++++
 2 files changed, 9 insertions(+), 4 deletions(-)
 rename library/proc_macro/tests/test.rs => src/test/ui/proc-macro/auxiliary/api/cmp.rs (88%)

diff --git a/library/proc_macro/tests/test.rs b/src/test/ui/proc-macro/auxiliary/api/cmp.rs
similarity index 88%
rename from library/proc_macro/tests/test.rs
rename to src/test/ui/proc-macro/auxiliary/api/cmp.rs
index d2e6b0bb8093b..3d17e9e350e64 100644
--- a/library/proc_macro/tests/test.rs
+++ b/src/test/ui/proc-macro/auxiliary/api/cmp.rs
@@ -1,8 +1,10 @@
-#![feature(proc_macro_span)]
-
 use proc_macro::{LineColumn, Punct};
 
-#[test]
+pub fn test() {
+    test_line_column_ord();
+    test_punct_eq();
+}
+
 fn test_line_column_ord() {
     let line0_column0 = LineColumn { line: 0, column: 0 };
     let line0_column1 = LineColumn { line: 0, column: 1 };
@@ -11,7 +13,6 @@ fn test_line_column_ord() {
     assert!(line0_column1 < line1_column0);
 }
 
-#[test]
 fn test_punct_eq() {
     // Good enough if it typechecks, since proc_macro::Punct can't exist in a test.
     fn _check(punct: Punct) {
diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs
index 72b02ad554e52..019fb2e7ec874 100644
--- a/src/test/ui/proc-macro/auxiliary/api/mod.rs
+++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs
@@ -3,14 +3,18 @@
 
 #![crate_type = "proc-macro"]
 #![crate_name = "proc_macro_api_tests"]
+#![feature(proc_macro_span)]
 #![deny(dead_code)] // catch if a test function is never called
 
 extern crate proc_macro;
 
+mod cmp;
+
 use proc_macro::TokenStream;
 
 #[proc_macro]
 pub fn run(input: TokenStream) -> TokenStream {
     assert!(input.is_empty());
+    cmp::test();
     TokenStream::new()
 }

From faad7e209deee6d09d335ca00c06d9f41bc040b5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Thu, 29 Apr 2021 11:20:27 -0700
Subject: [PATCH 24/26] Make a more meaningful test for Punct eq

---
 src/test/ui/proc-macro/auxiliary/api/cmp.rs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/test/ui/proc-macro/auxiliary/api/cmp.rs b/src/test/ui/proc-macro/auxiliary/api/cmp.rs
index 3d17e9e350e64..5784a6e5d94db 100644
--- a/src/test/ui/proc-macro/auxiliary/api/cmp.rs
+++ b/src/test/ui/proc-macro/auxiliary/api/cmp.rs
@@ -1,4 +1,4 @@
-use proc_macro::{LineColumn, Punct};
+use proc_macro::{LineColumn, Punct, Spacing};
 
 pub fn test() {
     test_line_column_ord();
@@ -14,8 +14,8 @@ fn test_line_column_ord() {
 }
 
 fn test_punct_eq() {
-    // Good enough if it typechecks, since proc_macro::Punct can't exist in a test.
-    fn _check(punct: Punct) {
-        let _ = punct == ':';
-    }
+    let colon_alone = Punct::new(':', Spacing::Alone);
+    assert_eq!(colon_alone, ':');
+    let colon_joint = Punct::new(':', Spacing::Joint);
+    assert_eq!(colon_joint, ':');
 }

From 965bce48348bbcc3c86898bdb5e18d4c57c35d00 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Thu, 29 Apr 2021 12:03:35 -0700
Subject: [PATCH 25/26] Add proc macro Literal parse test

---
 src/test/ui/proc-macro/auxiliary/api/mod.rs   |  4 ++++
 src/test/ui/proc-macro/auxiliary/api/parse.rs | 23 +++++++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 src/test/ui/proc-macro/auxiliary/api/parse.rs

diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs
index 019fb2e7ec874..739c25132e77b 100644
--- a/src/test/ui/proc-macro/auxiliary/api/mod.rs
+++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs
@@ -9,12 +9,16 @@
 extern crate proc_macro;
 
 mod cmp;
+mod parse;
 
 use proc_macro::TokenStream;
 
 #[proc_macro]
 pub fn run(input: TokenStream) -> TokenStream {
     assert!(input.is_empty());
+
     cmp::test();
+    parse::test();
+
     TokenStream::new()
 }
diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs
new file mode 100644
index 0000000000000..4105236b7f2d3
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs
@@ -0,0 +1,23 @@
+use proc_macro::Literal;
+
+pub fn test() {
+    test_parse_literal();
+}
+
+fn test_parse_literal() {
+    assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1");
+    assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0");
+    assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'");
+    assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\"");
+    assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
+    assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
+    assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
+
+    assert!("0 1".parse::<Literal>().is_err());
+    assert!("'a".parse::<Literal>().is_err());
+    assert!(" 0".parse::<Literal>().is_err());
+    assert!("0 ".parse::<Literal>().is_err());
+    assert!("/* comment */0".parse::<Literal>().is_err());
+    assert!("0/* comment */".parse::<Literal>().is_err());
+    assert!("0// comment".parse::<Literal>().is_err());
+}

From 34585cb678bc492be7e48ff48a2633f4ce1dc5ae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Thu, 29 Apr 2021 12:08:35 -0700
Subject: [PATCH 26/26] impl FromStr for proc_macro::Literal

---
 .../rustc_expand/src/proc_macro_server.rs     | 31 +++++++++++++++++--
 library/proc_macro/src/bridge/mod.rs          | 14 +++++++++
 library/proc_macro/src/lib.rs                 | 28 +++++++++++++++++
 3 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 7bf6502c976ca..92315c4d4f6c7 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -1,9 +1,7 @@
 use crate::base::{ExtCtxt, ResolverExpand};
 
 use rustc_ast as ast;
-use rustc_ast::token;
-use rustc_ast::token::Nonterminal;
-use rustc_ast::token::NtIdent;
+use rustc_ast::token::{self, Nonterminal, NtIdent, TokenKind};
 use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens};
 use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing};
 use rustc_ast_pretty::pprust;
@@ -541,6 +539,33 @@ impl server::Ident for Rustc<'_> {
 }
 
 impl server::Literal for Rustc<'_> {
+    fn from_str(&mut self, s: &str) -> Result<Self::Literal, ()> {
+        let override_span = None;
+        let stream = parse_stream_from_source_str(
+            FileName::proc_macro_source_code(s),
+            s.to_owned(),
+            self.sess,
+            override_span,
+        );
+        if stream.len() != 1 {
+            return Err(());
+        }
+        let tree = stream.into_trees().next().unwrap();
+        let token = match tree {
+            tokenstream::TokenTree::Token(token) => token,
+            tokenstream::TokenTree::Delimited { .. } => return Err(()),
+        };
+        let span_data = token.span.data();
+        if (span_data.hi.0 - span_data.lo.0) as usize != s.len() {
+            // There is a comment or whitespace adjacent to the literal.
+            return Err(());
+        }
+        let lit = match token.kind {
+            TokenKind::Literal(lit) => lit,
+            _ => return Err(()),
+        };
+        Ok(Literal { lit, span: self.call_site })
+    }
     fn debug_kind(&mut self, literal: &Self::Literal) -> String {
         format!("{:?}", literal.lit.kind)
     }
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 355ad1f9f881c..a2953b68564a8 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -107,6 +107,7 @@ macro_rules! with_api {
             Literal {
                 fn drop($self: $S::Literal);
                 fn clone($self: &$S::Literal) -> $S::Literal;
+                fn from_str(s: &str) -> Result<$S::Literal, ()>;
                 fn debug_kind($self: &$S::Literal) -> String;
                 fn symbol($self: &$S::Literal) -> String;
                 fn suffix($self: &$S::Literal) -> Option<String>;
@@ -315,6 +316,19 @@ impl<T: Unmark> Unmark for Option<T> {
     }
 }
 
+impl<T: Mark, E: Mark> Mark for Result<T, E> {
+    type Unmarked = Result<T::Unmarked, E::Unmarked>;
+    fn mark(unmarked: Self::Unmarked) -> Self {
+        unmarked.map(T::mark).map_err(E::mark)
+    }
+}
+impl<T: Unmark, E: Unmark> Unmark for Result<T, E> {
+    type Unmarked = Result<T::Unmarked, E::Unmarked>;
+    fn unmark(self) -> Self::Unmarked {
+        self.map(T::unmark).map_err(E::unmark)
+    }
+}
+
 macro_rules! mark_noop {
     ($($ty:ty),* $(,)?) => {
         $(
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 525fd0fbe3431..281999fe71588 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -91,6 +91,12 @@ pub struct LexError {
     _inner: (),
 }
 
+impl LexError {
+    fn new() -> Self {
+        LexError { _inner: () }
+    }
+}
+
 #[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")]
 impl fmt::Display for LexError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -1171,6 +1177,28 @@ impl Literal {
     }
 }
 
+/// Parse a single literal from its stringified representation.
+///
+/// In order to parse successfully, the input string must not contain anything
+/// but the literal token. Specifically, it must not contain whitespace or
+/// comments in addition to the literal.
+///
+/// The resulting literal token will have a `Span::call_site()` span.
+///
+/// NOTE: some errors may cause panics instead of returning `LexError`. We
+/// reserve the right to change these errors into `LexError`s later.
+#[stable(feature = "proc_macro_literal_parse", since = "1.54.0")]
+impl FromStr for Literal {
+    type Err = LexError;
+
+    fn from_str(src: &str) -> Result<Self, LexError> {
+        match bridge::client::Literal::from_str(src) {
+            Ok(literal) => Ok(Literal(literal)),
+            Err(()) => Err(LexError::new()),
+        }
+    }
+}
+
 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
 // based on it (the reverse of the usual relationship between the two).
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]