]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/cell.rs
Rollup merge of #69340 - Centril:self-ctor-normalize, r=nikomatsakis
[rust.git] / src / libcore / cell.rs
index e7eecf7540ad74121d4a0c840536afff154a98e5..9ebb317641875ae42b31634c61f3eeff9781cff2 100644 (file)
@@ -1245,6 +1245,38 @@ pub fn map_split<U: ?Sized, V: ?Sized, F>(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>
         let borrow = orig.borrow.clone();
         (Ref { value: a, borrow }, Ref { value: b, borrow: orig.borrow })
     }
+
+    /// Convert into a reference to the underlying data.
+    ///
+    /// The underlying `RefCell` can never be mutably borrowed from again and will always appear
+    /// already immutably borrowed. It is not a good idea to leak more than a constant number of
+    /// references. The `RefCell` can be immutably borrowed again if only a smaller number of leaks
+    /// have occurred in total.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `Ref::leak(...)`. A method would interfere with methods of the
+    /// same name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_leak)]
+    /// use std::cell::{RefCell, Ref};
+    /// let cell = RefCell::new(0);
+    ///
+    /// let value = Ref::leak(cell.borrow());
+    /// assert_eq!(*value, 0);
+    ///
+    /// assert!(cell.try_borrow().is_ok());
+    /// assert!(cell.try_borrow_mut().is_err());
+    /// ```
+    #[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.
+        mem::forget(orig.borrow);
+        orig.value
+    }
 }
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
@@ -1330,6 +1362,37 @@ pub fn map_split<U: ?Sized, V: ?Sized, F>(
         let borrow = orig.borrow.clone();
         (RefMut { value: a, borrow }, RefMut { value: b, borrow: orig.borrow })
     }
+
+    /// Convert into a mutable reference to the underlying data.
+    ///
+    /// The underlying `RefCell` can not be borrowed from again and will always appear already
+    /// mutably borrowed, making the returned reference the only to the interior.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `RefMut::leak(...)`. A method would interfere with methods of the
+    /// same name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_leak)]
+    /// use std::cell::{RefCell, RefMut};
+    /// let cell = RefCell::new(0);
+    ///
+    /// let value = RefMut::leak(cell.borrow_mut());
+    /// assert_eq!(*value, 0);
+    /// *value = 1;
+    ///
+    /// assert!(cell.try_borrow_mut().is_err());
+    /// ```
+    #[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.
+        mem::forget(orig.borrow);
+        orig.value
+    }
 }
 
 struct BorrowRefMut<'b> {
@@ -1475,6 +1538,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
+#[cfg_attr(not(bootstrap), repr(no_niche))] // rust-lang/rust#68303.
 pub struct UnsafeCell<T: ?Sized> {
     value: T,
 }