From 0fc6df9ae666fbd5dcad57f2e14a1307f0795b16 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Thu, 2 May 2024 15:52:59 -0400 Subject: [PATCH] Restate `Immutable`'s guarantees (#1165) This PR adjust's `Immutable`'s informal public contract. Previously, we publicly documented that `Immutable` denoted that a type does not directly contain `UnsafeCell`. Now, we only document that `Immutable` types do not permit interrior mutation. This change is made in recognition that: - Containing `UnsafeCell` may be fine, so long as that the special properties of that `UnsafeCell` cannot be exercised in safe code. - In contrast to what's guaranteed by the compiler's `Freeze` trait, we almost certainly need *recursive* immutability for safe transmutation. Makes progress towards #1155. --- README.md | 3 ++- src/lib.rs | 35 ++++++++++++++++++----------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index bba16817c7..091e1fda21 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,8 @@ functionality themselves, but are required to call certain methods provided by the conversion traits: - `KnownLayout` indicates that zerocopy can reason about certain layout qualities of a type -- `Immutable` indicates that a type does not contain any `UnsafeCell`s +- `Immutable` indicates that a type is free from interior mutability, + except by ownership or an exclusive (`&mut`) borrow - `Unaligned` indicates that a type's alignment requirement is 1 You should generally derive these marker traits whenever possible. diff --git a/src/lib.rs b/src/lib.rs index ec42e834a5..f5bf22770d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,8 @@ //! by the conversion traits: //! - [`KnownLayout`] indicates that zerocopy can reason about certain layout //! qualities of a type -//! - [`Immutable`] indicates that a type does not contain any [`UnsafeCell`]s +//! - [`Immutable`] indicates that a type is free from interior mutability, +//! except by ownership or an exclusive (`&mut`) borrow //! - [`Unaligned`] indicates that a type's alignment requirement is 1 //! //! You should generally derive these marker traits whenever possible. @@ -758,9 +759,8 @@ pub use zerocopy_derive::FromZeros; /// /// *This section describes, roughly, the analysis performed by this derive to /// determine whether it is sound to implement `Immutable` for a given type. -/// Unless you are modifying the implementation of this derive, or attempting to -/// manually implement `Immutable` for a type yourself, you don't need to read -/// this section.* +/// Unless you are modifying the implementation of this derive, you don't need +/// to read this section.* /// /// If a type has the following properties, then this derive can implement /// `Immutable` for that type: @@ -776,11 +776,10 @@ pub use zerocopy_derive::FromZeros; #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] pub use zerocopy_derive::Immutable; -/// Types which do not directly contain any [`UnsafeCell`]s. +/// Types which are free from interior mutability. /// -/// `T: Immutable` indicates that `T` does not contain any `UnsafeCell`s in its -/// fields. `T` may still refer to types which contain `UnsafeCell`s: for -/// example, `&UnsafeCell` implements `Immutable`. +/// `T: Immutable` indicates that `T` does not permit interior mutability, except +/// by ownership or an exclusive (`&mut`) borrow. /// /// # Implementation /// @@ -818,21 +817,23 @@ pub use zerocopy_derive::Immutable; /// /// # Safety /// -/// If `T: Immutable`, unsafe code *inside of this crate* may assume that, given -/// `t: &T`, `t` does not contain any [`UnsafeCell`]s at any byte location -/// within the byte range addressed by `t`. This includes ranges of length 0 -/// (e.g., `UnsafeCell<()>` and `[UnsafeCell; 0]`). If a type implements -/// `Immutable` which violates this assumptions, it may cause this crate to -/// exhibit [undefined behavior]. -/// /// Unsafe code outside of this crate must not make any assumptions about `T` /// based on `T: Immutable`. We reserve the right to relax the requirements for /// `Immutable` in the future, and if unsafe code outside of this crate makes /// assumptions based on `T: Immutable`, future relaxations may cause that code /// to become unsound. /// -/// [`UnsafeCell`]: core::cell::UnsafeCell -/// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html +// # Safety (Internal) +// +// If `T: Immutable`, unsafe code *inside of this crate* may assume that, given +// `t: &T`, `t` does not contain any [`UnsafeCell`]s at any byte location +// within the byte range addressed by `t`. This includes ranges of length 0 +// (e.g., `UnsafeCell<()>` and `[UnsafeCell; 0]`). If a type implements +// `Immutable` which violates this assumptions, it may cause this crate to +// exhibit [undefined behavior]. +// +// [`UnsafeCell`]: core::cell::UnsafeCell +// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html #[cfg_attr( feature = "derive", doc = "[derive]: zerocopy_derive::Immutable",