diff options
| author | bors <bors@rust-lang.org> | 2013-11-08 20:31:23 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-11-08 20:31:23 -0800 |
| commit | d14a647dc355dda43bddfc84903ad53820469fb3 (patch) | |
| tree | f0a26f93fd82ae930df1b55aaa250dc434fda637 /src/libstd | |
| parent | a594a999fbccf04710c9dfea3ef3d231c14e1bd1 (diff) | |
| parent | 6943ca8dcd2f08d6e7291e30bbc6a8c99c4a28c5 (diff) | |
| download | rust-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.rs | 50 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 24 |
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 |
