about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2021-02-22 18:26:11 +0900
committerGitHub <noreply@github.com>2021-02-22 18:26:11 +0900
commit7958166300cc92da90b95a8c13cbf8f469832485 (patch)
tree0b95d1d9cc0e5e222aaa8d8824b7088c8b86d3ea
parent1870b3bac6f8144316f82d763230c7ad8432c0d0 (diff)
parent12608832c3b624c3d59b1371f3935804e8364127 (diff)
downloadrust-7958166300cc92da90b95a8c13cbf8f469832485.tar.gz
rust-7958166300cc92da90b95a8c13cbf8f469832485.zip
Rollup merge of #82372 - RalfJung:unsafe-cell, r=KodrAus
improve UnsafeCell docs

Sometimes [questions like this come up](https://rust-lang.zulipchat.com/#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/UnsafeCells.20as.20raw.20pointers) because the UnsafeCell docs say "it's the only legal way to obtain aliasable data that is considered mutable". That is not entirely correct, since raw pointers also provide that option. So I propose we focus the docs on the interaction of `UnsafeCell` and *shared references* specifically, which is really where they are needed.
-rw-r--r--library/core/src/cell.rs21
1 files changed, 11 insertions, 10 deletions
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index cb772458e50..cce1242d84f 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1619,17 +1619,18 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 
 /// The core primitive for interior mutability in Rust.
 ///
-/// `UnsafeCell<T>` is a type that wraps some `T` and indicates unsafe interior operations on the
-/// wrapped type. Types with an `UnsafeCell<T>` field are considered to have an 'unsafe interior'.
-/// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
-/// mutable. In general, transmuting a `&T` type into a `&mut T` is considered undefined behavior.
+/// If you have a reference `&T`, then normally in Rust the compiler performs optimizations based on
+/// the knowledge that `&T` points to immutable data. Mutating that data, for example through an
+/// alias or by transmuting an `&T` into an `&mut T`, is considered undefined behavior.
+/// `UnsafeCell<T>` opts-out of the immutability guarantee for `&T`: a shared reference
+/// `&UnsafeCell<T>` may point to data that is being mutated. This is called "interior mutability".
 ///
-/// If you have a reference `&SomeStruct`, then normally in Rust all fields of `SomeStruct` are
-/// immutable. The compiler makes optimizations based on the knowledge that `&T` is not mutably
-/// aliased or mutated, and that `&mut T` is unique. `UnsafeCell<T>` is the only core language
-/// feature to work around the restriction that `&T` may not be mutated. All other types that
-/// allow internal mutability, such as `Cell<T>` and `RefCell<T>`, use `UnsafeCell` to wrap their
-/// internal data. There is *no* legal way to obtain aliasing `&mut`, not even with `UnsafeCell<T>`.
+/// All other types that allow internal mutability, such as `Cell<T>` and `RefCell<T>`, internally
+/// use `UnsafeCell` to wrap their data.
+///
+/// Note that only the immutability guarantee for shared references is affected by `UnsafeCell`. The
+/// uniqueness guarantee for mutable references is unaffected. There is *no* legal way to obtain
+/// aliasing `&mut`, not even with `UnsafeCell<T>`.
 ///
 /// The `UnsafeCell` API itself is technically very simple: [`.get()`] gives you a raw pointer
 /// `*mut T` to its contents. It is up to _you_ as the abstraction designer to use that raw pointer