Skip to content

Commit 75822f2

Browse files
committed
add a DeepClone trait
for deep copies through shared ownership boundaries
1 parent fa45958 commit 75822f2

File tree

3 files changed

+126
-12
lines changed

3 files changed

+126
-12
lines changed

src/libcore/clone.rs

+45-7
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@ pub trait Clone {
2828
fn clone(&self) -> Self;
2929
}
3030

31-
impl Clone for () {
32-
/// Return a copy of the value.
33-
#[inline(always)]
34-
fn clone(&self) -> () { () }
35-
}
36-
3731
impl<T: Clone> Clone for ~T {
3832
/// Return a deep copy of the owned box.
3933
#[inline(always)]
@@ -55,7 +49,7 @@ impl<T> Clone for @mut T {
5549
macro_rules! clone_impl(
5650
($t:ty) => {
5751
impl Clone for $t {
58-
/// Return a copy of the value.
52+
/// Return a deep copy of the value.
5953
#[inline(always)]
6054
fn clone(&self) -> $t { *self }
6155
}
@@ -78,9 +72,53 @@ clone_impl!(float)
7872
clone_impl!(f32)
7973
clone_impl!(f64)
8074

75+
clone_impl!(())
8176
clone_impl!(bool)
8277
clone_impl!(char)
8378

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+
84122
#[test]
85123
fn test_owned_clone() {
86124
let a: ~int = ~5i;

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

+80-4
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,46 @@ 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.with_borrow |cell| {
107+
do value.with_mut_ref |inner| {
108+
*inner = 20;
109+
}
110+
}
111+
do y.with_borrow |value| {
112+
assert_eq!(value.take(), 20);
113+
}
114+
}
115+
116+
#[test]
117+
fn test_deep_clone() {
118+
let x = Rc::new(Cell(5));
119+
let y = x.deep_clone();
120+
do x.with_borrow |cell| {
121+
do value.with_mut_ref |inner| {
122+
*inner = 20;
123+
}
124+
}
125+
do y.with_borrow |value| {
126+
assert_eq!(value.take(), 5);
127+
}
128+
}
91129

92130
#[test]
93131
fn test_simple() {
@@ -149,24 +187,26 @@ pub impl<T: Owned> RcMut<T> {
149187

150188
/// Fails if there is already a mutable borrow of the box
151189
#[inline]
152-
fn with_borrow(&self, f: &fn(&T)) {
190+
fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
153191
unsafe {
154192
assert!((*self.ptr).borrow != Mutable);
155193
let previous = (*self.ptr).borrow;
156194
(*self.ptr).borrow = Immutable;
157-
f(&(*self.ptr).value);
195+
let res = f(&(*self.ptr).value);
158196
(*self.ptr).borrow = previous;
197+
res
159198
}
160199
}
161200

162201
/// Fails if there is already a mutable or immutable borrow of the box
163202
#[inline]
164-
fn with_mut_borrow(&self, f: &fn(&mut T)) {
203+
fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
165204
unsafe {
166205
assert!((*self.ptr).borrow == Nothing);
167206
(*self.ptr).borrow = Mutable;
168-
f(&mut (*self.ptr).value);
207+
let res = f(&mut (*self.ptr).value);
169208
(*self.ptr).borrow = Nothing;
209+
res
170210
}
171211
}
172212
}
@@ -200,6 +240,7 @@ impl<T: Owned> Drop for RcMut<T> {
200240
}
201241

202242
impl<T: Owned> Clone for RcMut<T> {
243+
/// Return a shallow copy of the reference counted pointer.
203244
#[inline]
204245
fn clone(&self) -> RcMut<T> {
205246
unsafe {
@@ -209,10 +250,45 @@ impl<T: Owned> Clone for RcMut<T> {
209250
}
210251
}
211252

253+
impl<T: Owned + DeepClone> DeepClone for RcMut<T> {
254+
/// Return a deep copy of the reference counted pointer.
255+
#[inline]
256+
fn deep_clone(&self) -> RcMut<T> {
257+
do self.with_borrow |x| {
258+
// FIXME: #6497: should avoid freeze (slow)
259+
RcMut::new(x.deep_clone())
260+
}
261+
}
262+
}
263+
212264
#[cfg(test)]
213265
mod test_rc_mut {
214266
use super::*;
215267

268+
#[test]
269+
fn test_clone() {
270+
let x = RcMut::new(5);
271+
let y = x.clone();
272+
do x.with_mut_borrow |value| {
273+
*value = 20;
274+
}
275+
do y.with_borrow |value| {
276+
assert_eq!(*value, 20);
277+
}
278+
}
279+
280+
#[test]
281+
fn test_deep_clone() {
282+
let x = RcMut::new(5);
283+
let y = x.deep_clone();
284+
do x.with_mut_borrow |value| {
285+
*value = 20;
286+
}
287+
do y.with_borrow |value| {
288+
assert_eq!(*value, 5);
289+
}
290+
}
291+
216292
#[test]
217293
fn borrow_many() {
218294
let x = RcMut::new(5);

0 commit comments

Comments
 (0)