about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNeil Roberts <bpeeluk@yahoo.co.uk>2023-01-28 14:19:01 +0100
committerNeil Roberts <bpeeluk@yahoo.co.uk>2023-01-28 20:37:01 +0100
commitba80c662f448c69cbd184d18630b8824f0169b2e (patch)
tree9204e8b8b73c81e9b386b1a5b4f16144ba1b0a66
parentd6f0642827e21a088b0130c84857d84f5433301d (diff)
downloadrust-ba80c662f448c69cbd184d18630b8824f0169b2e.tar.gz
rust-ba80c662f448c69cbd184d18630b8824f0169b2e.zip
slice: Add a specialization for clone_into when T is Copy
The implementation for the ToOwned::clone_into method on [T] is a copy
of the code for vec::clone_from. In 361398009be6 the code for
vec::clone_from gained a specialization for when T is Copy. This commit
copies that specialization over to the clone_into implementation.
-rw-r--r--library/alloc/src/slice.rs43
1 files changed, 33 insertions, 10 deletions
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index fecacc2bb63..093dcbbe8bf 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -782,6 +782,38 @@ impl<T, A: Allocator> BorrowMut<[T]> for Vec<T, A> {
     }
 }
 
+// Specializable trait for implementing ToOwned::clone_into. This is
+// public in the crate and has the Allocator parameter so that
+// vec::clone_from use it too.
+#[cfg(not(no_global_oom_handling))]
+pub(crate) trait SpecCloneIntoVec<T, A: Allocator> {
+    fn clone_into(&self, target: &mut Vec<T, A>);
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+    default fn clone_into(&self, target: &mut Vec<T, A>) {
+        // drop anything in target that will not be overwritten
+        target.truncate(self.len());
+
+        // target.len <= self.len due to the truncate above, so the
+        // slices here are always in-bounds.
+        let (init, tail) = self.split_at(target.len());
+
+        // reuse the contained values' allocations/resources.
+        target.clone_from_slice(init);
+        target.extend_from_slice(tail);
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+    fn clone_into(&self, target: &mut Vec<T, A>) {
+        target.clear();
+        target.extend_from_slice(self);
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> ToOwned for [T] {
@@ -797,16 +829,7 @@ impl<T: Clone> ToOwned for [T] {
     }
 
     fn clone_into(&self, target: &mut Vec<T>) {
-        // drop anything in target that will not be overwritten
-        target.truncate(self.len());
-
-        // target.len <= self.len due to the truncate above, so the
-        // slices here are always in-bounds.
-        let (init, tail) = self.split_at(target.len());
-
-        // reuse the contained values' allocations/resources.
-        target.clone_from_slice(init);
-        target.extend_from_slice(tail);
+        SpecCloneIntoVec::clone_into(self, target);
     }
 }