about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPointerbender <pointerbender@gmail.com>2022-10-12 23:34:13 +0200
committerPointerbender <pointerbender@gmail.com>2022-10-12 23:34:13 +0200
commitddd119b2fed57eb6b19c44c18108de95c564a48d (patch)
treedda0f5715e7abf9ca8ffcdd52f5cd7b6815b275c
parent9c37c801ad737006c494f6b3bd97ff59764573ae (diff)
downloadrust-ddd119b2fed57eb6b19c44c18108de95c564a48d.tar.gz
rust-ddd119b2fed57eb6b19c44c18108de95c564a48d.zip
expand documentation on type conversion w.r.t. `UnsafeCell`
-rw-r--r--library/core/src/cell.rs21
1 files changed, 13 insertions, 8 deletions
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index be1017e5842..4dee386f887 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1811,14 +1811,19 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 ///
 /// [`.get_mut()`]: `UnsafeCell::get_mut`
 ///
-/// `UnsafeCell<T>` has the same in-memory representation as its inner type `T` if and only if
-/// the type `T` does not contain a [niche] (e.g. the type `Option<NonNull<u8>>` is typically
-/// 8 bytes large on 64-bit platforms, but the type `Option<UnsafeCell<NonNull<u8>>>` takes
-/// up 16 bytes of space). A consequence of this guarantee is that it is possible to convert
-/// between `T` and `UnsafeCell<T>` when `T` has no niches. However, it is only valid to obtain
-/// a `*mut T` pointer to the contents of a _shared_ `UnsafeCell<T>` through [`.get()`] or
-/// [`.raw_get()`]. A `&mut T` reference can be obtained by either dereferencing this pointer
-/// or by calling [`.get_mut()`] on an _exclusive_ `UnsafeCell<T>`, e.g.:
+/// `UnsafeCell<T>` has the same in-memory representation as its inner type `T`. A consequence
+/// of this guarantee is that it is possible to convert between `T` and `UnsafeCell<T>`.
+/// Special care has to be taken when converting a nested `T` inside of an `Outer<T>` type
+/// to an `Outer<UnsafeCell<T>>` type: this is not sound when the `Outer<T>` type enables [niche]
+/// optimizations. For example, the type `Option<NonNull<u8>>` is typically 8 bytes large on
+/// 64-bit platforms, but the type `Option<UnsafeCell<NonNull<u8>>>` takes up 16 bytes of space.
+/// Therefore this is not a valid conversion, despite `NonNull<u8>` and `UnsafeCell<NonNull<u8>>>`
+/// having the same memory layout. This is because `UnsafeCell` disables niche optimizations in
+/// order to avoid its interior mutability property from spreading from `T` into the `Outer` type,
+/// thus this can cause distortions in the type size in these cases. Furthermore, it is only valid
+/// to obtain a `*mut T` pointer to the contents of a _shared_ `UnsafeCell<T>` through [`.get()`]
+/// or [`.raw_get()`]. A `&mut T` reference can be obtained by either dereferencing this pointer or
+/// by calling [`.get_mut()`] on an _exclusive_ `UnsafeCell<T>`, e.g.:
 ///
 /// ```rust
 /// use std::cell::UnsafeCell;