From 75bbef960517af9b0d44050bb8edebc106738227 Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Wed, 12 Oct 2022 23:34:13 +0200 Subject: [PATCH] expand documentation on type conversion w.r.t. `UnsafeCell` --- core/src/cell.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/core/src/cell.rs b/core/src/cell.rs index be1017e58..4dee386f8 100644 --- a/core/src/cell.rs +++ b/core/src/cell.rs @@ -1811,14 +1811,19 @@ impl fmt::Display for RefMut<'_, T> { /// /// [`.get_mut()`]: `UnsafeCell::get_mut` /// -/// `UnsafeCell` 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>` is typically -/// 8 bytes large on 64-bit platforms, but the type `Option>>` takes -/// up 16 bytes of space). A consequence of this guarantee is that it is possible to convert -/// between `T` and `UnsafeCell` when `T` has no niches. However, it is only valid to obtain -/// a `*mut T` pointer to the contents of a _shared_ `UnsafeCell` 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`, e.g.: +/// `UnsafeCell` 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`. +/// Special care has to be taken when converting a nested `T` inside of an `Outer` type +/// to an `Outer>` type: this is not sound when the `Outer` type enables [niche] +/// optimizations. For example, the type `Option>` is typically 8 bytes large on +/// 64-bit platforms, but the type `Option>>` takes up 16 bytes of space. +/// Therefore this is not a valid conversion, despite `NonNull` and `UnsafeCell>>` +/// 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` 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`, e.g.: /// /// ```rust /// use std::cell::UnsafeCell;