about summary refs log tree commit diff
path: root/library/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src')
-rw-r--r--library/core/src/array/mod.rs27
-rw-r--r--library/core/src/ascii/ascii_char.rs2
-rw-r--r--library/core/src/borrow.rs21
-rw-r--r--library/core/src/bstr/mod.rs45
-rw-r--r--library/core/src/cell.rs18
-rw-r--r--library/core/src/cell/once.rs3
-rw-r--r--library/core/src/char/convert.rs28
-rw-r--r--library/core/src/char/methods.rs38
-rw-r--r--library/core/src/clone.rs3
-rw-r--r--library/core/src/cmp.rs3
-rw-r--r--library/core/src/cmp/bytewise.rs2
-rw-r--r--library/core/src/convert/mod.rs58
-rw-r--r--library/core/src/convert/num.rs19
-rw-r--r--library/core/src/default.rs3
-rw-r--r--library/core/src/ffi/c_str.rs3
-rw-r--r--library/core/src/fmt/num.rs389
-rw-r--r--library/core/src/intrinsics/fallback.rs78
-rw-r--r--library/core/src/intrinsics/mod.rs55
-rw-r--r--library/core/src/iter/adapters/chain.rs1
-rw-r--r--library/core/src/iter/adapters/peekable.rs102
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/marker.rs3
-rw-r--r--library/core/src/mem/manually_drop.rs6
-rw-r--r--library/core/src/net/ip_addr.rs24
-rw-r--r--library/core/src/net/socket_addr.rs6
-rw-r--r--library/core/src/num/error.rs4
-rw-r--r--library/core/src/num/f128.rs8
-rw-r--r--library/core/src/num/f16.rs8
-rw-r--r--library/core/src/num/f32.rs14
-rw-r--r--library/core/src/num/f64.rs8
-rw-r--r--library/core/src/num/int_macros.rs119
-rw-r--r--library/core/src/num/mod.rs26
-rw-r--r--library/core/src/num/nonzero.rs2
-rw-r--r--library/core/src/num/uint_macros.rs189
-rw-r--r--library/core/src/ops/arith.rs33
-rw-r--r--library/core/src/ops/bit.rs33
-rw-r--r--library/core/src/ops/control_flow.rs6
-rw-r--r--library/core/src/ops/deref.rs16
-rw-r--r--library/core/src/ops/drop.rs3
-rw-r--r--library/core/src/ops/function.rs9
-rw-r--r--library/core/src/ops/index.rs6
-rw-r--r--library/core/src/ops/range.rs1
-rw-r--r--library/core/src/ops/try_trait.rs9
-rw-r--r--library/core/src/option.rs26
-rw-r--r--library/core/src/panic/unwind_safe.rs6
-rw-r--r--library/core/src/pat.rs3
-rw-r--r--library/core/src/pin.rs24
-rw-r--r--library/core/src/pin/unsafe_pinned.rs3
-rw-r--r--library/core/src/ptr/alignment.rs10
-rw-r--r--library/core/src/ptr/mut_ptr.rs1
-rw-r--r--library/core/src/ptr/non_null.rs9
-rw-r--r--library/core/src/ptr/unique.rs6
-rw-r--r--library/core/src/range.rs9
-rw-r--r--library/core/src/result.rs18
-rw-r--r--library/core/src/slice/cmp.rs3
-rw-r--r--library/core/src/slice/index.rs2
-rw-r--r--library/core/src/str/mod.rs3
-rw-r--r--library/core/src/str/traits.rs5
-rw-r--r--library/core/src/sync/atomic.rs7
-rw-r--r--library/core/src/sync/exclusive.rs3
-rw-r--r--library/core/src/task/poll.rs3
-rw-r--r--library/core/src/task/wake.rs3
-rw-r--r--library/core/src/tuple.rs2
-rw-r--r--library/core/src/unicode/unicode_data.rs523
64 files changed, 1394 insertions, 707 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index c4bb5ab7b21..d14419a23a1 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -48,6 +48,7 @@ pub use iter::IntoIter;
 /// assert_eq!(strings, ["Hello there!", "Hello there!"]);
 /// ```
 #[inline]
+#[must_use = "cloning is often expensive and is not expected to have side effects"]
 #[stable(feature = "array_repeat", since = "CURRENT_RUSTC_VERSION")]
 pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] {
     from_trusted_iterator(repeat_n(val, N))
@@ -190,7 +191,7 @@ impl fmt::Display for TryFromSliceError {
 impl Error for TryFromSliceError {}
 
 #[stable(feature = "try_from_slice_error", since = "1.36.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Infallible> for TryFromSliceError {
     fn from(x: Infallible) -> TryFromSliceError {
         match x {}
@@ -198,7 +199,8 @@ impl const From<Infallible> for TryFromSliceError {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, const N: usize> AsRef<[T]> for [T; N] {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T, const N: usize> const AsRef<[T]> for [T; N] {
     #[inline]
     fn as_ref(&self) -> &[T] {
         &self[..]
@@ -206,7 +208,8 @@ impl<T, const N: usize> AsRef<[T]> for [T; N] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, const N: usize> AsMut<[T]> for [T; N] {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T, const N: usize> const AsMut<[T]> for [T; N] {
     #[inline]
     fn as_mut(&mut self) -> &mut [T] {
         &mut self[..]
@@ -214,14 +217,16 @@ impl<T, const N: usize> AsMut<[T]> for [T; N] {
 }
 
 #[stable(feature = "array_borrow", since = "1.4.0")]
-impl<T, const N: usize> Borrow<[T]> for [T; N] {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T, const N: usize> const Borrow<[T]> for [T; N] {
     fn borrow(&self) -> &[T] {
         self
     }
 }
 
 #[stable(feature = "array_borrow", since = "1.4.0")]
-impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T, const N: usize> const BorrowMut<[T]> for [T; N] {
     fn borrow_mut(&mut self) -> &mut [T] {
         self
     }
@@ -240,7 +245,8 @@ impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
 /// assert_eq!(512, u16::from_le_bytes(bytes_tail));
 /// ```
 #[stable(feature = "try_from", since = "1.34.0")]
-impl<T, const N: usize> TryFrom<&[T]> for [T; N]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T, const N: usize> const TryFrom<&[T]> for [T; N]
 where
     T: Copy,
 {
@@ -265,7 +271,8 @@ where
 /// assert_eq!(512, u16::from_le_bytes(bytes_tail));
 /// ```
 #[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")]
-impl<T, const N: usize> TryFrom<&mut [T]> for [T; N]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T, const N: usize> const TryFrom<&mut [T]> for [T; N]
 where
     T: Copy,
 {
@@ -290,7 +297,8 @@ where
 /// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
 /// ```
 #[stable(feature = "try_from", since = "1.34.0")]
-impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<'a, T, const N: usize> const TryFrom<&'a [T]> for &'a [T; N] {
     type Error = TryFromSliceError;
 
     #[inline]
@@ -312,7 +320,8 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
 /// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
 /// ```
 #[stable(feature = "try_from", since = "1.34.0")]
-impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<'a, T, const N: usize> const TryFrom<&'a mut [T]> for &'a mut [T; N] {
     type Error = TryFromSliceError;
 
     #[inline]
diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs
index 419e4694594..49d540314a2 100644
--- a/library/core/src/ascii/ascii_char.rs
+++ b/library/core/src/ascii/ascii_char.rs
@@ -1156,7 +1156,7 @@ macro_rules! into_int_impl {
     ($($ty:ty)*) => {
         $(
             #[unstable(feature = "ascii_char", issue = "110998")]
-            #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+            #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
             impl const From<AsciiChar> for $ty {
                 #[inline]
                 fn from(chr: AsciiChar) -> $ty {
diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs
index da05f236d2f..78ba69fec14 100644
--- a/library/core/src/borrow.rs
+++ b/library/core/src/borrow.rs
@@ -154,7 +154,8 @@
 /// [`String`]: ../../std/string/struct.String.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Borrow"]
-pub trait Borrow<Borrowed: ?Sized> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait Borrow<Borrowed: ?Sized> {
     /// Immutably borrows from an owned value.
     ///
     /// # Examples
@@ -185,7 +186,8 @@ pub trait Borrow<Borrowed: ?Sized> {
 /// for more information on borrowing as another type.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "BorrowMut"]
-pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
     /// Mutably borrows from an owned value.
     ///
     /// # Examples
@@ -206,7 +208,8 @@ pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Borrow<T> for T {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: ?Sized> const Borrow<T> for T {
     #[rustc_diagnostic_item = "noop_method_borrow"]
     fn borrow(&self) -> &T {
         self
@@ -214,28 +217,32 @@ impl<T: ?Sized> Borrow<T> for T {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> BorrowMut<T> for T {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: ?Sized> const BorrowMut<T> for T {
     fn borrow_mut(&mut self) -> &mut T {
         self
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Borrow<T> for &T {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: ?Sized> const Borrow<T> for &T {
     fn borrow(&self) -> &T {
         self
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Borrow<T> for &mut T {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: ?Sized> const Borrow<T> for &mut T {
     fn borrow(&self) -> &T {
         self
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> BorrowMut<T> for &mut T {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: ?Sized> const BorrowMut<T> for &mut T {
     fn borrow_mut(&mut self) -> &mut T {
         self
     }
diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs
index 13127d645a2..e13dc5cd44d 100644
--- a/library/core/src/bstr/mod.rs
+++ b/library/core/src/bstr/mod.rs
@@ -63,14 +63,16 @@ impl ByteStr {
     /// ```
     #[inline]
     #[unstable(feature = "bstr", issue = "134915")]
-    pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self {
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn new<B: ?Sized + [const] AsRef<[u8]>>(bytes: &B) -> &Self {
         ByteStr::from_bytes(bytes.as_ref())
     }
 
     #[doc(hidden)]
     #[unstable(feature = "bstr_internals", issue = "none")]
     #[inline]
-    pub fn from_bytes(slice: &[u8]) -> &Self {
+    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
+    pub const fn from_bytes(slice: &[u8]) -> &Self {
         // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
         // the wrapped type into a reference to the wrapper type.
         unsafe { &*(slice as *const [u8] as *const Self) }
@@ -79,7 +81,8 @@ impl ByteStr {
     #[doc(hidden)]
     #[unstable(feature = "bstr_internals", issue = "none")]
     #[inline]
-    pub fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
+    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
+    pub const fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
         // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
         // the wrapped type into a reference to the wrapper type.
         unsafe { &mut *(slice as *mut [u8] as *mut Self) }
@@ -88,20 +91,23 @@ impl ByteStr {
     #[doc(hidden)]
     #[unstable(feature = "bstr_internals", issue = "none")]
     #[inline]
-    pub fn as_bytes(&self) -> &[u8] {
+    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
+    pub const fn as_bytes(&self) -> &[u8] {
         &self.0
     }
 
     #[doc(hidden)]
     #[unstable(feature = "bstr_internals", issue = "none")]
     #[inline]
-    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
+    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
+    pub const fn as_bytes_mut(&mut self) -> &mut [u8] {
         &mut self.0
     }
 }
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl Deref for ByteStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const Deref for ByteStr {
     type Target = [u8];
 
     #[inline]
@@ -111,7 +117,8 @@ impl Deref for ByteStr {
 }
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl DerefMut for ByteStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const DerefMut for ByteStr {
     #[inline]
     fn deref_mut(&mut self) -> &mut [u8] {
         &mut self.0
@@ -185,7 +192,8 @@ impl fmt::Display for ByteStr {
 }
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl AsRef<[u8]> for ByteStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsRef<[u8]> for ByteStr {
     #[inline]
     fn as_ref(&self) -> &[u8] {
         &self.0
@@ -193,7 +201,8 @@ impl AsRef<[u8]> for ByteStr {
 }
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl AsRef<ByteStr> for ByteStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsRef<ByteStr> for ByteStr {
     #[inline]
     fn as_ref(&self) -> &ByteStr {
         self
@@ -203,7 +212,8 @@ impl AsRef<ByteStr> for ByteStr {
 // `impl AsRef<ByteStr> for [u8]` omitted to avoid widespread inference failures
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl AsRef<ByteStr> for str {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsRef<ByteStr> for str {
     #[inline]
     fn as_ref(&self) -> &ByteStr {
         ByteStr::new(self)
@@ -211,7 +221,8 @@ impl AsRef<ByteStr> for str {
 }
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl AsMut<[u8]> for ByteStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsMut<[u8]> for ByteStr {
     #[inline]
     fn as_mut(&mut self) -> &mut [u8] {
         &mut self.0
@@ -225,7 +236,8 @@ impl AsMut<[u8]> for ByteStr {
 // `impl Borrow<ByteStr> for str` omitted to avoid widespread inference failures
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl Borrow<[u8]> for ByteStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const Borrow<[u8]> for ByteStr {
     #[inline]
     fn borrow(&self) -> &[u8] {
         &self.0
@@ -235,7 +247,8 @@ impl Borrow<[u8]> for ByteStr {
 // `impl BorrowMut<ByteStr> for [u8]` omitted to avoid widespread inference failures
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl BorrowMut<[u8]> for ByteStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const BorrowMut<[u8]> for ByteStr {
     #[inline]
     fn borrow_mut(&mut self) -> &mut [u8] {
         &mut self.0
@@ -303,7 +316,8 @@ impl<'a> Default for &'a mut ByteStr {
 // }
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl<'a> TryFrom<&'a ByteStr> for &'a str {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<'a> const TryFrom<&'a ByteStr> for &'a str {
     type Error = crate::str::Utf8Error;
 
     #[inline]
@@ -313,7 +327,8 @@ impl<'a> TryFrom<&'a ByteStr> for &'a str {
 }
 
 #[unstable(feature = "bstr", issue = "134915")]
-impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<'a> const TryFrom<&'a mut ByteStr> for &'a mut str {
     type Error = crate::str::Utf8Error;
 
     #[inline]
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 59a6aa70620..9b53b75ebee 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -390,7 +390,8 @@ impl<T: Ord + Copy> Ord for Cell<T> {
 }
 
 #[stable(feature = "cell_from", since = "1.12.0")]
-impl<T> From<T> for Cell<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for Cell<T> {
     /// Creates a new `Cell<T>` containing the given value.
     fn from(t: T) -> Cell<T> {
         Cell::new(t)
@@ -1402,7 +1403,8 @@ impl<T: ?Sized + Ord> Ord for RefCell<T> {
 }
 
 #[stable(feature = "cell_from", since = "1.12.0")]
-impl<T> From<T> for RefCell<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for RefCell<T> {
     /// Creates a new `RefCell<T>` containing the given value.
     fn from(t: T) -> RefCell<T> {
         RefCell::new(t)
@@ -1483,7 +1485,7 @@ pub struct Ref<'b, T: ?Sized + 'b> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: ?Sized> const Deref for Ref<'_, T> {
     type Target = T;
 
@@ -1967,7 +1969,7 @@ pub struct RefMut<'b, T: ?Sized + 'b> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: ?Sized> const Deref for RefMut<'_, T> {
     type Target = T;
 
@@ -1979,7 +1981,7 @@ impl<T: ?Sized> const Deref for RefMut<'_, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: ?Sized> const DerefMut for RefMut<'_, T> {
     #[inline]
     fn deref_mut(&mut self) -> &mut T {
@@ -2434,7 +2436,8 @@ impl<T: [const] Default> const Default for UnsafeCell<T> {
 }
 
 #[stable(feature = "cell_from", since = "1.12.0")]
-impl<T> From<T> for UnsafeCell<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for UnsafeCell<T> {
     /// Creates a new `UnsafeCell<T>` containing the given value.
     fn from(t: T) -> UnsafeCell<T> {
         UnsafeCell::new(t)
@@ -2539,7 +2542,8 @@ impl<T: [const] Default> const Default for SyncUnsafeCell<T> {
 }
 
 #[unstable(feature = "sync_unsafe_cell", issue = "95439")]
-impl<T> From<T> for SyncUnsafeCell<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for SyncUnsafeCell<T> {
     /// Creates a new `SyncUnsafeCell<T>` containing the given value.
     fn from(t: T) -> SyncUnsafeCell<T> {
         SyncUnsafeCell::new(t)
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index c6c96571d33..833be059d75 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -395,7 +395,8 @@ impl<T: PartialEq> PartialEq for OnceCell<T> {
 impl<T: Eq> Eq for OnceCell<T> {}
 
 #[stable(feature = "once_cell", since = "1.70.0")]
-impl<T> From<T> for OnceCell<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for OnceCell<T> {
     /// Creates a new `OnceCell<T>` which already contains the given `value`.
     #[inline]
     fn from(value: T) -> Self {
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index cf5a91bf8dd..6380f42d320 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -36,7 +36,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
 }
 
 #[stable(feature = "char_convert", since = "1.13.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<char> for u32 {
     /// Converts a [`char`] into a [`u32`].
     ///
@@ -54,7 +54,7 @@ impl const From<char> for u32 {
 }
 
 #[stable(feature = "more_char_conversions", since = "1.51.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<char> for u64 {
     /// Converts a [`char`] into a [`u64`].
     ///
@@ -74,7 +74,7 @@ impl const From<char> for u64 {
 }
 
 #[stable(feature = "more_char_conversions", since = "1.51.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<char> for u128 {
     /// Converts a [`char`] into a [`u128`].
     ///
@@ -98,7 +98,8 @@ impl const From<char> for u128 {
 ///
 /// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding.
 #[stable(feature = "u8_from_char", since = "1.59.0")]
-impl TryFrom<char> for u8 {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const TryFrom<char> for u8 {
     type Error = TryFromCharError;
 
     /// Tries to convert a [`char`] into a [`u8`].
@@ -113,7 +114,11 @@ impl TryFrom<char> for u8 {
     /// ```
     #[inline]
     fn try_from(c: char) -> Result<u8, Self::Error> {
-        u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
+        // FIXME(const-hack): this should use map_err instead
+        match u8::try_from(u32::from(c)) {
+            Ok(b) => Ok(b),
+            Err(_) => Err(TryFromCharError(())),
+        }
     }
 }
 
@@ -122,7 +127,8 @@ impl TryFrom<char> for u8 {
 ///
 /// This corresponds to the UCS-2 encoding, as specified in ISO/IEC 10646:2003.
 #[stable(feature = "u16_from_char", since = "1.74.0")]
-impl TryFrom<char> for u16 {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const TryFrom<char> for u16 {
     type Error = TryFromCharError;
 
     /// Tries to convert a [`char`] into a [`u16`].
@@ -137,7 +143,11 @@ impl TryFrom<char> for u16 {
     /// ```
     #[inline]
     fn try_from(c: char) -> Result<u16, Self::Error> {
-        u16::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
+        // FIXME(const-hack): this should use map_err instead
+        match u16::try_from(u32::from(c)) {
+            Ok(x) => Ok(x),
+            Err(_) => Err(TryFromCharError(())),
+        }
     }
 }
 
@@ -160,7 +170,7 @@ impl TryFrom<char> for u16 {
 /// for a superset of Windows-1252 that fills the remaining blanks with corresponding
 /// C0 and C1 control codes.
 #[stable(feature = "char_convert", since = "1.13.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<u8> for char {
     /// Converts a [`u8`] into a [`char`].
     ///
@@ -246,7 +256,7 @@ const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
 }
 
 #[stable(feature = "try_from", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const TryFrom<u32> for char {
     type Error = CharTryFromError;
 
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 3336d028e27..76f54db2870 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -969,7 +969,43 @@ impl char {
     #[must_use]
     #[inline]
     pub(crate) fn is_grapheme_extended(self) -> bool {
-        unicode::Grapheme_Extend(self)
+        !self.is_ascii() && unicode::Grapheme_Extend(self)
+    }
+
+    /// Returns `true` if this `char` has the `Cased` property.
+    ///
+    /// `Cased` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
+    /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
+    #[must_use]
+    #[inline]
+    #[doc(hidden)]
+    #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
+    pub fn is_cased(self) -> bool {
+        if self.is_ascii() { self.is_ascii_alphabetic() } else { unicode::Cased(self) }
+    }
+
+    /// Returns `true` if this `char` has the `Case_Ignorable` property.
+    ///
+    /// `Case_Ignorable` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
+    /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
+    #[must_use]
+    #[inline]
+    #[doc(hidden)]
+    #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
+    pub fn is_case_ignorable(self) -> bool {
+        if self.is_ascii() {
+            matches!(self, '\'' | '.' | ':' | '^' | '`')
+        } else {
+            unicode::Case_Ignorable(self)
+        }
     }
 
     /// Returns `true` if this `char` has one of the general categories for numbers.
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 0add77b2bc8..7f2a40f753f 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -191,8 +191,7 @@ mod uninit;
 #[rustc_diagnostic_item = "Clone"]
 #[rustc_trivial_field_reads]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-#[const_trait]
-pub trait Clone: Sized {
+pub const trait Clone: Sized {
     /// Returns a duplicate of the value.
     ///
     /// Note that what "duplicate" means varies by type:
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index ab018fa2675..0812322f3fb 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -247,9 +247,8 @@ use crate::ops::ControlFlow;
     append_const_msg
 )]
 #[rustc_diagnostic_item = "PartialEq"]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-pub trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized {
+pub const trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized {
     /// Tests for `self` and `other` values to be equal, and is used by `==`.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs
index a06a6e8b69a..2265fa7a353 100644
--- a/library/core/src/cmp/bytewise.rs
+++ b/library/core/src/cmp/bytewise.rs
@@ -17,7 +17,7 @@ use crate::num::NonZero;
 /// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct.
 /// - `<Self as PartialEq<Rhs>>::{eq,ne}` are equivalent to comparing the bytes.
 #[rustc_specialization_trait]
-#[const_trait]
+#[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed.
 pub(crate) unsafe trait BytewiseEq<Rhs = Self>:
     [const] PartialEq<Rhs> + Sized
 {
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index a0a7b7928d1..a3cfd85974a 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -216,9 +216,8 @@ pub const fn identity<T>(x: T) -> T {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "AsRef"]
-#[const_trait]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
-pub trait AsRef<T: PointeeSized>: PointeeSized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait AsRef<T: PointeeSized>: PointeeSized {
     /// Converts this type into a shared reference of the (usually inferred) input type.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn as_ref(&self) -> &T;
@@ -369,9 +368,8 @@ pub trait AsRef<T: PointeeSized>: PointeeSized {
 /// `&mut Vec<u8>`, for example, is the better choice (callers need to pass the correct type then).
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "AsMut"]
-#[const_trait]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
-pub trait AsMut<T: PointeeSized>: PointeeSized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait AsMut<T: PointeeSized>: PointeeSized {
     /// Converts this type into a mutable reference of the (usually inferred) input type.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn as_mut(&mut self) -> &mut T;
@@ -449,9 +447,8 @@ pub trait AsMut<T: PointeeSized>: PointeeSized {
 #[rustc_diagnostic_item = "Into"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(search_unbox)]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
-#[const_trait]
-pub trait Into<T>: Sized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait Into<T>: Sized {
     /// Converts this type into the (usually inferred) input type.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -586,9 +583,8 @@ pub trait Into<T>: Sized {
     note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
 ))]
 #[doc(search_unbox)]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
-#[const_trait]
-pub trait From<T>: Sized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait From<T>: Sized {
     /// Converts to this type from the input type.
     #[rustc_diagnostic_item = "from_fn"]
     #[must_use]
@@ -615,9 +611,8 @@ pub trait From<T>: Sized {
 /// [`Into`], see there for details.
 #[rustc_diagnostic_item = "TryInto"]
 #[stable(feature = "try_from", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
-#[const_trait]
-pub trait TryInto<T>: Sized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait TryInto<T>: Sized {
     /// The type returned in the event of a conversion error.
     #[stable(feature = "try_from", since = "1.34.0")]
     type Error;
@@ -695,9 +690,8 @@ pub trait TryInto<T>: Sized {
 /// [`try_from`]: TryFrom::try_from
 #[rustc_diagnostic_item = "TryFrom"]
 #[stable(feature = "try_from", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
-#[const_trait]
-pub trait TryFrom<T>: Sized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait TryFrom<T>: Sized {
     /// The type returned in the event of a conversion error.
     #[stable(feature = "try_from", since = "1.34.0")]
     type Error;
@@ -714,7 +708,7 @@ pub trait TryFrom<T>: Sized {
 
 // As lifts over &
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: PointeeSized, U: PointeeSized> const AsRef<U> for &T
 where
     T: [const] AsRef<U>,
@@ -727,7 +721,7 @@ where
 
 // As lifts over &mut
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: PointeeSized, U: PointeeSized> const AsRef<U> for &mut T
 where
     T: [const] AsRef<U>,
@@ -748,7 +742,7 @@ where
 
 // AsMut lifts over &mut
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: PointeeSized, U: PointeeSized> const AsMut<U> for &mut T
 where
     T: [const] AsMut<U>,
@@ -769,7 +763,7 @@ where
 
 // From implies Into
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T, U> const Into<U> for T
 where
     U: [const] From<T>,
@@ -787,7 +781,7 @@ where
 
 // From (and thus Into) is reflexive
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const From<T> for T {
     /// Returns the argument unchanged.
     #[inline(always)]
@@ -804,7 +798,7 @@ impl<T> const From<T> for T {
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_reservation_impl = "permitting this impl would forbid us from adding \
                             `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const From<!> for T {
     fn from(t: !) -> T {
         t
@@ -813,7 +807,7 @@ impl<T> const From<!> for T {
 
 // TryFrom implies TryInto
 #[stable(feature = "try_from", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T, U> const TryInto<U> for T
 where
     U: [const] TryFrom<T>,
@@ -829,7 +823,7 @@ where
 // Infallible conversions are semantically equivalent to fallible conversions
 // with an uninhabited error type.
 #[stable(feature = "try_from", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_from", issue = "143773")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T, U> const TryFrom<U> for T
 where
     U: [const] Into<T>,
@@ -847,7 +841,7 @@ where
 ////////////////////////////////////////////////////////////////////////////////
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const AsRef<[T]> for [T] {
     #[inline(always)]
     fn as_ref(&self) -> &[T] {
@@ -856,7 +850,7 @@ impl<T> const AsRef<[T]> for [T] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const AsMut<[T]> for [T] {
     #[inline(always)]
     fn as_mut(&mut self) -> &mut [T] {
@@ -865,7 +859,7 @@ impl<T> const AsMut<[T]> for [T] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const AsRef<str> for str {
     #[inline(always)]
     fn as_ref(&self) -> &str {
@@ -874,7 +868,7 @@ impl const AsRef<str> for str {
 }
 
 #[stable(feature = "as_mut_str_for_str", since = "1.51.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const AsMut<str> for str {
     #[inline(always)]
     fn as_mut(&mut self) -> &mut str {
@@ -936,7 +930,7 @@ impl const AsMut<str> for str {
 pub enum Infallible {}
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
 impl const Clone for Infallible {
     fn clone(&self) -> Infallible {
         match *self {}
@@ -986,7 +980,7 @@ impl Ord for Infallible {
 }
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<!> for Infallible {
     #[inline]
     fn from(x: !) -> Self {
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index affb4eb64d3..6ae588a4e04 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -69,7 +69,7 @@ macro_rules! impl_from {
     };
     ($Small:ty => $Large:ty, #[$attr:meta], $doc:expr $(,)?) => {
         #[$attr]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const From<$Small> for $Large {
             // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
             // Rustdocs on functions do not.
@@ -201,7 +201,7 @@ macro_rules! impl_float_from_bool {
         )?
     ) => {
         #[stable(feature = "float_from_bool", since = "1.68.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
             impl const From<bool> for $float {
             #[doc = concat!("Converts a [`bool`] to [`", stringify!($float),"`] losslessly.")]
             /// The resulting value is positive `0.0` for `false` and `1.0` for `true` values.
@@ -252,7 +252,7 @@ impl_float_from_bool!(
 macro_rules! impl_try_from_unbounded {
     ($source:ty => $($target:ty),+) => {$(
         #[stable(feature = "try_from", since = "1.34.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -271,7 +271,7 @@ macro_rules! impl_try_from_unbounded {
 macro_rules! impl_try_from_lower_bounded {
     ($source:ty => $($target:ty),+) => {$(
         #[stable(feature = "try_from", since = "1.34.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -294,7 +294,7 @@ macro_rules! impl_try_from_lower_bounded {
 macro_rules! impl_try_from_upper_bounded {
     ($source:ty => $($target:ty),+) => {$(
         #[stable(feature = "try_from", since = "1.34.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -317,7 +317,7 @@ macro_rules! impl_try_from_upper_bounded {
 macro_rules! impl_try_from_both_bounded {
     ($source:ty => $($target:ty),+) => {$(
         #[stable(feature = "try_from", since = "1.34.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -456,7 +456,7 @@ use crate::num::NonZero;
 macro_rules! impl_nonzero_int_from_nonzero_int {
     ($Small:ty => $Large:ty) => {
         #[stable(feature = "nz_int_conv", since = "1.41.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const From<NonZero<$Small>> for NonZero<$Large> {
             // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
             // Rustdocs on functions do not.
@@ -515,7 +515,8 @@ impl_nonzero_int_from_nonzero_int!(u64 => i128);
 macro_rules! impl_nonzero_int_try_from_int {
     ($Int:ty) => {
         #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")]
-        impl TryFrom<$Int> for NonZero<$Int> {
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+        impl const TryFrom<$Int> for NonZero<$Int> {
             type Error = TryFromIntError;
 
             // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
@@ -547,7 +548,7 @@ impl_nonzero_int_try_from_int!(isize);
 macro_rules! impl_nonzero_int_try_from_nonzero_int {
     ($source:ty => $($target:ty),+) => {$(
         #[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const TryFrom<NonZero<$source>> for NonZero<$target> {
             type Error = TryFromIntError;
 
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 897267968aa..cc9289307c1 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -103,9 +103,8 @@ use crate::ascii::Char as AsciiChar;
 /// ```
 #[rustc_diagnostic_item = "Default"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-pub trait Default: Sized {
+pub const trait Default: Sized {
     /// Returns the "default value" for a type.
     ///
     /// Default values are often some kind of initial value, identity value, or anything else that
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index e6b599fafcf..d0b53e3a237 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -708,7 +708,8 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
 }
 
 #[stable(feature = "cstring_asref", since = "1.7.0")]
-impl AsRef<CStr> for CStr {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsRef<CStr> for CStr {
     #[inline]
     fn as_ref(&self) -> &CStr {
         self
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index 605ba42c541..253a7b7587e 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -3,7 +3,7 @@
 use crate::fmt::NumBuffer;
 use crate::mem::MaybeUninit;
 use crate::num::fmt as numfmt;
-use crate::{fmt, ptr, slice, str};
+use crate::{fmt, str};
 
 /// Formatting of integers with a non-decimal radix.
 macro_rules! radix_integer {
@@ -96,8 +96,8 @@ macro_rules! impl_Debug {
     };
 }
 
-// 2 digit decimal look up table
-static DEC_DIGITS_LUT: &[u8; 200] = b"\
+// The string of all two-digit numbers in range 00..99 is used as a lookup table.
+static DECIMAL_PAIRS: &[u8; 200] = b"\
       0001020304050607080910111213141516171819\
       2021222324252627282930313233343536373839\
       4041424344454647484950515253545556575859\
@@ -123,6 +123,9 @@ macro_rules! impl_Display {
 
         $(
         const _: () = {
+            assert!($Signed::MIN < 0, "need signed");
+            assert!($Unsigned::MIN == 0, "need unsigned");
+            assert!($Signed::BITS == $Unsigned::BITS, "need counterparts");
             assert!($Signed::BITS <= $T::BITS, "need lossless conversion");
             assert!($Unsigned::BITS <= $T::BITS, "need lossless conversion");
         };
@@ -207,10 +210,10 @@ macro_rules! impl_Display {
                     remain /= scale;
                     let pair1 = (quad / 100) as usize;
                     let pair2 = (quad % 100) as usize;
-                    buf[offset + 0].write(DEC_DIGITS_LUT[pair1 * 2 + 0]);
-                    buf[offset + 1].write(DEC_DIGITS_LUT[pair1 * 2 + 1]);
-                    buf[offset + 2].write(DEC_DIGITS_LUT[pair2 * 2 + 0]);
-                    buf[offset + 3].write(DEC_DIGITS_LUT[pair2 * 2 + 1]);
+                    buf[offset + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
+                    buf[offset + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
+                    buf[offset + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
+                    buf[offset + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
                 }
 
                 // Format per two digits from the lookup table.
@@ -225,8 +228,8 @@ macro_rules! impl_Display {
 
                     let pair = (remain % 100) as usize;
                     remain /= 100;
-                    buf[offset + 0].write(DEC_DIGITS_LUT[pair * 2 + 0]);
-                    buf[offset + 1].write(DEC_DIGITS_LUT[pair * 2 + 1]);
+                    buf[offset + 0].write(DECIMAL_PAIRS[pair * 2 + 0]);
+                    buf[offset + 1].write(DECIMAL_PAIRS[pair * 2 + 1]);
                 }
 
                 // Format the last remaining digit, if any.
@@ -242,7 +245,7 @@ macro_rules! impl_Display {
                     // Either the compiler sees that remain < 10, or it prevents
                     // a boundary check up next.
                     let last = (remain & 15) as usize;
-                    buf[offset].write(DEC_DIGITS_LUT[last * 2 + 1]);
+                    buf[offset].write(DECIMAL_PAIRS[last * 2 + 1]);
                     // not used: remain = 0;
                 }
 
@@ -335,7 +338,6 @@ macro_rules! impl_Display {
             }
         }
 
-
         )*
 
         #[cfg(feature = "optimize_for_size")]
@@ -374,178 +376,213 @@ macro_rules! impl_Display {
 
 macro_rules! impl_Exp {
     ($($Signed:ident, $Unsigned:ident),* ; as $T:ident into $fmt_fn:ident) => {
+        const _: () = assert!($T::MIN == 0, "need unsigned");
+
         fn $fmt_fn(
-            mut n: $T,
+            f: &mut fmt::Formatter<'_>,
+            n: $T,
             is_nonnegative: bool,
-            upper: bool,
-            f: &mut fmt::Formatter<'_>
+            letter_e: u8
         ) -> fmt::Result {
-            let (mut n, mut exponent, trailing_zeros, added_precision) = {
-                let mut exponent = 0;
-                // count and remove trailing decimal zeroes
-                while n % 10 == 0 && n >= 10 {
-                    n /= 10;
-                    exponent += 1;
-                }
-                let (added_precision, subtracted_precision) = match f.precision() {
-                    Some(fmt_prec) => {
-                        // number of decimal digits minus 1
-                        let mut tmp = n;
-                        let mut prec = 0;
-                        while tmp >= 10 {
-                            tmp /= 10;
-                            prec += 1;
-                        }
-                        (fmt_prec.saturating_sub(prec), prec.saturating_sub(fmt_prec))
+            debug_assert!(letter_e.is_ascii_alphabetic(), "single-byte character");
+
+            // Print the integer as a coefficient in range (-10, 10).
+            let mut exp = n.checked_ilog10().unwrap_or(0) as usize;
+            debug_assert!(n / (10 as $T).pow(exp as u32) < 10);
+
+            // Precisison is counted as the number of digits in the fraction.
+            let mut coef_prec = exp;
+            // Keep the digits as an integer (paired with its coef_prec count).
+            let mut coef = n;
+
+            // A Formatter may set the precision to a fixed number of decimals.
+            let more_prec = match f.precision() {
+                None => {
+                    // Omit any and all trailing zeroes.
+                    while coef_prec != 0 && coef % 10 == 0 {
+                        coef /= 10;
+                        coef_prec -= 1;
                     }
-                    None => (0, 0)
-                };
-                for _ in 1..subtracted_precision {
-                    n /= 10;
-                    exponent += 1;
-                }
-                if subtracted_precision != 0 {
-                    let rem = n % 10;
-                    n /= 10;
-                    exponent += 1;
-                    // round up last digit, round to even on a tie
-                    if rem > 5 || (rem == 5 && (n % 2 != 0 || subtracted_precision > 1 )) {
-                        n += 1;
-                        // if the digit is rounded to the next power
-                        // instead adjust the exponent
-                        if n.ilog10() > (n - 1).ilog10() {
-                            n /= 10;
-                            exponent += 1;
-                        }
+                    0
+                },
+
+                Some(fmt_prec) if fmt_prec >= coef_prec => {
+                    // Count the number of additional zeroes needed.
+                    fmt_prec - coef_prec
+                },
+
+                Some(fmt_prec) => {
+                    // Count the number of digits to drop.
+                    let less_prec = coef_prec - fmt_prec;
+                    assert!(less_prec > 0);
+                    // Scale down the coefficient/precision pair. For example,
+                    // coef 123456 gets coef_prec 5 (to make 1.23456). To format
+                    // the number with 2 decimals, i.e., fmt_prec 2, coef should
+                    // be scaled by 10⁵⁻²=1000 to get coef 123 with coef_prec 2.
+
+                    // SAFETY: Any precision less than coef_prec will cause a
+                    // power of ten below the coef value.
+                    let scale = unsafe {
+                        (10 as $T).checked_pow(less_prec as u32).unwrap_unchecked()
+                    };
+                    let floor = coef / scale;
+                    // Round half to even conform documentation.
+                    let over = coef % scale;
+                    let half = scale / 2;
+                    let round_up = if over < half {
+                        0
+                    } else if over > half {
+                        1
+                    } else {
+                        floor & 1 // round odd up to even
+                    };
+                    // Adding one to a scale down of at least 10 won't overflow.
+                    coef = floor + round_up;
+                    coef_prec = fmt_prec;
+
+                    // The round_up may have caused the coefficient to reach 10
+                    // (which is not permitted). For example, anything in range
+                    // [9.95, 10) becomes 10.0 when adjusted to precision 1.
+                    if round_up != 0 && coef.checked_ilog10().unwrap_or(0) as usize > coef_prec {
+                        debug_assert_eq!(coef, (10 as $T).pow(coef_prec as u32 + 1));
+                        coef /= 10; // drop one trailing zero
+                        exp += 1;   // one power of ten higher
                     }
-                }
-                (n, exponent, exponent, added_precision)
+                    0
+                },
             };
 
-            // Since `curr` always decreases by the number of digits copied, this means
-            // that `curr >= 0`.
-            let mut buf = [MaybeUninit::<u8>::uninit(); 40];
-            let mut curr = buf.len(); //index for buf
-            let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
-            let lut_ptr = DEC_DIGITS_LUT.as_ptr();
-
-            // decode 2 chars at a time
-            while n >= 100 {
-                let d1 = ((n % 100) as usize) << 1;
-                curr -= 2;
-                // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since
-                // `DEC_DIGITS_LUT` has a length of 200.
-                unsafe {
-                    ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
-                }
-                n /= 100;
-                exponent += 2;
-            }
-            // n is <= 99, so at most 2 chars long
-            let mut n = n as isize; // possibly reduce 64bit math
-            // decode second-to-last character
-            if n >= 10 {
-                curr -= 1;
-                // SAFETY: Safe since `40 > curr >= 0` (see comment)
-                unsafe {
-                    *buf_ptr.add(curr) = (n as u8 % 10_u8) + b'0';
+            // Allocate a text buffer with lazy initialization.
+            const MAX_DEC_N: usize = $T::MAX.ilog10() as usize + 1;
+            const MAX_COEF_LEN: usize = MAX_DEC_N + ".".len();
+            const MAX_TEXT_LEN: usize = MAX_COEF_LEN + "e99".len();
+            let mut buf = [MaybeUninit::<u8>::uninit(); MAX_TEXT_LEN];
+
+            // Encode the coefficient in buf[..coef_len].
+            let (lead_dec, coef_len) = if coef_prec == 0 && more_prec == 0 {
+                (coef, 1_usize) // single digit; no fraction
+            } else {
+                buf[1].write(b'.');
+                let fraction_range = 2..(2 + coef_prec);
+
+                // Consume the least-significant decimals from a working copy.
+                let mut remain = coef;
+                #[cfg(feature = "optimize_for_size")] {
+                    for i in fraction_range.clone().rev() {
+                        let digit = (remain % 10) as usize;
+                        remain /= 10;
+                        buf[i].write(b'0' + digit as u8);
+                    }
                 }
-                n /= 10;
-                exponent += 1;
-            }
-            // add decimal point iff >1 mantissa digit will be printed
-            if exponent != trailing_zeros || added_precision != 0 {
-                curr -= 1;
-                // SAFETY: Safe since `40 > curr >= 0`
-                unsafe {
-                    *buf_ptr.add(curr) = b'.';
+                #[cfg(not(feature = "optimize_for_size"))] {
+                    // Write digits per two at a time with a lookup table.
+                    for i in fraction_range.clone().skip(1).rev().step_by(2) {
+                        let pair = (remain % 100) as usize;
+                        remain /= 100;
+                        buf[i - 1].write(DECIMAL_PAIRS[pair * 2 + 0]);
+                        buf[i - 0].write(DECIMAL_PAIRS[pair * 2 + 1]);
+                    }
+                    // An odd number of digits leave one digit remaining.
+                    if coef_prec & 1 != 0 {
+                        let digit = (remain % 10) as usize;
+                        remain /= 10;
+                        buf[fraction_range.start].write(b'0' + digit as u8);
+                    }
                 }
-            }
 
-            // SAFETY: Safe since `40 > curr >= 0`
-            let buf_slice = unsafe {
-                // decode last character
-                curr -= 1;
-                *buf_ptr.add(curr) = (n as u8) + b'0';
-
-                let len = buf.len() - curr as usize;
-                slice::from_raw_parts(buf_ptr.add(curr), len)
+                (remain, fraction_range.end)
             };
-
-            // stores 'e' (or 'E') and the up to 2-digit exponent
-            let mut exp_buf = [MaybeUninit::<u8>::uninit(); 3];
-            let exp_ptr = MaybeUninit::slice_as_mut_ptr(&mut exp_buf);
-            // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]`
-            // is contained within `exp_buf` since `len <= 3`.
-            let exp_slice = unsafe {
-                *exp_ptr.add(0) = if upper { b'E' } else { b'e' };
-                let len = if exponent < 10 {
-                    *exp_ptr.add(1) = (exponent as u8) + b'0';
-                    2
-                } else {
-                    let off = exponent << 1;
-                    ptr::copy_nonoverlapping(lut_ptr.add(off), exp_ptr.add(1), 2);
-                    3
-                };
-                slice::from_raw_parts(exp_ptr, len)
+            debug_assert!(lead_dec < 10);
+            debug_assert!(lead_dec != 0 || coef == 0, "significant digits only");
+            buf[0].write(b'0' + lead_dec as u8);
+
+            // SAFETY: The number of decimals is limited, captured by MAX.
+            unsafe { core::hint::assert_unchecked(coef_len <= MAX_COEF_LEN) }
+            // Encode the scale factor in buf[coef_len..text_len].
+            buf[coef_len].write(letter_e);
+            let text_len: usize = match exp {
+                ..10 => {
+                    buf[coef_len + 1].write(b'0' + exp as u8);
+                    coef_len + 2
+                },
+                10..100 => {
+                    #[cfg(feature = "optimize_for_size")] {
+                        buf[coef_len + 1].write(b'0' + (exp / 10) as u8);
+                        buf[coef_len + 2].write(b'0' + (exp % 10) as u8);
+                    }
+                    #[cfg(not(feature = "optimize_for_size"))] {
+                        buf[coef_len + 1].write(DECIMAL_PAIRS[exp * 2 + 0]);
+                        buf[coef_len + 2].write(DECIMAL_PAIRS[exp * 2 + 1]);
+                    }
+                    coef_len + 3
+                },
+                _ => {
+                    const { assert!($T::MAX.ilog10() < 100) };
+                    // SAFETY: A `u256::MAX` would get exponent 77.
+                    unsafe { core::hint::unreachable_unchecked() }
+                }
             };
-
-            let parts = &[
-                numfmt::Part::Copy(buf_slice),
-                numfmt::Part::Zero(added_precision),
-                numfmt::Part::Copy(exp_slice),
-            ];
-            let sign = if !is_nonnegative {
-                "-"
-            } else if f.sign_plus() {
-                "+"
+            // SAFETY: All bytes up until text_len have been set.
+            let text = unsafe { buf[..text_len].assume_init_ref() };
+
+            if more_prec == 0 {
+                // SAFETY: Text is set with ASCII exclusively: either a decimal,
+                // or a LETTER_E, or a dot. ASCII implies valid UTF-8.
+                let as_str = unsafe { str::from_utf8_unchecked(text) };
+                f.pad_integral(is_nonnegative, "", as_str)
             } else {
-                ""
-            };
-            let formatted = numfmt::Formatted { sign, parts };
-            // SAFETY: `buf_slice` and `exp_slice` contain only ASCII characters.
-            unsafe { f.pad_formatted_parts(&formatted) }
+                let parts = &[
+                    numfmt::Part::Copy(&text[..coef_len]),
+                    numfmt::Part::Zero(more_prec),
+                    numfmt::Part::Copy(&text[coef_len..]),
+                ];
+                let sign = if !is_nonnegative {
+                    "-"
+                } else if f.sign_plus() {
+                    "+"
+                } else {
+                    ""
+                };
+                // SAFETY: Text is set with ASCII exclusively: either a decimal,
+                // or a LETTER_E, or a dot. ASCII implies valid UTF-8.
+                unsafe { f.pad_formatted_parts(&numfmt::Formatted { sign, parts }) }
+            }
         }
 
         $(
-            #[stable(feature = "integer_exp_format", since = "1.42.0")]
-            impl fmt::LowerExp for $Signed {
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    let is_nonnegative = *self >= 0;
-                    let n = if is_nonnegative {
-                        *self as $T
-                    } else {
-                        self.unsigned_abs() as $T
-                    };
-                    $fmt_fn(n, is_nonnegative, false, f)
-                }
+        const _: () = {
+            assert!($Signed::MIN < 0, "need signed");
+            assert!($Unsigned::MIN == 0, "need unsigned");
+            assert!($Signed::BITS == $Unsigned::BITS, "need counterparts");
+            assert!($Signed::BITS <= $T::BITS, "need lossless conversion");
+            assert!($Unsigned::BITS <= $T::BITS, "need lossless conversion");
+        };
+        #[stable(feature = "integer_exp_format", since = "1.42.0")]
+        impl fmt::LowerExp for $Signed {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                $fmt_fn(f, self.unsigned_abs() as $T, *self >= 0, b'e')
             }
-            #[stable(feature = "integer_exp_format", since = "1.42.0")]
-            impl fmt::LowerExp for $Unsigned {
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    $fmt_fn(*self as $T, true, false, f)
-                }
-            })*
-
-        $(
-            #[stable(feature = "integer_exp_format", since = "1.42.0")]
-            impl fmt::UpperExp for $Signed {
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    let is_nonnegative = *self >= 0;
-                    let n = if is_nonnegative {
-                        *self as $T
-                    } else {
-                        self.unsigned_abs() as $T
-                    };
-                    $fmt_fn(n, is_nonnegative, true, f)
-                }
+        }
+        #[stable(feature = "integer_exp_format", since = "1.42.0")]
+        impl fmt::LowerExp for $Unsigned {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                $fmt_fn(f, *self as $T, true, b'e')
             }
-            #[stable(feature = "integer_exp_format", since = "1.42.0")]
-            impl fmt::UpperExp for $Unsigned {
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    $fmt_fn(*self as $T, true, true, f)
-                }
-            })*
+        }
+        #[stable(feature = "integer_exp_format", since = "1.42.0")]
+        impl fmt::UpperExp for $Signed {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                $fmt_fn(f, self.unsigned_abs() as $T, *self >= 0, b'E')
+            }
+        }
+        #[stable(feature = "integer_exp_format", since = "1.42.0")]
+        impl fmt::UpperExp for $Unsigned {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                $fmt_fn(f, *self as $T, true, b'E')
+            }
+        }
+        )*
+
     };
 }
 
@@ -658,10 +695,10 @@ impl u128 {
             remain /= 1_00_00;
             let pair1 = (quad / 100) as usize;
             let pair2 = (quad % 100) as usize;
-            buf[offset + 0].write(DEC_DIGITS_LUT[pair1 * 2 + 0]);
-            buf[offset + 1].write(DEC_DIGITS_LUT[pair1 * 2 + 1]);
-            buf[offset + 2].write(DEC_DIGITS_LUT[pair2 * 2 + 0]);
-            buf[offset + 3].write(DEC_DIGITS_LUT[pair2 * 2 + 1]);
+            buf[offset + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
+            buf[offset + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
+            buf[offset + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
+            buf[offset + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
         }
 
         // Format per two digits from the lookup table.
@@ -676,8 +713,8 @@ impl u128 {
 
             let pair = (remain % 100) as usize;
             remain /= 100;
-            buf[offset + 0].write(DEC_DIGITS_LUT[pair * 2 + 0]);
-            buf[offset + 1].write(DEC_DIGITS_LUT[pair * 2 + 1]);
+            buf[offset + 0].write(DECIMAL_PAIRS[pair * 2 + 0]);
+            buf[offset + 1].write(DECIMAL_PAIRS[pair * 2 + 1]);
         }
 
         // Format the last remaining digit, if any.
@@ -693,7 +730,7 @@ impl u128 {
             // Either the compiler sees that remain < 10, or it prevents
             // a boundary check up next.
             let last = (remain & 15) as usize;
-            buf[offset].write(DEC_DIGITS_LUT[last * 2 + 1]);
+            buf[offset].write(DECIMAL_PAIRS[last * 2 + 1]);
             // not used: remain = 0;
         }
         offset
@@ -792,10 +829,10 @@ fn enc_16lsd<const OFFSET: usize>(buf: &mut [MaybeUninit<u8>], n: u64) {
         remain /= 1_00_00;
         let pair1 = (quad / 100) as usize;
         let pair2 = (quad % 100) as usize;
-        buf[quad_index * 4 + OFFSET + 0].write(DEC_DIGITS_LUT[pair1 * 2 + 0]);
-        buf[quad_index * 4 + OFFSET + 1].write(DEC_DIGITS_LUT[pair1 * 2 + 1]);
-        buf[quad_index * 4 + OFFSET + 2].write(DEC_DIGITS_LUT[pair2 * 2 + 0]);
-        buf[quad_index * 4 + OFFSET + 3].write(DEC_DIGITS_LUT[pair2 * 2 + 1]);
+        buf[quad_index * 4 + OFFSET + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
+        buf[quad_index * 4 + OFFSET + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
+        buf[quad_index * 4 + OFFSET + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
+        buf[quad_index * 4 + OFFSET + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
     }
 }
 
diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs
index eec5c4d646d..932537f2581 100644
--- a/library/core/src/intrinsics/fallback.rs
+++ b/library/core/src/intrinsics/fallback.rs
@@ -7,9 +7,8 @@
 )]
 #![allow(missing_docs)]
 
-#[const_trait]
 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
-pub trait CarryingMulAdd: Copy + 'static {
+pub const trait CarryingMulAdd: Copy + 'static {
     type Unsigned: Copy + 'static;
     fn carrying_mul_add(
         self,
@@ -111,9 +110,8 @@ impl const CarryingMulAdd for i128 {
     }
 }
 
-#[const_trait]
 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
-pub trait DisjointBitOr: Copy + 'static {
+pub const trait DisjointBitOr: Copy + 'static {
     /// See [`super::disjoint_bitor`]; we just need the trait indirection to handle
     /// different types since calling intrinsics with generics doesn't work.
     unsafe fn disjoint_bitor(self, other: Self) -> Self;
@@ -148,3 +146,75 @@ impl_disjoint_bitor! {
     u8, u16, u32, u64, u128, usize,
     i8, i16, i32, i64, i128, isize,
 }
+
+#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
+pub const trait FunnelShift: Copy + 'static {
+    /// See [`super::unchecked_funnel_shl`]; we just need the trait indirection to handle
+    /// different types since calling intrinsics with generics doesn't work.
+    unsafe fn unchecked_funnel_shl(self, rhs: Self, shift: u32) -> Self;
+
+    /// See [`super::unchecked_funnel_shr`]; we just need the trait indirection to handle
+    /// different types since calling intrinsics with generics doesn't work.
+    unsafe fn unchecked_funnel_shr(self, rhs: Self, shift: u32) -> Self;
+}
+
+macro_rules! impl_funnel_shifts {
+    ($($type:ident),*) => {$(
+        #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
+        impl const FunnelShift for $type {
+            #[cfg_attr(miri, track_caller)]
+            #[inline]
+            unsafe fn unchecked_funnel_shl(self, rhs: Self, shift: u32) -> Self {
+                // This implementation is also used by Miri so we have to check the precondition.
+                // SAFETY: this is guaranteed by the caller
+                unsafe { super::assume(shift < $type::BITS) };
+                if shift == 0 {
+                    self
+                } else {
+                    // SAFETY:
+                    //  - `shift < T::BITS`, which satisfies `unchecked_shl`
+                    //  - this also ensures that `T::BITS - shift < T::BITS` (shift = 0 is checked
+                    //    above), which satisfies `unchecked_shr`
+                    //  - because the types are unsigned, the combination are disjoint bits (this is
+                    //    not true if they're signed, since SHR will fill in the empty space with a
+                    //    sign bit, not zero)
+                    unsafe {
+                        super::disjoint_bitor(
+                            super::unchecked_shl(self, shift),
+                            super::unchecked_shr(rhs, $type::BITS - shift),
+                        )
+                    }
+                }
+            }
+
+            #[cfg_attr(miri, track_caller)]
+            #[inline]
+            unsafe fn unchecked_funnel_shr(self, rhs: Self, shift: u32) -> Self {
+                // This implementation is also used by Miri so we have to check the precondition.
+                // SAFETY: this is guaranteed by the caller
+                unsafe { super::assume(shift < $type::BITS) };
+                if shift == 0 {
+                    rhs
+                } else {
+                    // SAFETY:
+                    //  - `shift < T::BITS`, which satisfies `unchecked_shr`
+                    //  - this also ensures that `T::BITS - shift < T::BITS` (shift = 0 is checked
+                    //    above), which satisfies `unchecked_shl`
+                    //  - because the types are unsigned, the combination are disjoint bits (this is
+                    //    not true if they're signed, since SHR will fill in the empty space with a
+                    //    sign bit, not zero)
+                    unsafe {
+                        super::disjoint_bitor(
+                            super::unchecked_shl(self, $type::BITS - shift),
+                            super::unchecked_shr(rhs, shift),
+                        )
+                    }
+                }
+            }
+        }
+    )*};
+}
+
+impl_funnel_shifts! {
+    u8, u16, u32, u64, u128, usize
+}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 904aa52c784..bffffbc29c1 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -2102,6 +2102,61 @@ pub const fn saturating_add<T: Copy>(a: T, b: T) -> T;
 #[rustc_intrinsic]
 pub const fn saturating_sub<T: Copy>(a: T, b: T) -> T;
 
+/// Funnel Shift left.
+///
+/// Concatenates `a` and `b` (with `a` in the most significant half),
+/// creating an integer twice as wide. Then shift this integer left
+/// by `shift`), and extract the most significant half. If `a` and `b`
+/// are the same, this is equivalent to a rotate left operation.
+///
+/// It is undefined behavior if `shift` is greater than or equal to the
+/// bit size of `T`.
+///
+/// Safe versions of this intrinsic are available on the integer primitives
+/// via the `funnel_shl` method. For example, [`u32::funnel_shl`].
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
+#[unstable(feature = "funnel_shifts", issue = "145686")]
+#[track_caller]
+#[miri::intrinsic_fallback_is_spec]
+pub const unsafe fn unchecked_funnel_shl<T: [const] fallback::FunnelShift>(
+    a: T,
+    b: T,
+    shift: u32,
+) -> T {
+    // SAFETY: caller ensures that `shift` is in-range
+    unsafe { a.unchecked_funnel_shl(b, shift) }
+}
+
+/// Funnel Shift right.
+///
+/// Concatenates `a` and `b` (with `a` in the most significant half),
+/// creating an integer twice as wide. Then shift this integer right
+/// by `shift` (taken modulo the bit size of `T`), and extract the
+/// least significant half. If `a` and `b` are the same, this is equivalent
+/// to a rotate right operation.
+///
+/// It is undefined behavior if `shift` is greater than or equal to the
+/// bit size of `T`.
+///
+/// Safer versions of this intrinsic are available on the integer primitives
+/// via the `funnel_shr` method. For example, [`u32::funnel_shr`]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
+#[unstable(feature = "funnel_shifts", issue = "145686")]
+#[track_caller]
+#[miri::intrinsic_fallback_is_spec]
+pub const unsafe fn unchecked_funnel_shr<T: [const] fallback::FunnelShift>(
+    a: T,
+    b: T,
+    shift: u32,
+) -> T {
+    // SAFETY: caller ensures that `shift` is in-range
+    unsafe { a.unchecked_funnel_shr(b, shift) }
+}
+
 /// This is an implementation detail of [`crate::ptr::read`] and should
 /// not be used anywhere else.  See its comments for why this exists.
 ///
diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs
index 943b88e2330..3ebdf7b4727 100644
--- a/library/core/src/iter/adapters/chain.rs
+++ b/library/core/src/iter/adapters/chain.rs
@@ -321,6 +321,7 @@ impl<A: Default, B: Default> Default for Chain<A, B> {
     ///
     /// // take requires `Default`
     /// let _: Chain<_, _> = mem::take(&mut foo.0);
+    /// ```
     fn default() -> Self {
         Chain::new(Default::default(), Default::default())
     }
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
index a6522659620..a55de75d56c 100644
--- a/library/core/src/iter/adapters/peekable.rs
+++ b/library/core/src/iter/adapters/peekable.rs
@@ -317,6 +317,108 @@ impl<I: Iterator> Peekable<I> {
     {
         self.next_if(|next| next == expected)
     }
+
+    /// Consumes the next value of this iterator and applies a function `f` on it,
+    /// returning the result if the closure returns `Ok`.
+    ///
+    /// Otherwise if the closure returns `Err` the value is put back for the next iteration.
+    ///
+    /// The content of the `Err` variant is typically the original value of the closure,
+    /// but this is not required. If a different value is returned,
+    /// the next `peek()` or `next()` call will result in this new value.
+    /// This is similar to modifying the output of `peek_mut()`.
+    ///
+    /// If the closure panics, the next value will always be consumed and dropped
+    /// even if the panic is caught, because the closure never returned an `Err` value to put back.
+    ///
+    /// # Examples
+    ///
+    /// Parse the leading decimal number from an iterator of characters.
+    /// ```
+    /// #![feature(peekable_next_if_map)]
+    /// let mut iter = "125 GOTO 10".chars().peekable();
+    /// let mut line_num = 0_u32;
+    /// while let Some(digit) = iter.next_if_map(|c| c.to_digit(10).ok_or(c)) {
+    ///     line_num = line_num * 10 + digit;
+    /// }
+    /// assert_eq!(line_num, 125);
+    /// assert_eq!(iter.collect::<String>(), " GOTO 10");
+    /// ```
+    ///
+    /// Matching custom types.
+    /// ```
+    /// #![feature(peekable_next_if_map)]
+    ///
+    /// #[derive(Debug, PartialEq, Eq)]
+    /// enum Node {
+    ///     Comment(String),
+    ///     Red(String),
+    ///     Green(String),
+    ///     Blue(String),
+    /// }
+    ///
+    /// /// Combines all consecutive `Comment` nodes into a single one.
+    /// fn combine_comments(nodes: Vec<Node>) -> Vec<Node> {
+    ///     let mut result = Vec::with_capacity(nodes.len());
+    ///     let mut iter = nodes.into_iter().peekable();
+    ///     let mut comment_text = None::<String>;
+    ///     loop {
+    ///         // Typically the closure in .next_if_map() matches on the input,
+    ///         //  extracts the desired pattern into an `Ok`,
+    ///         //  and puts the rest into an `Err`.
+    ///         while let Some(text) = iter.next_if_map(|node| match node {
+    ///             Node::Comment(text) => Ok(text),
+    ///             other => Err(other),
+    ///         }) {
+    ///             comment_text.get_or_insert_default().push_str(&text);
+    ///         }
+    ///
+    ///         if let Some(text) = comment_text.take() {
+    ///             result.push(Node::Comment(text));
+    ///         }
+    ///         if let Some(node) = iter.next() {
+    ///             result.push(node);
+    ///         } else {
+    ///             break;
+    ///         }
+    ///     }
+    ///     result
+    /// }
+    ///# assert_eq!( // hiding the test to avoid cluttering the documentation.
+    ///#     combine_comments(vec![
+    ///#         Node::Comment("The".to_owned()),
+    ///#         Node::Comment("Quick".to_owned()),
+    ///#         Node::Comment("Brown".to_owned()),
+    ///#         Node::Red("Fox".to_owned()),
+    ///#         Node::Green("Jumped".to_owned()),
+    ///#         Node::Comment("Over".to_owned()),
+    ///#         Node::Blue("The".to_owned()),
+    ///#         Node::Comment("Lazy".to_owned()),
+    ///#         Node::Comment("Dog".to_owned()),
+    ///#     ]),
+    ///#     vec![
+    ///#         Node::Comment("TheQuickBrown".to_owned()),
+    ///#         Node::Red("Fox".to_owned()),
+    ///#         Node::Green("Jumped".to_owned()),
+    ///#         Node::Comment("Over".to_owned()),
+    ///#         Node::Blue("The".to_owned()),
+    ///#         Node::Comment("LazyDog".to_owned()),
+    ///#     ],
+    ///# )
+    /// ```
+    #[unstable(feature = "peekable_next_if_map", issue = "143702")]
+    pub fn next_if_map<R>(&mut self, f: impl FnOnce(I::Item) -> Result<R, I::Item>) -> Option<R> {
+        let unpeek = if let Some(item) = self.next() {
+            match f(item) {
+                Ok(result) => return Some(result),
+                Err(item) => Some(item),
+            }
+        } else {
+            None
+        };
+        self.peeked = Some(unpeek);
+        None
+    }
 }
 
 #[unstable(feature = "trusted_len", issue = "37572")]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 82506379cac..c306011bdda 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -156,6 +156,7 @@
 #![feature(f128)]
 #![feature(freeze_impls)]
 #![feature(fundamental)]
+#![feature(funnel_shifts)]
 #![feature(if_let_guard)]
 #![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 73aad27afef..d03d7a43469 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -1057,8 +1057,7 @@ marker_impls! {
 #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
 #[rustc_deny_explicit_impl]
 #[rustc_do_not_implement_via_object]
-#[const_trait]
-pub trait Destruct {}
+pub const trait Destruct {}
 
 /// A marker for tuple types.
 ///
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 02bb8179293..8868f05f1b9 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -258,7 +258,8 @@ impl<T: ?Sized> ManuallyDrop<T> {
 }
 
 #[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> Deref for ManuallyDrop<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: ?Sized> const Deref for ManuallyDrop<T> {
     type Target = T;
     #[inline(always)]
     fn deref(&self) -> &T {
@@ -267,7 +268,8 @@ impl<T: ?Sized> Deref for ManuallyDrop<T> {
 }
 
 #[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: ?Sized> const DerefMut for ManuallyDrop<T> {
     #[inline(always)]
     fn deref_mut(&mut self) -> &mut T {
         &mut self.value
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index 3bf113d017c..9779fb8fe4d 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1087,7 +1087,7 @@ impl fmt::Debug for IpAddr {
 }
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Ipv4Addr> for IpAddr {
     /// Copies this address to a new `IpAddr::V4`.
     ///
@@ -1110,7 +1110,7 @@ impl const From<Ipv4Addr> for IpAddr {
 }
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Ipv6Addr> for IpAddr {
     /// Copies this address to a new `IpAddr::V6`.
     ///
@@ -1221,7 +1221,7 @@ impl Ord for Ipv4Addr {
 }
 
 #[stable(feature = "ip_u32", since = "1.1.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Ipv4Addr> for u32 {
     /// Uses [`Ipv4Addr::to_bits`] to convert an IPv4 address to a host byte order `u32`.
     #[inline]
@@ -1231,7 +1231,7 @@ impl const From<Ipv4Addr> for u32 {
 }
 
 #[stable(feature = "ip_u32", since = "1.1.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<u32> for Ipv4Addr {
     /// Uses [`Ipv4Addr::from_bits`] to convert a host byte order `u32` into an IPv4 address.
     #[inline]
@@ -1241,7 +1241,7 @@ impl const From<u32> for Ipv4Addr {
 }
 
 #[stable(feature = "from_slice_v4", since = "1.9.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<[u8; 4]> for Ipv4Addr {
     /// Creates an `Ipv4Addr` from a four element byte array.
     ///
@@ -1260,7 +1260,7 @@ impl const From<[u8; 4]> for Ipv4Addr {
 }
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<[u8; 4]> for IpAddr {
     /// Creates an `IpAddr::V4` from a four element byte array.
     ///
@@ -2215,7 +2215,7 @@ impl Ord for Ipv6Addr {
 }
 
 #[stable(feature = "i128", since = "1.26.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Ipv6Addr> for u128 {
     /// Uses [`Ipv6Addr::to_bits`] to convert an IPv6 address to a host byte order `u128`.
     #[inline]
@@ -2224,7 +2224,7 @@ impl const From<Ipv6Addr> for u128 {
     }
 }
 #[stable(feature = "i128", since = "1.26.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<u128> for Ipv6Addr {
     /// Uses [`Ipv6Addr::from_bits`] to convert a host byte order `u128` to an IPv6 address.
     #[inline]
@@ -2234,7 +2234,7 @@ impl const From<u128> for Ipv6Addr {
 }
 
 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<[u8; 16]> for Ipv6Addr {
     /// Creates an `Ipv6Addr` from a sixteen element byte array.
     ///
@@ -2262,7 +2262,7 @@ impl const From<[u8; 16]> for Ipv6Addr {
 }
 
 #[stable(feature = "ipv6_from_segments", since = "1.16.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<[u16; 8]> for Ipv6Addr {
     /// Creates an `Ipv6Addr` from an eight element 16-bit array.
     ///
@@ -2291,7 +2291,7 @@ impl const From<[u16; 8]> for Ipv6Addr {
 }
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<[u8; 16]> for IpAddr {
     /// Creates an `IpAddr::V6` from a sixteen element byte array.
     ///
@@ -2319,7 +2319,7 @@ impl const From<[u8; 16]> for IpAddr {
 }
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<[u16; 8]> for IpAddr {
     /// Creates an `IpAddr::V6` from an eight element 16-bit array.
     ///
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
index df99e9b20c2..ccc53c156d3 100644
--- a/library/core/src/net/socket_addr.rs
+++ b/library/core/src/net/socket_addr.rs
@@ -592,7 +592,7 @@ impl SocketAddrV6 {
 }
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<SocketAddrV4> for SocketAddr {
     /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
     #[inline]
@@ -602,7 +602,7 @@ impl const From<SocketAddrV4> for SocketAddr {
 }
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<SocketAddrV6> for SocketAddr {
     /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
     #[inline]
@@ -612,7 +612,7 @@ impl const From<SocketAddrV6> for SocketAddr {
 }
 
 #[stable(feature = "addr_from_into_ip", since = "1.17.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<I: [const] Into<IpAddr>> const From<(I, u16)> for SocketAddr {
     /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
     ///
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index faa52329827..8a353dc0fbe 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -20,7 +20,7 @@ impl fmt::Display for TryFromIntError {
 impl Error for TryFromIntError {}
 
 #[stable(feature = "try_from", since = "1.34.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Infallible> for TryFromIntError {
     fn from(x: Infallible) -> TryFromIntError {
         match x {}
@@ -28,7 +28,7 @@ impl const From<Infallible> for TryFromIntError {
 }
 
 #[unstable(feature = "never_type", issue = "35121")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<!> for TryFromIntError {
     #[inline]
     fn from(never: !) -> TryFromIntError {
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 4282b1af9f2..66c892aadd0 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -832,7 +832,6 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
     pub const fn midpoint(self, other: f128) -> f128 {
-        const LO: f128 = f128::MIN_POSITIVE * 2.;
         const HI: f128 = f128::MAX / 2.;
 
         let (a, b) = (self, other);
@@ -842,14 +841,7 @@ impl f128 {
         if abs_a <= HI && abs_b <= HI {
             // Overflow is impossible
             (a + b) / 2.
-        } else if abs_a < LO {
-            // Not safe to halve `a` (would underflow)
-            a + (b / 2.)
-        } else if abs_b < LO {
-            // Not safe to halve `b` (would underflow)
-            (a / 2.) + b
         } else {
-            // Safe to halve `a` and `b`
             (a / 2.) + (b / 2.)
         }
     }
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 23a8661c14b..81220065e72 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -820,7 +820,6 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
     pub const fn midpoint(self, other: f16) -> f16 {
-        const LO: f16 = f16::MIN_POSITIVE * 2.;
         const HI: f16 = f16::MAX / 2.;
 
         let (a, b) = (self, other);
@@ -830,14 +829,7 @@ impl f16 {
         if abs_a <= HI && abs_b <= HI {
             // Overflow is impossible
             (a + b) / 2.
-        } else if abs_a < LO {
-            // Not safe to halve `a` (would underflow)
-            a + (b / 2.)
-        } else if abs_b < LO {
-            // Not safe to halve `b` (would underflow)
-            (a / 2.) + b
         } else {
-            // Safe to halve `a` and `b`
             (a / 2.) + (b / 2.)
         }
     }
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index da08bfc5950..cefcf1d1fe2 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1025,7 +1025,6 @@ impl f32 {
                 ((self as f64 + other as f64) / 2.0) as f32
             }
             _ => {
-                const LO: f32 = f32::MIN_POSITIVE * 2.;
                 const HI: f32 = f32::MAX / 2.;
 
                 let (a, b) = (self, other);
@@ -1035,14 +1034,7 @@ impl f32 {
                 if abs_a <= HI && abs_b <= HI {
                     // Overflow is impossible
                     (a + b) / 2.
-                } else if abs_a < LO {
-                    // Not safe to halve `a` (would underflow)
-                    a + (b / 2.)
-                } else if abs_b < LO {
-                    // Not safe to halve `b` (would underflow)
-                    (a / 2.) + b
                 } else {
-                    // Safe to halve `a` and `b`
                     (a / 2.) + (b / 2.)
                 }
             }
@@ -1954,8 +1946,8 @@ pub mod math {
     /// let abs_difference_x = (f32::math::abs_sub(x, 1.0) - 2.0).abs();
     /// let abs_difference_y = (f32::math::abs_sub(y, 1.0) - 0.0).abs();
     ///
-    /// assert!(abs_difference_x <= f32::EPSILON);
-    /// assert!(abs_difference_y <= f32::EPSILON);
+    /// assert!(abs_difference_x <= 1e-6);
+    /// assert!(abs_difference_y <= 1e-6);
     /// ```
     ///
     /// _This standalone function is for testing only.
@@ -2000,7 +1992,7 @@ pub mod math {
     /// // x^(1/3) - 2 == 0
     /// let abs_difference = (f32::math::cbrt(x) - 2.0).abs();
     ///
-    /// assert!(abs_difference <= f32::EPSILON);
+    /// assert!(abs_difference <= 1e-6);
     /// ```
     ///
     /// _This standalone function is for testing only.
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index dc0977cb147..9dd1141e703 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1026,7 +1026,6 @@ impl f64 {
     #[stable(feature = "num_midpoint", since = "1.85.0")]
     #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
     pub const fn midpoint(self, other: f64) -> f64 {
-        const LO: f64 = f64::MIN_POSITIVE * 2.;
         const HI: f64 = f64::MAX / 2.;
 
         let (a, b) = (self, other);
@@ -1036,14 +1035,7 @@ impl f64 {
         if abs_a <= HI && abs_b <= HI {
             // Overflow is impossible
             (a + b) / 2.
-        } else if abs_a < LO {
-            // Not safe to halve `a` (would underflow)
-            a + (b / 2.)
-        } else if abs_b < LO {
-            // Not safe to halve `b` (would underflow)
-            (a / 2.) + b
         } else {
-            // Safe to halve `a` and `b`
             (a / 2.) + (b / 2.)
         }
     }
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 25864db5fea..64a3dd3e8bc 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1285,7 +1285,7 @@ macro_rules! int_impl {
         ///
         /// ```should_panic
         #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")]
-        ///
+        /// ```
         #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
         #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
@@ -1413,6 +1413,66 @@ macro_rules! int_impl {
             }
         }
 
+        /// Exact shift left. Computes `self << rhs` as long as it can be reversed losslessly.
+        ///
+        /// Returns `None` if any bits that would be shifted out differ from the resulting sign bit
+        /// or if `rhs` >=
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        /// Otherwise, returns `Some(self << rhs)`.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(exact_bitshifts)]
+        ///
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(4), Some(0x10));")]
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 2), Some(1 << ", stringify!($SelfT), "::BITS - 2));")]
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
+        #[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 2), Some(-0x2 << ", stringify!($SelfT), "::BITS - 2));")]
+        #[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
+        /// ```
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn exact_shl(self, rhs: u32) -> Option<$SelfT> {
+            if rhs < self.leading_zeros() || rhs < self.leading_ones() {
+                // SAFETY: rhs is checked above
+                Some(unsafe { self.unchecked_shl(rhs) })
+            } else {
+                None
+            }
+        }
+
+        /// Unchecked exact shift left. Computes `self << rhs`, assuming the operation can be
+        /// losslessly reversed and `rhs` cannot be larger than
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `rhs >= self.leading_zeros() && rhs >=
+        /// self.leading_ones()` i.e. when
+        #[doc = concat!("[`", stringify!($SelfT), "::exact_shl`]")]
+        /// would return `None`.
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn unchecked_exact_shl(self, rhs: u32) -> $SelfT {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::unchecked_exact_shl cannot shift out non-zero bits"),
+                (
+                    zeros: u32 = self.leading_zeros(),
+                    ones: u32 = self.leading_ones(),
+                    rhs: u32 = rhs,
+                ) => rhs < zeros || rhs < ones,
+            );
+
+            // SAFETY: this is guaranteed to be safe by the caller
+            unsafe { self.unchecked_shl(rhs) }
+        }
+
         /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
         /// larger than or equal to the number of bits in `self`.
         ///
@@ -1534,6 +1594,63 @@ macro_rules! int_impl {
             }
         }
 
+        /// Exact shift right. Computes `self >> rhs` as long as it can be reversed losslessly.
+        ///
+        /// Returns `None` if any non-zero bits would be shifted out or if `rhs` >=
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        /// Otherwise, returns `Some(self >> rhs)`.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(exact_bitshifts)]
+        ///
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(4), Some(0x1));")]
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(5), None);")]
+        /// ```
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn exact_shr(self, rhs: u32) -> Option<$SelfT> {
+            if rhs <= self.trailing_zeros() && rhs < <$SelfT>::BITS {
+                // SAFETY: rhs is checked above
+                Some(unsafe { self.unchecked_shr(rhs) })
+            } else {
+                None
+            }
+        }
+
+        /// Unchecked exact shift right. Computes `self >> rhs`, assuming the operation can be
+        /// losslessly reversed and `rhs` cannot be larger than
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `rhs > self.trailing_zeros() || rhs >=
+        #[doc = concat!(stringify!($SelfT), "::BITS`")]
+        /// i.e. when
+        #[doc = concat!("[`", stringify!($SelfT), "::exact_shr`]")]
+        /// would return `None`.
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn unchecked_exact_shr(self, rhs: u32) -> $SelfT {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::unchecked_exact_shr cannot shift out non-zero bits"),
+                (
+                    zeros: u32 = self.trailing_zeros(),
+                    bits: u32 =  <$SelfT>::BITS,
+                    rhs: u32 = rhs,
+                ) => rhs <= zeros && rhs < bits,
+            );
+
+            // SAFETY: this is guaranteed to be safe by the caller
+            unsafe { self.unchecked_shr(rhs) }
+        }
+
         /// Checked absolute value. Computes `self.abs()`, returning `None` if
         /// `self == MIN`.
         ///
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index acfe38b7a37..54d5a63633c 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -454,6 +454,9 @@ impl u8 {
         rot = 2,
         rot_op = "0x82",
         rot_result = "0xa",
+        fsh_op = "0x36",
+        fshl_result = "0x8",
+        fshr_result = "0x8d",
         swap_op = "0x12",
         swapped = "0x12",
         reversed = "0x48",
@@ -1088,6 +1091,9 @@ impl u16 {
         rot = 4,
         rot_op = "0xa003",
         rot_result = "0x3a",
+        fsh_op = "0x2de",
+        fshl_result = "0x30",
+        fshr_result = "0x302d",
         swap_op = "0x1234",
         swapped = "0x3412",
         reversed = "0x2c48",
@@ -1135,6 +1141,9 @@ impl u32 {
         rot = 8,
         rot_op = "0x10000b3",
         rot_result = "0xb301",
+        fsh_op = "0x2fe78e45",
+        fshl_result = "0xb32f",
+        fshr_result = "0xb32fe78e",
         swap_op = "0x12345678",
         swapped = "0x78563412",
         reversed = "0x1e6a2c48",
@@ -1158,6 +1167,9 @@ impl u64 {
         rot = 12,
         rot_op = "0xaa00000000006e1",
         rot_result = "0x6e10aa",
+        fsh_op = "0x2fe78e45983acd98",
+        fshl_result = "0x6e12fe",
+        fshr_result = "0x6e12fe78e45983ac",
         swap_op = "0x1234567890123456",
         swapped = "0x5634129078563412",
         reversed = "0x6a2c48091e6a2c48",
@@ -1181,6 +1193,9 @@ impl u128 {
         rot = 16,
         rot_op = "0x13f40000000000000000000000004f76",
         rot_result = "0x4f7613f4",
+        fsh_op = "0x2fe78e45983acd98039000008736273",
+        fshl_result = "0x4f7602fe",
+        fshr_result = "0x4f7602fe78e45983acd9803900000873",
         swap_op = "0x12345678901234567890123456789012",
         swapped = "0x12907856341290785634129078563412",
         reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
@@ -1207,6 +1222,9 @@ impl usize {
         rot = 4,
         rot_op = "0xa003",
         rot_result = "0x3a",
+        fsh_op = "0x2fe78e45983acd98039000008736273",
+        fshl_result = "0x4f7602fe",
+        fshr_result = "0x4f7602fe78e45983acd9803900000873",
         swap_op = "0x1234",
         swapped = "0x3412",
         reversed = "0x2c48",
@@ -1231,6 +1249,9 @@ impl usize {
         rot = 8,
         rot_op = "0x10000b3",
         rot_result = "0xb301",
+        fsh_op = "0x2fe78e45",
+        fshl_result = "0xb32f",
+        fshr_result = "0xb32fe78e",
         swap_op = "0x12345678",
         swapped = "0x78563412",
         reversed = "0x1e6a2c48",
@@ -1255,6 +1276,9 @@ impl usize {
         rot = 12,
         rot_op = "0xaa00000000006e1",
         rot_result = "0x6e10aa",
+        fsh_op = "0x2fe78e45983acd98",
+        fshl_result = "0x6e12fe",
+        fshr_result = "0x6e12fe78e45983ac",
         swap_op = "0x1234567890123456",
         swapped = "0x5634129078563412",
         reversed = "0x6a2c48091e6a2c48",
@@ -1378,7 +1402,7 @@ const fn from_ascii_radix_panic(radix: u32) -> ! {
 macro_rules! from_str_int_impl {
     ($signedness:ident $($int_ty:ty)+) => {$(
         #[stable(feature = "rust1", since = "1.0.0")]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const FromStr for $int_ty {
             type Err = ParseIntError;
 
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index e02d9260a16..0f38081c355 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -297,7 +297,7 @@ where
 }
 
 #[stable(feature = "from_nonzero", since = "1.31.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const From<NonZero<T>> for T
 where
     T: ZeroablePrimitive,
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index c1e656fdea2..bf72ec83197 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -14,6 +14,9 @@ macro_rules! uint_impl {
         rot = $rot:literal,
         rot_op = $rot_op:literal,
         rot_result = $rot_result:literal,
+        fsh_op = $fsh_op:literal,
+        fshl_result = $fshl_result:literal,
+        fshr_result = $fshr_result:literal,
         swap_op = $swap_op:literal,
         swapped = $swapped:literal,
         reversed = $reversed:literal,
@@ -375,6 +378,76 @@ macro_rules! uint_impl {
             return intrinsics::rotate_right(self, n);
         }
 
+        /// Performs a left funnel shift (concatenates `self` with `rhs`, with `self`
+        /// making up the most significant half, then shifts the combined value left
+        /// by `n`, and most significant half is extracted to produce the result).
+        ///
+        /// Please note this isn't the same operation as the `<<` shifting operator or
+        /// [`rotate_left`](Self::rotate_left), although `a.funnel_shl(a, n)` is *equivalent*
+        /// to `a.rotate_left(n)`.
+        ///
+        /// # Panics
+        ///
+        /// If `n` is greater than or equal to the number of bits in `self`
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(funnel_shifts)]
+        #[doc = concat!("let a = ", $rot_op, stringify!($SelfT), ";")]
+        #[doc = concat!("let b = ", $fsh_op, stringify!($SelfT), ";")]
+        #[doc = concat!("let m = ", $fshl_result, ";")]
+        ///
+        #[doc = concat!("assert_eq!(a.funnel_shl(b, ", $rot, "), m);")]
+        /// ```
+        #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
+        #[unstable(feature = "funnel_shifts", issue = "145686")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline(always)]
+        pub const fn funnel_shl(self, rhs: Self, n: u32) -> Self {
+            assert!(n < Self::BITS, "attempt to funnel shift left with overflow");
+            // SAFETY: just checked that `shift` is in-range
+            unsafe { intrinsics::unchecked_funnel_shl(self, rhs, n) }
+        }
+
+        /// Performs a right funnel shift (concatenates `self` and `rhs`, with `self`
+        /// making up the most significant half, then shifts the combined value right
+        /// by `n`, and least significant half is extracted to produce the result).
+        ///
+        /// Please note this isn't the same operation as the `>>` shifting operator or
+        /// [`rotate_right`](Self::rotate_right), although `a.funnel_shr(a, n)` is *equivalent*
+        /// to `a.rotate_right(n)`.
+        ///
+        /// # Panics
+        ///
+        /// If `n` is greater than or equal to the number of bits in `self`
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(funnel_shifts)]
+        #[doc = concat!("let a = ", $rot_op, stringify!($SelfT), ";")]
+        #[doc = concat!("let b = ", $fsh_op, stringify!($SelfT), ";")]
+        #[doc = concat!("let m = ", $fshr_result, ";")]
+        ///
+        #[doc = concat!("assert_eq!(a.funnel_shr(b, ", $rot, "), m);")]
+        /// ```
+        #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
+        #[unstable(feature = "funnel_shifts", issue = "145686")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline(always)]
+        pub const fn funnel_shr(self, rhs: Self, n: u32) -> Self {
+            assert!(n < Self::BITS, "attempt to funnel shift right with overflow");
+            // SAFETY: just checked that `shift` is in-range
+            unsafe { intrinsics::unchecked_funnel_shr(self, rhs, n) }
+        }
+
         /// Reverses the byte order of the integer.
         ///
         /// # Examples
@@ -1620,7 +1693,7 @@ macro_rules! uint_impl {
         ///
         /// ```should_panic
         #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")]
-        ///
+        /// ```
         #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
         #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
@@ -1748,6 +1821,63 @@ macro_rules! uint_impl {
             }
         }
 
+        /// Exact shift left. Computes `self << rhs` as long as it can be reversed losslessly.
+        ///
+        /// Returns `None` if any non-zero bits would be shifted out or if `rhs` >=
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        /// Otherwise, returns `Some(self << rhs)`.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(exact_bitshifts)]
+        ///
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(4), Some(0x10));")]
+        #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(129), None);")]
+        /// ```
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn exact_shl(self, rhs: u32) -> Option<$SelfT> {
+            if rhs <= self.leading_zeros() && rhs < <$SelfT>::BITS {
+                // SAFETY: rhs is checked above
+                Some(unsafe { self.unchecked_shl(rhs) })
+            } else {
+                None
+            }
+        }
+
+        /// Unchecked exact shift left. Computes `self << rhs`, assuming the operation can be
+        /// losslessly reversed `rhs` cannot be larger than
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `rhs > self.leading_zeros() || rhs >=
+        #[doc = concat!(stringify!($SelfT), "::BITS`")]
+        /// i.e. when
+        #[doc = concat!("[`", stringify!($SelfT), "::exact_shl`]")]
+        /// would return `None`.
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn unchecked_exact_shl(self, rhs: u32) -> $SelfT {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::exact_shl_unchecked cannot shift out non-zero bits"),
+                (
+                    zeros: u32 = self.leading_zeros(),
+                    bits: u32 =  <$SelfT>::BITS,
+                    rhs: u32 = rhs,
+                ) => rhs <= zeros && rhs < bits,
+            );
+
+            // SAFETY: this is guaranteed to be safe by the caller
+            unsafe { self.unchecked_shl(rhs) }
+        }
+
         /// Checked shift right. Computes `self >> rhs`, returning `None`
         /// if `rhs` is larger than or equal to the number of bits in `self`.
         ///
@@ -1863,6 +1993,63 @@ macro_rules! uint_impl {
             }
         }
 
+        /// Exact shift right. Computes `self >> rhs` as long as it can be reversed losslessly.
+        ///
+        /// Returns `None` if any non-zero bits would be shifted out or if `rhs` >=
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        /// Otherwise, returns `Some(self >> rhs)`.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(exact_bitshifts)]
+        ///
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(4), Some(0x1));")]
+        #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(5), None);")]
+        /// ```
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn exact_shr(self, rhs: u32) -> Option<$SelfT> {
+            if rhs <= self.trailing_zeros() && rhs < <$SelfT>::BITS {
+                // SAFETY: rhs is checked above
+                Some(unsafe { self.unchecked_shr(rhs) })
+            } else {
+                None
+            }
+        }
+
+        /// Unchecked exact shift right. Computes `self >> rhs`, assuming the operation can be
+        /// losslessly reversed and `rhs` cannot be larger than
+        #[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `rhs > self.trailing_zeros() || rhs >=
+        #[doc = concat!(stringify!($SelfT), "::BITS`")]
+        /// i.e. when
+        #[doc = concat!("[`", stringify!($SelfT), "::exact_shr`]")]
+        /// would return `None`.
+        #[unstable(feature = "exact_bitshifts", issue = "144336")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn unchecked_exact_shr(self, rhs: u32) -> $SelfT {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::exact_shr_unchecked cannot shift out non-zero bits"),
+                (
+                    zeros: u32 = self.trailing_zeros(),
+                    bits: u32 =  <$SelfT>::BITS,
+                    rhs: u32 = rhs,
+                ) => rhs <= zeros && rhs < bits,
+            );
+
+            // SAFETY: this is guaranteed to be safe by the caller
+            unsafe { self.unchecked_shr(rhs) }
+        }
+
         /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
         /// overflow occurred.
         ///
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index 16c719b0c39..6c6479c9984 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -74,8 +74,7 @@
     append_const_msg
 )]
 #[doc(alias = "+")]
-#[const_trait]
-pub trait Add<Rhs = Self> {
+pub const trait Add<Rhs = Self> {
     /// The resulting type after applying the `+` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -188,8 +187,7 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
     append_const_msg
 )]
 #[doc(alias = "-")]
-#[const_trait]
-pub trait Sub<Rhs = Self> {
+pub const trait Sub<Rhs = Self> {
     /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -323,8 +321,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
     label = "no implementation for `{Self} * {Rhs}`"
 )]
 #[doc(alias = "*")]
-#[const_trait]
-pub trait Mul<Rhs = Self> {
+pub const trait Mul<Rhs = Self> {
     /// The resulting type after applying the `*` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -462,8 +459,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
     label = "no implementation for `{Self} / {Rhs}`"
 )]
 #[doc(alias = "/")]
-#[const_trait]
-pub trait Div<Rhs = Self> {
+pub const trait Div<Rhs = Self> {
     /// The resulting type after applying the `/` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -572,8 +568,7 @@ div_impl_float! { f16 f32 f64 f128 }
     label = "no implementation for `{Self} % {Rhs}`"
 )]
 #[doc(alias = "%")]
-#[const_trait]
-pub trait Rem<Rhs = Self> {
+pub const trait Rem<Rhs = Self> {
     /// The resulting type after applying the `%` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -694,8 +689,7 @@ rem_impl_float! { f16 f32 f64 f128 }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
 #[doc(alias = "-")]
-#[const_trait]
-pub trait Neg {
+pub const trait Neg {
     /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -772,8 +766,7 @@ neg_impl! { isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 )]
 #[doc(alias = "+")]
 #[doc(alias = "+=")]
-#[const_trait]
-pub trait AddAssign<Rhs = Self> {
+pub const trait AddAssign<Rhs = Self> {
     /// Performs the `+=` operation.
     ///
     /// # Example
@@ -844,8 +837,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f
 )]
 #[doc(alias = "-")]
 #[doc(alias = "-=")]
-#[const_trait]
-pub trait SubAssign<Rhs = Self> {
+pub const trait SubAssign<Rhs = Self> {
     /// Performs the `-=` operation.
     ///
     /// # Example
@@ -907,8 +899,7 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f
 )]
 #[doc(alias = "*")]
 #[doc(alias = "*=")]
-#[const_trait]
-pub trait MulAssign<Rhs = Self> {
+pub const trait MulAssign<Rhs = Self> {
     /// Performs the `*=` operation.
     ///
     /// # Example
@@ -970,8 +961,7 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f
 )]
 #[doc(alias = "/")]
 #[doc(alias = "/=")]
-#[const_trait]
-pub trait DivAssign<Rhs = Self> {
+pub const trait DivAssign<Rhs = Self> {
     /// Performs the `/=` operation.
     ///
     /// # Example
@@ -1036,8 +1026,7 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f
 )]
 #[doc(alias = "%")]
 #[doc(alias = "%=")]
-#[const_trait]
-pub trait RemAssign<Rhs = Self> {
+pub const trait RemAssign<Rhs = Self> {
     /// Performs the `%=` operation.
     ///
     /// # Example
diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs
index 00196728219..0cd61b07373 100644
--- a/library/core/src/ops/bit.rs
+++ b/library/core/src/ops/bit.rs
@@ -32,8 +32,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
 #[doc(alias = "!")]
-#[const_trait]
-pub trait Not {
+pub const trait Not {
     /// The resulting type after applying the `!` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -148,8 +147,7 @@ impl const Not for ! {
     message = "no implementation for `{Self} & {Rhs}`",
     label = "no implementation for `{Self} & {Rhs}`"
 )]
-#[const_trait]
-pub trait BitAnd<Rhs = Self> {
+pub const trait BitAnd<Rhs = Self> {
     /// The resulting type after applying the `&` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -253,8 +251,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
     message = "no implementation for `{Self} | {Rhs}`",
     label = "no implementation for `{Self} | {Rhs}`"
 )]
-#[const_trait]
-pub trait BitOr<Rhs = Self> {
+pub const trait BitOr<Rhs = Self> {
     /// The resulting type after applying the `|` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -358,8 +355,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
     message = "no implementation for `{Self} ^ {Rhs}`",
     label = "no implementation for `{Self} ^ {Rhs}`"
 )]
-#[const_trait]
-pub trait BitXor<Rhs = Self> {
+pub const trait BitXor<Rhs = Self> {
     /// The resulting type after applying the `^` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -462,8 +458,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
     message = "no implementation for `{Self} << {Rhs}`",
     label = "no implementation for `{Self} << {Rhs}`"
 )]
-#[const_trait]
-pub trait Shl<Rhs = Self> {
+pub const trait Shl<Rhs = Self> {
     /// The resulting type after applying the `<<` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -585,8 +580,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
     message = "no implementation for `{Self} >> {Rhs}`",
     label = "no implementation for `{Self} >> {Rhs}`"
 )]
-#[const_trait]
-pub trait Shr<Rhs = Self> {
+pub const trait Shr<Rhs = Self> {
     /// The resulting type after applying the `>>` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -717,8 +711,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
     message = "no implementation for `{Self} &= {Rhs}`",
     label = "no implementation for `{Self} &= {Rhs}`"
 )]
-#[const_trait]
-pub trait BitAndAssign<Rhs = Self> {
+pub const trait BitAndAssign<Rhs = Self> {
     /// Performs the `&=` operation.
     ///
     /// # Examples
@@ -793,8 +786,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
     message = "no implementation for `{Self} |= {Rhs}`",
     label = "no implementation for `{Self} |= {Rhs}`"
 )]
-#[const_trait]
-pub trait BitOrAssign<Rhs = Self> {
+pub const trait BitOrAssign<Rhs = Self> {
     /// Performs the `|=` operation.
     ///
     /// # Examples
@@ -869,8 +861,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
     message = "no implementation for `{Self} ^= {Rhs}`",
     label = "no implementation for `{Self} ^= {Rhs}`"
 )]
-#[const_trait]
-pub trait BitXorAssign<Rhs = Self> {
+pub const trait BitXorAssign<Rhs = Self> {
     /// Performs the `^=` operation.
     ///
     /// # Examples
@@ -943,8 +934,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
     message = "no implementation for `{Self} <<= {Rhs}`",
     label = "no implementation for `{Self} <<= {Rhs}`"
 )]
-#[const_trait]
-pub trait ShlAssign<Rhs = Self> {
+pub const trait ShlAssign<Rhs = Self> {
     /// Performs the `<<=` operation.
     ///
     /// # Examples
@@ -1030,8 +1020,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
     message = "no implementation for `{Self} >>= {Rhs}`",
     label = "no implementation for `{Self} >>= {Rhs}`"
 )]
-#[const_trait]
-pub trait ShrAssign<Rhs = Self> {
+pub const trait ShrAssign<Rhs = Self> {
     /// Performs the `>>=` operation.
     ///
     /// # Examples
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index 7489a8bb6e7..73b74d53323 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -99,7 +99,8 @@ pub enum ControlFlow<B, C = ()> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
-impl<B, C> ops::Try for ControlFlow<B, C> {
+#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+impl<B, C> const ops::Try for ControlFlow<B, C> {
     type Output = C;
     type Residual = ControlFlow<B, convert::Infallible>;
 
@@ -118,9 +119,10 @@ impl<B, C> ops::Try for ControlFlow<B, C> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
+#[rustc_const_unstable(feature = "const_try", issue = "74935")]
 // Note: manually specifying the residual type instead of using the default to work around
 // https://github.com/rust-lang/rust/issues/99940
-impl<B, C> ops::FromResidual<ControlFlow<B, convert::Infallible>> for ControlFlow<B, C> {
+impl<B, C> const ops::FromResidual<ControlFlow<B, convert::Infallible>> for ControlFlow<B, C> {
     #[inline]
     fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
         match residual {
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 5f68c1f55c2..305861ea7b6 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -135,9 +135,8 @@ use crate::marker::PointeeSized;
 #[doc(alias = "&*")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Deref"]
-#[const_trait]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
-pub trait Deref: PointeeSized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait Deref: PointeeSized {
     /// The resulting type after dereferencing.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_diagnostic_item = "deref_target"]
@@ -152,7 +151,7 @@ pub trait Deref: PointeeSized {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: ?Sized> const Deref for &T {
     type Target = T;
 
@@ -166,7 +165,7 @@ impl<T: ?Sized> const Deref for &T {
 impl<T: ?Sized> !DerefMut for &T {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: ?Sized> const Deref for &mut T {
     type Target = T;
 
@@ -267,9 +266,8 @@ impl<T: ?Sized> const Deref for &mut T {
 #[lang = "deref_mut"]
 #[doc(alias = "*")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[const_trait]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
-pub trait DerefMut: [const] Deref + PointeeSized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait DerefMut: [const] Deref + PointeeSized {
     /// Mutably dereferences the value.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_diagnostic_item = "deref_mut_method"]
@@ -277,7 +275,7 @@ pub trait DerefMut: [const] Deref + PointeeSized {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T: ?Sized> const DerefMut for &mut T {
     fn deref_mut(&mut self) -> &mut T {
         self
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index bbef7023207..7125bf54701 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -203,9 +203,8 @@
 /// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle
 #[lang = "drop"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
-pub trait Drop {
+pub const trait Drop {
     /// Executes the destructor for this type.
     ///
     /// This method is called implicitly when the value goes out of scope,
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index ad46e52a475..479368ba8f8 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -72,9 +72,8 @@ use crate::marker::Tuple;
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-pub trait Fn<Args: Tuple>: FnMut<Args> {
+pub const trait Fn<Args: Tuple>: FnMut<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
@@ -160,9 +159,8 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-pub trait FnMut<Args: Tuple>: FnOnce<Args> {
+pub const trait FnMut<Args: Tuple>: FnOnce<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
@@ -240,9 +238,8 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-pub trait FnOnce<Args: Tuple> {
+pub const trait FnOnce<Args: Tuple> {
     /// The returned type after the call operator is used.
     #[lang = "fn_once_output"]
     #[stable(feature = "fn_once_output", since = "1.12.0")]
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index 1aed2fb4742..2c62a3930c2 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -55,9 +55,8 @@
 #[doc(alias = "]")]
 #[doc(alias = "[")]
 #[doc(alias = "[]")]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-pub trait Index<Idx: ?Sized> {
+pub const trait Index<Idx: ?Sized> {
     /// The returned type after indexing.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_diagnostic_item = "IndexOutput"]
@@ -168,8 +167,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
 #[doc(alias = "]")]
 #[doc(alias = "[]")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-#[const_trait]
-pub trait IndexMut<Idx: ?Sized>: [const] Index<Idx> {
+pub const trait IndexMut<Idx: ?Sized>: [const] Index<Idx> {
     /// Performs the mutable indexing (`container[index]`) operation.
     ///
     /// # Panics
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index c0a27775694..58a9431bd84 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -836,6 +836,7 @@ pub trait RangeBounds<T: ?Sized> {
     /// assert!(!(0.0..1.0).contains(&f32::NAN));
     /// assert!(!(0.0..f32::NAN).contains(&0.5));
     /// assert!(!(f32::NAN..1.0).contains(&0.5));
+    /// ```
     #[inline]
     #[stable(feature = "range_contains", since = "1.35.0")]
     fn contains<U>(&self, item: &U) -> bool
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 76bf438878f..e1f2ebcf4c2 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -128,9 +128,8 @@ use crate::ops::ControlFlow;
 )]
 #[doc(alias = "?")]
 #[lang = "Try"]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-pub trait Try: [const] FromResidual {
+pub const trait Try: [const] FromResidual {
     /// The type of the value produced by `?` when *not* short-circuiting.
     #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
     type Output;
@@ -306,9 +305,8 @@ pub trait Try: [const] FromResidual {
 )]
 #[rustc_diagnostic_item = "FromResidual"]
 #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-pub trait FromResidual<R = <Self as Try>::Residual> {
+pub const trait FromResidual<R = <Self as Try>::Residual> {
     /// Constructs the type from a compatible `Residual` type.
     ///
     /// This should be implemented consistently with the `branch` method such
@@ -361,9 +359,8 @@ where
 /// and in the other direction,
 /// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
 #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-pub trait Residual<O> {
+pub const trait Residual<O> {
     /// The "return" type of this meta-function.
     #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
     type TryType: Try<Output = O, Residual = Self>;
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index fa09409b6da..198636c67d0 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1379,11 +1379,12 @@ impl<T> Option<T> {
     /// ```
     #[inline]
     #[stable(feature = "option_deref", since = "1.40.0")]
-    pub fn as_deref(&self) -> Option<&T::Target>
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn as_deref(&self) -> Option<&T::Target>
     where
-        T: Deref,
+        T: [const] Deref,
     {
-        self.as_ref().map(|t| t.deref())
+        self.as_ref().map(Deref::deref)
     }
 
     /// Converts from `Option<T>` (or `&mut Option<T>`) to `Option<&mut T::Target>`.
@@ -1402,11 +1403,12 @@ impl<T> Option<T> {
     /// ```
     #[inline]
     #[stable(feature = "option_deref", since = "1.40.0")]
-    pub fn as_deref_mut(&mut self) -> Option<&mut T::Target>
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn as_deref_mut(&mut self) -> Option<&mut T::Target>
     where
-        T: DerefMut,
+        T: [const] DerefMut,
     {
-        self.as_mut().map(|t| t.deref_mut())
+        self.as_mut().map(DerefMut::deref_mut)
     }
 
     /////////////////////////////////////////////////////////////////////////
@@ -1638,7 +1640,7 @@ impl<T> Option<T> {
     pub const fn or_else<F>(self, f: F) -> Option<T>
     where
         F: [const] FnOnce() -> Option<T> + [const] Destruct,
-        //FIXME(const_hack): this `T: ~const Destruct` is unnecessary, but even precise live drops can't tell
+        //FIXME(const_hack): this `T: [const] Destruct` is unnecessary, but even precise live drops can't tell
         // no value of type `T` gets dropped here
         T: [const] Destruct,
     {
@@ -2180,10 +2182,10 @@ const fn expect_failed(msg: &str) -> ! {
 /////////////////////////////////////////////////////////////////////////////
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
 impl<T> const Clone for Option<T>
 where
-    // FIXME(const_hack): the T: ~const Destruct should be inferred from the Self: ~const Destruct in clone_from.
+    // FIXME(const_hack): the T: [const] Destruct should be inferred from the Self: [const] Destruct in clone_from.
     // See https://github.com/rust-lang/rust/issues/144207
     T: [const] Clone + [const] Destruct,
 {
@@ -2269,7 +2271,7 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
 }
 
 #[stable(since = "1.12.0", feature = "option_from")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const From<T> for Option<T> {
     /// Moves `val` into a new [`Some`].
     ///
@@ -2286,7 +2288,7 @@ impl<T> const From<T> for Option<T> {
 }
 
 #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<'a, T> const From<&'a Option<T>> for Option<&'a T> {
     /// Converts from `&Option<T>` to `Option<&T>`.
     ///
@@ -2314,7 +2316,7 @@ impl<'a, T> const From<&'a Option<T>> for Option<&'a T> {
 }
 
 #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<'a, T> const From<&'a mut Option<T>> for Option<&'a mut T> {
     /// Converts from `&mut Option<T>` to `Option<&mut T>`
     ///
diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs
index a60f0799c0e..722af551038 100644
--- a/library/core/src/panic/unwind_safe.rs
+++ b/library/core/src/panic/unwind_safe.rs
@@ -248,7 +248,8 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicBool {}
 impl<T> RefUnwindSafe for crate::sync::atomic::AtomicPtr<T> {}
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
-impl<T> Deref for AssertUnwindSafe<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const Deref for AssertUnwindSafe<T> {
     type Target = T;
 
     fn deref(&self) -> &T {
@@ -257,7 +258,8 @@ impl<T> Deref for AssertUnwindSafe<T> {
 }
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
-impl<T> DerefMut for AssertUnwindSafe<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const DerefMut for AssertUnwindSafe<T> {
     fn deref_mut(&mut self) -> &mut T {
         &mut self.0
     }
diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs
index 91d015b1bc5..a13eea3fb58 100644
--- a/library/core/src/pat.rs
+++ b/library/core/src/pat.rs
@@ -18,12 +18,11 @@ macro_rules! pattern_type {
 /// used right now to simplify ast lowering of pattern type ranges.
 #[unstable(feature = "pattern_type_range_trait", issue = "123646")]
 #[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
-#[const_trait]
 #[diagnostic::on_unimplemented(
     message = "`{Self}` is not a valid base type for range patterns",
     label = "only integer types and `char` are supported"
 )]
-pub trait RangePattern {
+pub const trait RangePattern {
     /// Trait version of the inherent `MIN` assoc const.
     #[lang = "RangeMin"]
     const MIN: Self;
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 14bf7ba9015..535830f2e74 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1359,7 +1359,11 @@ impl<Ptr: Deref> Pin<Ptr> {
     /// ruled out by the contract of `Pin::new_unchecked`.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn as_ref(&self) -> Pin<&Ptr::Target> {
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn as_ref(&self) -> Pin<&Ptr::Target>
+    where
+        Ptr: [const] Deref,
+    {
         // SAFETY: see documentation on this function
         unsafe { Pin::new_unchecked(&*self.pointer) }
     }
@@ -1403,7 +1407,11 @@ impl<Ptr: DerefMut> Pin<Ptr> {
     /// ```
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn as_mut(&mut self) -> Pin<&mut Ptr::Target>
+    where
+        Ptr: [const] DerefMut,
+    {
         // SAFETY: see documentation on this function
         unsafe { Pin::new_unchecked(&mut *self.pointer) }
     }
@@ -1418,7 +1426,11 @@ impl<Ptr: DerefMut> Pin<Ptr> {
     #[stable(feature = "pin_deref_mut", since = "1.84.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline(always)]
-    pub fn as_deref_mut(self: Pin<&mut Self>) -> Pin<&mut Ptr::Target> {
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn as_deref_mut(self: Pin<&mut Self>) -> Pin<&mut Ptr::Target>
+    where
+        Ptr: [const] DerefMut,
+    {
         // SAFETY: What we're asserting here is that going from
         //
         //     Pin<&mut Pin<Ptr>>
@@ -1669,7 +1681,8 @@ impl<T: ?Sized> Pin<&'static mut T> {
 }
 
 #[stable(feature = "pin", since = "1.33.0")]
-impl<Ptr: Deref> Deref for Pin<Ptr> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<Ptr: [const] Deref> const Deref for Pin<Ptr> {
     type Target = Ptr::Target;
     fn deref(&self) -> &Ptr::Target {
         Pin::get_ref(Pin::as_ref(self))
@@ -1677,7 +1690,8 @@ impl<Ptr: Deref> Deref for Pin<Ptr> {
 }
 
 #[stable(feature = "pin", since = "1.33.0")]
-impl<Ptr: DerefMut<Target: Unpin>> DerefMut for Pin<Ptr> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<Ptr: [const] DerefMut<Target: Unpin>> const DerefMut for Pin<Ptr> {
     fn deref_mut(&mut self) -> &mut Ptr::Target {
         Pin::get_mut(Pin::as_mut(self))
     }
diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs
index ede6e0d6106..ae03809b458 100644
--- a/library/core/src/pin/unsafe_pinned.rs
+++ b/library/core/src/pin/unsafe_pinned.rs
@@ -148,7 +148,8 @@ impl<T: Default> Default for UnsafePinned<T> {
 }
 
 #[unstable(feature = "unsafe_pinned", issue = "125735")]
-impl<T> From<T> for UnsafePinned<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for UnsafePinned<T> {
     /// Creates a new `UnsafePinned<T>` containing the given value.
     fn from(value: T) -> Self {
         UnsafePinned::new(value)
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index 402634e49b3..bc7d3a1de71 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -171,7 +171,8 @@ impl fmt::Debug for Alignment {
 }
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
-impl TryFrom<NonZero<usize>> for Alignment {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const TryFrom<NonZero<usize>> for Alignment {
     type Error = num::TryFromIntError;
 
     #[inline]
@@ -181,7 +182,8 @@ impl TryFrom<NonZero<usize>> for Alignment {
 }
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
-impl TryFrom<usize> for Alignment {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const TryFrom<usize> for Alignment {
     type Error = num::TryFromIntError;
 
     #[inline]
@@ -191,7 +193,7 @@ impl TryFrom<usize> for Alignment {
 }
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Alignment> for NonZero<usize> {
     #[inline]
     fn from(align: Alignment) -> NonZero<usize> {
@@ -200,7 +202,7 @@ impl const From<Alignment> for NonZero<usize> {
 }
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<Alignment> for usize {
     #[inline]
     fn from(align: Alignment) -> usize {
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 3fe4b08d459..ce6eee4f911 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -106,6 +106,7 @@ impl<T: PointeeSized> *mut T {
     ///
     /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
     /// println!("{:?}", unsafe { &*bad });
+    /// ```
     #[unstable(feature = "set_ptr_value", issue = "75091")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[inline]
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 117eb18826e..10f83120428 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1711,7 +1711,8 @@ impl<T: PointeeSized> hash::Hash for NonNull<T> {
 }
 
 #[unstable(feature = "ptr_internals", issue = "none")]
-impl<T: PointeeSized> From<Unique<T>> for NonNull<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: PointeeSized> const From<Unique<T>> for NonNull<T> {
     #[inline]
     fn from(unique: Unique<T>) -> Self {
         unique.as_non_null_ptr()
@@ -1719,7 +1720,8 @@ impl<T: PointeeSized> From<Unique<T>> for NonNull<T> {
 }
 
 #[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: PointeeSized> From<&mut T> for NonNull<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: PointeeSized> const From<&mut T> for NonNull<T> {
     /// Converts a `&mut T` to a `NonNull<T>`.
     ///
     /// This conversion is safe and infallible since references cannot be null.
@@ -1730,7 +1732,8 @@ impl<T: PointeeSized> From<&mut T> for NonNull<T> {
 }
 
 #[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: PointeeSized> From<&T> for NonNull<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: PointeeSized> const From<&T> for NonNull<T> {
     /// Converts a `&T` to a `NonNull<T>`.
     ///
     /// This conversion is safe and infallible since references cannot be null.
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index 4302c1b1e44..cdc8b6cc936 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -189,7 +189,8 @@ impl<T: PointeeSized> fmt::Pointer for Unique<T> {
 }
 
 #[unstable(feature = "ptr_internals", issue = "none")]
-impl<T: PointeeSized> From<&mut T> for Unique<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: PointeeSized> const From<&mut T> for Unique<T> {
     /// Converts a `&mut T` to a `Unique<T>`.
     ///
     /// This conversion is infallible since references cannot be null.
@@ -200,7 +201,8 @@ impl<T: PointeeSized> From<&mut T> for Unique<T> {
 }
 
 #[unstable(feature = "ptr_internals", issue = "none")]
-impl<T: PointeeSized> From<NonNull<T>> for Unique<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T: PointeeSized> const From<NonNull<T>> for Unique<T> {
     /// Converts a `NonNull<T>` to a `Unique<T>`.
     ///
     /// This conversion is infallible since `NonNull` cannot be null.
diff --git a/library/core/src/range.rs b/library/core/src/range.rs
index 7158fa0fcf0..332ae51d848 100644
--- a/library/core/src/range.rs
+++ b/library/core/src/range.rs
@@ -192,7 +192,7 @@ impl<T> IntoBounds<T> for Range<T> {
 }
 
 #[unstable(feature = "new_range_api", issue = "125687")]
-#[rustc_const_unstable(feature = "const_index", issue = "143775")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const From<Range<T>> for legacy::Range<T> {
     #[inline]
     fn from(value: Range<T>) -> Self {
@@ -201,7 +201,7 @@ impl<T> const From<Range<T>> for legacy::Range<T> {
 }
 
 #[unstable(feature = "new_range_api", issue = "125687")]
-#[rustc_const_unstable(feature = "const_index", issue = "143775")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const From<legacy::Range<T>> for Range<T> {
     #[inline]
     fn from(value: legacy::Range<T>) -> Self {
@@ -377,7 +377,7 @@ impl<T> IntoBounds<T> for RangeInclusive<T> {
 }
 
 #[unstable(feature = "new_range_api", issue = "125687")]
-#[rustc_const_unstable(feature = "const_index", issue = "143775")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
     #[inline]
     fn from(value: RangeInclusive<T>) -> Self {
@@ -385,7 +385,8 @@ impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
     }
 }
 #[unstable(feature = "new_range_api", issue = "125687")]
-impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
     #[inline]
     fn from(value: legacy::RangeInclusive<T>) -> Self {
         assert!(
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 6148bdb866a..7dffab9b316 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1034,11 +1034,12 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "inner_deref", since = "1.47.0")]
-    pub fn as_deref(&self) -> Result<&T::Target, &E>
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn as_deref(&self) -> Result<&T::Target, &E>
     where
-        T: Deref,
+        T: [const] Deref,
     {
-        self.as_ref().map(|t| t.deref())
+        self.as_ref().map(Deref::deref)
     }
 
     /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut <T as DerefMut>::Target, &mut E>`.
@@ -1061,11 +1062,12 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "inner_deref", since = "1.47.0")]
-    pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E>
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+    pub const fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E>
     where
-        T: DerefMut,
+        T: [const] DerefMut,
     {
-        self.as_mut().map(|t| t.deref_mut())
+        self.as_mut().map(DerefMut::deref_mut)
     }
 
     /////////////////////////////////////////////////////////////////////////
@@ -1347,7 +1349,7 @@ impl<T, E> Result<T, E> {
     #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
     #[inline]
     #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
-    #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
     pub const fn into_ok(self) -> T
     where
         E: [const] Into<!>,
@@ -1384,7 +1386,7 @@ impl<T, E> Result<T, E> {
     #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
     #[inline]
     #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
-    #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
     pub const fn into_err(self) -> E
     where
         T: [const] Into<!>,
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index 68bd12aa7bf..0d801306984 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -95,9 +95,8 @@ impl<T: PartialOrd> PartialOrd for [T] {
 
 #[doc(hidden)]
 // intermediate trait for specialization of slice's PartialEq
-#[const_trait]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-trait SlicePartialEq<B> {
+const trait SlicePartialEq<B> {
     fn equal(&self, other: &[B]) -> bool;
 
     fn not_equal(&self, other: &[B]) -> bool {
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 98091e9fe83..8e1bc0bae70 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -151,7 +151,7 @@ mod private_slice_index {
     message = "the type `{T}` cannot be indexed by `{Self}`",
     label = "slice indices are of type `usize` or ranges of `usize`"
 )]
-#[const_trait]
+#[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed.
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
 pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
     /// The output type returned by methods.
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index f1db385e212..04fdaa8143e 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -3078,7 +3078,8 @@ impl str {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl AsRef<[u8]> for str {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsRef<[u8]> for str {
     #[inline]
     fn as_ref(&self) -> &[u8] {
         self.as_bytes()
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index dc88f35eca7..4f228edf78e 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -825,9 +825,8 @@ unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
 /// assert!(Point::from_str("(1 2)").is_err());
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[const_trait]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
-pub trait FromStr: Sized {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+pub const trait FromStr: Sized {
     /// The associated error which can be returned from parsing.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Err;
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 7bd68bcd0bc..1b4a54b1b7a 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2516,7 +2516,7 @@ impl<T> AtomicPtr<T> {
 
 #[cfg(target_has_atomic_load_store = "8")]
 #[stable(feature = "atomic_bool_from", since = "1.24.0")]
-#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 impl const From<bool> for AtomicBool {
     /// Converts a `bool` into an `AtomicBool`.
     ///
@@ -2535,7 +2535,8 @@ impl const From<bool> for AtomicBool {
 
 #[cfg(target_has_atomic_load_store = "ptr")]
 #[stable(feature = "atomic_from", since = "1.23.0")]
-impl<T> From<*mut T> for AtomicPtr<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<*mut T> for AtomicPtr<T> {
     /// Converts a `*mut T` into an `AtomicPtr<T>`.
     #[inline]
     fn from(p: *mut T) -> Self {
@@ -2614,7 +2615,7 @@ macro_rules! atomic_int {
         }
 
         #[$stable_from]
-        #[rustc_const_unstable(feature = "const_try", issue = "74935")]
+        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
         impl const From<$int_type> for $atomic_type {
             #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
             #[inline]
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index 340b0b79e40..cf086bf4f50 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -163,7 +163,8 @@ impl<T: ?Sized> Exclusive<T> {
 }
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
-impl<T> From<T> for Exclusive<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for Exclusive<T> {
     #[inline]
     fn from(t: T) -> Self {
         Self::new(t)
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 59ffe7ad49c..380abac0ae9 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -215,7 +215,8 @@ impl<T, E> Poll<Option<Result<T, E>>> {
 }
 
 #[stable(feature = "futures_api", since = "1.36.0")]
-impl<T> From<T> for Poll<T> {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl<T> const From<T> for Poll<T> {
     /// Moves the value into a [`Poll::Ready`] to make a `Poll<T>`.
     ///
     /// # Example
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index bb7efe582f7..97eb9ec7dc5 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -901,7 +901,8 @@ impl Clone for LocalWaker {
 }
 
 #[unstable(feature = "local_waker", issue = "118959")]
-impl AsRef<LocalWaker> for Waker {
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsRef<LocalWaker> for Waker {
     fn as_ref(&self) -> &LocalWaker {
         // SAFETY: LocalWaker is just Waker without thread safety
         unsafe { transmute(self) }
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 23a0a6877df..2cdee1803a9 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -133,6 +133,7 @@ macro_rules! tuple_impls {
         maybe_tuple_doc! {
             $($T)+ @
             #[stable(feature = "array_tuple_conv", since = "1.71.0")]
+            // can't do const From due to https://github.com/rust-lang/rust/issues/144280
             impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) {
                 #[inline]
                 #[allow(non_snake_case)]
@@ -146,6 +147,7 @@ macro_rules! tuple_impls {
         maybe_tuple_doc! {
             $($T)+ @
             #[stable(feature = "array_tuple_conv", since = "1.71.0")]
+            // can't do const From due to https://github.com/rust-lang/rust/issues/144280
             impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] {
                 #[inline]
                 #[allow(non_snake_case)]
diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs
index 55f64f1e96e..2f53de183f6 100644
--- a/library/core/src/unicode/unicode_data.rs
+++ b/library/core/src/unicode/unicode_data.rs
@@ -1,4 +1,15 @@
-///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!
+//! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!
+// Alphabetic      :  1723 bytes, 142707 codepoints in 755 ranges (U+0000AA - U+0323B0) using skiplist
+// Case_Ignorable  :  1043 bytes,   2744 codepoints in 447 ranges (U+0000A8 - U+0E01F0) using skiplist
+// Cased           :   403 bytes,   4526 codepoints in 157 ranges (U+0000AA - U+01F18A) using skiplist
+// Grapheme_Extend :   887 bytes,   2193 codepoints in 375 ranges (U+000300 - U+0E01F0) using skiplist
+// Lowercase       :   933 bytes,   2543 codepoints in 674 ranges (U+0000AA - U+01E944) using bitset
+// N               :   455 bytes,   1901 codepoints in 143 ranges (U+0000B2 - U+01FBFA) using skiplist
+// Uppercase       :   797 bytes,   1952 codepoints in 655 ranges (U+0000C0 - U+01F18A) using bitset
+// White_Space     :   256 bytes,     19 codepoints in   8 ranges (U+000085 - U+003001) using cascading
+// to_lower        : 11484 bytes
+// to_upper        : 13432 bytes
+// Total           : 31413 bytes
 
 #[inline(always)]
 const fn bitset_search<
@@ -136,93 +147,100 @@ pub mod alphabetic {
     use super::ShortOffsetRunHeader;
 
     static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 53] = [
-        ShortOffsetRunHeader::new(0, 706), ShortOffsetRunHeader::new(16, 4681),
-        ShortOffsetRunHeader::new(418, 5741), ShortOffsetRunHeader::new(456, 7958),
-        ShortOffsetRunHeader::new(556, 9398), ShortOffsetRunHeader::new(627, 11264),
-        ShortOffsetRunHeader::new(629, 12293), ShortOffsetRunHeader::new(667, 13312),
-        ShortOffsetRunHeader::new(691, 19904), ShortOffsetRunHeader::new(692, 42125),
-        ShortOffsetRunHeader::new(694, 42509), ShortOffsetRunHeader::new(698, 55204),
-        ShortOffsetRunHeader::new(788, 63744), ShortOffsetRunHeader::new(793, 64110),
-        ShortOffsetRunHeader::new(794, 64830), ShortOffsetRunHeader::new(816, 66176),
-        ShortOffsetRunHeader::new(857, 67383), ShortOffsetRunHeader::new(904, 73440),
-        ShortOffsetRunHeader::new(1221, 74650), ShortOffsetRunHeader::new(1232, 77712),
-        ShortOffsetRunHeader::new(1237, 78896), ShortOffsetRunHeader::new(1240, 82939),
-        ShortOffsetRunHeader::new(1244, 83527), ShortOffsetRunHeader::new(1246, 90368),
-        ShortOffsetRunHeader::new(1247, 92160), ShortOffsetRunHeader::new(1249, 92729),
-        ShortOffsetRunHeader::new(1250, 93504), ShortOffsetRunHeader::new(1265, 100344),
-        ShortOffsetRunHeader::new(1282, 101590), ShortOffsetRunHeader::new(1284, 110576),
-        ShortOffsetRunHeader::new(1287, 110883), ShortOffsetRunHeader::new(1294, 111356),
-        ShortOffsetRunHeader::new(1304, 113664), ShortOffsetRunHeader::new(1305, 119808),
-        ShortOffsetRunHeader::new(1315, 120486), ShortOffsetRunHeader::new(1352, 122624),
-        ShortOffsetRunHeader::new(1375, 123536), ShortOffsetRunHeader::new(1399, 124112),
-        ShortOffsetRunHeader::new(1403, 124896), ShortOffsetRunHeader::new(1409, 126464),
-        ShortOffsetRunHeader::new(1425, 127280), ShortOffsetRunHeader::new(1491, 131072),
-        ShortOffsetRunHeader::new(1497, 173792), ShortOffsetRunHeader::new(1498, 177978),
-        ShortOffsetRunHeader::new(1500, 183970), ShortOffsetRunHeader::new(1504, 191457),
-        ShortOffsetRunHeader::new(1506, 192094), ShortOffsetRunHeader::new(1508, 194560),
-        ShortOffsetRunHeader::new(1509, 195102), ShortOffsetRunHeader::new(1510, 196608),
-        ShortOffsetRunHeader::new(1511, 201547), ShortOffsetRunHeader::new(1512, 205744),
-        ShortOffsetRunHeader::new(1514, 1319856),
+        ShortOffsetRunHeader::new(0, 706), ShortOffsetRunHeader::new(12, 4681),
+        ShortOffsetRunHeader::new(414, 5741), ShortOffsetRunHeader::new(452, 7958),
+        ShortOffsetRunHeader::new(552, 9398), ShortOffsetRunHeader::new(623, 11264),
+        ShortOffsetRunHeader::new(625, 12293), ShortOffsetRunHeader::new(663, 13312),
+        ShortOffsetRunHeader::new(687, 19904), ShortOffsetRunHeader::new(688, 42125),
+        ShortOffsetRunHeader::new(690, 42509), ShortOffsetRunHeader::new(694, 55204),
+        ShortOffsetRunHeader::new(784, 63744), ShortOffsetRunHeader::new(789, 64110),
+        ShortOffsetRunHeader::new(790, 64830), ShortOffsetRunHeader::new(812, 66176),
+        ShortOffsetRunHeader::new(853, 67383), ShortOffsetRunHeader::new(900, 73440),
+        ShortOffsetRunHeader::new(1217, 74650), ShortOffsetRunHeader::new(1228, 77712),
+        ShortOffsetRunHeader::new(1233, 78896), ShortOffsetRunHeader::new(1236, 82939),
+        ShortOffsetRunHeader::new(1240, 83527), ShortOffsetRunHeader::new(1242, 90368),
+        ShortOffsetRunHeader::new(1243, 92160), ShortOffsetRunHeader::new(1245, 92729),
+        ShortOffsetRunHeader::new(1246, 93504), ShortOffsetRunHeader::new(1261, 100344),
+        ShortOffsetRunHeader::new(1278, 101590), ShortOffsetRunHeader::new(1280, 110576),
+        ShortOffsetRunHeader::new(1283, 110883), ShortOffsetRunHeader::new(1290, 111356),
+        ShortOffsetRunHeader::new(1300, 113664), ShortOffsetRunHeader::new(1301, 119808),
+        ShortOffsetRunHeader::new(1311, 120486), ShortOffsetRunHeader::new(1348, 122624),
+        ShortOffsetRunHeader::new(1371, 123536), ShortOffsetRunHeader::new(1395, 124112),
+        ShortOffsetRunHeader::new(1399, 124896), ShortOffsetRunHeader::new(1405, 126464),
+        ShortOffsetRunHeader::new(1421, 127280), ShortOffsetRunHeader::new(1487, 131072),
+        ShortOffsetRunHeader::new(1493, 173792), ShortOffsetRunHeader::new(1494, 177978),
+        ShortOffsetRunHeader::new(1496, 183970), ShortOffsetRunHeader::new(1500, 191457),
+        ShortOffsetRunHeader::new(1502, 192094), ShortOffsetRunHeader::new(1504, 194560),
+        ShortOffsetRunHeader::new(1505, 195102), ShortOffsetRunHeader::new(1506, 196608),
+        ShortOffsetRunHeader::new(1507, 201547), ShortOffsetRunHeader::new(1508, 205744),
+        ShortOffsetRunHeader::new(1510, 1319856),
     ];
-    static OFFSETS: [u8; 1515] = [
-        65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29,
-        18, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41,
-        39, 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3,
-        10, 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6,
-        8, 1, 8, 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1,
-        3, 4, 3, 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7,
-        1, 2, 1, 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7,
-        1, 2, 1, 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5,
-        3, 8, 2, 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2,
-        3, 3, 3, 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8,
-        2, 1, 3, 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1,
-        4, 13, 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3,
-        24, 1, 9, 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24,
-        1, 1, 1, 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67,
-        55, 1, 1, 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2,
-        41, 1, 4, 2, 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3,
-        0, 2, 17, 1, 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14,
-        1, 4, 1, 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4,
-        63, 2, 20, 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55,
-        22, 3, 10, 36, 2, 11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2,
-        38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13,
-        5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4,
-        1, 11, 2, 4, 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1,
-        16, 23, 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2,
-        5, 4, 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16,
-        10, 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 67, 2, 2, 1, 1, 1, 8, 21, 20, 1, 33, 24, 52,
-        12, 68, 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5,
-        1, 55, 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7,
-        1, 43, 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5,
-        1, 1, 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11,
-        89, 3, 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0,
-        29, 3, 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40,
-        8, 52, 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24,
-        6, 1, 42, 1, 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22,
-        10, 26, 70, 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54,
-        10, 22, 10, 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2,
-        3, 2, 16, 3, 55, 1, 3, 29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1,
-        13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6,
-        4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8,
-        2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3,
-        1, 1, 1, 44, 66, 1, 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1,
-        3, 1, 59, 54, 2, 1, 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30,
-        1, 2, 2, 2, 2, 4, 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 199,
-        33, 31, 9, 1, 45, 1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1,
-        1, 2, 2, 24, 6, 1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0,
-        102, 111, 17, 196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18,
-        48, 16, 4, 31, 21, 5, 19, 0, 45, 211, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0,
-        8, 0, 41, 10, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9,
-        7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1,
-        7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1,
-        25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45,
-        10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68,
-        3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1,
-        1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1,
-        10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, 0, 6, 222, 2, 0, 14, 0, 15, 0,
-        0, 0, 0, 0, 5, 0, 0,
+    static OFFSETS: [u8; 1511] = [
+        170, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, 18, 1, 2, 2,
+        4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39, 14, 1, 1,
+        1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10, 3, 2, 1,
+        16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, 8, 1, 8, 42,
+        10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, 3, 4, 3, 8,
+        2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, 2,
+        1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1, 5,
+        3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2,
+        2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3, 12,
+        4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, 1, 3, 2,
+        1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, 4, 13, 3,
+        12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, 1, 9, 1,
+        1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, 1, 1, 19,
+        1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, 55, 1, 1, 2, 5,
+        16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2, 33,
+        1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, 17, 1, 26,
+        5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, 1, 67, 89,
+        7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, 20, 50, 1,
+        23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, 10, 36, 2,
+        11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2, 38, 2, 6, 2, 8, 1,
+        1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116, 1,
+        13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, 4, 5, 5,
+        4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23, 9, 7, 1,
+        7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4, 86, 6, 3,
+        1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10, 2, 20, 47,
+        5, 8, 3, 113, 39, 9, 2, 103, 2, 67, 2, 2, 1, 1, 1, 8, 21, 20, 1, 33, 24, 52, 12, 68, 1, 1,
+        44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1, 55, 9, 14,
+        18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 43, 1, 14,
+        6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1, 1, 1, 2, 1,
+        2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89, 3, 6, 2, 6,
+        2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3, 49, 47, 32,
+        13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, 8, 52, 12, 11, 1,
+        15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, 6, 1, 42, 1, 9,
+        69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, 10, 26, 70, 56,
+        6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, 10, 22, 10, 19,
+        13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2, 3, 2, 16, 3,
+        55, 1, 3, 29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, 13, 25, 23,
+        51, 17, 4, 8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 4, 62, 7, 1,
+        1, 1, 4, 1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2,
+        3, 1, 6, 1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3, 1, 1, 1, 44,
+        66, 1, 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54,
+        2, 1, 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2,
+        4, 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 199, 33, 31, 9, 1,
+        45, 1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24,
+        6, 1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, 102, 111, 17,
+        196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18, 48, 16, 4,
+        31, 21, 5, 19, 0, 45, 211, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, 8, 0, 41,
+        10, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, 7, 10, 4,
+        1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28,
+        1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31,
+        1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, 10, 7, 16,
+        1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1,
+        0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2,
+        1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17,
+        5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, 0, 6, 222, 2, 0, 14, 0, 15, 0, 0, 0, 0, 0,
+        5, 0, 0,
     ];
+    #[inline]
     pub fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
+        (c as u32) >= 0xaa && lookup_slow(c)
+    }
+
+    #[inline(never)]
+    fn lookup_slow(c: char) -> bool {
         const {
             assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
             let mut i = 0;
@@ -242,62 +260,69 @@ pub mod case_ignorable {
     use super::ShortOffsetRunHeader;
 
     static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 37] = [
-        ShortOffsetRunHeader::new(0, 688), ShortOffsetRunHeader::new(21, 4957),
-        ShortOffsetRunHeader::new(273, 5906), ShortOffsetRunHeader::new(275, 8125),
-        ShortOffsetRunHeader::new(385, 11388), ShortOffsetRunHeader::new(419, 12293),
-        ShortOffsetRunHeader::new(431, 40981), ShortOffsetRunHeader::new(443, 42232),
-        ShortOffsetRunHeader::new(445, 42508), ShortOffsetRunHeader::new(447, 64286),
-        ShortOffsetRunHeader::new(543, 65024), ShortOffsetRunHeader::new(547, 66045),
-        ShortOffsetRunHeader::new(577, 67456), ShortOffsetRunHeader::new(583, 68097),
-        ShortOffsetRunHeader::new(589, 68900), ShortOffsetRunHeader::new(601, 69291),
-        ShortOffsetRunHeader::new(609, 71727), ShortOffsetRunHeader::new(733, 71995),
-        ShortOffsetRunHeader::new(737, 72752), ShortOffsetRunHeader::new(765, 73459),
-        ShortOffsetRunHeader::new(795, 78896), ShortOffsetRunHeader::new(807, 90398),
-        ShortOffsetRunHeader::new(811, 92912), ShortOffsetRunHeader::new(815, 93504),
-        ShortOffsetRunHeader::new(821, 94031), ShortOffsetRunHeader::new(825, 110576),
-        ShortOffsetRunHeader::new(833, 113821), ShortOffsetRunHeader::new(839, 118528),
-        ShortOffsetRunHeader::new(843, 119143), ShortOffsetRunHeader::new(847, 121344),
-        ShortOffsetRunHeader::new(857, 122880), ShortOffsetRunHeader::new(869, 123566),
-        ShortOffsetRunHeader::new(885, 124139), ShortOffsetRunHeader::new(889, 125136),
-        ShortOffsetRunHeader::new(893, 127995), ShortOffsetRunHeader::new(897, 917505),
-        ShortOffsetRunHeader::new(899, 2032112),
+        ShortOffsetRunHeader::new(0, 688), ShortOffsetRunHeader::new(11, 4957),
+        ShortOffsetRunHeader::new(263, 5906), ShortOffsetRunHeader::new(265, 8125),
+        ShortOffsetRunHeader::new(375, 11388), ShortOffsetRunHeader::new(409, 12293),
+        ShortOffsetRunHeader::new(421, 40981), ShortOffsetRunHeader::new(433, 42232),
+        ShortOffsetRunHeader::new(435, 42508), ShortOffsetRunHeader::new(437, 64286),
+        ShortOffsetRunHeader::new(533, 65024), ShortOffsetRunHeader::new(537, 66045),
+        ShortOffsetRunHeader::new(567, 67456), ShortOffsetRunHeader::new(573, 68097),
+        ShortOffsetRunHeader::new(579, 68900), ShortOffsetRunHeader::new(591, 69291),
+        ShortOffsetRunHeader::new(599, 71727), ShortOffsetRunHeader::new(723, 71995),
+        ShortOffsetRunHeader::new(727, 72752), ShortOffsetRunHeader::new(755, 73459),
+        ShortOffsetRunHeader::new(785, 78896), ShortOffsetRunHeader::new(797, 90398),
+        ShortOffsetRunHeader::new(801, 92912), ShortOffsetRunHeader::new(805, 93504),
+        ShortOffsetRunHeader::new(811, 94031), ShortOffsetRunHeader::new(815, 110576),
+        ShortOffsetRunHeader::new(823, 113821), ShortOffsetRunHeader::new(829, 118528),
+        ShortOffsetRunHeader::new(833, 119143), ShortOffsetRunHeader::new(837, 121344),
+        ShortOffsetRunHeader::new(847, 122880), ShortOffsetRunHeader::new(859, 123566),
+        ShortOffsetRunHeader::new(875, 124139), ShortOffsetRunHeader::new(879, 125136),
+        ShortOffsetRunHeader::new(883, 127995), ShortOffsetRunHeader::new(887, 917505),
+        ShortOffsetRunHeader::new(889, 2032112),
     ];
-    static OFFSETS: [u8; 905] = [
-        39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2,
-        1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35,
-        1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24,
-        24, 43, 3, 44, 1, 7, 2, 5, 9, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1,
-        58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2,
-        57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1,
-        61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1,
-        5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1, 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9,
-        98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1,
-        102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3,
-        29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118,
-        3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31,
-        49, 4, 48, 1, 1, 5, 1, 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3,
-        58, 8, 2, 2, 64, 6, 82, 3, 1, 13, 1, 7, 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1,
-        3, 11, 3, 13, 3, 13, 3, 13, 2, 12, 5, 8, 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1,
-        16, 13, 51, 33, 0, 2, 113, 3, 125, 1, 15, 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6,
-        93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10, 1, 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 103, 3, 3,
-        2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4,
-        2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2,
-        1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3,
-        1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3,
-        0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1,
-        26, 5, 1, 1, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2,
-        1, 4, 1, 10, 1, 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6,
-        1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85,
-        8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2,
-        106, 1, 1, 1, 2, 6, 1, 1, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2,
-        2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2,
-        7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1,
-        1, 1, 23, 1, 0, 17, 6, 15, 0, 12, 3, 3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2,
-        1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55,
-        4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14, 0,
-        1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0,
+    static OFFSETS: [u8; 895] = [
+        168, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, 1, 1, 251, 7, 207, 1, 5, 1, 49,
+        45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, 1, 10, 21, 16, 1, 101, 8, 1, 10,
+        1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, 24, 43, 3, 44, 1, 7, 2, 5, 9, 41,
+        58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2,
+        2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6,
+        1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3,
+        5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, 5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1,
+        20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9, 98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1,
+        1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3,
+        16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3, 29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1,
+        2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118, 3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58,
+        1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31, 49, 4, 48, 1, 1, 5, 1, 1, 5, 1, 40, 9,
+        12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 64, 6, 82, 3, 1, 13, 1, 7,
+        4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1, 3, 11, 3, 13, 3, 13, 3, 13, 2, 12, 5, 8,
+        2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1, 16, 13, 51, 33, 0, 2, 113, 3, 125, 1, 15,
+        1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6, 93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10, 1,
+        1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 103, 3, 3, 2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2,
+        26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4, 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12,
+        1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9,
+        3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1,
+        11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0,
+        3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1, 26, 5, 1, 1, 0, 2, 79, 4, 70, 11, 49, 4,
+        123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1, 50, 3, 36, 5, 1, 8, 62,
+        1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 3,
+        1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4,
+        2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 1, 1,
+        1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1,
+        9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1,
+        7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 23, 1, 0, 17, 6, 15, 0, 12, 3,
+        3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4,
+        0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0,
+        7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14, 0, 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8,
+        0, 5, 0, 1, 30, 96, 128, 240, 0,
     ];
+    #[inline]
     pub fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
+        (c as u32) >= 0xa8 && lookup_slow(c)
+    }
+
+    #[inline(never)]
+    fn lookup_slow(c: char) -> bool {
         const {
             assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
             let mut i = 0;
@@ -317,33 +342,40 @@ pub mod cased {
     use super::ShortOffsetRunHeader;
 
     static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 22] = [
-        ShortOffsetRunHeader::new(0, 4256), ShortOffsetRunHeader::new(55, 5024),
-        ShortOffsetRunHeader::new(65, 7296), ShortOffsetRunHeader::new(69, 7958),
-        ShortOffsetRunHeader::new(78, 9398), ShortOffsetRunHeader::new(153, 11264),
-        ShortOffsetRunHeader::new(155, 42560), ShortOffsetRunHeader::new(167, 43824),
-        ShortOffsetRunHeader::new(187, 64256), ShortOffsetRunHeader::new(193, 65313),
-        ShortOffsetRunHeader::new(197, 66560), ShortOffsetRunHeader::new(201, 67456),
-        ShortOffsetRunHeader::new(223, 68736), ShortOffsetRunHeader::new(231, 71840),
-        ShortOffsetRunHeader::new(239, 93760), ShortOffsetRunHeader::new(241, 119808),
-        ShortOffsetRunHeader::new(243, 120486), ShortOffsetRunHeader::new(280, 122624),
-        ShortOffsetRunHeader::new(303, 122928), ShortOffsetRunHeader::new(309, 125184),
-        ShortOffsetRunHeader::new(311, 127280), ShortOffsetRunHeader::new(313, 1241482),
+        ShortOffsetRunHeader::new(0, 4256), ShortOffsetRunHeader::new(51, 5024),
+        ShortOffsetRunHeader::new(61, 7296), ShortOffsetRunHeader::new(65, 7958),
+        ShortOffsetRunHeader::new(74, 9398), ShortOffsetRunHeader::new(149, 11264),
+        ShortOffsetRunHeader::new(151, 42560), ShortOffsetRunHeader::new(163, 43824),
+        ShortOffsetRunHeader::new(183, 64256), ShortOffsetRunHeader::new(189, 65313),
+        ShortOffsetRunHeader::new(193, 66560), ShortOffsetRunHeader::new(197, 67456),
+        ShortOffsetRunHeader::new(219, 68736), ShortOffsetRunHeader::new(227, 71840),
+        ShortOffsetRunHeader::new(235, 93760), ShortOffsetRunHeader::new(237, 119808),
+        ShortOffsetRunHeader::new(239, 120486), ShortOffsetRunHeader::new(276, 122624),
+        ShortOffsetRunHeader::new(299, 122928), ShortOffsetRunHeader::new(305, 125184),
+        ShortOffsetRunHeader::new(307, 127280), ShortOffsetRunHeader::new(309, 1241482),
     ];
-    static OFFSETS: [u8; 319] = [
-        65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5,
-        96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9,
-        41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6,
-        2, 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4,
-        13, 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1,
-        4, 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5,
-        1, 0, 46, 18, 30, 132, 102, 3, 4, 1, 62, 2, 2, 1, 1, 1, 8, 21, 5, 1, 3, 0, 43, 1, 14, 6, 80,
-        0, 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15,
-        1, 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 0, 85, 1,
-        71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5,
-        1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1,
-        8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0,
+    static OFFSETS: [u8; 315] = [
+        170, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, 96, 1, 42, 4,
+        2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, 41, 0, 38, 1, 1,
+        5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2, 38, 2, 6, 2, 8,
+        1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116,
+        1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 6, 4, 1, 2, 4,
+        5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 0, 46, 18, 30, 132,
+        102, 3, 4, 1, 62, 2, 2, 1, 1, 1, 8, 21, 5, 1, 3, 0, 43, 1, 14, 6, 80, 0, 7, 12, 5, 0, 26, 6,
+        26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 0, 1, 2, 3,
+        1, 42, 1, 9, 0, 51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2,
+        4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25,
+        1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 6, 6, 0,
+        62, 0, 68, 0, 26, 6, 26, 6, 26, 0,
     ];
+    #[inline]
     pub fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
+        (c as u32) >= 0xaa && lookup_slow(c)
+    }
+
+    #[inline(never)]
+    fn lookup_slow(c: char) -> bool {
         const {
             assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
             let mut i = 0;
@@ -412,6 +444,7 @@ pub mod grapheme_extend {
     ];
     #[inline]
     pub fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
         (c as u32) >= 0x300 && lookup_slow(c)
     }
 
@@ -434,7 +467,7 @@ pub mod grapheme_extend {
 #[rustfmt::skip]
 pub mod lowercase {
     static BITSET_CHUNKS_MAP: [u8; 123] = [
-        14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        12, 17, 0, 0, 9, 0, 0, 13, 14, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0,
@@ -446,37 +479,37 @@ pub mod lowercase {
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 56, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 43, 0, 52, 48, 50, 33],
-        [0, 0, 0, 0, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 3, 0, 16, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27],
         [0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 34, 17, 23, 53, 54, 49, 47, 7, 35, 42, 0, 28, 12, 31],
         [0, 0, 46, 0, 56, 56, 56, 0, 22, 22, 69, 22, 36, 25, 24, 37],
         [0, 5, 70, 0, 29, 15, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 66, 34, 17, 23, 53, 54, 49, 47, 8, 35, 42, 0, 28, 13, 31],
-        [11, 60, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0],
+        [10, 60, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0],
         [16, 26, 22, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [16, 51, 2, 21, 68, 9, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [16, 51, 2, 21, 68, 8, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [16, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [65, 41, 55, 12, 77, 63, 18, 1, 7, 64, 76, 20, 73, 74, 4, 45],
+        [65, 41, 55, 11, 66, 63, 18, 13, 1, 64, 76, 20, 73, 74, 4, 45],
     ];
     static BITSET_CANONICAL: [u64; 56] = [
         0b0000000000000000000000000000000000000000000000000000000000000000,
-        0b1111111111111111110000000000000000000000000011111111111111111111,
+        0b0000111111111111111111111111110000000000000000000000000011111111,
         0b1010101010101010101010101010101010101010101010101010100000000010,
         0b0000000000000111111111111111111111111111111111111111111111111111,
         0b1111111111111111111111000000000000000000000000001111110111111111,
         0b1000000000000010000000000000000000000000000000000000000000000000,
         0b0000111111111111111111111111111111111111000000000000000000000000,
-        0b0000111111111111111111111111110000000000000000000000000011111111,
         0b1111111111111111111111111111111111111111111111111010101010000101,
         0b1111111111111111111111111111111100000000000000000000000000000000,
         0b1111111111111111111111111111110000000000000000000000000000000000,
         0b1111111111111111111111110000000000000000000000000000000000000000,
         0b1111111111111111111111000000000000000000000000001111111111101111,
         0b1111111111111111111100000000000000000000000000010000000000000000,
+        0b1111111111111111110000000000000000000000000011111111111111111111,
         0b1111111111111111000000111111111111110111111111111111111111111111,
         0b1111111111111111000000000000000000000000000000000100001111000000,
         0b1111111111111111000000000000000000000000000000000000000000000000,
@@ -520,13 +553,15 @@ pub mod lowercase {
         0b1110011001010001001011010010101001001110001001000011000100101001,
         0b1110101111000000000000000000000000001111111111111111111111111100,
     ];
-    static BITSET_MAPPING: [(u8, u8); 22] = [
-        (0, 64), (1, 188), (1, 186), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66),
-        (1, 70), (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6),
-        (5, 187), (6, 78), (7, 132),
+    static BITSET_MAPPING: [(u8, u8); 21] = [
+        (0, 64), (1, 184), (1, 182), (1, 179), (1, 172), (1, 161), (1, 146), (1, 144), (1, 140),
+        (1, 136), (1, 132), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12),
+        (4, 6), (5, 187), (6, 78),
     ];
 
     pub const fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
+        (c as u32) >= 0xaa &&
         super::bitset_search(
             c as u32,
             &BITSET_CHUNKS_MAP,
@@ -542,43 +577,50 @@ pub mod n {
     use super::ShortOffsetRunHeader;
 
     static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 42] = [
-        ShortOffsetRunHeader::new(0, 1632), ShortOffsetRunHeader::new(9, 2406),
-        ShortOffsetRunHeader::new(15, 4160), ShortOffsetRunHeader::new(49, 4969),
-        ShortOffsetRunHeader::new(53, 5870), ShortOffsetRunHeader::new(55, 6470),
-        ShortOffsetRunHeader::new(63, 8304), ShortOffsetRunHeader::new(79, 9312),
-        ShortOffsetRunHeader::new(89, 10102), ShortOffsetRunHeader::new(93, 11517),
-        ShortOffsetRunHeader::new(95, 12295), ShortOffsetRunHeader::new(97, 12690),
-        ShortOffsetRunHeader::new(103, 42528), ShortOffsetRunHeader::new(115, 43056),
-        ShortOffsetRunHeader::new(119, 44016), ShortOffsetRunHeader::new(131, 65296),
-        ShortOffsetRunHeader::new(133, 65799), ShortOffsetRunHeader::new(135, 66273),
-        ShortOffsetRunHeader::new(141, 67672), ShortOffsetRunHeader::new(153, 68858),
-        ShortOffsetRunHeader::new(183, 69216), ShortOffsetRunHeader::new(189, 70736),
-        ShortOffsetRunHeader::new(209, 71248), ShortOffsetRunHeader::new(213, 71904),
-        ShortOffsetRunHeader::new(221, 72688), ShortOffsetRunHeader::new(225, 73552),
-        ShortOffsetRunHeader::new(233, 74752), ShortOffsetRunHeader::new(237, 90416),
-        ShortOffsetRunHeader::new(239, 92768), ShortOffsetRunHeader::new(241, 93552),
-        ShortOffsetRunHeader::new(249, 93824), ShortOffsetRunHeader::new(251, 118000),
-        ShortOffsetRunHeader::new(253, 119488), ShortOffsetRunHeader::new(255, 120782),
-        ShortOffsetRunHeader::new(261, 123200), ShortOffsetRunHeader::new(263, 123632),
-        ShortOffsetRunHeader::new(265, 124144), ShortOffsetRunHeader::new(267, 125127),
-        ShortOffsetRunHeader::new(271, 126065), ShortOffsetRunHeader::new(275, 127232),
-        ShortOffsetRunHeader::new(285, 130032), ShortOffsetRunHeader::new(287, 1244154),
+        ShortOffsetRunHeader::new(0, 1632), ShortOffsetRunHeader::new(7, 2406),
+        ShortOffsetRunHeader::new(13, 4160), ShortOffsetRunHeader::new(47, 4969),
+        ShortOffsetRunHeader::new(51, 5870), ShortOffsetRunHeader::new(53, 6470),
+        ShortOffsetRunHeader::new(61, 8304), ShortOffsetRunHeader::new(77, 9312),
+        ShortOffsetRunHeader::new(87, 10102), ShortOffsetRunHeader::new(91, 11517),
+        ShortOffsetRunHeader::new(93, 12295), ShortOffsetRunHeader::new(95, 12690),
+        ShortOffsetRunHeader::new(101, 42528), ShortOffsetRunHeader::new(113, 43056),
+        ShortOffsetRunHeader::new(117, 44016), ShortOffsetRunHeader::new(129, 65296),
+        ShortOffsetRunHeader::new(131, 65799), ShortOffsetRunHeader::new(133, 66273),
+        ShortOffsetRunHeader::new(139, 67672), ShortOffsetRunHeader::new(151, 68858),
+        ShortOffsetRunHeader::new(181, 69216), ShortOffsetRunHeader::new(187, 70736),
+        ShortOffsetRunHeader::new(207, 71248), ShortOffsetRunHeader::new(211, 71904),
+        ShortOffsetRunHeader::new(219, 72688), ShortOffsetRunHeader::new(223, 73552),
+        ShortOffsetRunHeader::new(231, 74752), ShortOffsetRunHeader::new(235, 90416),
+        ShortOffsetRunHeader::new(237, 92768), ShortOffsetRunHeader::new(239, 93552),
+        ShortOffsetRunHeader::new(247, 93824), ShortOffsetRunHeader::new(249, 118000),
+        ShortOffsetRunHeader::new(251, 119488), ShortOffsetRunHeader::new(253, 120782),
+        ShortOffsetRunHeader::new(259, 123200), ShortOffsetRunHeader::new(261, 123632),
+        ShortOffsetRunHeader::new(263, 124144), ShortOffsetRunHeader::new(265, 125127),
+        ShortOffsetRunHeader::new(269, 126065), ShortOffsetRunHeader::new(273, 127232),
+        ShortOffsetRunHeader::new(283, 130032), ShortOffsetRunHeader::new(285, 1244154),
     ];
-    static OFFSETS: [u8; 289] = [
-        48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118,
-        10, 118, 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10,
-        70, 20, 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10,
-        182, 10, 86, 10, 134, 10, 6, 10, 0, 1, 3, 6, 6, 10, 198, 51, 2, 5, 0, 60, 78, 22, 0, 30, 0,
-        1, 0, 1, 25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6,
-        154, 10, 38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4,
-        29, 1, 8, 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9,
-        52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112,
-        7, 134, 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20,
-        76, 12, 0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10,
-        86, 10, 134, 10, 1, 7, 0, 10, 0, 23, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0,
-        10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0,
+    static OFFSETS: [u8; 287] = [
+        178, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, 10, 118,
+        10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, 70, 20,
+        0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, 182, 10,
+        86, 10, 134, 10, 6, 10, 0, 1, 3, 6, 6, 10, 198, 51, 2, 5, 0, 60, 78, 22, 0, 30, 0, 1, 0, 1,
+        25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6, 154, 10,
+        38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4, 29, 1, 8,
+        1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, 52, 2,
+        30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112, 7, 134,
+        30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20, 76, 12,
+        0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10, 86, 10,
+        134, 10, 1, 7, 0, 10, 0, 23, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, 10, 247,
+        10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0,
     ];
+    #[inline]
     pub fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
+        (c as u32) >= 0xb2 && lookup_slow(c)
+    }
+
+    #[inline(never)]
+    fn lookup_slow(c: char) -> bool {
         const {
             assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
             let mut i = 0;
@@ -596,34 +638,34 @@ pub mod n {
 #[rustfmt::skip]
 pub mod uppercase {
     static BITSET_CHUNKS_MAP: [u8; 125] = [
-        12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-        6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-        6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6,
-        6, 6, 9, 6, 3,
+        3, 14, 6, 6, 0, 6, 6, 2, 5, 12, 6, 15, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+        6, 6, 6, 7, 6, 13, 6, 11, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+        6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 16, 6, 6,
+        6, 6, 10, 6, 4,
     ];
     static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [
-        [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 1],
+        [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 0],
         [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 63, 17, 43, 29, 24, 23],
+        [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 62, 17, 43, 29, 24, 23],
+        [44, 44, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39],
         [44, 44, 44, 44, 9, 8, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [44, 44, 44, 44, 37, 28, 67, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, 44],
+        [44, 44, 44, 44, 37, 28, 66, 44, 44, 44, 44, 44, 44, 44, 44, 44],
         [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [44, 44, 44, 44, 44, 44, 44, 44, 44, 55, 44, 44, 44, 44, 44, 44],
-        [44, 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 44, 20, 14, 16, 4],
-        [44, 44, 44, 44, 56, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [44, 44, 59, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [44, 44, 60, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [44, 49, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39],
-        [52, 54, 26, 50, 12, 7, 25, 51, 41, 53, 6, 3, 66, 65, 64, 68],
-        [57, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [58, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
-        [58, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
+        [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 44, 44, 44],
+        [44, 44, 44, 44, 44, 44, 44, 44, 44, 49, 44, 44, 44, 44, 44, 44],
+        [44, 44, 44, 44, 44, 44, 44, 44, 44, 61, 60, 44, 20, 14, 16, 4],
+        [44, 44, 44, 44, 50, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
+        [44, 44, 53, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
+        [44, 44, 54, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
+        [51, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44],
+        [52, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
+        [52, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
+        [58, 1, 26, 55, 12, 7, 25, 56, 41, 59, 6, 3, 65, 64, 63, 67],
     ];
     static BITSET_CANONICAL: [u64; 44] = [
-        0b0000011111111111111111111111111000000000000000000000000000000000,
         0b0000000000111111111111111111111111111111111111111111111111111111,
+        0b1111111111111111111111110000000000000000000000000011111111111111,
         0b0101010101010101010101010101010101010101010101010101010000000001,
         0b0000011111111111111111111111110000000000000000000000000000000001,
         0b0000000000100000000000000000000000010101010000010001101011110101,
@@ -667,13 +709,15 @@ pub mod uppercase {
         0b1111011111111111000000000000000000000000000000000000000000000000,
         0b1111111100000000111111110000000000111111000000001111111100000000,
     ];
-    static BITSET_MAPPING: [(u8, u8); 25] = [
-        (0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121),
-        (0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164),
-        (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171),
+    static BITSET_MAPPING: [(u8, u8); 24] = [
+        (0, 182), (0, 74), (0, 166), (0, 162), (0, 159), (0, 150), (0, 148), (0, 142), (0, 134),
+        (0, 131), (0, 64), (1, 66), (1, 70), (1, 83), (1, 12), (1, 8), (2, 164), (2, 146), (2, 20),
+        (3, 146), (3, 140), (3, 134), (4, 178), (4, 171),
     ];
 
     pub const fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
+        (c as u32) >= 0xc0 &&
         super::bitset_search(
             c as u32,
             &BITSET_CHUNKS_MAP,
@@ -687,8 +731,8 @@ pub mod uppercase {
 #[rustfmt::skip]
 pub mod white_space {
     static WHITESPACE_MAP: [u8; 256] = [
-        2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -699,6 +743,7 @@ pub mod white_space {
     ];
     #[inline]
     pub const fn lookup(c: char) -> bool {
+        debug_assert!(!c.is_ascii());
         match c as u32 >> 8 {
             0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0,
             22 => c as u32 == 0x1680,
@@ -747,7 +792,7 @@ pub mod conversions {
         }
     }
 
-    static LOWERCASE_TABLE: &[(char, u32)] = &[
+    static LOWERCASE_TABLE: &[(char, u32); 1434] = &[
         ('\u{c0}', 224), ('\u{c1}', 225), ('\u{c2}', 226), ('\u{c3}', 227), ('\u{c4}', 228),
         ('\u{c5}', 229), ('\u{c6}', 230), ('\u{c7}', 231), ('\u{c8}', 232), ('\u{c9}', 233),
         ('\u{ca}', 234), ('\u{cb}', 235), ('\u{cc}', 236), ('\u{cd}', 237), ('\u{ce}', 238),
@@ -1097,11 +1142,11 @@ pub mod conversions {
         ('\u{1e921}', 125251),
     ];
 
-    static LOWERCASE_TABLE_MULTI: &[[char; 3]] = &[
+    static LOWERCASE_TABLE_MULTI: &[[char; 3]; 1] = &[
         ['i', '\u{307}', '\u{0}'],
     ];
 
-    static UPPERCASE_TABLE: &[(char, u32)] = &[
+    static UPPERCASE_TABLE: &[(char, u32); 1526] = &[
         ('\u{b5}', 924), ('\u{df}', 4194304), ('\u{e0}', 192), ('\u{e1}', 193), ('\u{e2}', 194),
         ('\u{e3}', 195), ('\u{e4}', 196), ('\u{e5}', 197), ('\u{e6}', 198), ('\u{e7}', 199),
         ('\u{e8}', 200), ('\u{e9}', 201), ('\u{ea}', 202), ('\u{eb}', 203), ('\u{ec}', 204),
@@ -1474,7 +1519,7 @@ pub mod conversions {
         ('\u{1e941}', 125215), ('\u{1e942}', 125216), ('\u{1e943}', 125217),
     ];
 
-    static UPPERCASE_TABLE_MULTI: &[[char; 3]] = &[
+    static UPPERCASE_TABLE_MULTI: &[[char; 3]; 102] = &[
         ['S', 'S', '\u{0}'], ['\u{2bc}', 'N', '\u{0}'], ['J', '\u{30c}', '\u{0}'],
         ['\u{399}', '\u{308}', '\u{301}'], ['\u{3a5}', '\u{308}', '\u{301}'],
         ['\u{535}', '\u{552}', '\u{0}'], ['H', '\u{331}', '\u{0}'], ['T', '\u{308}', '\u{0}'],