diff --git a/.mailmap b/.mailmap
index cc7b2a677baf6..fa0728bd79461 100644
--- a/.mailmap
+++ b/.mailmap
@@ -55,6 +55,9 @@ Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccer
 Chris Pressey <cpressey@gmail.com>
 Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
 Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com>
+Christiaan Dirkx <christiaan@dirkx.email> <christiaan@dirkx.com>
+Christiaan Dirkx <christiaan@dirkx.email> CDirkx <christiaan@dirkx.com>
+Christiaan Dirkx <christiaan@dirkx.email> CDirkx <christiaan@dirkx.email>
 Christian Poveda <git@christianpoveda.xyz> <christianpoveda@protonmail.com>
 Christian Poveda <git@christianpoveda.xyz> <cn.poveda.ruiz@gmail.com>
 Christian Poveda <git@christianpoveda.xyz> <z1mvader@protonmail.com>
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 9f5fc5a2d3fbc..825221c22a8c1 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2280,6 +2280,12 @@ impl<'tcx> TyS<'tcx> {
     ///
     /// Returning true means the type is known to be sized. Returning
     /// `false` means nothing -- could be sized, might not be.
+    ///
+    /// Note that we could never rely on the fact that a type such as `[_]` is
+    /// trivially `!Sized` because we could be in a type environment with a
+    /// bound such as `[_]: Copy`. A function with such a bound obviously never
+    /// can be called, but that doesn't mean it shouldn't typecheck. This is why
+    /// this method doesn't return `Option<bool>`.
     pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
         match self.kind() {
             ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index dcd8379803319..611280b413dd7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1507,12 +1507,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                 // avoid inundating the user with unnecessary errors, but we now
                 // check upstream for type errors and don't add the obligations to
                 // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
+                if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
                     self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
                     return;
                 }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 7cc567dabb28f..2fad54013ad5b 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -110,25 +110,15 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
             .map(|i| chalk_ir::AssocTypeId(i.def_id))
             .collect();
 
-        let well_known = if self
-            .interner
-            .tcx
-            .lang_items()
-            .sized_trait()
-            .map(|t| def_id == t)
-            .unwrap_or(false)
-        {
+        let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Sized)
-        } else if self.interner.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Copy)
-        } else if self.interner.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Clone)
-        } else if self.interner.tcx.lang_items().drop_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Drop)
-        } else if self.interner.tcx.lang_items().fn_trait().map(|t| def_id == t).unwrap_or(false) {
+        } else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Fn)
         } else if self
             .interner
diff --git a/library/alloc/src/collections/vec_deque.rs b/library/alloc/src/collections/vec_deque.rs
index 253a3e9f2bea9..65cfe9a9b4996 100644
--- a/library/alloc/src/collections/vec_deque.rs
+++ b/library/alloc/src/collections/vec_deque.rs
@@ -1089,11 +1089,7 @@ impl<T> VecDeque<T> {
     where
         R: RangeBounds<usize>,
     {
-        // SAFETY: This buffer is only used to check the range. It might be partially
-        // uninitialized, but `check_range` needs a contiguous slice.
-        // https://github.com/rust-lang/rust/pull/75207#discussion_r471193682
-        let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) };
-        let Range { start, end } = buffer.check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         let tail = self.wrap_add(self.tail, start);
         let head = self.wrap_add(self.tail, end);
         (tail, head)
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 677bfdd2349ec..55afdd94f4468 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -91,6 +91,8 @@ use crate::borrow::ToOwned;
 use crate::boxed::Box;
 use crate::vec::Vec;
 
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub use core::slice::check_range;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunks;
 #[unstable(feature = "array_chunks", issue = "74985")]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index e1724bf3c9a90..2b0ce5ede5630 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -49,6 +49,7 @@ use core::iter::{FromIterator, FusedIterator};
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
 use core::ptr;
+use core::slice;
 use core::str::{lossy, pattern::Pattern};
 
 use crate::borrow::{Cow, ToOwned};
@@ -1506,7 +1507,7 @@ impl String {
         // of the vector version. The data is just plain bytes.
         // Because the range removal happens in Drop, if the Drain iterator is leaked,
         // the removal will not happen.
-        let Range { start, end } = self.as_bytes().check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         assert!(self.is_char_boundary(start));
         assert!(self.is_char_boundary(end));
 
diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index baa6c0919defe..3d48a06fd241a 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -1310,7 +1310,7 @@ impl<T> Vec<T> {
         // the hole, and the vector length is restored to the new length.
         //
         let len = self.len();
-        let Range { start, end } = self.check_range(range);
+        let Range { start, end } = slice::check_range(len, range);
 
         unsafe {
             // set self.vec length's to start, to be safe in case Drain is leaked
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 53b0d0a271844..e65bbb9b4dce8 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -880,7 +880,7 @@ fn test_from_iter_partially_drained_in_place_specialization() {
 #[test]
 fn test_from_iter_specialization_with_iterator_adapters() {
     fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
-    let src: Vec<usize> = vec![0usize; 65535];
+    let src: Vec<usize> = vec![0usize; 256];
     let srcptr = src.as_ptr();
     let iter = src
         .into_iter()
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index e02de0ce45dff..a854f70dcd0ba 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -8,11 +8,8 @@ use super::super::{
 
 /// An iterator that iterates two other iterators simultaneously.
 ///
-/// This `struct` is created by the [`zip`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`zip`]: trait.Iterator.html#method.zip
-/// [`Iterator`]: trait.Iterator.html
+/// This `struct` is created by [`Iterator::zip`]. See its documentation
+/// for more.
 #[derive(Clone)]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 4c027b23584bf..5e4537e5dc8fe 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -354,79 +354,6 @@ impl<T> [T] {
         unsafe { &mut *index.get_unchecked_mut(self) }
     }
 
-    /// Converts a range over this slice to [`Range`].
-    ///
-    /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
-    ///
-    /// [`get_unchecked`]: #method.get_unchecked
-    /// [`get_unchecked_mut`]: #method.get_unchecked_mut
-    ///
-    /// # Panics
-    ///
-    /// Panics if the range is out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(slice_check_range)]
-    ///
-    /// let v = [10, 40, 30];
-    /// assert_eq!(1..2, v.check_range(1..2));
-    /// assert_eq!(0..2, v.check_range(..2));
-    /// assert_eq!(1..3, v.check_range(1..));
-    /// ```
-    ///
-    /// Panics when [`Index::index`] would panic:
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(2..1);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..4);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..=usize::MAX);
-    /// ```
-    ///
-    /// [`Index::index`]: ops::Index::index
-    #[track_caller]
-    #[unstable(feature = "slice_check_range", issue = "76393")]
-    pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
-        let start = match range.start_bound() {
-            Bound::Included(&start) => start,
-            Bound::Excluded(start) => {
-                start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
-            }
-            Bound::Unbounded => 0,
-        };
-
-        let len = self.len();
-        let end = match range.end_bound() {
-            Bound::Included(end) => {
-                end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
-            }
-            Bound::Excluded(&end) => end,
-            Bound::Unbounded => len,
-        };
-
-        if start > end {
-            slice_index_order_fail(start, end);
-        }
-        if end > len {
-            slice_end_index_len_fail(end, len);
-        }
-
-        Range { start, end }
-    }
-
     /// Returns a raw pointer to the slice's buffer.
     ///
     /// The caller must ensure that the slice outlives the pointer this
@@ -2770,7 +2697,7 @@ impl<T> [T] {
     where
         T: Copy,
     {
-        let Range { start: src_start, end: src_end } = self.check_range(src);
+        let Range { start: src_start, end: src_end } = check_range(self.len(), src);
         let count = src_end - src_start;
         assert!(dest <= self.len() - count, "dest is out of bounds");
         // SAFETY: the conditions for `ptr::copy` have all been checked above,
@@ -6660,6 +6587,79 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
 // Free functions
 //
 
+/// Performs bounds-checking of the given range.
+/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
+/// for slices of the given length.
+///
+/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
+/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
+///
+/// # Panics
+///
+/// Panics if the range is out of bounds.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(slice_check_range)]
+/// use std::slice;
+///
+/// let v = [10, 40, 30];
+/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
+/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
+/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
+/// ```
+///
+/// Panics when [`Index::index`] would panic:
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 2..1);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..4);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..=usize::MAX);
+/// ```
+///
+/// [`Index::index`]: ops::Index::index
+#[track_caller]
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
+    let start = match range.start_bound() {
+        Bound::Included(&start) => start,
+        Bound::Excluded(start) => {
+            start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
+        }
+        Bound::Unbounded => 0,
+    };
+
+    let end = match range.end_bound() {
+        Bound::Included(end) => {
+            end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
+        }
+        Bound::Excluded(&end) => end,
+        Bound::Unbounded => len,
+    };
+
+    if start > end {
+        slice_index_order_fail(start, end);
+    }
+    if end > len {
+        slice_end_index_len_fail(end, len);
+    }
+
+    Range { start, end }
+}
+
 /// Forms a slice from a pointer and a length.
 ///
 /// The `len` argument is the number of **elements**, not the number of bytes.
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index f39781788d7c0..6dc542dee58e6 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -693,7 +693,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn from_secs_f64(secs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn from_secs_f64(secs: f64) -> Duration {
         const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64;
         let nanos = secs * (NANOS_PER_SEC as f64);
         if !nanos.is_finite() {
@@ -727,7 +728,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn from_secs_f32(secs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn from_secs_f32(secs: f32) -> Duration {
         const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32;
         let nanos = secs * (NANOS_PER_SEC as f32);
         if !nanos.is_finite() {
@@ -761,7 +763,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn mul_f64(self, rhs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn mul_f64(self, rhs: f64) -> Duration {
         Duration::from_secs_f64(rhs * self.as_secs_f64())
     }
 
@@ -782,7 +785,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn mul_f32(self, rhs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn mul_f32(self, rhs: f32) -> Duration {
         Duration::from_secs_f32(rhs * self.as_secs_f32())
     }
 
@@ -802,7 +806,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn div_f64(self, rhs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn div_f64(self, rhs: f64) -> Duration {
         Duration::from_secs_f64(self.as_secs_f64() / rhs)
     }
 
@@ -824,7 +829,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn div_f32(self, rhs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn div_f32(self, rhs: f32) -> Duration {
         Duration::from_secs_f32(self.as_secs_f32() / rhs)
     }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index a2e294ace1860..04402117f7da6 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -10,8 +10,11 @@
 #![feature(core_private_diy_float)]
 #![feature(debug_non_exhaustive)]
 #![feature(dec2flt)]
+#![feature(div_duration)]
+#![feature(duration_consts_2)]
 #![feature(duration_constants)]
 #![feature(duration_saturating_ops)]
+#![feature(duration_zero)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
 #![feature(flt2dec)]
diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs
index 4f90eb63b0472..7c43885040b3e 100644
--- a/library/core/tests/time.rs
+++ b/library/core/tests/time.rs
@@ -321,3 +321,104 @@ fn debug_formatting_precision_high() {
     assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s");
     assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s");
 }
+
+#[test]
+fn duration_const() {
+    // test that the methods of `Duration` are usable in a const context
+
+    const DURATION: Duration = Duration::new(0, 123_456_789);
+
+    const SUB_SEC_MILLIS: u32 = DURATION.subsec_millis();
+    assert_eq!(SUB_SEC_MILLIS, 123);
+
+    const SUB_SEC_MICROS: u32 = DURATION.subsec_micros();
+    assert_eq!(SUB_SEC_MICROS, 123_456);
+
+    const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos();
+    assert_eq!(SUB_SEC_NANOS, 123_456_789);
+
+    const ZERO: Duration = Duration::zero();
+    assert_eq!(ZERO, Duration::new(0, 0));
+
+    const IS_ZERO: bool = ZERO.is_zero();
+    assert!(IS_ZERO);
+
+    const ONE: Duration = Duration::new(1, 0);
+
+    const SECONDS: u64 = ONE.as_secs();
+    assert_eq!(SECONDS, 1);
+
+    const FROM_SECONDS: Duration = Duration::from_secs(1);
+    assert_eq!(FROM_SECONDS, ONE);
+
+    const SECONDS_F32: f32 = ONE.as_secs_f32();
+    assert_eq!(SECONDS_F32, 1.0);
+
+    const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0);
+    assert_eq!(FROM_SECONDS_F32, ONE);
+
+    const SECONDS_F64: f64 = ONE.as_secs_f64();
+    assert_eq!(SECONDS_F64, 1.0);
+
+    const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0);
+    assert_eq!(FROM_SECONDS_F64, ONE);
+
+    const MILLIS: u128 = ONE.as_millis();
+    assert_eq!(MILLIS, 1_000);
+
+    const FROM_MILLIS: Duration = Duration::from_millis(1_000);
+    assert_eq!(FROM_MILLIS, ONE);
+
+    const MICROS: u128 = ONE.as_micros();
+    assert_eq!(MICROS, 1_000_000);
+
+    const FROM_MICROS: Duration = Duration::from_micros(1_000_000);
+    assert_eq!(FROM_MICROS, ONE);
+
+    const NANOS: u128 = ONE.as_nanos();
+    assert_eq!(NANOS, 1_000_000_000);
+
+    const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000);
+    assert_eq!(FROM_NANOS, ONE);
+
+    const MAX: Duration = Duration::new(u64::MAX, 999_999_999);
+
+    const CHECKED_ADD: Option<Duration> = MAX.checked_add(ONE);
+    assert_eq!(CHECKED_ADD, None);
+
+    const CHECKED_SUB: Option<Duration> = ZERO.checked_sub(ONE);
+    assert_eq!(CHECKED_SUB, None);
+
+    const CHECKED_MUL: Option<Duration> = ONE.checked_mul(1);
+    assert_eq!(CHECKED_MUL, Some(ONE));
+
+    const MUL_F32: Duration = ONE.mul_f32(1.0);
+    assert_eq!(MUL_F32, ONE);
+
+    const MUL_F64: Duration = ONE.mul_f64(1.0);
+    assert_eq!(MUL_F64, ONE);
+
+    const CHECKED_DIV: Option<Duration> = ONE.checked_div(1);
+    assert_eq!(CHECKED_DIV, Some(ONE));
+
+    const DIV_F32: Duration = ONE.div_f32(1.0);
+    assert_eq!(DIV_F32, ONE);
+
+    const DIV_F64: Duration = ONE.div_f64(1.0);
+    assert_eq!(DIV_F64, ONE);
+
+    const DIV_DURATION_F32: f32 = ONE.div_duration_f32(ONE);
+    assert_eq!(DIV_DURATION_F32, 1.0);
+
+    const DIV_DURATION_F64: f64 = ONE.div_duration_f64(ONE);
+    assert_eq!(DIV_DURATION_F64, 1.0);
+
+    const SATURATING_ADD: Duration = MAX.saturating_add(ONE);
+    assert_eq!(SATURATING_ADD, MAX);
+
+    const SATURATING_SUB: Duration = ZERO.saturating_sub(ONE);
+    assert_eq!(SATURATING_SUB, ZERO);
+
+    const SATURATING_MUL: Duration = MAX.saturating_mul(2);
+    assert_eq!(SATURATING_MUL, MAX);
+}
diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs
index 091e2091fb095..e0095e64faf31 100644
--- a/library/std/src/lazy.rs
+++ b/library/std/src/lazy.rs
@@ -7,7 +7,7 @@ use crate::{
     cell::{Cell, UnsafeCell},
     fmt,
     marker::PhantomData,
-    mem::{self, MaybeUninit},
+    mem::MaybeUninit,
     ops::{Deref, Drop},
     panic::{RefUnwindSafe, UnwindSafe},
     sync::Once,
@@ -316,13 +316,7 @@ impl<T> SyncOnceCell<T> {
     /// ```
     #[unstable(feature = "once_cell", issue = "74465")]
     pub fn into_inner(mut self) -> Option<T> {
-        // SAFETY: Safe because we immediately free `self` without dropping
-        let inner = unsafe { self.take_inner() };
-
-        // Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set
-        // the state to uninitialized.
-        mem::forget(self);
-        inner
+        self.take()
     }
 
     /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
@@ -348,22 +342,12 @@ impl<T> SyncOnceCell<T> {
     /// ```
     #[unstable(feature = "once_cell", issue = "74465")]
     pub fn take(&mut self) -> Option<T> {
-        mem::take(self).into_inner()
-    }
-
-    /// Takes the wrapped value out of a `SyncOnceCell`.
-    /// Afterwards the cell is no longer initialized.
-    ///
-    /// Safety: The cell must now be free'd WITHOUT dropping. No other usages of the cell
-    /// are valid. Only used by `into_inner` and `drop`.
-    unsafe fn take_inner(&mut self) -> Option<T> {
-        // The mutable reference guarantees there are no other threads that can observe us
-        // taking out the wrapped value.
-        // Right after this function `self` is supposed to be freed, so it makes little sense
-        // to atomically set the state to uninitialized.
         if self.is_initialized() {
-            let value = mem::replace(&mut self.value, UnsafeCell::new(MaybeUninit::uninit()));
-            Some(value.into_inner().assume_init())
+            self.once = Once::new();
+            // SAFETY: `self.value` is initialized and contains a valid `T`.
+            // `self.once` is reset, so `is_initialized()` will be false again
+            // which prevents the value from being read twice.
+            unsafe { Some((&mut *self.value.get()).assume_init_read()) }
         } else {
             None
         }
@@ -416,9 +400,12 @@ impl<T> SyncOnceCell<T> {
 
 unsafe impl<#[may_dangle] T> Drop for SyncOnceCell<T> {
     fn drop(&mut self) {
-        // SAFETY: The cell is being dropped, so it can't be accessed again.
-        // We also don't touch the `T`, which validates our usage of #[may_dangle].
-        unsafe { self.take_inner() };
+        if self.is_initialized() {
+            // Safety: The cell is initialized and being dropped, so it can't
+            // be accessed again. We also don't touch the `T` other than
+            // dropping it, which validates our usage of #[may_dangle].
+            unsafe { (&mut *self.value.get()).assume_init_drop() };
+        }
     }
 }
 
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 8fed369bffc27..29ae338cb2ec7 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -191,6 +191,7 @@ struct WaiterQueue<'a> {
 
 impl Once {
     /// Creates a new `Once` value.
+    #[inline]
     #[stable(feature = "once_new", since = "1.2.0")]
     #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
     pub const fn new() -> Once {
diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs
index 487ac266ee9cd..4b9f4ceb29c49 100644
--- a/library/std/src/sys/unix/ext/fs.rs
+++ b/library/std/src/sys/unix/ext/fs.rs
@@ -836,15 +836,6 @@ impl DirEntryExt for fs::DirEntry {
 ///
 /// The `dst` path will be a symbolic link pointing to the `src` path.
 ///
-/// # Note
-///
-/// On Windows, you must specify whether a symbolic link points to a file
-/// or directory. Use `os::windows::fs::symlink_file` to create a
-/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
-/// symbolic link to a directory. Additionally, the process must have
-/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
-/// symbolic link.
-///
 /// # Examples
 ///
 /// ```no_run
diff --git a/library/std/src/sys/vxworks/ext/fs.rs b/library/std/src/sys/vxworks/ext/fs.rs
index 9b4c64bdb6d84..68dc21b806c0f 100644
--- a/library/std/src/sys/vxworks/ext/fs.rs
+++ b/library/std/src/sys/vxworks/ext/fs.rs
@@ -774,15 +774,6 @@ impl DirEntryExt for fs::DirEntry {
 ///
 /// The `dst` path will be a symbolic link pointing to the `src` path.
 ///
-/// # Note
-///
-/// On Windows, you must specify whether a symbolic link points to a file
-/// or directory.  Use `os::windows::fs::symlink_file` to create a
-/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
-/// symbolic link to a directory.  Additionally, the process must have
-/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
-/// symbolic link.
-///
 /// # Examples
 ///
 /// ```no_run
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9d784d24609dc..62a7b05cf566f 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -839,7 +839,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
         let mut where_predicates =
             where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
 
-        // Type parameters and have a Sized bound by default unless removed with
+        // Type parameters have a Sized bound by default unless removed with
         // ?Sized. Scan through the predicates and mark any type parameter with
         // a Sized bound, removing the bounds as we find them.
         //
diff --git a/src/test/ui/consts/duration-consts-2.rs b/src/test/ui/consts/duration-consts-2.rs
deleted file mode 100644
index bc0969e4f1fba..0000000000000
--- a/src/test/ui/consts/duration-consts-2.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-// run-pass
-
-#![feature(const_panic)]
-#![feature(duration_consts_2)]
-#![feature(div_duration)]
-#![feature(duration_saturating_ops)]
-
-use std::time::Duration;
-
-fn duration() {
-    const ZERO : Duration = Duration::new(0, 0);
-    assert_eq!(ZERO, Duration::from_secs(0));
-
-    const ONE : Duration = Duration::new(0, 1);
-    assert_eq!(ONE, Duration::from_nanos(1));
-
-    const MAX : Duration = Duration::new(u64::MAX, 1_000_000_000 - 1);
-
-    const MAX_CHECKED_ADD_ZERO : Option<Duration> = MAX.checked_add(ZERO);
-    assert_eq!(MAX_CHECKED_ADD_ZERO, Some(MAX));
-
-    const MAX_CHECKED_ADD_ONE : Option<Duration> = MAX.checked_add(ONE);
-    assert_eq!(MAX_CHECKED_ADD_ONE, None);
-
-    const ONE_CHECKED_SUB_ONE : Option<Duration> = ONE.checked_sub(ONE);
-    assert_eq!(ONE_CHECKED_SUB_ONE, Some(ZERO));
-
-    const ZERO_CHECKED_SUB_ONE : Option<Duration> = ZERO.checked_sub(ONE);
-    assert_eq!(ZERO_CHECKED_SUB_ONE, None);
-
-    const ONE_CHECKED_MUL_ONE : Option<Duration> = ONE.checked_mul(1);
-    assert_eq!(ONE_CHECKED_MUL_ONE, Some(ONE));
-
-    const MAX_CHECKED_MUL_TWO : Option<Duration> = MAX.checked_mul(2);
-    assert_eq!(MAX_CHECKED_MUL_TWO, None);
-
-    const ONE_CHECKED_DIV_ONE : Option<Duration> = ONE.checked_div(1);
-    assert_eq!(ONE_CHECKED_DIV_ONE, Some(ONE));
-
-    const ONE_CHECKED_DIV_ZERO : Option<Duration> = ONE.checked_div(0);
-    assert_eq!(ONE_CHECKED_DIV_ZERO, None);
-
-    const MAX_AS_F32 : f32 = MAX.as_secs_f32();
-    assert_eq!(MAX_AS_F32, 18446744000000000000.0_f32);
-
-    const MAX_AS_F64 : f64 = MAX.as_secs_f64();
-    assert_eq!(MAX_AS_F64, 18446744073709552000.0_f64);
-
-    const ONE_AS_F32 : f32 = ONE.div_duration_f32(ONE);
-    assert_eq!(ONE_AS_F32, 1.0_f32);
-
-    const ONE_AS_F64 : f64 = ONE.div_duration_f64(ONE);
-    assert_eq!(ONE_AS_F64, 1.0_f64);
-
-    const MAX_SATURATING_ADD_ONE : Duration = MAX.saturating_add(ONE);
-    assert_eq!(MAX_SATURATING_ADD_ONE, MAX);
-
-    const ZERO_SATURATING_SUB_ONE : Duration = ZERO.saturating_sub(ONE);
-    assert_eq!(ZERO_SATURATING_SUB_ONE, ZERO);
-
-    const MAX_SATURATING_MUL_TWO : Duration = MAX.saturating_mul(2);
-    assert_eq!(MAX_SATURATING_MUL_TWO, MAX);
-}
-
-fn main() {
-    duration();
-}
diff --git a/src/test/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs
index daa03ce6b6fd8..4df3ed502827e 100644
--- a/src/test/ui/union/union-drop.rs
+++ b/src/test/ui/union/union-drop.rs
@@ -48,6 +48,11 @@ fn main() {
         {
             let y = Y { a: S };
         }
-        assert_eq!(CHECK, 2); // 2, dtor of Y is called
+        assert_eq!(CHECK, 2); // 2, Y has no dtor
+        {
+            let u2 = U { a: 1 };
+            std::mem::forget(u2);
+        }
+        assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2
     }
 }
diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs
new file mode 100644
index 0000000000000..a0a2d0d659837
--- /dev/null
+++ b/src/test/ui/union/union-move.rs
@@ -0,0 +1,53 @@
+//! Test the behavior of moving out of non-`Copy` union fields.
+//! Avoid types that `Drop`, we want to focus on moving.
+#![feature(untagged_unions)]
+
+use std::cell::RefCell;
+
+fn move_out<T>(x: T) {}
+
+union U1 {
+    f1_nocopy: RefCell<i32>,
+    f2_nocopy: RefCell<i32>,
+    f3_copy: i32,
+}
+
+union U2 {
+    f1_nocopy: RefCell<i32>,
+}
+impl Drop for U2 {
+    fn drop(&mut self) {}
+}
+
+fn test1(x: U1) {
+    // Moving out of a nocopy field prevents accessing other nocopy field.
+    unsafe {
+        move_out(x.f1_nocopy);
+        move_out(x.f2_nocopy); //~ ERROR use of moved value: `x`
+    }
+}
+
+fn test2(x: U1) {
+    // "Moving" out of copy field doesn't prevent later field accesses.
+    unsafe {
+        move_out(x.f3_copy);
+        move_out(x.f2_nocopy); // no error
+    }
+}
+
+fn test3(x: U1) {
+    // Moving out of a nocopy field prevents accessing other copy field.
+    unsafe {
+        move_out(x.f2_nocopy);
+        move_out(x.f3_copy); //~ ERROR use of moved value: `x`
+    }
+}
+
+fn test4(x: U2) {
+    // Cannot move out of union that implements `Drop`.
+    unsafe {
+        move_out(x.f1_nocopy); //~ ERROR cannot move out of type `U2`, which implements the `Drop`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-move.stderr b/src/test/ui/union/union-move.stderr
new file mode 100644
index 0000000000000..4a29f3a77f3c9
--- /dev/null
+++ b/src/test/ui/union/union-move.stderr
@@ -0,0 +1,35 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:26:18
+   |
+LL | fn test1(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f1_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f2_nocopy);
+   |                  ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:42:18
+   |
+LL | fn test3(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f2_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f3_copy);
+   |                  ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+  --> $DIR/union-move.rs:49:18
+   |
+LL |         move_out(x.f1_nocopy);
+   |                  ^^^^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  move occurs because `x.f1_nocopy` has type `std::cell::RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.