@@ -496,10 +496,7 @@ impl<T: ?Sized> Cell<T> {
496
496
#[ inline]
497
497
#[ stable( feature = "cell_get_mut" , since = "1.11.0" ) ]
498
498
pub fn get_mut ( & mut self ) -> & mut T {
499
- // SAFETY: This can cause data races if called from a separate thread,
500
- // but `Cell` is `!Sync` so this won't happen, and `&mut` guarantees
501
- // unique access.
502
- unsafe { & mut * self . value . get ( ) }
499
+ self . value . get_mut ( )
503
500
}
504
501
505
502
/// Returns a `&Cell<T>` from a `&mut T`
@@ -945,8 +942,7 @@ impl<T: ?Sized> RefCell<T> {
945
942
#[ inline]
946
943
#[ stable( feature = "cell_get_mut" , since = "1.11.0" ) ]
947
944
pub fn get_mut ( & mut self ) -> & mut T {
948
- // SAFETY: `&mut` guarantees unique access.
949
- unsafe { & mut * self . value . get ( ) }
945
+ self . value . get_mut ( )
950
946
}
951
947
952
948
/// Undo the effect of leaked guards on the borrow state of the `RefCell`.
@@ -1543,8 +1539,11 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
1543
1539
/// allow internal mutability, such as `Cell<T>` and `RefCell<T>`, use `UnsafeCell` to wrap their
1544
1540
/// internal data. There is *no* legal way to obtain aliasing `&mut`, not even with `UnsafeCell<T>`.
1545
1541
///
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.
1542
+ /// The `UnsafeCell` API itself is technically very simple: [`.get()`] gives you a raw pointer
1543
+ /// `*mut T` to its contents. It is up to _you_ as the abstraction designer to use that raw pointer
1544
+ /// correctly.
1545
+ ///
1546
+ /// [`.get()`]: `UnsafeCell::get`
1548
1547
///
1549
1548
/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious:
1550
1549
///
@@ -1571,21 +1570,70 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
1571
1570
/// 2. A `&mut T` reference may be released to safe code provided neither other `&mut T` nor `&T`
1572
1571
/// co-exist with it. A `&mut T` must always be unique.
1573
1572
///
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.
1573
+ /// Note that whilst mutating the contents of an `&UnsafeCell<T>` (even while other
1574
+ /// `&UnsafeCell<T>` references alias the cell) is
1575
+ /// ok (provided you enforce the above invariants some other way), it is still undefined behavior
1576
+ /// to have multiple `&mut UnsafeCell<T>` aliases. That is, `UnsafeCell` is a wrapper
1577
+ /// designed to have a special interaction with _shared_ accesses (_i.e._, through an
1578
+ /// `&UnsafeCell<_>` reference); there is no magic whatsoever when dealing with _exclusive_
1579
+ /// accesses (_e.g._, through an `&mut UnsafeCell<_>`): neither the cell nor the wrapped value
1580
+ /// may be aliased for the duration of that `&mut` borrow.
1581
+ /// This is showcased by the [`.get_mut()`] accessor, which is a non-`unsafe` getter that yields
1582
+ /// a `&mut T`.
1583
+ ///
1584
+ /// [`.get_mut()`]: `UnsafeCell::get_mut`
1577
1585
///
1578
1586
/// # Examples
1579
1587
///
1588
+ /// Here is an example showcasing how to soundly mutate the contents of an `UnsafeCell<_>` despite
1589
+ /// there being multiple references aliasing the cell:
1590
+ ///
1580
1591
/// ```
1581
1592
/// use std::cell::UnsafeCell;
1582
1593
///
1583
- /// # #[allow(dead_code)]
1584
- /// struct NotThreadSafe<T> {
1585
- /// value: UnsafeCell<T>,
1594
+ /// let x: UnsafeCell<i32> = 42.into();
1595
+ /// // Get multiple / concurrent / shared references to the same `x`.
1596
+ /// let (p1, p2): (&UnsafeCell<i32>, &UnsafeCell<i32>) = (&x, &x);
1597
+ ///
1598
+ /// unsafe {
1599
+ /// // SAFETY: within this scope there are no other references to `x`'s contents,
1600
+ /// // so ours is effectively unique.
1601
+ /// let p1_exclusive: &mut i32 = &mut *p1.get(); // -- borrow --+
1602
+ /// *p1_exclusive += 27; // |
1603
+ /// } // <---------- cannot go beyond this point -------------------+
1604
+ ///
1605
+ /// unsafe {
1606
+ /// // SAFETY: within this scope nobody expects to have exclusive access to `x`'s contents,
1607
+ /// // so we can have multiple shared accesses concurrently.
1608
+ /// let p2_shared: &i32 = &*p2.get();
1609
+ /// assert_eq!(*p2_shared, 42 + 27);
1610
+ /// let p1_shared: &i32 = &*p1.get();
1611
+ /// assert_eq!(*p1_shared, *p2_shared);
1586
1612
/// }
1613
+ /// ```
1587
1614
///
1588
- /// unsafe impl<T> Sync for NotThreadSafe<T> {}
1615
+ /// The following example showcases the fact that exclusive access to an `UnsafeCell<T>`
1616
+ /// implies exclusive access to its `T`:
1617
+ ///
1618
+ /// ```rust
1619
+ /// #![feature(unsafe_cell_get_mut)]
1620
+ /// #![forbid(unsafe_code)] // with exclusive accesses,
1621
+ /// // `UnsafeCell` is a transparent no-op wrapper,
1622
+ /// // so no need for `unsafe` here.
1623
+ /// use std::cell::UnsafeCell;
1624
+ ///
1625
+ /// let mut x: UnsafeCell<i32> = 42.into();
1626
+ ///
1627
+ /// // Get a compile-time-checked unique reference to `x`.
1628
+ /// let p_unique: &mut UnsafeCell<i32> = &mut x;
1629
+ /// // With an exclusive reference, we can mutate the contents for free.
1630
+ /// *p_unique.get_mut() = 0;
1631
+ /// // Or, equivalently:
1632
+ /// x = UnsafeCell::new(0);
1633
+ ///
1634
+ /// // When we own the value, we can extract the contents for free.
1635
+ /// let contents: i32 = x.into_inner();
1636
+ /// assert_eq!(contents, 0);
1589
1637
/// ```
1590
1638
#[ lang = "unsafe_cell" ]
1591
1639
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1663,6 +1711,29 @@ impl<T: ?Sized> UnsafeCell<T> {
1663
1711
self as * const UnsafeCell < T > as * const T as * mut T
1664
1712
}
1665
1713
1714
+ /// Returns a mutable reference to the underlying data.
1715
+ ///
1716
+ /// This call borrows the `UnsafeCell` mutably (at compile-time) which
1717
+ /// guarantees that we possess the only reference.
1718
+ ///
1719
+ /// # Examples
1720
+ ///
1721
+ /// ```
1722
+ /// #![feature(unsafe_cell_get_mut)]
1723
+ /// use std::cell::UnsafeCell;
1724
+ ///
1725
+ /// let mut c = UnsafeCell::new(5);
1726
+ /// *c.get_mut() += 1;
1727
+ ///
1728
+ /// assert_eq!(*c.get_mut(), 6);
1729
+ /// ```
1730
+ #[ inline]
1731
+ #[ unstable( feature = "unsafe_cell_get_mut" , issue = "76943" ) ]
1732
+ pub fn get_mut ( & mut self ) -> & mut T {
1733
+ // SAFETY: (outer) `&mut` guarantees unique access.
1734
+ unsafe { & mut * self . get ( ) }
1735
+ }
1736
+
1666
1737
/// Gets a mutable pointer to the wrapped value.
1667
1738
/// The difference to [`get`] is that this function accepts a raw pointer,
1668
1739
/// which is useful to avoid the creation of temporary references.
0 commit comments