about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-14 14:52:33 +0000
committerbors <bors@rust-lang.org>2021-08-14 14:52:33 +0000
commita59e8853148c6a26ed583cccd0f1c3fc50444c9c (patch)
tree8645e66f2d42e1c40e76ffc0cbf033a8b289b699
parent136eaa1b25d13635b773a481ecab61a3162cb627 (diff)
parent94d6b22fc36f50b021e47eae2a9437689ee83077 (diff)
downloadrust-a59e8853148c6a26ed583cccd0f1c3fc50444c9c.tar.gz
rust-a59e8853148c6a26ed583cccd0f1c3fc50444c9c.zip
Auto merge of #87913 - a1phyr:vec_spec_clone_from, r=dtolnay
Specialize `Vec::clone_from` for `Copy` types

This should improve performance and reduce code size.

This also improves `clone_from` for `String`, `OsString` and `PathBuf`.
-rw-r--r--library/alloc/src/vec/mod.rs40
1 files changed, 30 insertions, 10 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index e14ebd869a3..933361d812c 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2379,6 +2379,35 @@ impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
 }
 
 #[cfg(not(no_global_oom_handling))]
+trait SpecCloneFrom {
+    fn clone_from(this: &mut Self, other: &Self);
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
+    default fn clone_from(this: &mut Self, other: &Self) {
+        // drop anything that will not be overwritten
+        this.truncate(other.len());
+
+        // self.len <= other.len due to the truncate above, so the
+        // slices here are always in-bounds.
+        let (init, tail) = other.split_at(this.len());
+
+        // reuse the contained values' allocations/resources.
+        this.clone_from_slice(init);
+        this.extend_from_slice(tail);
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
+    fn clone_from(this: &mut Self, other: &Self) {
+        this.clear();
+        this.extend_from_slice(other);
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
     #[cfg(not(test))]
@@ -2398,16 +2427,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
     }
 
     fn clone_from(&mut self, other: &Self) {
-        // drop anything that will not be overwritten
-        self.truncate(other.len());
-
-        // self.len <= other.len due to the truncate above, so the
-        // slices here are always in-bounds.
-        let (init, tail) = other.split_at(self.len());
-
-        // reuse the contained values' allocations/resources.
-        self.clone_from_slice(init);
-        self.extend_from_slice(tail);
+        SpecCloneFrom::clone_from(self, other)
     }
 }