@@ -1543,8 +1543,11 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
15431543/// allow internal mutability, such as `Cell<T>` and `RefCell<T>`, use `UnsafeCell` to wrap their
15441544/// internal data. There is *no* legal way to obtain aliasing `&mut`, not even with `UnsafeCell<T>`.
15451545///
1546- /// The `UnsafeCell` API itself is technically very simple: it gives you a raw pointer `*mut T` to
1547- /// its contents. It is up to _you_ as the abstraction designer to use that raw pointer correctly.
1546+ /// The `UnsafeCell` API itself is technically very simple: [`.get()`] gives you a raw pointer
1547+ /// `*mut T` to its contents. It is up to _you_ as the abstraction designer to use that raw pointer
1548+ /// correctly.
1549+ ///
1550+ /// [`.get()`]: `UnsafeCell::get`
15481551///
15491552/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious:
15501553///
@@ -1571,21 +1574,70 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
15711574/// 2. A `&mut T` reference may be released to safe code provided neither other `&mut T` nor `&T`
15721575/// co-exist with it. A `&mut T` must always be unique.
15731576///
1574- /// Note that while mutating or mutably aliasing the contents of an `&UnsafeCell<T>` is
1575- /// ok (provided you enforce the invariants some other way), it is still undefined behavior
1576- /// to have multiple `&mut UnsafeCell<T>` aliases.
1577+ /// Note that whilst mutating the contents of an `&UnsafeCell<T>` (even while other
1578+ /// `&UnsafeCell<T>` references alias the cell) is
1579+ /// ok (provided you enforce the above invariants some other way), it is still undefined behavior
1580+ /// to have multiple `&mut UnsafeCell<T>` aliases. That is, `UnsafeCell` is a wrapper
1581+ /// designed to have a special interaction with _shared_ accesses (_i.e._, through an
1582+ /// `&UnsafeCell<_>` reference); there is no magic whatsoever when dealing with _exclusive_
1583+ /// accesses (_e.g._, through an `&mut UnsafeCell<_>`): neither the cell nor the wrapped value
1584+ /// may be aliased for the duration of that `&mut` borrow.
1585+ /// This is showcased by the [`.get_mut()`] accessor, which is a non-`unsafe` getter that yields
1586+ /// a `&mut T`.
1587+ ///
1588+ /// [`.get_mut()`]: `UnsafeCell::get_mut`
15771589///
15781590/// # Examples
15791591///
1592+ /// Here is an example showcasing how to soundly mutate the contents of an `UnsafeCell<_>` despite
1593+ /// there being multiple references aliasing the cell:
1594+ ///
15801595/// ```
15811596/// use std::cell::UnsafeCell;
15821597///
1583- /// # #[allow(dead_code)]
1584- /// struct NotThreadSafe<T> {
1585- /// value: UnsafeCell<T>,
1598+ /// let x: UnsafeCell<i32> = 42.into();
1599+ /// // Get multiple / concurrent / shared references to the same `x`.
1600+ /// let (p1, p2): (&UnsafeCell<i32>, &UnsafeCell<i32>) = (&x, &x);
1601+ ///
1602+ /// unsafe {
1603+ /// // SAFETY: within this scope there are no other references to `x`'s contents,
1604+ /// // so ours is effectively unique.
1605+ /// let p1_exclusive: &mut i32 = &mut *p1.get(); // -- borrow --+
1606+ /// *p1_exclusive += 27; // |
1607+ /// } // <---------- cannot go beyond this point -------------------+
1608+ ///
1609+ /// unsafe {
1610+ /// // SAFETY: within this scope nobody expects to have exclusive access to `x`'s contents,
1611+ /// // so we can have multiple shared accesses concurrently.
1612+ /// let p2_shared: &i32 = &*p2.get();
1613+ /// assert_eq!(*p2_shared, 42 + 27);
1614+ /// let p1_shared: &i32 = &*p1.get();
1615+ /// assert_eq!(*p1_shared, *p2_shared);
15861616/// }
1617+ /// ```
1618+ ///
1619+ /// The following example showcases the fact that exclusive access to an `UnsafeCell<T>`
1620+ /// implies exclusive access to its `T`:
15871621///
1588- /// unsafe impl<T> Sync for NotThreadSafe<T> {}
1622+ /// ```rust
1623+ /// #![feature(unsafe_cell_get_mut)]
1624+ /// #![forbid(unsafe_code)] // with exclusive accesses,
1625+ /// // `UnsafeCell` is a transparent no-op wrapper,
1626+ /// // so no need for `unsafe` here.
1627+ /// use std::cell::UnsafeCell;
1628+ ///
1629+ /// let mut x: UnsafeCell<i32> = 42.into();
1630+ ///
1631+ /// // Get a compile-time-checked unique reference to `x`.
1632+ /// let p_unique: &mut UnsafeCell<i32> = &mut x;
1633+ /// // With an exclusive reference, we can mutate the contents for free.
1634+ /// *p_unique.get_mut() = 0;
1635+ /// // Or, equivalently:
1636+ /// x = UnsafeCell::new(0);
1637+ ///
1638+ /// // When we own the value, we can extract the contents for free.
1639+ /// let contents: i32 = x.into_inner();
1640+ /// assert_eq!(contents, 0);
15891641/// ```
15901642#[ lang = "unsafe_cell" ]
15911643#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1663,6 +1715,29 @@ impl<T: ?Sized> UnsafeCell<T> {
16631715 self as * const UnsafeCell < T > as * const T as * mut T
16641716 }
16651717
1718+ /// Returns a mutable reference to the underlying data.
1719+ ///
1720+ /// This call borrows the `UnsafeCell` mutably (at compile-time) which
1721+ /// guarantees that we possess the only reference.
1722+ ///
1723+ /// # Examples
1724+ ///
1725+ /// ```
1726+ /// #![feature(unsafe_cell_get_mut)]
1727+ /// use std::cell::UnsafeCell;
1728+ ///
1729+ /// let mut c = UnsafeCell::new(5);
1730+ /// *c.get_mut() += 1;
1731+ ///
1732+ /// assert_eq!(*c.get_mut(), 6);
1733+ /// ```
1734+ #[ inline]
1735+ #[ unstable( feature = "unsafe_cell_get_mut" , issue = "76943" ) ]
1736+ pub fn get_mut ( & mut self ) -> & mut T {
1737+ // SAFETY: (outer) `&mut` guarantees unique access.
1738+ unsafe { & mut * self . get ( ) }
1739+ }
1740+
16661741 /// Gets a mutable pointer to the wrapped value.
16671742 /// The difference to [`get`] is that this function accepts a raw pointer,
16681743 /// which is useful to avoid the creation of temporary references.
0 commit comments