未验证 提交 fdb5181f 编写于 作者: K kennytm 提交者: GitHub

Rollup merge of #48201 - NovemberZulu:master, r=steveklabnik

rephrase UnsafeCell doc

As shown by discussions on users.rust-lang.org [[1]], [[2]], UnsafeCell doc is not totally clear. I tried to made the doc univocal regarding what is allowed and what is not. The edits are based on my understanding following [[1]].

[1]: https://users.rust-lang.org/t/unsafecell-behavior-details/1560
[2]: https://users.rust-lang.org/t/is-there-a-better-way-to-overload-index-indexmut-for-a-rc-refcell/15591/12
......@@ -1203,21 +1203,42 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
/// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior.
///
/// The compiler makes optimizations based on the knowledge that `&T` is not mutably aliased or
/// mutated, and that `&mut T` is unique. When building abstractions like `Cell`, `RefCell`,
/// `Mutex`, etc, you need to turn these optimizations off. `UnsafeCell` is the only legal way
/// to do this. When `UnsafeCell<T>` is immutably aliased, it is still safe to obtain a mutable
/// reference to its interior and/or to mutate it. However, it is up to the abstraction designer
/// to ensure that no two mutable references obtained this way are active at the same time, and
/// that there are no active mutable references or mutations when an immutable reference is obtained
/// from the cell. This is often done via runtime checks.
/// 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. `UnsafeCel<T>` is the only core language
/// feature to work around this restriction. All other types that allow internal mutability, such as
/// `Cell<T>` and `RefCell<T>` use `UnsafeCell` to wrap their internal data.
///
/// Note that while mutating or mutably aliasing the contents of an `& UnsafeCell<T>` is
/// okay (provided you enforce the invariants some other way); it is still undefined behavior
/// to have multiple `&mut UnsafeCell<T>` aliases.
/// The `UnsafeCell` API itself is technically very simple: it gives you a raw pointer `*mut T` to
/// its contents. It is up to _you_ as the abstraction designer to use that raw pointer correctly.
///
/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious:
///
/// - If you create a safe reference with lifetime `'a` (either a `&T` or `&mut T` reference) that
/// is accessible by safe code (for example, because you returned it), then you must not access
/// the data in any way that contradicts that reference for the remainder of `'a`. For example, that
/// means that if you take the `*mut T` from an `UnsafeCell<T>` and case it to an `&T`, then until
/// that reference's lifetime expires, the data in `T` must remain immutable (modulo any
/// `UnsafeCell` data found within `T`, of course). Similarly, if you create an `&mut T` reference
/// that is released to safe code, then you must not access the data within the `UnsafeCell` until
/// that reference expires.
///
/// - At all times, you must avoid data races, meaning that if multiple threads have access to
/// the same `UnsafeCell`, then any writes must have a proper happens-before relation to all other
/// accesses (or use atomics).
///
/// To assist with proper design, the following scenarios are explicitly declared legal
/// for single-threaded code:
///
/// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data.
/// 1. A `&T` reference can be released to safe code and there it can co-exit with other `&T`
/// references, but not with a `&mut T`
///
/// 2. A `&mut T` reference may be released to safe code, provided neither other `&mut T` nor `&T`
/// co-exist with it. A `&mut T` must always be unique.
///
/// Note that while mutating or mutably aliasing the contents of an `& UnsafeCell<T>` is
/// okay (provided you enforce the invariants some other way), it is still undefined behavior
/// to have multiple `&mut UnsafeCell<T>` aliases.
///
/// # Examples
///
......@@ -1282,9 +1303,9 @@ impl<T: ?Sized> UnsafeCell<T> {
/// Gets a mutable pointer to the wrapped value.
///
/// This can be cast to a pointer of any kind.
/// Ensure that the access is unique when casting to
/// `&mut T`, and ensure that there are no mutations or mutable
/// aliases going on when casting to `&T`
/// Ensure that the access is unique (no active references, mutable or not)
/// when casting to `&mut T`, and ensure that there are no mutations
/// or mutable aliases going on when casting to `&T`
///
/// # Examples
///
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册