diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 0413b31e8b76e..8b3494f312733 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -186,6 +186,25 @@ impl<'b, T> Deref for Ref<'b, T> { } } +/// Copy a `Ref`. +/// +/// The `RefCell` is already immutably borrowed, so this cannot fail. +/// +/// A `Clone` implementation would interfere with the widespread +/// use of `r.borrow().clone()` to clone the contents of a `RefCell`. +#[experimental] +pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> { + // Since this Ref exists, we know the borrow flag + // is not set to WRITING. + let borrow = orig.parent.borrow.get(); + debug_assert!(borrow != WRITING && borrow != UNUSED); + orig.parent.borrow.set(borrow + 1); + + Ref { + parent: orig.parent, + } +} + /// Wraps a mutable borrowed reference to a value in a `RefCell` box. pub struct RefMut<'b, T> { parent: &'b RefCell @@ -307,4 +326,19 @@ mod test { let _ = _b; let _b = x.borrow_mut(); } + + #[test] + fn clone_ref_updates_flag() { + let x = RefCell::new(0); + { + let b1 = x.borrow(); + assert!(x.try_borrow_mut().is_none()); + { + let _b2 = clone_ref(&b1); + assert!(x.try_borrow_mut().is_none()); + } + assert!(x.try_borrow_mut().is_none()); + } + assert!(x.try_borrow_mut().is_some()); + } }