Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce RefCell::{try_replace, try_replace_with, try_swap} #132011

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,43 @@ impl<T> RefCell<T> {
mem::replace(&mut *self.borrow_mut(), t)
}

/// Replaces the wrapped value with a new one, returning the old value,
/// without deinitializing either one.
///
/// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html).
///
/// This is the non-panicking variant of [`replace`](#method.replace).
///
/// # Examples
///
/// ```
/// #![feature(refcell_try_replace)]
/// use std::cell::RefCell;
///
/// let cell = RefCell::new(5);
///
/// {
/// let borrowed_five = cell.borrow();
/// let replace_result = cell.try_replace(6);
/// assert!(replace_result.is_err());
/// assert_eq!(cell, RefCell::new(5));
///
/// }
///
/// {
/// let replace_result = cell.try_replace(6);
/// assert!(replace_result.is_ok());
/// assert_eq!(cell, RefCell::new(6));
/// }
/// ```
#[inline]
#[unstable(feature = "refcell_try_replace", issue = "none")]
#[track_caller]
#[rustc_confusables("try_swap")]
pub fn try_replace(&self, t: T) -> Result<T, BorrowMutError> {
Ok(mem::replace(&mut *self.try_borrow_mut()?, t))
}

/// Replaces the wrapped value with a new one computed from `f`, returning
/// the old value, without deinitializing either one.
///
Expand All @@ -924,6 +961,42 @@ impl<T> RefCell<T> {
mem::replace(mut_borrow, replacement)
}

/// Replaces the wrapped value with a new one computed from `f`, returning
/// the old value, without deinitializing either one.
///
/// This is the non-panicking variant of [`replace_with`](#method.replace_with).
///
/// # Examples
///
/// ```
/// #![feature(refcell_try_replace)]
/// use std::cell::RefCell;
///
/// let cell = RefCell::new(5);
///
/// {
/// let borrowed_five = cell.borrow();
/// let replace_result = cell.try_replace_with(|&mut old| old + 1);
/// assert!(replace_result.is_err());
/// assert_eq!(cell, RefCell::new(5));
///
/// }
///
/// {
/// let replace_result = cell.try_replace_with(|&mut old| old + 1);
/// assert!(replace_result.is_ok());
/// assert_eq!(cell, RefCell::new(6));
/// }
/// ```
#[inline]
#[unstable(feature = "refcell_try_replace", issue = "none")]
#[track_caller]
pub fn try_replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> Result<T, BorrowMutError> {
let mut_borrow = &mut *self.try_borrow_mut()?;
let replacement = f(mut_borrow);
Ok(mem::replace(mut_borrow, replacement))
}

/// Swaps the wrapped value of `self` with the wrapped value of `other`,
/// without deinitializing either one.
///
Expand All @@ -949,6 +1022,52 @@ impl<T> RefCell<T> {
pub fn swap(&self, other: &Self) {
mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
}

/// Swaps the wrapped value of `self` with the wrapped value of `other`,
/// without deinitializing either one.
///
/// This function corresponds to [`std::mem::swap`](../mem/fn.swap.html).
///
/// This is the non-panicking variant of [`swap`](#method.swap).
///
/// # Examples
///
/// ```
/// #![feature(refcell_try_replace)]
/// use std::cell::RefCell;
///
/// let c = RefCell::new(5);
/// let d = RefCell::new(6);
///
/// {
/// let borrowed_c = c.borrow();
/// let swap_result = c.try_swap(&d);
/// assert!(swap_result.is_err());
/// assert_eq!(c, RefCell::new(5));
/// assert_eq!(d, RefCell::new(6));
/// }
///
/// {
/// let borrowed_d = d.borrow();
/// let swap_result = c.try_swap(&d);
/// assert!(swap_result.is_err());
/// assert_eq!(c, RefCell::new(5));
/// assert_eq!(d, RefCell::new(6));
/// }
///
/// {
/// let swap_result = c.try_swap(&d);
/// assert!(swap_result.is_ok());
/// assert_eq!(c, RefCell::new(6));
/// assert_eq!(d, RefCell::new(5));
/// }
/// ```
#[inline]
#[unstable(feature = "refcell_try_replace", issue = "none")]
#[track_caller]
pub fn try_swap(&self, other: &Self) -> Result<(), BorrowMutError> {
Ok(mem::swap(&mut *self.try_borrow_mut()?, &mut *other.try_borrow_mut()?))
}
}

impl<T: ?Sized> RefCell<T> {
Expand Down
Loading