about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBenoît du Garreau <bdgdlm@outlook.com>2021-08-10 11:45:52 +0200
committerBenoît du Garreau <bdgdlm@outlook.com>2021-08-10 11:53:40 +0200
commit361398009be65f9aa6ae539c2ea37fbd943cc789 (patch)
treedd3e48855a93123c2ada11bf265cd50974eb469e
parentae90dcf0207c57c3034f00b07048d63f8b2363c8 (diff)
downloadrust-361398009be65f9aa6ae539c2ea37fbd943cc789.tar.gz
rust-361398009be65f9aa6ae539c2ea37fbd943cc789.zip
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.rs37
1 files changed, 27 insertions, 10 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index e14ebd869a3..e5441f13870 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2378,6 +2378,32 @@ impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
     }
 }
 
+trait SpecCloneFrom {
+    fn clone_from(this: &mut Self, other: &Self);
+}
+
+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);
+    }
+}
+
+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> {
@@ -2398,16 +2424,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)
     }
 }