Skip to content

Commit d14a647

Browse files
committed
auto merge of #10376 : thestinger/rust/clone, r=huonw
Closes #10240
2 parents a594a99 + 6943ca8 commit d14a647

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

src/libstd/clone.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,27 @@ pub trait Clone {
2929
/// are copied to maintain uniqueness, while the contents of
3030
/// managed pointers are not copied.
3131
fn clone(&self) -> Self;
32+
33+
/// Perform copy-assignment from `source`.
34+
///
35+
/// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
36+
/// but can be overriden to reuse the resources of `a` to avoid unnecessary
37+
/// allocations.
38+
#[inline(always)]
39+
fn clone_from(&mut self, source: &Self) {
40+
*self = source.clone()
41+
}
3242
}
3343

3444
impl<T: Clone> Clone for ~T {
35-
/// Return a deep copy of the owned box.
45+
/// Return a copy of the owned box.
3646
#[inline]
3747
fn clone(&self) -> ~T { ~(**self).clone() }
48+
49+
/// Perform copy-assignment from `source` by reusing the existing allocation.
50+
fn clone_from(&mut self, source: &~T) {
51+
**self = (**source).clone()
52+
}
3853
}
3954

4055
impl<T> Clone for @T {
@@ -118,16 +133,31 @@ extern_fn_clone!(A, B, C, D, E, F, G, H)
118133

119134
/// A trait distinct from `Clone` which represents "deep copies" of things like
120135
/// managed boxes which would otherwise not be copied.
121-
pub trait DeepClone {
136+
pub trait DeepClone: Clone {
122137
/// Return a deep copy of the value. Unlike `Clone`, the contents of shared pointer types
123138
/// *are* copied.
124139
fn deep_clone(&self) -> Self;
140+
141+
/// Perform deep copy-assignment from `source`.
142+
///
143+
/// `a.deep_clone_from(&b)` is equivalent to `a = b.deep_clone()` in
144+
/// functionality, but can be overriden to reuse the resources of `a` to
145+
/// avoid unnecessary allocations.
146+
#[inline(always)]
147+
fn deep_clone_from(&mut self, source: &Self) {
148+
*self = source.deep_clone()
149+
}
125150
}
126151

127152
impl<T: DeepClone> DeepClone for ~T {
128153
/// Return a deep copy of the owned box.
129154
#[inline]
130155
fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }
156+
157+
/// Perform deep copy-assignment from `source` by reusing the existing allocation.
158+
fn deep_clone_from(&mut self, source: &~T) {
159+
**self = (**source).deep_clone()
160+
}
131161
}
132162

133163
// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
@@ -234,6 +264,22 @@ fn test_borrowed_clone() {
234264
assert_eq!(*z, 5);
235265
}
236266

267+
#[test]
268+
fn test_clone_from() {
269+
let a = ~5;
270+
let mut b = ~10;
271+
b.clone_from(&a);
272+
assert_eq!(*b, 5);
273+
}
274+
275+
#[test]
276+
fn test_deep_clone_from() {
277+
let a = ~5;
278+
let mut b = ~10;
279+
b.deep_clone_from(&a);
280+
assert_eq!(*b, 5);
281+
}
282+
237283
#[test]
238284
fn test_extern_fn_clone() {
239285
trait Empty {}

src/libstd/vec.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -2029,7 +2029,7 @@ impl<'self, T:Clone> MutableCloneableVector<T> for &'self mut [T] {
20292029
#[inline]
20302030
fn copy_from(self, src: &[T]) -> uint {
20312031
for (a, b) in self.mut_iter().zip(src.iter()) {
2032-
*a = b.clone();
2032+
a.clone_from(b);
20332033
}
20342034
cmp::min(self.len(), src.len())
20352035
}
@@ -2282,13 +2282,35 @@ impl<A: Clone> Clone for ~[A] {
22822282
fn clone(&self) -> ~[A] {
22832283
self.iter().map(|item| item.clone()).collect()
22842284
}
2285+
2286+
fn clone_from(&mut self, source: &~[A]) {
2287+
if self.len() < source.len() {
2288+
*self = source.clone()
2289+
} else {
2290+
self.truncate(source.len());
2291+
for (x, y) in self.mut_iter().zip(source.iter()) {
2292+
x.clone_from(y);
2293+
}
2294+
}
2295+
}
22852296
}
22862297

22872298
impl<A: DeepClone> DeepClone for ~[A] {
22882299
#[inline]
22892300
fn deep_clone(&self) -> ~[A] {
22902301
self.iter().map(|item| item.deep_clone()).collect()
22912302
}
2303+
2304+
fn deep_clone_from(&mut self, source: &~[A]) {
2305+
if self.len() < source.len() {
2306+
*self = source.deep_clone()
2307+
} else {
2308+
self.truncate(source.len());
2309+
for (x, y) in self.mut_iter().zip(source.iter()) {
2310+
x.deep_clone_from(y);
2311+
}
2312+
}
2313+
}
22922314
}
22932315

22942316
// This works because every lifetime is a sub-lifetime of 'static

0 commit comments

Comments
 (0)