From 68d17bca4b12f514331322f938b56331f987ad68 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 6 Apr 2013 20:35:11 -0400 Subject: [PATCH] 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. --- src/libcore/clone.rs | 30 ++++++++++++------- .../borrowck-borrow-from-expr-block.rs | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index c4b5bb8d98bbc..9da970918b0d5 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -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, leaving the original value in place. These types do not require 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` trait for them. For other types copies must be made explicitly, 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 { + /// Return a deep copy of the owned object tree. Managed boxes are cloned with a shallow copy. fn clone(&self) -> Self; } impl Clone for () { + /// Return a copy of the value. #[inline(always)] fn clone(&self) -> () { () } } impl Clone for ~T { + /// Return a deep copy of the owned box. #[inline(always)] fn clone(&self) -> ~T { ~(**self).clone() } } -impl Clone for @T { +impl Clone for @T { + /// Return a shallow copy of the managed box. #[inline(always)] - fn clone(&self) -> @T { @(**self).clone() } + fn clone(&self) -> @T { *self } } -impl Clone for @mut T { +impl Clone for @mut T { + /// Return a shallow copy of the managed box. #[inline(always)] - fn clone(&self) -> @mut T { @mut (**self).clone() } + fn clone(&self) -> @mut T { *self } } macro_rules! clone_impl( ($t:ty) => { impl Clone for $t { + /// Return a copy of the value. #[inline(always)] fn clone(&self) -> $t { *self } } @@ -76,21 +82,23 @@ clone_impl!(char) #[test] fn test_owned_clone() { - let a : ~int = ~5i; - let b : ~int = a.clone(); + let a: ~int = ~5i; + let b: ~int = a.clone(); assert!(a == b); } #[test] fn test_managed_clone() { - let a : @int = @5i; - let b : @int = a.clone(); + let a: @int = @5i; + let b: @int = a.clone(); assert!(a == b); } #[test] fn test_managed_mut_clone() { - let a : @int = @5i; - let b : @int = a.clone(); + let a: @mut int = @mut 5i; + let b: @mut int = a.clone(); + assert!(a == b); + *b = 10; assert!(a == b); } diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck-borrow-from-expr-block.rs index 077de5c7eb125..afa312ea35e7e 100644 --- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs +++ b/src/test/run-pass/borrowck-borrow-from-expr-block.rs @@ -13,7 +13,7 @@ fn borrow(x: &int, f: &fn(x: &int)) { } fn test1(x: @~int) { - do borrow(&**x.clone()) |p| { + do borrow(&*(*x).clone()) |p| { let x_a = ptr::addr_of(&(**x)); assert!((x_a as uint) != ptr::to_uint(p)); assert!(unsafe{*x_a} == *p);