@@ -1543,8 +1543,11 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
1543
1543
/// allow internal mutability, such as `Cell<T>` and `RefCell<T>`, use `UnsafeCell` to wrap their
1544
1544
/// internal data. There is *no* legal way to obtain aliasing `&mut`, not even with `UnsafeCell<T>`.
1545
1545
///
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`
1548
1551
///
1549
1552
/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious:
1550
1553
///
@@ -1571,21 +1574,70 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
1571
1574
/// 2. A `&mut T` reference may be released to safe code provided neither other `&mut T` nor `&T`
1572
1575
/// co-exist with it. A `&mut T` must always be unique.
1573
1576
///
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`
1577
1589
///
1578
1590
/// # Examples
1579
1591
///
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
+ ///
1580
1595
/// ```
1581
1596
/// use std::cell::UnsafeCell;
1582
1597
///
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);
1586
1616
/// }
1617
+ /// ```
1618
+ ///
1619
+ /// The following example showcases the fact that exclusive access to an `UnsafeCell<T>`
1620
+ /// implies exclusive access to its `T`:
1587
1621
///
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);
1589
1641
/// ```
1590
1642
#[ lang = "unsafe_cell" ]
1591
1643
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1663,6 +1715,29 @@ impl<T: ?Sized> UnsafeCell<T> {
1663
1715
self as * const UnsafeCell < T > as * const T as * mut T
1664
1716
}
1665
1717
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
+
1666
1741
/// Gets a mutable pointer to the wrapped value.
1667
1742
/// The difference to [`get`] is that this function accepts a raw pointer,
1668
1743
/// which is useful to avoid the creation of temporary references.
0 commit comments