diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs index 701be1b3dfa..92db250ecca 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 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 Clone for @T { @@ -122,12 +137,27 @@ pub trait DeepClone { /// 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 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` @@ -234,6 +264,22 @@ fn test_borrowed_clone() { assert_eq!(*z, 5); } +#[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 {} 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 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 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 DeepClone for ~[A] { @@ -2289,6 +2300,17 @@ impl 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