Skip to content

Commit fe557ee

Browse files
committed
another rewrite
based on @nikomatsakis texthg
1 parent 78789ad commit fe557ee

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

src/libcore/cell.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,27 +1161,43 @@ impl<'a, T: ?Sized + fmt::Display> fmt::Display for RefMut<'a, T> {
11611161
/// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
11621162
/// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior.
11631163
///
1164-
/// The compiler makes optimizations based on the knowledge that `&T` is not mutably aliased or
1165-
/// mutated, and that `&mut T` is unique. When building abstractions like `Cell`, `RefCell`,
1166-
/// `Mutex`, etc, you need to turn these optimizations off. `UnsafeCell` is the only legal way
1167-
/// to do this. When `UnsafeCell<T>` itself is immutably aliased, it is still safe to obtain
1168-
/// a mutable reference to its interior and/or to mutate the interior. However, the abstraction
1169-
/// designer must ensure that any active mutable references to the interior obtained this way does
1170-
/// not co-exist with other active references to the interior, either mutable or not. This is often
1171-
/// done via runtime checks. Naturally, several active immutable references to the interior can
1172-
/// co-exits with each other (but not with a mutable reference).
1164+
/// If you have a reference `&SomeStruct`, then normally in Rust all fields of `SomeStruct` are
1165+
/// immutable. The compiler makes optimizations based on the knowledge that `&T` is not mutably
1166+
/// aliased or mutated, and that `&mut T` is unique. `UnsafeCel<T>` is the only core language
1167+
/// feature to work around this restriction. All other types that allow internal mutability, such as
1168+
/// `Cell<T>` and `RefCell<T>` use `UnsafeCell` to wrap their internal data.
11731169
///
1174-
/// To put it in other words, if a mutable reference to the contents is active, no other references
1175-
/// can be active at the same time, and if an immutable reference to the contents is active, then
1176-
/// only other immutable reference may be active.
1170+
/// The `UnsafeCell` API itself is technically very simple: it gives you a raw pointer `*mut T` to
1171+
/// its contents. It is up to _you_ as the abstraction designer to use that raw pointer correctly.
1172+
///
1173+
/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious:
1174+
///
1175+
/// - If you create a safe reference with lifetime `'a` (either a `&T` or `&mut T` reference) that
1176+
/// is accessible by safe code (for example, because you returned it), then you must not access
1177+
/// the data in any way that contradicts that reference for the remainder of `'a`. For example, that
1178+
/// means that if you take the `*mut T` from an `UnsafeCell<T>` and case it to an `&T`, then until
1179+
/// that reference's lifetime expires, the data in `T` must remain immutable (modulo any
1180+
/// `UnsafeCell` data found within `T`, of course). Similarly, if you create an `&mut T` reference
1181+
/// that is released to safe code, then you must not access the data within the `UnsafeCell` until
1182+
/// that reference expires.
1183+
///
1184+
/// - At all times, you must avoid data races, meaning that if multiple threads have access to
1185+
/// the same `UnsafeCell`, then any writes must have a proper happens-before relation to all other
1186+
/// accesses (or use atomics).
1187+
///
1188+
/// To assist with proper design, the following scenarios are explicitly declared legal
1189+
/// for single-threaded code:
1190+
///
1191+
/// 1. A `&T` reference can be released to safe code and there it can co-exit with other `&T`
1192+
/// references, but not with a `&mut T`
1193+
///
1194+
/// 2. A `&mut T` reference may be released to safe code, provided neither other `&mut T` nor `&T`
1195+
/// co-exist with it. A `&mut T` must always be unique.
11771196
///
11781197
/// Note that while mutating or mutably aliasing the contents of an `& UnsafeCell<T>` is
11791198
/// okay (provided you enforce the invariants some other way), it is still undefined behavior
11801199
/// to have multiple `&mut UnsafeCell<T>` aliases.
11811200
///
1182-
///
1183-
/// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data.
1184-
///
11851201
/// # Examples
11861202
///
11871203
/// ```

0 commit comments

Comments
 (0)