@@ -1816,6 +1816,50 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
1816
1816
///
1817
1817
/// [`.get_mut()`]: `UnsafeCell::get_mut`
1818
1818
///
1819
+ /// `UnsafeCell<T>` has the same in-memory representation as its inner type `T`. A consequence
1820
+ /// of this guarantee is that it is possible to convert between `T` and `UnsafeCell<T>`.
1821
+ /// Special care has to be taken when converting a nested `T` inside of an `Outer<T>` type
1822
+ /// to an `Outer<UnsafeCell<T>>` type: this is not sound when the `Outer<T>` type enables [niche]
1823
+ /// optimizations. For example, the type `Option<NonNull<u8>>` is typically 8 bytes large on
1824
+ /// 64-bit platforms, but the type `Option<UnsafeCell<NonNull<u8>>>` takes up 16 bytes of space.
1825
+ /// Therefore this is not a valid conversion, despite `NonNull<u8>` and `UnsafeCell<NonNull<u8>>>`
1826
+ /// having the same memory layout. This is because `UnsafeCell` disables niche optimizations in
1827
+ /// order to avoid its interior mutability property from spreading from `T` into the `Outer` type,
1828
+ /// thus this can cause distortions in the type size in these cases. Furthermore, it is only valid
1829
+ /// to obtain a `*mut T` pointer to the contents of a _shared_ `UnsafeCell<T>` through [`.get()`]
1830
+ /// or [`.raw_get()`]. A `&mut T` reference can be obtained by either dereferencing this pointer or
1831
+ /// by calling [`.get_mut()`] on an _exclusive_ `UnsafeCell<T>`, e.g.:
1832
+ ///
1833
+ /// ```rust
1834
+ /// use std::cell::UnsafeCell;
1835
+ ///
1836
+ /// let mut x: UnsafeCell<u32> = UnsafeCell::new(5);
1837
+ /// let shared: &UnsafeCell<u32> = &x;
1838
+ /// // using `.get()` is okay:
1839
+ /// unsafe {
1840
+ /// // SAFETY: there exist no other references to the contents of `x`
1841
+ /// let exclusive: &mut u32 = &mut *shared.get();
1842
+ /// };
1843
+ /// // using `.raw_get()` is also okay:
1844
+ /// unsafe {
1845
+ /// // SAFETY: there exist no other references to the contents of `x` in this scope
1846
+ /// let exclusive: &mut u32 = &mut *UnsafeCell::raw_get(shared as *const _);
1847
+ /// };
1848
+ /// // using `.get_mut()` is always safe:
1849
+ /// let exclusive: &mut u32 = x.get_mut();
1850
+ ///
1851
+ /// // when we have exclusive access, we can convert it to a shared `&UnsafeCell`:
1852
+ /// unsafe {
1853
+ /// // SAFETY: `u32` has no niche, therefore it has the same layout as `UnsafeCell<u32>`
1854
+ /// let shared: &UnsafeCell<u32> = &*(exclusive as *mut _ as *const UnsafeCell<u32>);
1855
+ /// // SAFETY: there exist no other *active* references to the contents of `x` in this scope
1856
+ /// let exclusive: &mut u32 = &mut *shared.get();
1857
+ /// }
1858
+ /// ```
1859
+ ///
1860
+ /// [niche]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#niche
1861
+ /// [`.raw_get()`]: `UnsafeCell::raw_get`
1862
+ ///
1819
1863
/// # Examples
1820
1864
///
1821
1865
/// Here is an example showcasing how to soundly mutate the contents of an `UnsafeCell<_>` despite
0 commit comments