From 344aa2a75e15bd565905bed640118cdbc415b942 Mon Sep 17 00:00:00 2001 From: David Ross Date: Mon, 21 Oct 2024 13:21:19 -0700 Subject: [PATCH] Implement RefCell::{try_replace, try_replace_with, try_swap} Resolves https://github.com/rust-lang/rust/issues/54493. --- library/core/src/cell.rs | 119 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index e1fa43296d020..ee71a9e449300 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -899,6 +899,43 @@ impl RefCell { 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 { + 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. /// @@ -924,6 +961,42 @@ impl RefCell { 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 T>(&self, f: F) -> Result { + 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. /// @@ -949,6 +1022,52 @@ impl RefCell { 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 RefCell {