diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-03-15 15:40:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-15 15:40:03 +0100 |
| commit | 83aad6b9a86e6331620d8ecb496ca2d62e887c7c (patch) | |
| tree | 0036f8e023f4d4d00be56c9cf4833d2d2e5e31bb /src/libcore | |
| parent | 5a72ecf2c5c97933cecce91cb58d104da8120624 (diff) | |
| parent | 51b93966240acffdbe3fbb898bb647a03b146e09 (diff) | |
| download | rust-83aad6b9a86e6331620d8ecb496ca2d62e887c7c.tar.gz rust-83aad6b9a86e6331620d8ecb496ca2d62e887c7c.zip | |
Rollup merge of #69528 - HeroicKatora:finalize-ref-cell, r=dtolnay
Add undo_leak to reset RefCell borrow state This method is complementary for the feature cell_leak added in an earlier PR. It allows *safely* reverting the effects of leaking a borrow guard by statically proving that such a guard could not longer exist. This was not added to the existing `get_mut` out of concern of impacting the complexity of the otherwise pure pointer cast and because the name `get_mut` poorly communicates the intent of resetting remaining borrows. This is a follow-up to #68712 and uses the same tracking issue, #69099, as these methods deal with the same mechanism and the idea came up [in a review comment](https://github.com/rust-lang/rust/pull/68712#discussion_r384670041). @dtolnay who reviewed the prior PR. cc @RalfJung
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/cell.rs | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9ebb3176418..dbf073cd479 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -958,6 +958,33 @@ impl<T: ?Sized> RefCell<T> { unsafe { &mut *self.value.get() } } + /// Undo the effect of leaked guards on the borrow state of the `RefCell`. + /// + /// This call is similar to [`get_mut`] but more specialized. It borrows `RefCell` mutably to + /// ensure no borrows exist and then resets the state tracking shared borrows. This is relevant + /// if some `Ref` or `RefMut` borrows have been leaked. + /// + /// [`get_mut`]: #method.get_mut + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::RefCell; + /// + /// let mut c = RefCell::new(0); + /// std::mem::forget(c.borrow_mut()); + /// + /// assert!(c.try_borrow().is_err()); + /// c.undo_leak(); + /// assert!(c.try_borrow().is_ok()); + /// ``` + #[unstable(feature = "cell_leak", issue = "69099")] + pub fn undo_leak(&mut self) -> &mut T { + *self.borrow.get_mut() = UNUSED; + self.get_mut() + } + /// Immutably borrows the wrapped value, returning an error if the value is /// currently mutably borrowed. /// @@ -1272,8 +1299,10 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// ``` #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: Ref<'b, T>) -> &'b T { - // By forgetting this Ref we ensure that the borrow counter in the RefCell never goes back - // to UNUSED again. No further mutable references can be created from the original cell. + // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to + // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a + // unique reference to the borrowed RefCell. No further mutable references can be created + // from the original cell. mem::forget(orig.borrow); orig.value } @@ -1387,9 +1416,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// ``` #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: RefMut<'b, T>) -> &'b mut T { - // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never - // goes back to UNUSED again. No further references can be created from the original cell, - // making the current borrow the only reference for the remaining lifetime. + // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't + // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would + // require a unique reference to the borrowed RefCell. No further references can be created + // from the original cell within that lifetime, making the current borrow the only + // reference for the remaining lifetime. mem::forget(orig.borrow); orig.value } |
