Skip to content

Commit 68d17bc

Browse files
committed
clone: managed boxes need to clone by shallow copy
Performing a deep copy isn't ever desired for a persistent data structure, and it requires a more complex implementation to do correctly. A deep copy needs to check for cycles to avoid an infinite loop.
1 parent 44d4d6d commit 68d17bc

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

src/libcore/clone.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ In Rust, some simple types are "implicitly copyable" and when you
1414
assign them or pass them as arguments, the receiver will get a copy,
1515
leaving the original value in place. These types do not require
1616
allocation to copy and do not have finalizers (i.e. they do not
17-
contain owned pointers or implement `Drop`), so the compiler considers
17+
contain owned boxes or implement `Drop`), so the compiler considers
1818
them cheap and safe to copy and automatically implements the `Copy`
1919
trait for them. For other types copies must be made explicitly,
2020
by convention implementing the `Clone` trait and calling the
@@ -23,32 +23,38 @@ by convention implementing the `Clone` trait and calling the
2323
*/
2424

2525
pub trait Clone {
26+
/// Return a deep copy of the owned object tree. Managed boxes are cloned with a shallow copy.
2627
fn clone(&self) -> Self;
2728
}
2829

2930
impl Clone for () {
31+
/// Return a copy of the value.
3032
#[inline(always)]
3133
fn clone(&self) -> () { () }
3234
}
3335

3436
impl<T:Clone> Clone for ~T {
37+
/// Return a deep copy of the owned box.
3538
#[inline(always)]
3639
fn clone(&self) -> ~T { ~(**self).clone() }
3740
}
3841

39-
impl<T:Clone> Clone for @T {
42+
impl<T> Clone for @T {
43+
/// Return a shallow copy of the managed box.
4044
#[inline(always)]
41-
fn clone(&self) -> @T { @(**self).clone() }
45+
fn clone(&self) -> @T { *self }
4246
}
4347

44-
impl<T:Clone> Clone for @mut T {
48+
impl<T> Clone for @mut T {
49+
/// Return a shallow copy of the managed box.
4550
#[inline(always)]
46-
fn clone(&self) -> @mut T { @mut (**self).clone() }
51+
fn clone(&self) -> @mut T { *self }
4752
}
4853

4954
macro_rules! clone_impl(
5055
($t:ty) => {
5156
impl Clone for $t {
57+
/// Return a copy of the value.
5258
#[inline(always)]
5359
fn clone(&self) -> $t { *self }
5460
}
@@ -76,21 +82,23 @@ clone_impl!(char)
7682

7783
#[test]
7884
fn test_owned_clone() {
79-
let a : ~int = ~5i;
80-
let b : ~int = a.clone();
85+
let a: ~int = ~5i;
86+
let b: ~int = a.clone();
8187
assert!(a == b);
8288
}
8389

8490
#[test]
8591
fn test_managed_clone() {
86-
let a : @int = @5i;
87-
let b : @int = a.clone();
92+
let a: @int = @5i;
93+
let b: @int = a.clone();
8894
assert!(a == b);
8995
}
9096

9197
#[test]
9298
fn test_managed_mut_clone() {
93-
let a : @int = @5i;
94-
let b : @int = a.clone();
99+
let a: @mut int = @mut 5i;
100+
let b: @mut int = a.clone();
101+
assert!(a == b);
102+
*b = 10;
95103
assert!(a == b);
96104
}

src/test/run-pass/borrowck-borrow-from-expr-block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn borrow(x: &int, f: &fn(x: &int)) {
1313
}
1414

1515
fn test1(x: @~int) {
16-
do borrow(&**x.clone()) |p| {
16+
do borrow(&*(*x).clone()) |p| {
1717
let x_a = ptr::addr_of(&(**x));
1818
assert!((x_a as uint) != ptr::to_uint(p));
1919
assert!(unsafe{*x_a} == *p);

0 commit comments

Comments
 (0)