Skip to content

Commit 8a15333

Browse files
committed
auto merge of #6498 : thestinger/rust/deep_clone, r=thestinger
This is mostly for `std::rc` and `std::arc` (but I haven't implemented it for ARC yet). Implementing it correctly for managed boxes is *very* non-trivial. It would probably require an unholy mix of reflection and TLS.
2 parents f4c88c7 + cda3ac9 commit 8a15333

File tree

5 files changed

+139
-15
lines changed

5 files changed

+139
-15
lines changed

src/libcore/cell.rs

+7
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,17 @@ Similar to a mutable option type, but friendlier.
2121
*/
2222

2323
#[mutable]
24+
#[deriving(Clone)]
2425
pub struct Cell<T> {
2526
priv value: Option<T>
2627
}
2728

29+
impl<T: DeepClone> DeepClone for Cell<T> {
30+
fn deep_clone(&self) -> Cell<T> {
31+
Cell{value: self.value.deep_clone()}
32+
}
33+
}
34+
2835
impl<T:cmp::Eq> cmp::Eq for Cell<T> {
2936
fn eq(&self, other: &Cell<T>) -> bool {
3037
(self.value) == (other.value)

src/libcore/clone.rs

+48-9
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,12 @@ 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.
26+
/// Return a deep copy of the owned object tree. Types with shared ownership like managed boxes
27+
/// are cloned with a shallow copy.
2728
fn clone(&self) -> Self;
2829
}
2930

30-
impl Clone for () {
31-
/// Return a copy of the value.
32-
#[inline(always)]
33-
fn clone(&self) -> () { () }
34-
}
35-
36-
impl<T:Clone> Clone for ~T {
31+
impl<T: Clone> Clone for ~T {
3732
/// Return a deep copy of the owned box.
3833
#[inline(always)]
3934
fn clone(&self) -> ~T { ~(**self).clone() }
@@ -54,7 +49,7 @@ impl<T> Clone for @mut T {
5449
macro_rules! clone_impl(
5550
($t:ty) => {
5651
impl Clone for $t {
57-
/// Return a copy of the value.
52+
/// Return a deep copy of the value.
5853
#[inline(always)]
5954
fn clone(&self) -> $t { *self }
6055
}
@@ -77,9 +72,53 @@ clone_impl!(float)
7772
clone_impl!(f32)
7873
clone_impl!(f64)
7974

75+
clone_impl!(())
8076
clone_impl!(bool)
8177
clone_impl!(char)
8278

79+
pub trait DeepClone {
80+
/// Return a deep copy of the object tree. Types with shared ownership are also copied via a
81+
/// deep copy, unlike `Clone`. Note that this is currently unimplemented for managed boxes, as
82+
/// it would need to handle cycles.
83+
fn deep_clone(&self) -> Self;
84+
}
85+
86+
macro_rules! deep_clone_impl(
87+
($t:ty) => {
88+
impl DeepClone for $t {
89+
/// Return a deep copy of the value.
90+
#[inline(always)]
91+
fn deep_clone(&self) -> $t { *self }
92+
}
93+
}
94+
)
95+
96+
impl<T: DeepClone> DeepClone for ~T {
97+
/// Return a deep copy of the owned box.
98+
#[inline(always)]
99+
fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }
100+
}
101+
102+
deep_clone_impl!(int)
103+
deep_clone_impl!(i8)
104+
deep_clone_impl!(i16)
105+
deep_clone_impl!(i32)
106+
deep_clone_impl!(i64)
107+
108+
deep_clone_impl!(uint)
109+
deep_clone_impl!(u8)
110+
deep_clone_impl!(u16)
111+
deep_clone_impl!(u32)
112+
deep_clone_impl!(u64)
113+
114+
deep_clone_impl!(float)
115+
deep_clone_impl!(f32)
116+
deep_clone_impl!(f64)
117+
118+
deep_clone_impl!(())
119+
deep_clone_impl!(bool)
120+
deep_clone_impl!(char)
121+
83122
#[test]
84123
fn test_owned_clone() {
85124
let a: ~int = ~5i;

src/libcore/option.rs

+10
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use num::Zero;
4949
use old_iter::{BaseIter, MutableIter, ExtendedIter};
5050
use old_iter;
5151
use str::StrSlice;
52+
use clone::DeepClone;
5253

5354
#[cfg(test)] use str;
5455

@@ -59,6 +60,15 @@ pub enum Option<T> {
5960
Some(T),
6061
}
6162

63+
impl<T: DeepClone> DeepClone for Option<T> {
64+
fn deep_clone(&self) -> Option<T> {
65+
match *self {
66+
Some(ref x) => Some(x.deep_clone()),
67+
None => None
68+
}
69+
}
70+
}
71+
6272
impl<T:Ord> Ord for Option<T> {
6373
fn lt(&self, other: &Option<T>) -> bool {
6474
match (self, other) {

src/libcore/prelude.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use io::{print, println};
2727

2828
/* Reexported types and traits */
2929

30-
pub use clone::Clone;
30+
pub use clone::{Clone, DeepClone};
3131
pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
3232
pub use container::{Container, Mutable, Map, Set};
3333
pub use hash::Hash;

src/libstd/rc.rs

+73-5
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ impl<T: Owned> Drop for Rc<T> {
7676

7777

7878
impl<T: Owned> Clone for Rc<T> {
79+
/// Return a shallow copy of the reference counted pointer.
7980
#[inline]
8081
fn clone(&self) -> Rc<T> {
8182
unsafe {
@@ -85,9 +86,38 @@ impl<T: Owned> Clone for Rc<T> {
8586
}
8687
}
8788

89+
impl<T: Owned + DeepClone> DeepClone for Rc<T> {
90+
/// Return a deep copy of the reference counted pointer.
91+
#[inline]
92+
fn deep_clone(&self) -> Rc<T> {
93+
Rc::new(self.borrow().deep_clone())
94+
}
95+
}
96+
8897
#[cfg(test)]
8998
mod test_rc {
9099
use super::*;
100+
use core::cell::Cell;
101+
102+
#[test]
103+
fn test_clone() {
104+
let x = Rc::new(Cell(5));
105+
let y = x.clone();
106+
do x.borrow().with_mut_ref |inner| {
107+
*inner = 20;
108+
}
109+
assert_eq!(y.borrow().take(), 20);
110+
}
111+
112+
#[test]
113+
fn test_deep_clone() {
114+
let x = Rc::new(Cell(5));
115+
let y = x.deep_clone();
116+
do x.borrow().with_mut_ref |inner| {
117+
*inner = 20;
118+
}
119+
assert_eq!(y.borrow().take(), 5);
120+
}
91121

92122
#[test]
93123
fn test_simple() {
@@ -96,7 +126,7 @@ mod test_rc {
96126
}
97127

98128
#[test]
99-
fn test_clone() {
129+
fn test_simple_clone() {
100130
let x = Rc::new(5);
101131
let y = x.clone();
102132
assert_eq!(*x.borrow(), 5);
@@ -149,24 +179,26 @@ pub impl<T: Owned> RcMut<T> {
149179

150180
/// Fails if there is already a mutable borrow of the box
151181
#[inline]
152-
fn with_borrow(&self, f: &fn(&T)) {
182+
fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
153183
unsafe {
154184
assert!((*self.ptr).borrow != Mutable);
155185
let previous = (*self.ptr).borrow;
156186
(*self.ptr).borrow = Immutable;
157-
f(&(*self.ptr).value);
187+
let res = f(&(*self.ptr).value);
158188
(*self.ptr).borrow = previous;
189+
res
159190
}
160191
}
161192

162193
/// Fails if there is already a mutable or immutable borrow of the box
163194
#[inline]
164-
fn with_mut_borrow(&self, f: &fn(&mut T)) {
195+
fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
165196
unsafe {
166197
assert!((*self.ptr).borrow == Nothing);
167198
(*self.ptr).borrow = Mutable;
168-
f(&mut (*self.ptr).value);
199+
let res = f(&mut (*self.ptr).value);
169200
(*self.ptr).borrow = Nothing;
201+
res
170202
}
171203
}
172204
}
@@ -200,6 +232,7 @@ impl<T: Owned> Drop for RcMut<T> {
200232
}
201233

202234
impl<T: Owned> Clone for RcMut<T> {
235+
/// Return a shallow copy of the reference counted pointer.
203236
#[inline]
204237
fn clone(&self) -> RcMut<T> {
205238
unsafe {
@@ -209,10 +242,45 @@ impl<T: Owned> Clone for RcMut<T> {
209242
}
210243
}
211244

245+
impl<T: Owned + DeepClone> DeepClone for RcMut<T> {
246+
/// Return a deep copy of the reference counted pointer.
247+
#[inline]
248+
fn deep_clone(&self) -> RcMut<T> {
249+
do self.with_borrow |x| {
250+
// FIXME: #6497: should avoid freeze (slow)
251+
RcMut::new(x.deep_clone())
252+
}
253+
}
254+
}
255+
212256
#[cfg(test)]
213257
mod test_rc_mut {
214258
use super::*;
215259

260+
#[test]
261+
fn test_clone() {
262+
let x = RcMut::new(5);
263+
let y = x.clone();
264+
do x.with_mut_borrow |value| {
265+
*value = 20;
266+
}
267+
do y.with_borrow |value| {
268+
assert_eq!(*value, 20);
269+
}
270+
}
271+
272+
#[test]
273+
fn test_deep_clone() {
274+
let x = RcMut::new(5);
275+
let y = x.deep_clone();
276+
do x.with_mut_borrow |value| {
277+
*value = 20;
278+
}
279+
do y.with_borrow |value| {
280+
assert_eq!(*value, 5);
281+
}
282+
}
283+
216284
#[test]
217285
fn borrow_many() {
218286
let x = RcMut::new(5);

0 commit comments

Comments
 (0)