diff options
| author | Pointerbender <pointerbender@gmail.com> | 2022-10-12 23:34:13 +0200 |
|---|---|---|
| committer | Pointerbender <pointerbender@gmail.com> | 2022-10-12 23:34:13 +0200 |
| commit | ddd119b2fed57eb6b19c44c18108de95c564a48d (patch) | |
| tree | dda0f5715e7abf9ca8ffcdd52f5cd7b6815b275c | |
| parent | 9c37c801ad737006c494f6b3bd97ff59764573ae (diff) | |
| download | rust-ddd119b2fed57eb6b19c44c18108de95c564a48d.tar.gz rust-ddd119b2fed57eb6b19c44c18108de95c564a48d.zip | |
expand documentation on type conversion w.r.t. `UnsafeCell`
| -rw-r--r-- | library/core/src/cell.rs | 21 |
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; |
