about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-11-08 20:31:23 -0800
committerbors <bors@rust-lang.org>2013-11-08 20:31:23 -0800
commitd14a647dc355dda43bddfc84903ad53820469fb3 (patch)
treef0a26f93fd82ae930df1b55aaa250dc434fda637 /src/libstd
parenta594a999fbccf04710c9dfea3ef3d231c14e1bd1 (diff)
parent6943ca8dcd2f08d6e7291e30bbc6a8c99c4a28c5 (diff)
downloadrust-d14a647dc355dda43bddfc84903ad53820469fb3.tar.gz
rust-d14a647dc355dda43bddfc84903ad53820469fb3.zip
auto merge of #10376 : thestinger/rust/clone, r=huonw
Closes #10240
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/clone.rs50
-rw-r--r--src/libstd/vec.rs24
2 files changed, 71 insertions, 3 deletions
diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs
index 701be1b3dfa..584963c36ca 100644
--- a/src/libstd/clone.rs
+++ b/src/libstd/clone.rs
@@ -29,12 +29,27 @@ pub trait Clone {
     /// are copied to maintain uniqueness, while the contents of
     /// managed pointers are not copied.
     fn clone(&self) -> Self;
+
+    /// Perform copy-assignment from `source`.
+    ///
+    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
+    /// but can be overriden to reuse the resources of `a` to avoid unnecessary
+    /// allocations.
+    #[inline(always)]
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
 }
 
 impl<T: Clone> Clone for ~T {
-    /// Return a deep copy of the owned box.
+    /// Return a copy of the owned box.
     #[inline]
     fn clone(&self) -> ~T { ~(**self).clone() }
+
+    /// Perform copy-assignment from `source` by reusing the existing allocation.
+    fn clone_from(&mut self, source: &~T) {
+        **self = (**source).clone()
+    }
 }
 
 impl<T> Clone for @T {
@@ -118,16 +133,31 @@ extern_fn_clone!(A, B, C, D, E, F, G, H)
 
 /// A trait distinct from `Clone` which represents "deep copies" of things like
 /// managed boxes which would otherwise not be copied.
-pub trait DeepClone {
+pub trait DeepClone: Clone {
     /// Return a deep copy of the value. Unlike `Clone`, the contents of shared pointer types
     /// *are* copied.
     fn deep_clone(&self) -> Self;
+
+    /// Perform deep copy-assignment from `source`.
+    ///
+    /// `a.deep_clone_from(&b)` is equivalent to `a = b.deep_clone()` in
+    /// functionality, but can be overriden to reuse the resources of `a` to
+    /// avoid unnecessary allocations.
+    #[inline(always)]
+    fn deep_clone_from(&mut self, source: &Self) {
+        *self = source.deep_clone()
+    }
 }
 
 impl<T: DeepClone> DeepClone for ~T {
     /// Return a deep copy of the owned box.
     #[inline]
     fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }
+
+    /// Perform deep copy-assignment from `source` by reusing the existing allocation.
+    fn deep_clone_from(&mut self, source: &~T) {
+        **self = (**source).deep_clone()
+    }
 }
 
 // FIXME: #6525: should also be implemented for `T: Send + DeepClone`
@@ -235,6 +265,22 @@ fn test_borrowed_clone() {
 }
 
 #[test]
+fn test_clone_from() {
+    let a = ~5;
+    let mut b = ~10;
+    b.clone_from(&a);
+    assert_eq!(*b, 5);
+}
+
+#[test]
+fn test_deep_clone_from() {
+    let a = ~5;
+    let mut b = ~10;
+    b.deep_clone_from(&a);
+    assert_eq!(*b, 5);
+}
+
+#[test]
 fn test_extern_fn_clone() {
     trait Empty {}
     impl Empty for int {}
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 194a72bad6f..055b0b92121 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -2029,7 +2029,7 @@ impl<'self, T:Clone> MutableCloneableVector<T> for &'self mut [T] {
     #[inline]
     fn copy_from(self, src: &[T]) -> uint {
         for (a, b) in self.mut_iter().zip(src.iter()) {
-            *a = b.clone();
+            a.clone_from(b);
         }
         cmp::min(self.len(), src.len())
     }
@@ -2282,6 +2282,17 @@ impl<A: Clone> Clone for ~[A] {
     fn clone(&self) -> ~[A] {
         self.iter().map(|item| item.clone()).collect()
     }
+
+    fn clone_from(&mut self, source: &~[A]) {
+        if self.len() < source.len() {
+            *self = source.clone()
+        } else {
+            self.truncate(source.len());
+            for (x, y) in self.mut_iter().zip(source.iter()) {
+                x.clone_from(y);
+            }
+        }
+    }
 }
 
 impl<A: DeepClone> DeepClone for ~[A] {
@@ -2289,6 +2300,17 @@ impl<A: DeepClone> DeepClone for ~[A] {
     fn deep_clone(&self) -> ~[A] {
         self.iter().map(|item| item.deep_clone()).collect()
     }
+
+    fn deep_clone_from(&mut self, source: &~[A]) {
+        if self.len() < source.len() {
+            *self = source.deep_clone()
+        } else {
+            self.truncate(source.len());
+            for (x, y) in self.mut_iter().zip(source.iter()) {
+                x.deep_clone_from(y);
+            }
+        }
+    }
 }
 
 // This works because every lifetime is a sub-lifetime of 'static