]> git.lizzy.rs Git - rust.git/commitdiff
Implement cell::clone_ref
authorKeegan McAllister <kmcallister@mozilla.com>
Wed, 14 May 2014 00:29:30 +0000 (17:29 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 15 May 2014 20:50:55 +0000 (13:50 -0700)
Per discussion with @alexcrichton, this is a free function.

src/libcore/cell.rs

index 0413b31e8b76efa1694e3204a4db420fe9983150..8b3494f3127339cc83beaa7f592393a4364c5732 100644 (file)
@@ -186,6 +186,25 @@ fn deref<'a>(&'a self) -> &'a 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<T>
@@ -307,4 +326,19 @@ fn discard_doesnt_unborrow() {
         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());
+    }
 }