1
Fork 0

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.
This commit is contained in:
Daniel Micay 2013-04-06 20:35:11 -04:00
parent 44d4d6de76
commit 68d17bca4b
2 changed files with 20 additions and 12 deletions

View file

@ -14,7 +14,7 @@ In Rust, some simple types are "implicitly copyable" and when you
assign them or pass them as arguments, the receiver will get a copy, assign them or pass them as arguments, the receiver will get a copy,
leaving the original value in place. These types do not require leaving the original value in place. These types do not require
allocation to copy and do not have finalizers (i.e. they do not allocation to copy and do not have finalizers (i.e. they do not
contain owned pointers or implement `Drop`), so the compiler considers contain owned boxes or implement `Drop`), so the compiler considers
them cheap and safe to copy and automatically implements the `Copy` them cheap and safe to copy and automatically implements the `Copy`
trait for them. For other types copies must be made explicitly, trait for them. For other types copies must be made explicitly,
by convention implementing the `Clone` trait and calling the by convention implementing the `Clone` trait and calling the
@ -23,32 +23,38 @@ by convention implementing the `Clone` trait and calling the
*/ */
pub trait Clone { pub trait Clone {
/// Return a deep copy of the owned object tree. Managed boxes are cloned with a shallow copy.
fn clone(&self) -> Self; fn clone(&self) -> Self;
} }
impl Clone for () { impl Clone for () {
/// Return a copy of the value.
#[inline(always)] #[inline(always)]
fn clone(&self) -> () { () } fn clone(&self) -> () { () }
} }
impl<T:Clone> Clone for ~T { impl<T:Clone> Clone for ~T {
/// Return a deep copy of the owned box.
#[inline(always)] #[inline(always)]
fn clone(&self) -> ~T { ~(**self).clone() } fn clone(&self) -> ~T { ~(**self).clone() }
} }
impl<T:Clone> Clone for @T { impl<T> Clone for @T {
/// Return a shallow copy of the managed box.
#[inline(always)] #[inline(always)]
fn clone(&self) -> @T { @(**self).clone() } fn clone(&self) -> @T { *self }
} }
impl<T:Clone> Clone for @mut T { impl<T> Clone for @mut T {
/// Return a shallow copy of the managed box.
#[inline(always)] #[inline(always)]
fn clone(&self) -> @mut T { @mut (**self).clone() } fn clone(&self) -> @mut T { *self }
} }
macro_rules! clone_impl( macro_rules! clone_impl(
($t:ty) => { ($t:ty) => {
impl Clone for $t { impl Clone for $t {
/// Return a copy of the value.
#[inline(always)] #[inline(always)]
fn clone(&self) -> $t { *self } fn clone(&self) -> $t { *self }
} }
@ -76,21 +82,23 @@ clone_impl!(char)
#[test] #[test]
fn test_owned_clone() { fn test_owned_clone() {
let a : ~int = ~5i; let a: ~int = ~5i;
let b : ~int = a.clone(); let b: ~int = a.clone();
assert!(a == b); assert!(a == b);
} }
#[test] #[test]
fn test_managed_clone() { fn test_managed_clone() {
let a : @int = @5i; let a: @int = @5i;
let b : @int = a.clone(); let b: @int = a.clone();
assert!(a == b); assert!(a == b);
} }
#[test] #[test]
fn test_managed_mut_clone() { fn test_managed_mut_clone() {
let a : @int = @5i; let a: @mut int = @mut 5i;
let b : @int = a.clone(); let b: @mut int = a.clone();
assert!(a == b);
*b = 10;
assert!(a == b); assert!(a == b);
} }

View file

@ -13,7 +13,7 @@ fn borrow(x: &int, f: &fn(x: &int)) {
} }
fn test1(x: @~int) { fn test1(x: @~int) {
do borrow(&**x.clone()) |p| { do borrow(&*(*x).clone()) |p| {
let x_a = ptr::addr_of(&(**x)); let x_a = ptr::addr_of(&(**x));
assert!((x_a as uint) != ptr::to_uint(p)); assert!((x_a as uint) != ptr::to_uint(p));
assert!(unsafe{*x_a} == *p); assert!(unsafe{*x_a} == *p);