]> git.lizzy.rs Git - rust.git/blobdiff - library/core/src/slice/mod.rs
Auto merge of #81574 - tmiasko:p, r=oli-obk
[rust.git] / library / core / src / slice / mod.rs
index 6ed461aba7693bf449e50a6ce67b0bd8ee63164c..1c1b9e0b27e2558a8bc53e2b13a0da1f119572c4 100644 (file)
@@ -94,9 +94,23 @@ impl<T> [T] {
     // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
     #[rustc_allow_const_fn_unstable(const_fn_union)]
     pub const fn len(&self) -> usize {
-        // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
-        // Only `std` can make this guarantee.
-        unsafe { crate::ptr::Repr { rust: self }.raw.len }
+        #[cfg(bootstrap)]
+        {
+            // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
+            // Only `std` can make this guarantee.
+            unsafe { crate::ptr::Repr { rust: self }.raw.len }
+        }
+        #[cfg(not(bootstrap))]
+        {
+            // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
+            // As of this writing this causes a "Const-stable functions can only call other
+            // const-stable functions" error.
+
+            // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
+            // and PtrComponents<T> have the same memory layouts. Only std can make this
+            // guarantee.
+            unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
+        }
     }
 
     /// Returns `true` if the slice has a length of 0.
@@ -2944,15 +2958,7 @@ pub fn clone_from_slice(&mut self, src: &[T])
     where
         T: Clone,
     {
-        assert!(self.len() == src.len(), "destination and source slices have different lengths");
-        // NOTE: We need to explicitly slice them to the same length
-        // for bounds checking to be elided, and the optimizer will
-        // generate memcpy for simple cases (for example T = u8).
-        let len = self.len();
-        let src = &src[..len];
-        for i in 0..len {
-            self[i].clone_from(&src[i]);
-        }
+        self.spec_clone_from(src);
     }
 
     /// Copies all elements from `src` into `self`, using a memcpy.
@@ -3425,8 +3431,6 @@ pub fn is_sorted_by_key<F, K>(&self, f: F) -> bool
     /// # Examples
     ///
     /// ```
-    /// #![feature(partition_point)]
-    ///
     /// let v = [1, 2, 3, 3, 5, 6, 7];
     /// let i = v.partition_point(|&x| x < 5);
     ///
@@ -3434,7 +3438,7 @@ pub fn is_sorted_by_key<F, K>(&self, f: F) -> bool
     /// assert!(v[..i].iter().all(|&x| x < 5));
     /// assert!(v[i..].iter().all(|&x| !(x < 5)));
     /// ```
-    #[unstable(feature = "partition_point", reason = "new API", issue = "73831")]
+    #[stable(feature = "partition_point", since = "1.52.0")]
     pub fn partition_point<P>(&self, mut pred: P) -> usize
     where
         P: FnMut(&T) -> bool,
@@ -3463,6 +3467,36 @@ pub fn partition_point<P>(&self, mut pred: P) -> usize
     }
 }
 
+trait CloneFromSpec<T> {
+    fn spec_clone_from(&mut self, src: &[T]);
+}
+
+impl<T> CloneFromSpec<T> for [T]
+where
+    T: Clone,
+{
+    default fn spec_clone_from(&mut self, src: &[T]) {
+        assert!(self.len() == src.len(), "destination and source slices have different lengths");
+        // NOTE: We need to explicitly slice them to the same length
+        // to make it easier for the optimizer to elide bounds checking.
+        // But since it can't be relied on we also have an explicit specialization for T: Copy.
+        let len = self.len();
+        let src = &src[..len];
+        for i in 0..len {
+            self[i].clone_from(&src[i]);
+        }
+    }
+}
+
+impl<T> CloneFromSpec<T> for [T]
+where
+    T: Copy,
+{
+    fn spec_clone_from(&mut self, src: &[T]) {
+        self.copy_from_slice(src);
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for &[T] {
     /// Creates an empty slice.