Skip to content

Commit 2fbd431

Browse files
committed
Restate Immutable's guarantees
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.
1 parent f6beda4 commit 2fbd431

File tree

2 files changed

+20
-18
lines changed

2 files changed

+20
-18
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ functionality themselves, but are required to call certain methods provided
4444
by the conversion traits:
4545
- `KnownLayout` indicates that zerocopy can reason about certain layout
4646
qualities of a type
47-
- `Immutable` indicates that a type does not contain any `UnsafeCell`s
47+
- `Immutable` indicates that a type is free from interior mutability,
48+
except by ownership or an exclusive (`&mut`) borrow
4849
- `Unaligned` indicates that a type's alignment requirement is 1
4950

5051
You should generally derive these marker traits whenever possible.

src/lib.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
//! by the conversion traits:
4545
//! - [`KnownLayout`] indicates that zerocopy can reason about certain layout
4646
//! qualities of a type
47-
//! - [`Immutable`] indicates that a type does not contain any [`UnsafeCell`]s
47+
//! - [`Immutable`] indicates that a type is free from interior mutability,
48+
//! except by ownership or an exclusive (`&mut`) borrow
4849
//! - [`Unaligned`] indicates that a type's alignment requirement is 1
4950
//!
5051
//! You should generally derive these marker traits whenever possible.
@@ -758,9 +759,8 @@ pub use zerocopy_derive::FromZeros;
758759
///
759760
/// *This section describes, roughly, the analysis performed by this derive to
760761
/// determine whether it is sound to implement `Immutable` for a given type.
761-
/// Unless you are modifying the implementation of this derive, or attempting to
762-
/// manually implement `Immutable` for a type yourself, you don't need to read
763-
/// this section.*
762+
/// Unless you are modifying the implementation of this derive, you don't need
763+
/// to read this section.*
764764
///
765765
/// If a type has the following properties, then this derive can implement
766766
/// `Immutable` for that type:
@@ -776,11 +776,10 @@ pub use zerocopy_derive::FromZeros;
776776
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
777777
pub use zerocopy_derive::Immutable;
778778

779-
/// Types which do not directly contain any [`UnsafeCell`]s.
779+
/// Types which are free from interior mutability.
780780
///
781-
/// `T: Immutable` indicates that `T` does not contain any `UnsafeCell`s in its
782-
/// fields. `T` may still refer to types which contain `UnsafeCell`s: for
783-
/// example, `&UnsafeCell<T>` implements `Immutable`.
781+
/// `T: Immutable` indicates that `T` does not permit interior mutability, except
782+
/// by ownership or an exclusive (`&mut`) borrow.
784783
///
785784
/// # Implementation
786785
///
@@ -818,21 +817,23 @@ pub use zerocopy_derive::Immutable;
818817
///
819818
/// # Safety
820819
///
821-
/// If `T: Immutable`, unsafe code *inside of this crate* may assume that, given
822-
/// `t: &T`, `t` does not contain any [`UnsafeCell`]s at any byte location
823-
/// within the byte range addressed by `t`. This includes ranges of length 0
824-
/// (e.g., `UnsafeCell<()>` and `[UnsafeCell<u8>; 0]`). If a type implements
825-
/// `Immutable` which violates this assumptions, it may cause this crate to
826-
/// exhibit [undefined behavior].
827-
///
828820
/// Unsafe code outside of this crate must not make any assumptions about `T`
829821
/// based on `T: Immutable`. We reserve the right to relax the requirements for
830822
/// `Immutable` in the future, and if unsafe code outside of this crate makes
831823
/// assumptions based on `T: Immutable`, future relaxations may cause that code
832824
/// to become unsound.
833825
///
834-
/// [`UnsafeCell`]: core::cell::UnsafeCell
835-
/// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
826+
// # Safety (Internal)
827+
//
828+
// If `T: Immutable`, unsafe code *inside of this crate* may assume that, given
829+
// `t: &T`, `t` does not contain any [`UnsafeCell`]s at any byte location
830+
// within the byte range addressed by `t`. This includes ranges of length 0
831+
// (e.g., `UnsafeCell<()>` and `[UnsafeCell<u8>; 0]`). If a type implements
832+
// `Immutable` which violates this assumptions, it may cause this crate to
833+
// exhibit [undefined behavior].
834+
//
835+
// [`UnsafeCell`]: core::cell::UnsafeCell
836+
// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
836837
#[cfg_attr(
837838
feature = "derive",
838839
doc = "[derive]: zerocopy_derive::Immutable",

0 commit comments

Comments
 (0)